parse: implement parsing of semicolon-delimited statement lists

This commit is contained in:
2026-05-12 22:52:48 +01:00
parent cc450da31e
commit 440561cb39
+86 -2
View File
@@ -1,15 +1,99 @@
#include "../syntax.h" #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) 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; bool ok = false;
if (peek_arith_expr(ctx)) { if (peek_keyword_expr(ctx)) {
ok = parse_arith_expr(ctx, out); 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)) { if (!ok && peek_command(ctx)) {
unknown = false;
ok = parse_command(ctx, out); ok = parse_command(ctx, out);
} }
if (!ok && unknown) {
report_error(
ctx,
"encountered unknown token while parsing statement");
return false;
}
return ok; 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;
}