Build for loop decl inits correctly

The multiple expressions are chained together and evaluate in left to
right order.
This commit is contained in:
Bill Currie 2019-06-09 13:54:03 +09:00
parent d29ea55826
commit ec89149b29
3 changed files with 39 additions and 1 deletions

View file

@ -314,6 +314,17 @@ expr_t *new_bool_expr (ex_list_t *true_list, ex_list_t *false_list, expr_t *e);
*/
expr_t *new_block_expr (void);
/** Create a new statement block expression node from an expression list
The returned block holds the expression list in reverse order. This makes
it easy to build the list in a parser.
\param expr_list The expression list to convert to an expression block.
Note that the evaluation order will be reversed.
\return The new block expression (::ex_block_t) node.
*/
expr_t *build_block_expr (expr_t *expr_list);
/** Create a new binary expression node node.
If either \a e1 or \a e2 are error expressions, then that expression will

View file

@ -539,6 +539,20 @@ new_binary_expr (int op, expr_t *e1, expr_t *e2)
return e;
}
expr_t *
build_block_expr (expr_t *expr_list)
{
expr_t *b = new_block_expr ();
while (expr_list) {
expr_t *e = expr_list;
expr_list = e->next;
e->next = 0;
append_expr (b, e);
}
return b;
}
expr_t *
new_unary_expr (int op, expr_t *e1)
{

View file

@ -1153,6 +1153,9 @@ statement
| FOR push_scope break_label continue_label
'(' opt_init ';' opt_expr ';' opt_expr ')' statement pop_scope
{
if ($6) {
$6 = build_block_expr ($6);
}
$$ = build_for_statement ($6, $8, $10, $12,
break_label, continue_label);
break_label = $3;
@ -1234,12 +1237,22 @@ opt_init
init_var_decl_list
: init_var_decl
| init_var_decl_list ',' init_var_decl
{
printf ("a\n");
$$ = $1;
}
| init_var_decl_list ',' { $<spec>$ = $<spec>0; } init_var_decl
{
printf ("b\n");
$4->next = $1;
$$ = $4;
}
;
init_var_decl
: var_decl opt_initializer
{
printf ("c\n");
specifier_t spec = $<spec>0;
$1->type = append_type ($1->type, spec.type);
$1->type = find_type ($1->type);