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
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
)
29 return priorities
[op
];
36 case LEQCMP
: return 10;
38 case NEQCMP
: return 9;
39 case ANDAND
: return 5;
45 static int priority_esc (Token op
)
53 case E('-'): return 12;
57 case E('>'): return 10;
59 case E(NEQCMP
): return 9;
60 case E(ANDAND
): return 5;
61 case E(OROR
): return 4;
68 static inline bool isassignment (Token t
)
71 return t
== '=' || ISASSIGNMENT (t
);
74 static bool isassignment_esc (Token t
)
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
)
88 if (t
< 128) return unaries
[t
];
89 return t
== PLUSPLUS
|| t
== MINUSMINUS
;
92 static inline bool isunary_esc (Token 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
)
118 if (e
->expr
[p
] == -1)
121 if (isunary_esc (e
->expr
[p
])) {
122 bool lesc_op
= esc_op
;
123 p
= unary_expression (e
, p
+ 1);
125 parse_error_ll ("unary operator w/o operand");
127 e
->operators
[0] = ps
;
133 if (e
->expr
[p
] == RESERVED_new
|| e
->expr
[p
] == RESERVED_localloc
) {
135 e
->operators
[0] = p
++;
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
;
152 /* __declexpr__ operator */
153 if (e
->expr
[p
] == RESERVED___declexpr__
) {
155 e
->operators
[0] = p
++;
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] == '.')
170 e
->operators
[0] = p
;
172 p
= skip_buffer_parenthesis (e
->expr
, p
+ 2);
175 e
->et
= SIZEOF_EXPRESSION
;
176 p
= unary_expression (e
, p
+ 1);
178 e
->operators
[0] = ps
;
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] == '.')) {
188 p
= skip_buffer_parenthesis (e
->expr
, p
+ 1);
190 p
= unary_expression (e
, p
);
191 e
->et
= PARENTH_CAST
;
193 e
->operators
[0] = ps
;
194 e
->operators
[1] = ps2
;
199 p
= primary_expression (e
, p
);
200 return postfix_expression (e
, p
);
203 static NormPtr
skip_statement_expression (bexpr
*e
, NormPtr p
)
206 Token
*code
= e
->expr
;
208 while (code
[p
] != -1 && bno
)
209 switch (code
[p
++]) {
214 if (code
[p
- 1] == -1) parse_error (0, "missing '}'");
219 static NormPtr
primary_expression (bexpr
*e
, NormPtr p
)
221 if (e
->expr
[p
] == '(') {
223 if (e
->expr
[p
] == '{') {
224 e
->operators
[0] = p
++;
225 p
= e
->operators
[1] = skip_statement_expression (e
, p
);
227 if (e
->expr
[++p
] != ')')
228 parse_error (p
, "({statement})");
231 p
= expression (e
, p
);
232 if (e
->expr
[p
] != ')')
233 parse_error (p
, "missing ')'");
234 e
->et
= PARENTH_SYNTAX
;
236 e
->operators
[0] = ps
;
237 e
->operators
[1] = p
;
242 if (ISSYMBOL (e
->expr
[p
]) || e
->expr
[p
] == RESERVED_postfix
243 || ISVALUE (e
->expr
[p
]) || e
->expr
[p
] == RESERVED_this
) {
245 e
->operators
[0] = p
;
249 if (e
->expr
[p
] == '{') {
250 /* "compound statement in expression" */
252 e
->operators
[0] = p
;
253 e
->operators
[1] = p
= skip_statement_expression (e
, p
+ 1);
260 static NormPtr
postfix_expression (bexpr
*e
, NormPtr p
)
265 switch (e
->expr
[p
]) {
266 case ESCBASE
+ PLUSPLUS
:
267 case ESCBASE
+ MINUSMINUS
:
272 e
->operators
[0] = p
;
274 return postfix_expression (e
, p
+ 1);
279 p
= expression (e
, p
+ 1);
281 e
->operators
[0] = ps
;
282 e
->operators
[1] = p
;
284 return postfix_expression (e
, p
+ 1);
285 case POINTSAT
+ ESCBASE
:
290 e
->operators
[0] = p
++;
291 if (!ISSYMBOL (e
->expr
[p
]))
292 parse_error (p
, "member indentifier must follow . and ->");
294 return postfix_expression (e
, p
+ 1);
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
;
304 return postfix_expression (e
, p
+ 1);
309 static NormPtr
binary_expression (bexpr
*e
, NormPtr p
, int pri
)
312 bool lesc_op
= esc_op
;
316 p
= unary_expression (e
, p
+ 1);
318 parse_error (p
, "two operands expected");
320 xpri
= priority_esc (e
->expr
[p
]);
322 p
= binary_expression (e
, p
, xpri
);
325 e
->operators
[0] = ps
;
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
);
339 while ((pri
= priority_esc (e
->expr
[p
])))
340 p
= binary_expression (e
, p
, pri
);
345 static NormPtr
conditional_expression (bexpr
*e
, NormPtr p
)
347 p
= logical_OR_expression (e
, p
);
349 if (e
->nop
== 0 || e
->expr
[p
] != '?')
352 NormPtr ps1
= p
, ps2
;
353 p
= expression (e
, p
+ 1);
354 if (e
->expr
[p
] != ':')
355 parse_error (p
, "missing ':'");
357 p
= conditional_expression (e
, p
+ 1);
359 e
->operators
[0] = ps1
;
360 e
->operators
[1] = ps2
;
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
]))
373 bool lesc_op
= esc_op
;
377 p
= assignment_expression (e
, p
+ 1);
379 parse_error (p
, "missing right operand in assignment");
381 e
->operators
[0] = ps
;
387 static NormPtr
argument_expression_list (bexpr
*e
, NormPtr p
)
392 p
= assignment_expression (e
, p
);
396 while (e
->expr
[p
] == ',') {
399 p
= assignment_expression (e
, p
);
401 parse_error_ll ("missing argument?");
404 for (i
= 0; i
< nc
; i
++)
405 e
->operators
[i
+ 1] = commas
[i
];
412 static NormPtr
expression (bexpr
*e
, NormPtr p
)
414 p
= assignment_expression (e
, p
);
418 while (e
->expr
[p
] == ',') {
421 p
= assignment_expression (e
, p
+ 1);
423 expr_error ("missing expression in ,,");
425 e
->operators
[0] = po
;
432 void break_expr (bexpr
*e
)
435 if (debugflag
.PEXPR_EXTREME
)
436 INTPRINTF ("Request to break: ", e
->expr
);
439 esc_op
= e
->esc_op
= false;
442 if (e
->expr
[expression (e
, 0)] != -1)
443 expr_error ("Invalid expression");
446 e
->expr
[e
->operators
[0]] -= ESCBASE
;
449 NormPtr
skip_expression (Token
*code
, NormPtr p
, int et
)
454 return et
== NORMAL_EXPR
? expression (&E
, p
) :
455 et
== INIT_EXPR
? assignment_expression (&E
, p
) :
456 conditional_expression (&E
, p
);