parse: implement parsing of semicolon-delimited statement lists
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user