parse: make multi-line structure parsing more robust

This commit is contained in:
2026-05-17 15:29:59 +01:00
parent d78f80a121
commit 405686f6ec
3 changed files with 46 additions and 9 deletions
+1
View File
@@ -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: {
+26 -5
View File
@@ -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;
+19 -4
View File
@@ -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;