Added package with the documentation and the examples
[lwc.git] / breakexpr.c
blob776bc47f298bd2d0cd56d604e05d3b824e5c6313
1 #include "global.h"
3 /******************************************************************************
5 Break an expression string by returning
6 pointer(s) to root operator of the expression tree
8 ******************************************************************************/
11 // optimized is-operator checks
14 #define E(x) ESCBASE + x
15 static bool esc_op;
17 static const signed char priorities [128] = {
18 ['*'] = 13, ['/'] = 13, ['%'] = 13,
19 ['+'] = 12, ['-'] = 12,
20 ['<'] = 10, ['>'] = 10,
21 ['&'] = 8, ['^'] = 7, ['|'] = 6
24 static int priority (Token op)
26 esc_op = false;
28 if (op < 128)
29 return priorities [op];
31 switch (op) {
32 case LSH:
33 case RSH: return 11;
34 case PERLOP:
35 case GEQCMP:
36 case LEQCMP: return 10;
37 case EQCMP:
38 case NEQCMP: return 9;
39 case ANDAND: return 5;
40 case OROR: return 4;
41 default: return 0;
45 static int priority_esc (Token op)
47 if (op < ESCBASE)
48 return priority (op);
49 if (op > ESCBASE) {
50 esc_op = true;
51 switch (op) {
52 case E('+'):
53 case E('-'): return 12;
54 case E(GEQCMP):
55 case E(LEQCMP):
56 case E('<'):
57 case E('>'): return 10;
58 case E(EQCMP):
59 case E(NEQCMP): return 9;
60 case E(ANDAND): return 5;
61 case E(OROR): return 4;
64 esc_op = false;
65 return 0;
68 static inline bool isassignment (Token t)
70 esc_op = false;
71 return t == '=' || ISASSIGNMENT (t);
74 static bool isassignment_esc (Token t)
76 if (t < ESCBASE)
77 return isassignment (t);
78 return esc_op = t > ESCBASE && (t == E('=') || t == E(ASSIGNA) || t == E(ASSIGNS));
81 static const signed char unaries [128] = {
82 ['-'] = 1, ['!'] = 1, ['+'] = 1, ['*'] = 1, ['&'] = 2, ['~'] = 1
85 static inline bool isunary (Token t)
87 esc_op = false;
88 if (t < 128) return unaries [t];
89 return t == PLUSPLUS || t == MINUSMINUS;
92 static inline bool isunary_esc (Token t)
94 if (t < ESCBASE)
95 return isunary (t);
96 if (t == RESERVED_delete || t == RESERVED_dereference) return 2;
97 return esc_op = isunary (t - ESCBASE) == 1;
101 // here begins the parser
104 static NormPtr expression (bexpr*, NormPtr);
105 static NormPtr unary_expression (bexpr*, NormPtr);
106 static NormPtr primary_expression (bexpr*, NormPtr);
107 static NormPtr postfix_expression (bexpr*, NormPtr);
108 static NormPtr argument_expression_list (bexpr*, NormPtr);
109 static NormPtr binary_expression (bexpr*, NormPtr, int);
110 static NormPtr logical_OR_expression (bexpr*, NormPtr);
111 static NormPtr conditional_expression (bexpr*, NormPtr);
112 static NormPtr assignment_expression (bexpr*, NormPtr);
114 static NormPtr unary_expression (bexpr *e, NormPtr p)
116 NormPtr ps = p, ps2;
118 if (e->expr [p] == -1)
119 return p;
121 if (isunary_esc (e->expr [p])) {
122 bool lesc_op = esc_op;
123 p = unary_expression (e, p + 1);
124 if (e->nop == 0)
125 parse_error_ll ("unary operator w/o operand");
126 e->nop = 1;
127 e->operators [0] = ps;
128 e->esc_op = lesc_op;
129 return p;
132 /* new operator */
133 if (e->expr [p] == RESERVED_new || e->expr [p] == RESERVED_localloc) {
134 e->nop = 2;
135 e->operators [0] = p++;
136 e->esc_op = false;
137 if (!ISSYMBOL (e->expr [p]))
138 parse_error_ll ("new/localloc may be followed by symbol only");
139 if (e->expr [++p] == '(')
140 p = skip_buffer_parenthesis (e->expr, p + 1);
141 else if (e->expr [p] == '[')
142 p = skip_buffer_brackets (e->expr, p + 1);
143 /* Feature: alt ctor */
144 else if (ISSYMBOL (e->expr [p]) && e->expr [p + 1] == '(')
145 p = skip_buffer_parenthesis (e->expr, p + 2);
146 if (e->expr [p] == POINTSAT)
147 return postfix_expression (e, p);
148 e->operators [1] = p;
149 return p;
152 /* __declexpr__ operator */
153 if (e->expr [p] == RESERVED___declexpr__) {
154 e->nop = 2;
155 e->operators [0] = p++;
156 e->esc_op = false;
157 if (e->expr [p] != '(')
158 parse_error_ll ("__declexpr__ '('");
159 return e->operators [1] = skip_buffer_parenthesis (e->expr, p + 1);
162 if (e->expr [p] == RESERVED_sizeof)
163 if (e->expr [p + 1] == '(' && is_dcl_start (e->expr [p + 2])) {
164 /* * Feature: classname.symbol is an expression * */
165 if (ISSYMBOL (e->expr [p + 2]) && e->expr [p + 3] == '.')
166 goto eelse;
167 /* * * * * * * * */
168 e->et = SIZEOF_TYPE;
169 e->nop = 1;
170 e->operators [0] = p;
171 e->esc_op = false;
172 p = skip_buffer_parenthesis (e->expr, p + 2);
173 return p;
174 } else eelse: {
175 e->et = SIZEOF_EXPRESSION;
176 p = unary_expression (e, p + 1);
177 e->nop = 1;
178 e->operators [0] = ps;
179 e->esc_op = false;
180 return p;
183 if (e->expr [p] == '(')
184 if (is_dcl_start (e->expr [p + 1])
185 && !(e->expr [p + 2] == '(' && e->expr [p + 3] != '*')
186 && !(ISSYMBOL (e->expr [p + 1]) && e->expr [p + 2] == '.')) {
187 ps = p;
188 p = skip_buffer_parenthesis (e->expr, p + 1);
189 ps2 = p - 1;
190 p = unary_expression (e, p);
191 e->et = PARENTH_CAST;
192 e->nop = 2;
193 e->operators [0] = ps;
194 e->operators [1] = ps2;
195 e->esc_op = false;
196 return p;
199 p = primary_expression (e, p);
200 return postfix_expression (e, p);
203 static NormPtr skip_statement_expression (bexpr *e, NormPtr p)
205 int bno = 1;
206 Token *code = e->expr;
208 while (code [p] != -1 && bno)
209 switch (code [p++]) {
210 case '{': bno++;
211 ncase '}': bno--;
214 if (code [p - 1] == -1) parse_error (0, "missing '}'");
216 return p - 1;
219 static NormPtr primary_expression (bexpr *e, NormPtr p)
221 if (e->expr [p] == '(') {
222 NormPtr ps = p++;
223 if (e->expr [p] == '{') {
224 e->operators [0] = p++;
225 p = e->operators [1] = skip_statement_expression (e, p);
226 e->nop = 2;
227 if (e->expr [++p] != ')')
228 parse_error (p, "({statement})");
229 return p + 1;
231 p = expression (e, p);
232 if (e->expr [p] != ')')
233 parse_error (p, "missing ')'");
234 e->et = PARENTH_SYNTAX;
235 e->nop = 2;
236 e->operators [0] = ps;
237 e->operators [1] = p;
238 e->esc_op = false;
239 return p + 1;
242 if (ISSYMBOL (e->expr [p]) || e->expr [p] == RESERVED_postfix
243 || ISVALUE (e->expr [p]) || e->expr [p] == RESERVED_this) {
244 e->nop = 1;
245 e->operators [0] = p;
246 return p + 1;
249 if (e->expr [p] == '{') {
250 /* "compound statement in expression" */
251 e->nop = 2;
252 e->operators [0] = p;
253 e->operators [1] = p = skip_statement_expression (e, p + 1);
254 return p + 1;
257 return p;
260 static NormPtr postfix_expression (bexpr *e, NormPtr p)
262 NormPtr ps;
263 bool esc_op = false;
265 switch (e->expr [p]) {
266 case ESCBASE + PLUSPLUS:
267 case ESCBASE + MINUSMINUS:
268 esc_op = true;
269 case PLUSPLUS:
270 case MINUSMINUS:
271 e->nop = 1;
272 e->operators [0] = p;
273 e->esc_op = esc_op;
274 return postfix_expression (e, p + 1);
275 case '[' + ESCBASE:
276 esc_op = true;
277 case '[':
278 ps = p;
279 p = expression (e, p + 1);
280 e->nop = 2;
281 e->operators [0] = ps;
282 e->operators [1] = p;
283 e->esc_op = esc_op;
284 return postfix_expression (e, p + 1);
285 case POINTSAT + ESCBASE:
286 esc_op = true;
287 case '.':
288 case POINTSAT:
289 e->nop = 1;
290 e->operators [0] = p++;
291 if (!ISSYMBOL (e->expr [p]))
292 parse_error (p, "member indentifier must follow . and ->");
293 e->esc_op = esc_op;
294 return postfix_expression (e, p + 1);
295 case '(':
296 ps = p;
297 p = argument_expression_list (e, p + 1);
298 if (e->expr [p] != ')')
299 parse_error (p, "missing ')' in function call");
300 e->et = PARENTH_FCALL;
301 e->operators [0] = ps;
302 e->operators [e->nop++] = p;
303 e->esc_op = false;
304 return postfix_expression (e, p + 1);
306 return p;
309 static NormPtr binary_expression (bexpr *e, NormPtr p, int pri)
311 static int xpri;
312 bool lesc_op = esc_op;
313 NormPtr ps = p;
315 e->nop = 0;
316 p = unary_expression (e, p + 1);
317 if (e->nop == 0)
318 parse_error (p, "two operands expected");
320 xpri = priority_esc (e->expr [p]);
321 while (xpri > pri)
322 p = binary_expression (e, p, xpri);
324 e->nop = 1;
325 e->operators [0] = ps;
326 e->esc_op = lesc_op;
328 return xpri < pri ? p : binary_expression (e, p, pri);
331 static NormPtr logical_OR_expression (bexpr *e, NormPtr p)
333 p = unary_expression (e, p);
335 if (e->nop == 0)
336 return p;
338 int pri;
339 while ((pri = priority_esc (e->expr [p])))
340 p = binary_expression (e, p, pri);
342 return p;
345 static NormPtr conditional_expression (bexpr *e, NormPtr p)
347 p = logical_OR_expression (e, p);
349 if (e->nop == 0 || e->expr [p] != '?')
350 return p;
352 NormPtr ps1 = p, ps2;
353 p = expression (e, p + 1);
354 if (e->expr [p] != ':')
355 parse_error (p, "missing ':'");
356 ps2 = p;
357 p = conditional_expression (e, p + 1);
358 e->nop = 2;
359 e->operators [0] = ps1;
360 e->operators [1] = ps2;
361 e->esc_op = false;
363 return p;
366 static NormPtr assignment_expression (bexpr *e, NormPtr p)
368 p = conditional_expression (e, p);
370 if (e->nop == 0 || !isassignment_esc (e->expr [p]))
371 return p;
373 bool lesc_op = esc_op;
374 NormPtr ps = p;
376 e->nop = 0;
377 p = assignment_expression (e, p + 1);
378 if (e->nop == 0)
379 parse_error (p, "missing right operand in assignment");
380 e->nop = 1;
381 e->operators [0] = ps;
382 e->esc_op = lesc_op;
384 return p;
387 static NormPtr argument_expression_list (bexpr *e, NormPtr p)
389 int commas [128];
390 int nc = 0, i;
392 p = assignment_expression (e, p);
393 if (e->nop == 0)
394 return p;
396 while (e->expr [p] == ',') {
397 commas [nc++] = p++;
398 e->nop = 0;
399 p = assignment_expression (e, p);
400 if (e->nop == 0)
401 parse_error_ll ("missing argument?");
404 for (i = 0; i < nc; i++)
405 e->operators [i + 1] = commas [i];
406 e->nop = i + 1;
407 e->esc_op = false;
409 return p;
412 static NormPtr expression (bexpr *e, NormPtr p)
414 p = assignment_expression (e, p);
415 if (e->nop == 0)
416 return p;
418 while (e->expr [p] == ',') {
419 NormPtr po = p;
420 e->nop = 0;
421 p = assignment_expression (e, p + 1);
422 if (e->nop == 0)
423 expr_error ("missing expression in ,,");
424 e->nop = 1;
425 e->operators [0] = po;
426 e->esc_op = false;
429 return p;
432 void break_expr (bexpr *e)
434 #ifdef DEBUG
435 if (debugflag.PEXPR_EXTREME)
436 INTPRINTF ("Request to break: ", e->expr);
437 #endif
439 esc_op = e->esc_op = false;
440 e->nop = 0;
441 e->et = NOAMBIG;
442 if (e->expr [expression (e, 0)] != -1)
443 expr_error ("Invalid expression");
445 if (e->esc_op)
446 e->expr [e->operators [0]] -= ESCBASE;
449 NormPtr skip_expression (Token *code, NormPtr p, int et)
451 bexpr E;
452 E.expr = code;
453 E.nop = 0;
454 return et == NORMAL_EXPR ? expression (&E, p) :
455 et == INIT_EXPR ? assignment_expression (&E, p) :
456 conditional_expression (&E, p);