comparison lwcc/cc-parse.c @ 506:7e8298f7bc0a

Add basic syntax for typecasting Add parser support for type casts. This current scheme handles only integer types. Also include parenthesis grouping in expressions.
author William Astle <lost@l-w.ca>
date Sun, 27 Oct 2019 12:06:01 -0600
parents 14a40f8bb4eb
children
comparison
equal deleted inserted replaced
505:59b8c8b15bd4 506:7e8298f7bc0a
169 169
170 } 170 }
171 171
172 node_t *parse_expr_real(struct parser_state *ps, int prec); 172 node_t *parse_expr_real(struct parser_state *ps, int prec);
173 173
174 // parse an elementary type (int, etc.)
175 node_t *parse_elem_type(struct parser_state *ps)
176 {
177 int sgn = -1;
178 int nt = -1;
179 int nn = 1;
180
181 if (ps -> curtok -> ttype == TOK_KW_SIGNED)
182 {
183 sgn = 1;
184 parse_next(ps);
185 }
186 else if (ps -> curtok -> ttype == TOK_KW_UNSIGNED)
187 {
188 sgn = 0;
189 parse_next(ps);
190 }
191
192 switch (ps -> curtok -> ttype)
193 {
194 // NOTE: char is unsigned by default
195 case TOK_KW_CHAR:
196 if (sgn == -1 || sgn == 0)
197 nt = NODE_TYPE_UCHAR;
198 else
199 nt = NODE_TYPE_CHAR;
200 break;
201
202 case TOK_KW_SHORT:
203 nt = sgn ? NODE_TYPE_SHORT : NODE_TYPE_USHORT;
204 break;
205
206 case TOK_KW_INT:
207 nt = sgn ? NODE_TYPE_INT : NODE_TYPE_UINT;
208 break;
209
210 case TOK_KW_LONG:
211 parse_next(ps);
212 if (ps -> curtok -> ttype == TOK_KW_LONG)
213 {
214 nt = sgn ? NODE_TYPE_LONGLONG : NODE_TYPE_ULONGLONG;
215 break;
216 }
217 nn = 0;
218 nt = sgn ? NODE_TYPE_LONG : NODE_TYPE_ULONG;
219 break;
220
221 }
222 if (nt == -1)
223 {
224 if (sgn == -1)
225 {
226 return NULL;
227 }
228 else
229 {
230 nt = sgn ? NODE_TYPE_INT : NODE_TYPE_UINT;
231 }
232 }
233 else if (nn)
234 {
235 parse_next(ps);
236 }
237 return node_create(nt);
238 }
239
240 // if ident is non-zero, accept an identifier as part of the type; otherwise
241 // do not accept an identifier; currently a stub
242 node_t *parse_type(struct parser_state *ps, int ident)
243 {
244 node_t *rv;
245
246 // see if we have an elementary type
247 rv = parse_elem_type(ps);
248
249 // look for "struct", etc.
250
251 // look for pointer indicator(s)
252
253 // look for identifier if wanted/allowed
254
255 // look for array indicator or function parameter list
256 return rv;
257 }
258
174 node_t *parse_term_real(struct parser_state *ps) 259 node_t *parse_term_real(struct parser_state *ps)
175 { 260 {
176 node_t *rv; 261 node_t *rv, *rv2;
177 262
178 switch (ps -> curtok -> ttype) 263 switch (ps -> curtok -> ttype)
179 { 264 {
180 case TOK_CONST_INT: 265 case TOK_CONST_INT:
181 rv = node_create(NODE_CONST_INT, ps -> curtok -> strval); 266 rv = node_create(NODE_CONST_INT, ps -> curtok -> strval);
267 parse_next(ps);
268 return rv;
269
270 // opening paren: either grouping or type cast
271 case TOK_OPAREN:
272 parse_next(ps);
273 // parse a type without an identifier
274 rv2 = parse_type(ps, 0);
275 if (rv2)
276 {
277 if (ps -> curtok -> ttype != TOK_CPAREN)
278 {
279 node_destroy(rv2);
280 parse_generr(ps, "missing ) on type cast");
281 return NULL;
282 }
283 parse_next(ps);
284 // detect C99 compound literal here
285 rv = parse_expr_real(ps, 175);
286 if (!rv)
287 {
288 node_destroy(rv);
289 return NULL;
290 }
291 return node_create(NODE_TYPECAST, rv2, rv);
292 }
293 // grouping
294 rv = parse_expr_real(ps, 0);
295 if (ps -> curtok -> ttype != TOK_CPAREN)
296 {
297 node_destroy(rv);
298 parse_generr(ps, "missing ) on expression grouping");
299 return NULL;
300 }
182 parse_next(ps); 301 parse_next(ps);
183 return rv; 302 return rv;
184 } 303 }
185 304
186 parse_generr(ps, "term"); 305 parse_generr(ps, "term");