From 405686f6ec20503f39438c43e7fd074988961e70 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 17 May 2026 15:29:59 +0100 Subject: [PATCH] parse: make multi-line structure parsing more robust --- bshell/parse/syntax/arith.c | 1 + bshell/parse/syntax/block.c | 31 ++++++++++++++++++++++++++----- bshell/parse/syntax/if-else.c | 23 +++++++++++++++++++---- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/bshell/parse/syntax/arith.c b/bshell/parse/syntax/arith.c index d17ff52..91510ee 100644 --- a/bshell/parse/syntax/arith.c +++ b/bshell/parse/syntax/arith.c @@ -848,6 +848,7 @@ bool parse_arith_expr( case SYM_DOLLAR_LEFT_PAREN: case SYM_AT_LEFT_PAREN: case SYM_AT_LEFT_BRACE: + case SYM_LEFT_BRACE: expr.expr_fail = !parse_operand(ctx, &expr); break; default: { diff --git a/bshell/parse/syntax/block.c b/bshell/parse/syntax/block.c index ca0d809..998aa0f 100644 --- a/bshell/parse/syntax/block.c +++ b/bshell/parse/syntax/block.c @@ -6,23 +6,44 @@ bool parse_block(struct parse_ctx *ctx, struct ast_node **out) return false; } + parse_linefeed(ctx); + struct block_ast_node *block = (struct block_ast_node *)ast_node_create(AST_BLOCK); + bool ok = true; while (1) { + if (parse_symbol(ctx, SYM_RIGHT_BRACE)) { + break; + } + 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)) { break; } - struct ast_node *stmt = NULL; - if (!parse_statement(ctx, &stmt)) { - ast_node_destroy((struct ast_node *)block); - return false; + if (!parse_linefeed(ctx) && !parse_symbol(ctx, SYM_SEMICOLON)) { + report_error( + ctx, + "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; diff --git a/bshell/parse/syntax/if-else.c b/bshell/parse/syntax/if-else.c index 5195173..dae787d 100644 --- a/bshell/parse/syntax/if-else.c +++ b/bshell/parse/syntax/if-else.c @@ -5,8 +5,8 @@ static bool add_branch( struct ast_node *cond, struct ast_node *body) { - struct if_branch_ast_node *branch - = (struct if_branch_ast_node *)ast_node_create(AST_IF_BRANCH); + struct if_branch_ast_node *branch = (struct if_branch_ast_node *) + ast_node_create(AST_IF_BRANCH); if (!branch) { return false; } @@ -47,8 +47,8 @@ bool parse_if(struct parse_ctx *ctx, struct ast_node **out) return false; } - struct if_ast_node *if_group - = (struct if_ast_node *)ast_node_create(AST_IF); + struct if_ast_node *if_group = (struct if_ast_node *)ast_node_create( + AST_IF); if (!if_group) { ctx->p_status = BSHELL_ERR_NO_MEMORY; 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)) { done = true; } 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)) { report_error( ctx, @@ -77,6 +84,14 @@ bool parse_if(struct parse_ctx *ctx, struct ast_node **out) ast_node_destroy((struct ast_node *)if_group); return false; } + + if (!parse_symbol(ctx, SYM_RIGHT_PAREN)) { + report_error( + ctx, + "expected `)` after elseif-condition"); + ast_node_destroy(if_cond); + return false; + } } else { done = true; break;