Mercurial > hg > index.cgi
annotate 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 |
rev | line source |
---|---|
25 | 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 | |
26
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
28 #include <lw_alloc.h> |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
29 #include <lw_string.h> |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
30 |
25 | 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; | |
26
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
58 char *subname; |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
59 int vis = 0; |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
60 |
25 | 61 lexer(state); |
62 if (state -> lexer_token != token_identifier) | |
63 { | |
64 lwb_error("Invalid sub name '%s'", state -> lexer_token_string); | |
65 } | |
66 | |
26
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
67 subname = lw_strdup(state -> lexer_token_string); |
25 | 68 |
69 lexer(state); | |
70 if (state -> lexer_token == token_kw_public || state -> lexer_token == token_kw_private) | |
71 { | |
26
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
72 if (state -> lexer_token == token_kw_public) |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
73 vis = 1; |
25 | 74 lexer(state); |
75 } | |
76 | |
77 /* ignore the "PARAMS" keyword if present */ | |
78 if (state -> lexer_token == token_kw_params) | |
79 lexer(state); | |
80 | |
26
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
81 if (state -> lexer_token == token_eol || state -> lexer_token == token_kw_returns) |
25 | 82 goto noparms; |
83 | |
84 paramagain: | |
85 if (state -> lexer_token != token_identifier) | |
86 { | |
26
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
87 lwb_error("Parameter name expected, got %d, %s\n", state -> lexer_token, state -> lexer_token_string); |
25 | 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 } | |
26
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
139 |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
140 |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
141 printf("Sub/Func %s, vis %s\n", subname, vis ? "public" : "private"); |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
142 |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
143 state -> currentsub = subname; |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
144 |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
145 /* consume EOL */ |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
146 lexer(state); |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
147 |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
148 /* variable declarations */ |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
149 /* parse_decls(state); */ |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
150 |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
151 /* output function/sub prolog */ |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
152 emit_prolog(state, vis, 0); |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
153 |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
154 /* parse statement block */ |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
155 /* parse_statemetns(state); */ |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
156 |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
157 if (issub) |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
158 { |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
159 if (state -> lexer_token != token_kw_endsub) |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
160 { |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
161 lwb_error("Expecting ENDSUB, got %d (%s)\n", state -> lexer_token, state -> lexer_token_string); |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
162 } |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
163 } |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
164 else |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
165 { |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
166 if (state -> lexer_token != token_kw_endfunction) |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
167 { |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
168 lwb_error("Expecting ENDFUNCTION, got %d (%s)\n", state -> lexer_token, state -> lexer_token_string); |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
169 } |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
170 } |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
171 /* output function/sub epilog */ |
27 | 172 emit_epilog(state, 0); |
26
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
173 |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
174 lw_free(state -> currentsub); |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
175 state -> currentsub = NULL; |
26aa76da75ad
Additional parsing in function/sub; emission of prolog/epilog code
lost@l-w.ca
parents:
25
diff
changeset
|
176 |
25 | 177 } |
178 | |
30
bcd532a90e53
Renamed "compiler" to "parser" for more consistent terminology
lost@l-w.ca
parents:
27
diff
changeset
|
179 void parser(cstate *state) |
25 | 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 } |