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