parse: make multi-line structure parsing more robust
This commit is contained in:
@@ -848,6 +848,7 @@ bool parse_arith_expr(
|
|||||||
case SYM_DOLLAR_LEFT_PAREN:
|
case SYM_DOLLAR_LEFT_PAREN:
|
||||||
case SYM_AT_LEFT_PAREN:
|
case SYM_AT_LEFT_PAREN:
|
||||||
case SYM_AT_LEFT_BRACE:
|
case SYM_AT_LEFT_BRACE:
|
||||||
|
case SYM_LEFT_BRACE:
|
||||||
expr.expr_fail = !parse_operand(ctx, &expr);
|
expr.expr_fail = !parse_operand(ctx, &expr);
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
@@ -6,23 +6,44 @@ bool parse_block(struct parse_ctx *ctx, struct ast_node **out)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse_linefeed(ctx);
|
||||||
|
|
||||||
struct block_ast_node *block
|
struct block_ast_node *block
|
||||||
= (struct block_ast_node *)ast_node_create(AST_BLOCK);
|
= (struct block_ast_node *)ast_node_create(AST_BLOCK);
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
if (parse_symbol(ctx, SYM_RIGHT_BRACE)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
parse_linefeed(ctx);
|
parse_linefeed(ctx);
|
||||||
|
|
||||||
|
struct ast_node *stmt = NULL;
|
||||||
|
if (!parse_statement(ctx, &stmt)) {
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_queue_push_back(&block->n_statements, &stmt->n_entry);
|
||||||
|
|
||||||
if (parse_symbol(ctx, SYM_RIGHT_BRACE)) {
|
if (parse_symbol(ctx, SYM_RIGHT_BRACE)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ast_node *stmt = NULL;
|
if (!parse_linefeed(ctx) && !parse_symbol(ctx, SYM_SEMICOLON)) {
|
||||||
if (!parse_statement(ctx, &stmt)) {
|
report_error(
|
||||||
ast_node_destroy((struct ast_node *)block);
|
ctx,
|
||||||
return false;
|
"expected `;`, `}`, or linefeed after "
|
||||||
|
"statement");
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_queue_push_back(&block->n_statements, &stmt->n_entry);
|
if (!ok) {
|
||||||
|
ast_node_destroy((struct ast_node *)block);
|
||||||
|
block = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = (struct ast_node *)block;
|
*out = (struct ast_node *)block;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ static bool add_branch(
|
|||||||
struct ast_node *cond,
|
struct ast_node *cond,
|
||||||
struct ast_node *body)
|
struct ast_node *body)
|
||||||
{
|
{
|
||||||
struct if_branch_ast_node *branch
|
struct if_branch_ast_node *branch = (struct if_branch_ast_node *)
|
||||||
= (struct if_branch_ast_node *)ast_node_create(AST_IF_BRANCH);
|
ast_node_create(AST_IF_BRANCH);
|
||||||
if (!branch) {
|
if (!branch) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -47,8 +47,8 @@ bool parse_if(struct parse_ctx *ctx, struct ast_node **out)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct if_ast_node *if_group
|
struct if_ast_node *if_group = (struct if_ast_node *)ast_node_create(
|
||||||
= (struct if_ast_node *)ast_node_create(AST_IF);
|
AST_IF);
|
||||||
if (!if_group) {
|
if (!if_group) {
|
||||||
ctx->p_status = BSHELL_ERR_NO_MEMORY;
|
ctx->p_status = BSHELL_ERR_NO_MEMORY;
|
||||||
ast_node_destroy(if_cond);
|
ast_node_destroy(if_cond);
|
||||||
@@ -70,6 +70,13 @@ bool parse_if(struct parse_ctx *ctx, struct ast_node **out)
|
|||||||
if (parse_keyword(ctx, KW_ELSE)) {
|
if (parse_keyword(ctx, KW_ELSE)) {
|
||||||
done = true;
|
done = true;
|
||||||
} else if (parse_keyword(ctx, KW_ELSEIF)) {
|
} else if (parse_keyword(ctx, KW_ELSEIF)) {
|
||||||
|
if (!parse_symbol(ctx, SYM_LEFT_PAREN)) {
|
||||||
|
report_error(
|
||||||
|
ctx,
|
||||||
|
"expected `(` after `elseif`");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!parse_expr(ctx, &cond)) {
|
if (!parse_expr(ctx, &cond)) {
|
||||||
report_error(
|
report_error(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -77,6 +84,14 @@ bool parse_if(struct parse_ctx *ctx, struct ast_node **out)
|
|||||||
ast_node_destroy((struct ast_node *)if_group);
|
ast_node_destroy((struct ast_node *)if_group);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!parse_symbol(ctx, SYM_RIGHT_PAREN)) {
|
||||||
|
report_error(
|
||||||
|
ctx,
|
||||||
|
"expected `)` after elseif-condition");
|
||||||
|
ast_node_destroy(if_cond);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user