From 440561cb390881fe9496c42f280169591c1f5b29 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 12 May 2026 22:52:48 +0100 Subject: [PATCH] parse: implement parsing of semicolon-delimited statement lists --- bshell/parse/syntax/statement.c | 88 ++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/bshell/parse/syntax/statement.c b/bshell/parse/syntax/statement.c index c28ef8c..aa064ea 100644 --- a/bshell/parse/syntax/statement.c +++ b/bshell/parse/syntax/statement.c @@ -1,15 +1,99 @@ #include "../syntax.h" +bool peek_statement(struct parse_ctx *ctx) +{ + if (peek_keyword_expr(ctx)) { + return true; + } + + if (peek_arith_expr(ctx)) { + return true; + } + + if (peek_command(ctx)) { + return true; + } + + return false; +} + bool parse_statement(struct parse_ctx *ctx, struct ast_node **out) { + if (!peek_token(ctx)) { + /* error, or EOF */ + return false; + } + + bool unknown = true; bool ok = false; - if (peek_arith_expr(ctx)) { - ok = parse_arith_expr(ctx, out); + if (peek_keyword_expr(ctx)) { + unknown = false; + ok = parse_keyword_expr(ctx, out); + } + + if (!ok && peek_arith_expr(ctx)) { + unknown = false; + ok = parse_arith_expr(ctx, PRECEDENCE_MINIMUM, out); } if (!ok && peek_command(ctx)) { + unknown = false; ok = parse_command(ctx, out); } + if (!ok && unknown) { + report_error( + ctx, + "encountered unknown token while parsing statement"); + return false; + } + return ok; } + +static struct ast_node *convert_single_statement( + struct stmt_list_ast_node *list) +{ + fx_queue_entry *first_entry = fx_queue_first(&list->n_statements); + if (!first_entry || fx_queue_next(first_entry)) { + return (struct ast_node *)list; + } + + fx_queue_delete(&list->n_statements, first_entry); + struct ast_node *first + = fx_unbox(struct ast_node, first_entry, n_entry); + ast_node_destroy((struct ast_node *)list); + + return first; +} + +bool parse_statement_list(struct parse_ctx *ctx, struct ast_node **out) +{ + struct stmt_list_ast_node *stmt_list + = (struct stmt_list_ast_node *)ast_node_create(AST_STMT_LIST); + + bool ok = true; + while (ok) { + parse_linefeed(ctx); + + struct ast_node *stmt = NULL; + if (!parse_statement(ctx, &stmt)) { + ok = false; + break; + } + + fx_queue_push_back(&stmt_list->n_statements, &stmt->n_entry); + + if (!parse_symbol(ctx, SYM_SEMICOLON)) { + break; + } + } + + if (!ok) { + ast_node_destroy((struct ast_node *)stmt_list); + return false; + } + + *out = convert_single_statement(stmt_list); + return true; +}