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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4204ad9 was 37f527b, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Update SBI to rev. 144.

  • Property mode set to 100644
File size: 9.7 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 "lex.h"
34#include "list.h"
35#include "mytypes.h"
36#include "p_type.h"
37#include "parse.h"
38#include "stree.h"
39
40#include "p_expr.h"
41
42static stree_expr_t *parse_assign(parse_t *parse);
43static stree_expr_t *parse_comparative(parse_t *parse);
44static stree_expr_t *parse_additive(parse_t *parse);
45static stree_expr_t *parse_prefix(parse_t *parse);
46static stree_expr_t *parse_prefix_new(parse_t *parse);
47static stree_expr_t *parse_postfix(parse_t *parse);
48static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a);
49static stree_expr_t *parse_pf_call(parse_t *parse, stree_expr_t *a);
50static stree_expr_t *parse_pf_index(parse_t *parse, stree_expr_t *a);
51static stree_expr_t *parse_pf_as(parse_t *parse, stree_expr_t *a);
52static stree_expr_t *parse_primitive(parse_t *parse);
53static stree_expr_t *parse_nameref(parse_t *parse);
54static stree_expr_t *parse_lit_int(parse_t *parse);
55static stree_expr_t *parse_lit_ref(parse_t *parse);
56static stree_expr_t *parse_lit_string(parse_t *parse);
57static stree_expr_t *parse_self_ref(parse_t *parse);
58
59/** Parse expression. */
60stree_expr_t *parse_expr(parse_t *parse)
61{
62 return parse_assign(parse);
63}
64
65/** Parse assignment expression. */
66static stree_expr_t *parse_assign(parse_t *parse)
67{
68 stree_expr_t *a, *b, *tmp;
69 stree_assign_t *assign;
70
71 a = parse_comparative(parse);
72
73 switch (lcur_lc(parse)) {
74 case lc_assign:
75 assign = stree_assign_new(ac_set);
76 break;
77 case lc_increase:
78 assign = stree_assign_new(ac_increase);
79 break;
80 default:
81 return a;
82 }
83
84 lskip(parse);
85 b = parse_comparative(parse);
86
87 assign->dest = a;
88 assign->src = b;
89
90 tmp = stree_expr_new(ec_assign);
91 tmp->u.assign = assign;
92 return tmp;
93}
94
95/** Parse comparative expression. */
96static stree_expr_t *parse_comparative(parse_t *parse)
97{
98 stree_expr_t *a, *b, *tmp;
99 stree_binop_t *binop;
100 binop_class_t bc;
101
102 a = parse_additive(parse);
103
104 while (lcur_lc(parse) == lc_equal || lcur_lc(parse) == lc_notequal ||
105 lcur_lc(parse) == lc_lt || lcur_lc(parse) == lc_gt ||
106 lcur_lc(parse) == lc_lt_equal || lcur_lc(parse) == lc_gt_equal) {
107
108 switch (lcur_lc(parse)) {
109 case lc_equal: bc = bo_equal; break;
110 case lc_notequal: bc = bo_notequal; break;
111 case lc_lt: bc = bo_lt; break;
112 case lc_gt: bc = bo_gt; break;
113 case lc_lt_equal: bc = bo_lt_equal; break;
114 case lc_gt_equal: bc = bo_gt_equal; break;
115 default: assert(b_false);
116 }
117
118 lskip(parse);
119 b = parse_additive(parse);
120
121 binop = stree_binop_new(bc);
122 binop->arg1 = a;
123 binop->arg2 = b;
124
125 tmp = stree_expr_new(ec_binop);
126 tmp->u.binop = binop;
127 a = tmp;
128 }
129
130 return a;
131}
132
133/** Parse additive expression. */
134static stree_expr_t *parse_additive(parse_t *parse)
135{
136 stree_expr_t *a, *b, *tmp;
137 stree_binop_t *binop;
138
139 a = parse_prefix(parse);
140 while (lcur_lc(parse) == lc_plus) {
141 lskip(parse);
142 b = parse_prefix(parse);
143
144 binop = stree_binop_new(bo_plus);
145 binop->arg1 = a;
146 binop->arg2 = b;
147
148 tmp = stree_expr_new(ec_binop);
149 tmp->u.binop = binop;
150 a = tmp;
151 }
152
153 return a;
154}
155
156/** Parse prefix expression. */
157static stree_expr_t *parse_prefix(parse_t *parse)
158{
159 stree_expr_t *a;
160
161 switch (lcur_lc(parse)) {
162 case lc_plus:
163 printf("Unimplemented: Unary plus.\n");
164 exit(1);
165 case lc_new:
166 a = parse_prefix_new(parse);
167 break;
168 default:
169 a = parse_postfix(parse);
170 break;
171 }
172
173 return a;
174}
175
176/** Parse @c new operator. */
177static stree_expr_t *parse_prefix_new(parse_t *parse)
178{
179 stree_texpr_t *texpr;
180 stree_new_t *new_op;
181 stree_expr_t *expr;
182
183 lmatch(parse, lc_new);
184 texpr = parse_texpr(parse);
185
186 /* Parenthesis should be present except for arrays. */
187 if (texpr->tc != tc_tindex) {
188 lmatch(parse, lc_lparen);
189 lmatch(parse, lc_rparen);
190 }
191
192 new_op = stree_new_new();
193 new_op->texpr = texpr;
194 expr = stree_expr_new(ec_new);
195 expr->u.new_op = new_op;
196
197 return expr;
198}
199
200/** Parse postfix expression. */
201static stree_expr_t *parse_postfix(parse_t *parse)
202{
203 stree_expr_t *a;
204 stree_expr_t *tmp;
205
206 a = parse_primitive(parse);
207
208 while (lcur_lc(parse) == lc_period || lcur_lc(parse) == lc_lparen ||
209 lcur_lc(parse) == lc_lsbr || lcur_lc(parse) == lc_as) {
210
211 switch (lcur_lc(parse)) {
212 case lc_period:
213 tmp = parse_pf_access(parse, a);
214 break;
215 case lc_lparen:
216 tmp = parse_pf_call(parse, a);
217 break;
218 case lc_lsbr:
219 tmp = parse_pf_index(parse, a);
220 break;
221 case lc_as:
222 tmp = parse_pf_as(parse, a);
223 break;
224 default:
225 assert(b_false);
226 }
227
228 a = tmp;
229 }
230
231 return a;
232}
233
234/** Parse member access expression */
235static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a)
236{
237 stree_ident_t *ident;
238 stree_expr_t *expr;
239 stree_access_t *access;
240
241 lmatch(parse, lc_period);
242 ident = parse_ident(parse);
243
244 access = stree_access_new();
245 access->arg = a;
246 access->member_name = ident;
247
248 expr = stree_expr_new(ec_access);
249 expr->u.access = access;
250
251 return expr;
252}
253
254/** Parse function call expression. */
255static stree_expr_t *parse_pf_call(parse_t *parse, stree_expr_t *a)
256{
257 stree_expr_t *expr;
258 stree_call_t *call;
259 stree_expr_t *arg;
260
261 lmatch(parse, lc_lparen);
262
263 call = stree_call_new();
264 call->fun = a;
265 list_init(&call->args);
266
267 /* Parse function arguments */
268
269 if (lcur_lc(parse) != lc_rparen) {
270 while (b_true) {
271 arg = parse_expr(parse);
272 list_append(&call->args, arg);
273
274 if (lcur_lc(parse) == lc_rparen)
275 break;
276 lmatch(parse, lc_comma);
277 }
278 }
279
280 lmatch(parse, lc_rparen);
281
282 expr = stree_expr_new(ec_call);
283 expr->u.call = call;
284
285 return expr;
286}
287
288/** Parse index expression. */
289static stree_expr_t *parse_pf_index(parse_t *parse, stree_expr_t *a)
290{
291 stree_expr_t *expr;
292 stree_index_t *index;
293 stree_expr_t *arg;
294
295 lmatch(parse, lc_lsbr);
296
297 index = stree_index_new();
298 index->base = a;
299 list_init(&index->args);
300
301 /* Parse indices */
302
303 if (lcur_lc(parse) != lc_rsbr) {
304 while (b_true) {
305 arg = parse_expr(parse);
306 list_append(&index->args, arg);
307
308 if (lcur_lc(parse) == lc_rsbr)
309 break;
310 lmatch(parse, lc_comma);
311 }
312 }
313
314 lmatch(parse, lc_rsbr);
315
316 expr = stree_expr_new(ec_index);
317 expr->u.index = index;
318
319 return expr;
320}
321
322/** Parse @c as operator. */
323static stree_expr_t *parse_pf_as(parse_t *parse, stree_expr_t *a)
324{
325 stree_expr_t *expr;
326 stree_texpr_t *texpr;
327 stree_as_t *as_op;
328
329 lmatch(parse, lc_as);
330 texpr = parse_texpr(parse);
331
332 as_op = stree_as_new();
333 as_op->arg = a;
334 as_op->dtype = texpr;
335 expr = stree_expr_new(ec_as);
336 expr->u.as_op = as_op;
337
338 return expr;
339}
340
341/** Parse primitive expression. */
342static stree_expr_t *parse_primitive(parse_t *parse)
343{
344 stree_expr_t *expr;
345
346 switch (lcur_lc(parse)) {
347 case lc_ident:
348 expr = parse_nameref(parse);
349 break;
350 case lc_lit_int:
351 expr = parse_lit_int(parse);
352 break;
353 case lc_nil:
354 expr = parse_lit_ref(parse);
355 break;
356 case lc_lit_string:
357 expr = parse_lit_string(parse);
358 break;
359 case lc_self:
360 expr = parse_self_ref(parse);
361 break;
362 default:
363 lunexpected_error(parse);
364 exit(1);
365 }
366
367 return expr;
368}
369
370/** Parse name reference. */
371static stree_expr_t *parse_nameref(parse_t *parse)
372{
373 stree_nameref_t *nameref;
374 stree_expr_t *expr;
375
376 nameref = stree_nameref_new();
377 nameref->name = parse_ident(parse);
378 expr = stree_expr_new(ec_nameref);
379 expr->u.nameref = nameref;
380
381 return expr;
382}
383
384/** Parse integer literal. */
385static stree_expr_t *parse_lit_int(parse_t *parse)
386{
387 stree_literal_t *literal;
388 stree_expr_t *expr;
389
390 lcheck(parse, lc_lit_int);
391
392 literal = stree_literal_new(ltc_int);
393 literal->u.lit_int.value = lcur(parse)->u.lit_int.value;
394
395 lskip(parse);
396
397 expr = stree_expr_new(ec_literal);
398 expr->u.literal = literal;
399
400 return expr;
401}
402
403/** Parse reference literal (@c nil). */
404static stree_expr_t *parse_lit_ref(parse_t *parse)
405{
406 stree_literal_t *literal;
407 stree_expr_t *expr;
408
409 lmatch(parse, lc_nil);
410
411 literal = stree_literal_new(ltc_ref);
412
413 expr = stree_expr_new(ec_literal);
414 expr->u.literal = literal;
415
416 return expr;
417}
418
419/** Parse string literal. */
420static stree_expr_t *parse_lit_string(parse_t *parse)
421{
422 stree_literal_t *literal;
423 stree_expr_t *expr;
424
425 lcheck(parse, lc_lit_string);
426
427 literal = stree_literal_new(ltc_string);
428 literal->u.lit_string.value = lcur(parse)->u.lit_string.value;
429
430 lskip(parse);
431
432 expr = stree_expr_new(ec_literal);
433 expr->u.literal = literal;
434
435 return expr;
436}
437
438/** Parse @c self keyword. */
439static stree_expr_t *parse_self_ref(parse_t *parse)
440{
441 stree_self_ref_t *self_ref;
442 stree_expr_t *expr;
443
444 lmatch(parse, lc_self);
445
446 self_ref = stree_self_ref_new();
447
448 expr = stree_expr_new(ec_self_ref);
449 expr->u.self_ref = self_ref;
450
451 return expr;
452}
Note: See TracBrowser for help on using the repository browser.