source: mainline/uspace/app/sbi/src/p_expr.c@ a95310e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a95310e was 1ebc1a62, checked in by Jiri Svoboda <jiri@…>, 16 years ago

Update SBI to rev. 157.

  • Property mode set to 100644
File size: 11.4 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Parse arithmetic expressions. */
30
31#include <assert.h>
32#include <stdlib.h>
33#include "debug.h"
34#include "lex.h"
35#include "list.h"
36#include "mytypes.h"
37#include "p_type.h"
38#include "parse.h"
39#include "stree.h"
40
41#include "p_expr.h"
42
43static stree_expr_t *parse_assign(parse_t *parse);
44static stree_expr_t *parse_comparative(parse_t *parse);
45static stree_expr_t *parse_additive(parse_t *parse);
46static stree_expr_t *parse_prefix(parse_t *parse);
47static stree_expr_t *parse_prefix_new(parse_t *parse);
48static stree_expr_t *parse_postfix(parse_t *parse);
49static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a);
50static stree_expr_t *parse_pf_call(parse_t *parse, stree_expr_t *a);
51static stree_expr_t *parse_pf_index(parse_t *parse, stree_expr_t *a);
52static stree_expr_t *parse_pf_as(parse_t *parse, stree_expr_t *a);
53static stree_expr_t *parse_primitive(parse_t *parse);
54static stree_expr_t *parse_nameref(parse_t *parse);
55static stree_expr_t *parse_lit_int(parse_t *parse);
56static stree_expr_t *parse_lit_ref(parse_t *parse);
57static stree_expr_t *parse_lit_string(parse_t *parse);
58static stree_expr_t *parse_self_ref(parse_t *parse);
59
60static stree_expr_t *parse_recovery_expr(parse_t *parse);
61
62/** Parse expression.
63 *
64 * Input is read from the input object associated with @a parse. If any
65 * error occurs, parse->error will @c b_true when this function
66 * returns. parse->error_bailout will be @c b_true if the error has not
67 * been recovered yet. Similar holds for other parsing functions in this
68 * module.
69 *
70 * @param parse Parser object.
71 */
72stree_expr_t *parse_expr(parse_t *parse)
73{
74#ifdef DEBUG_PARSE_TRACE
75 printf("Parse expression.\n");
76#endif
77 if (parse_is_error(parse))
78 return parse_recovery_expr(parse);
79
80 return parse_assign(parse);
81}
82
83/** Parse assignment expression.
84 *
85 * @param parse Parser object.
86 */
87static stree_expr_t *parse_assign(parse_t *parse)
88{
89 stree_expr_t *a, *b, *tmp;
90 stree_assign_t *assign;
91
92 a = parse_comparative(parse);
93
94 switch (lcur_lc(parse)) {
95 case lc_assign:
96 assign = stree_assign_new(ac_set);
97 break;
98 case lc_increase:
99 assign = stree_assign_new(ac_increase);
100 break;
101 default:
102 return a;
103 }
104
105 lskip(parse);
106 b = parse_comparative(parse);
107
108 assign->dest = a;
109 assign->src = b;
110
111 tmp = stree_expr_new(ec_assign);
112 tmp->u.assign = assign;
113 return tmp;
114}
115
116/** Parse comparative expression.
117 *
118 * @param parse Parser object.
119 */
120static stree_expr_t *parse_comparative(parse_t *parse)
121{
122 stree_expr_t *a, *b, *tmp;
123 stree_binop_t *binop;
124 binop_class_t bc;
125
126 a = parse_additive(parse);
127
128 while (lcur_lc(parse) == lc_equal || lcur_lc(parse) == lc_notequal ||
129 lcur_lc(parse) == lc_lt || lcur_lc(parse) == lc_gt ||
130 lcur_lc(parse) == lc_lt_equal || lcur_lc(parse) == lc_gt_equal) {
131
132 if (parse_is_error(parse))
133 break;
134
135 switch (lcur_lc(parse)) {
136 case lc_equal: bc = bo_equal; break;
137 case lc_notequal: bc = bo_notequal; break;
138 case lc_lt: bc = bo_lt; break;
139 case lc_gt: bc = bo_gt; break;
140 case lc_lt_equal: bc = bo_lt_equal; break;
141 case lc_gt_equal: bc = bo_gt_equal; break;
142 default: assert(b_false);
143 }
144
145 lskip(parse);
146 b = parse_additive(parse);
147
148 binop = stree_binop_new(bc);
149 binop->arg1 = a;
150 binop->arg2 = b;
151
152 tmp = stree_expr_new(ec_binop);
153 tmp->u.binop = binop;
154 a = tmp;
155 }
156
157 return a;
158}
159
160/** Parse additive expression.
161 *
162 * @param parse Parser object.
163 */
164static stree_expr_t *parse_additive(parse_t *parse)
165{
166 stree_expr_t *a, *b, *tmp;
167 stree_binop_t *binop;
168
169 a = parse_prefix(parse);
170 while (lcur_lc(parse) == lc_plus) {
171 if (parse_is_error(parse))
172 break;
173
174 lskip(parse);
175 b = parse_prefix(parse);
176
177 binop = stree_binop_new(bo_plus);
178 binop->arg1 = a;
179 binop->arg2 = b;
180
181 tmp = stree_expr_new(ec_binop);
182 tmp->u.binop = binop;
183 a = tmp;
184 }
185
186 return a;
187}
188
189/** Parse prefix expression.
190 *
191 * @param parse Parser object.
192 */
193static stree_expr_t *parse_prefix(parse_t *parse)
194{
195 stree_expr_t *a;
196
197 switch (lcur_lc(parse)) {
198 case lc_plus:
199 printf("Unimplemented: Unary plus.\n");
200 a = parse_recovery_expr(parse);
201 parse_note_error(parse);
202 break;
203 case lc_new:
204 a = parse_prefix_new(parse);
205 break;
206 default:
207 a = parse_postfix(parse);
208 break;
209 }
210
211 return a;
212}
213
214/** Parse @c new operator.
215 *
216 * @param parse Parser object.
217 */
218static stree_expr_t *parse_prefix_new(parse_t *parse)
219{
220 stree_texpr_t *texpr;
221 stree_new_t *new_op;
222 stree_expr_t *expr;
223
224 lmatch(parse, lc_new);
225 texpr = parse_texpr(parse);
226
227 /* Parenthesis should be present except for arrays. */
228 if (texpr->tc != tc_tindex) {
229 lmatch(parse, lc_lparen);
230 lmatch(parse, lc_rparen);
231 }
232
233 new_op = stree_new_new();
234 new_op->texpr = texpr;
235 expr = stree_expr_new(ec_new);
236 expr->u.new_op = new_op;
237
238 return expr;
239}
240
241/** Parse postfix expression.
242 *
243 * @param parse Parser object.
244 */
245static stree_expr_t *parse_postfix(parse_t *parse)
246{
247 stree_expr_t *a;
248 stree_expr_t *tmp;
249
250 a = parse_primitive(parse);
251
252 while (lcur_lc(parse) == lc_period || lcur_lc(parse) == lc_lparen ||
253 lcur_lc(parse) == lc_lsbr || lcur_lc(parse) == lc_as) {
254
255 if (parse_is_error(parse))
256 break;
257
258 switch (lcur_lc(parse)) {
259 case lc_period:
260 tmp = parse_pf_access(parse, a);
261 break;
262 case lc_lparen:
263 tmp = parse_pf_call(parse, a);
264 break;
265 case lc_lsbr:
266 tmp = parse_pf_index(parse, a);
267 break;
268 case lc_as:
269 tmp = parse_pf_as(parse, a);
270 break;
271 default:
272 assert(b_false);
273 }
274
275 a = tmp;
276 }
277
278 return a;
279}
280
281/** Parse member access expression
282 *
283 * @param parse Parser object.
284 */
285static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a)
286{
287 stree_ident_t *ident;
288 stree_expr_t *expr;
289 stree_access_t *access;
290
291 lmatch(parse, lc_period);
292 ident = parse_ident(parse);
293
294 access = stree_access_new();
295 access->arg = a;
296 access->member_name = ident;
297
298 expr = stree_expr_new(ec_access);
299 expr->u.access = access;
300
301 return expr;
302}
303
304/** Parse function call expression.
305 *
306 * @param parse Parser object.
307 */
308static stree_expr_t *parse_pf_call(parse_t *parse, stree_expr_t *a)
309{
310 stree_expr_t *expr;
311 stree_call_t *call;
312 stree_expr_t *arg;
313
314 lmatch(parse, lc_lparen);
315
316 call = stree_call_new();
317 call->fun = a;
318 list_init(&call->args);
319
320 /* Parse function arguments */
321
322 if (lcur_lc(parse) != lc_rparen) {
323 while (!parse_is_error(parse)) {
324 arg = parse_expr(parse);
325 list_append(&call->args, arg);
326
327 if (lcur_lc(parse) == lc_rparen)
328 break;
329 lmatch(parse, lc_comma);
330 }
331 }
332
333 lmatch(parse, lc_rparen);
334
335 expr = stree_expr_new(ec_call);
336 expr->u.call = call;
337
338 return expr;
339}
340
341/** Parse index expression.
342 *
343 * @param parse Parser object.
344 */
345static stree_expr_t *parse_pf_index(parse_t *parse, stree_expr_t *a)
346{
347 stree_expr_t *expr;
348 stree_index_t *index;
349 stree_expr_t *arg;
350
351 lmatch(parse, lc_lsbr);
352
353 index = stree_index_new();
354 index->base = a;
355 list_init(&index->args);
356
357 /* Parse indices */
358
359 if (lcur_lc(parse) != lc_rsbr) {
360 while (!parse_is_error(parse)) {
361 arg = parse_expr(parse);
362 list_append(&index->args, arg);
363
364 if (lcur_lc(parse) == lc_rsbr)
365 break;
366 lmatch(parse, lc_comma);
367 }
368 }
369
370 lmatch(parse, lc_rsbr);
371
372 expr = stree_expr_new(ec_index);
373 expr->u.index = index;
374
375 return expr;
376}
377
378/** Parse @c as operator.
379 *
380 * @param parse Parser object.
381 */
382static stree_expr_t *parse_pf_as(parse_t *parse, stree_expr_t *a)
383{
384 stree_expr_t *expr;
385 stree_texpr_t *texpr;
386 stree_as_t *as_op;
387
388 lmatch(parse, lc_as);
389 texpr = parse_texpr(parse);
390
391 as_op = stree_as_new();
392 as_op->arg = a;
393 as_op->dtype = texpr;
394 expr = stree_expr_new(ec_as);
395 expr->u.as_op = as_op;
396
397 return expr;
398}
399
400/** Parse primitive expression.
401 *
402 * @param parse Parser object.
403 */
404static stree_expr_t *parse_primitive(parse_t *parse)
405{
406 stree_expr_t *expr;
407
408 switch (lcur_lc(parse)) {
409 case lc_ident:
410 expr = parse_nameref(parse);
411 break;
412 case lc_lit_int:
413 expr = parse_lit_int(parse);
414 break;
415 case lc_nil:
416 expr = parse_lit_ref(parse);
417 break;
418 case lc_lit_string:
419 expr = parse_lit_string(parse);
420 break;
421 case lc_self:
422 expr = parse_self_ref(parse);
423 break;
424 default:
425 lunexpected_error(parse);
426 expr = parse_recovery_expr(parse);
427 }
428
429 return expr;
430}
431
432/** Parse name reference.
433 *
434 * @param parse Parser object.
435 */
436static stree_expr_t *parse_nameref(parse_t *parse)
437{
438 stree_nameref_t *nameref;
439 stree_expr_t *expr;
440
441 nameref = stree_nameref_new();
442 nameref->name = parse_ident(parse);
443 expr = stree_expr_new(ec_nameref);
444 expr->u.nameref = nameref;
445
446 return expr;
447}
448
449/** Parse integer literal.
450 *
451 * @param parse Parser object.
452 */
453static stree_expr_t *parse_lit_int(parse_t *parse)
454{
455 stree_literal_t *literal;
456 stree_expr_t *expr;
457
458 lcheck(parse, lc_lit_int);
459
460 literal = stree_literal_new(ltc_int);
461 literal->u.lit_int.value = lcur(parse)->u.lit_int.value;
462
463 lskip(parse);
464
465 expr = stree_expr_new(ec_literal);
466 expr->u.literal = literal;
467
468 return expr;
469}
470
471/** Parse reference literal (@c nil).
472 *
473 * @param parse Parser object.
474 */
475static stree_expr_t *parse_lit_ref(parse_t *parse)
476{
477 stree_literal_t *literal;
478 stree_expr_t *expr;
479
480 lmatch(parse, lc_nil);
481
482 literal = stree_literal_new(ltc_ref);
483
484 expr = stree_expr_new(ec_literal);
485 expr->u.literal = literal;
486
487 return expr;
488}
489
490/** Parse string literal.
491 *
492 * @param parse Parser object.
493 */
494static stree_expr_t *parse_lit_string(parse_t *parse)
495{
496 stree_literal_t *literal;
497 stree_expr_t *expr;
498
499 lcheck(parse, lc_lit_string);
500
501 literal = stree_literal_new(ltc_string);
502 literal->u.lit_string.value = lcur(parse)->u.lit_string.value;
503
504 lskip(parse);
505
506 expr = stree_expr_new(ec_literal);
507 expr->u.literal = literal;
508
509 return expr;
510}
511
512/** Parse @c self keyword.
513 *
514 * @param parse Parser object.
515 */
516static stree_expr_t *parse_self_ref(parse_t *parse)
517{
518 stree_self_ref_t *self_ref;
519 stree_expr_t *expr;
520
521 lmatch(parse, lc_self);
522
523 self_ref = stree_self_ref_new();
524
525 expr = stree_expr_new(ec_self_ref);
526 expr->u.self_ref = self_ref;
527
528 return expr;
529}
530
531/** Construct a special recovery expression.
532 *
533 * @param parse Parser object.
534 */
535static stree_expr_t *parse_recovery_expr(parse_t *parse)
536{
537 stree_literal_t *literal;
538 stree_expr_t *expr;
539
540 (void) parse;
541
542 literal = stree_literal_new(ltc_ref);
543
544 expr = stree_expr_new(ec_literal);
545 expr->u.literal = literal;
546
547 return expr;
548}
Note: See TracBrowser for help on using the repository browser.