comparison lwbasic/parser.c @ 30:bcd532a90e53

Renamed "compiler" to "parser" for more consistent terminology
author lost@l-w.ca
date Thu, 03 Feb 2011 21:19:11 -0700
parents lwbasic/compiler.c@77626fc37af2
children 574931d87abd
comparison
equal deleted inserted replaced
29:bc96cd02fbf4 30:bcd532a90e53
1 /*
2 compiler.c
3
4 Copyright © 2011 William Astle
5
6 This file is part of LWTOOLS.
7
8 LWTOOLS is free software: you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation, either version 3 of the License, or (at your option) any later
11 version.
12
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 more details.
17
18 You should have received a copy of the GNU General Public License along with
19 this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23 This is the actual compiler bit; it drives the parser and code generation
24 */
25
26 #include <stdio.h>
27
28 #include <lw_alloc.h>
29 #include <lw_string.h>
30
31 #include "lwbasic.h"
32
33 /* parse a type; the next token will be acquired as a result */
34 /* the token advancement is to provide consistency */
35 static int parse_type(cstate *state)
36 {
37 int pt = -1;
38
39 switch (state -> lexer_token)
40 {
41 case token_kw_integer:
42 pt = 1;
43 break;
44
45 default:
46 lwb_error("Invalid type specification");
47 }
48 lexer(state);
49 /* look for "unsigned" modifier for integer types */
50 return pt;
51 }
52
53
54 /* issub means RETURNS is not allowed; !issub means RETURNS is required */
55 static void parse_subfunc(cstate *state, int issub)
56 {
57 int pt;
58 char *subname;
59 int vis = 0;
60
61 lexer(state);
62 if (state -> lexer_token != token_identifier)
63 {
64 lwb_error("Invalid sub name '%s'", state -> lexer_token_string);
65 }
66
67 subname = lw_strdup(state -> lexer_token_string);
68
69 lexer(state);
70 if (state -> lexer_token == token_kw_public || state -> lexer_token == token_kw_private)
71 {
72 if (state -> lexer_token == token_kw_public)
73 vis = 1;
74 lexer(state);
75 }
76
77 /* ignore the "PARAMS" keyword if present */
78 if (state -> lexer_token == token_kw_params)
79 lexer(state);
80
81 if (state -> lexer_token == token_eol || state -> lexer_token == token_kw_returns)
82 goto noparms;
83
84 paramagain:
85 if (state -> lexer_token != token_identifier)
86 {
87 lwb_error("Parameter name expected, got %d, %s\n", state -> lexer_token, state -> lexer_token_string);
88 }
89 printf("Got <param> = %s\n", state -> lexer_token_string);
90 lexer(state);
91
92 if (state -> lexer_token != token_kw_as)
93 lwb_error("Expecting AS\n");
94 lexer(state);
95
96 pt = parse_type(state);
97 printf("Got <type> = %d\n", pt);
98
99 if (state -> lexer_token == token_char && state -> lexer_token_string[0] == ',')
100 {
101 lexer(state);
102 goto paramagain;
103 }
104
105 noparms:
106 if (!issub)
107 {
108 int rt;
109
110 if (state -> lexer_token != token_kw_returns)
111 {
112 lwb_error("FUNCTION must have RETURNS\n");
113 }
114 lexer(state);
115 if (state -> lexer_token == token_identifier)
116 {
117 printf("Return value named: %s\n", state -> lexer_token_string);
118 lexer(state);
119 if (state -> lexer_token != token_kw_as)
120 lwb_error("Execting AS after RETURNS");
121 lexer(state);
122 }
123 rt = parse_type(state);
124 printf("Return type: %d\n", rt);
125 }
126 else
127 {
128 if (state -> lexer_token == token_kw_returns)
129 {
130 lwb_error("SUB cannot specify RETURNS\n");
131 }
132 }
133
134
135 if (state -> lexer_token != token_eol)
136 {
137 lwb_error("EOL expected; found %d, %s\n", state -> lexer_token, state -> lexer_token_string);
138 }
139
140
141 printf("Sub/Func %s, vis %s\n", subname, vis ? "public" : "private");
142
143 state -> currentsub = subname;
144
145 /* consume EOL */
146 lexer(state);
147
148 /* variable declarations */
149 /* parse_decls(state); */
150
151 /* output function/sub prolog */
152 emit_prolog(state, vis, 0);
153
154 /* parse statement block */
155 /* parse_statemetns(state); */
156
157 if (issub)
158 {
159 if (state -> lexer_token != token_kw_endsub)
160 {
161 lwb_error("Expecting ENDSUB, got %d (%s)\n", state -> lexer_token, state -> lexer_token_string);
162 }
163 }
164 else
165 {
166 if (state -> lexer_token != token_kw_endfunction)
167 {
168 lwb_error("Expecting ENDFUNCTION, got %d (%s)\n", state -> lexer_token, state -> lexer_token_string);
169 }
170 }
171 /* output function/sub epilog */
172 emit_epilog(state, 0);
173
174 lw_free(state -> currentsub);
175 state -> currentsub = NULL;
176
177 }
178
179 void parser(cstate *state)
180 {
181 state -> lexer_curchar = -1;
182
183 /* now look for a global declaration */
184 for (;;)
185 {
186 state -> parser_state = parser_state_global;
187 lexer(state);
188 switch (state -> lexer_token)
189 {
190 case token_kw_function:
191 printf("Function\n");
192 parse_subfunc(state, 0);
193 break;
194
195 case token_kw_sub:
196 printf("Sub\n");
197 parse_subfunc(state, 1);
198 break;
199
200 /* blank lines are allowed */
201 case token_eol:
202 continue;
203
204 /* EOF is allowed - end of parsing */
205 case token_eof:
206 return;
207
208 default:
209 lwb_error("Invalid token %d, %s in global state\n", state -> lexer_token, state -> lexer_token_string);
210 }
211 }
212 }