lang: replace stack-based parser with a recursive parser
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
#include "ctx.h"
|
||||
|
||||
#include <ivy/lang/ast.h>
|
||||
|
||||
static bool parse_dynamic_package(
|
||||
struct ivy_parser *parser, struct ivy_ast_node *expr,
|
||||
struct ivy_ast_node **out)
|
||||
{
|
||||
if (!parse_keyword(parser, IVY_KW_FOR)) {
|
||||
parse_trace(
|
||||
parser,
|
||||
"expected `for` after package comprehension "
|
||||
"expression");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ivy_ast_pkg_dynamic_node *pkg = create_node(IVY_AST_PKG_DYNAMIC);
|
||||
pkg->n_transform = expr;
|
||||
|
||||
if (!parse_expr(parser, EXPR_PARSE_STOP_KW_IN, &pkg->n_item)) {
|
||||
parse_trace(parser, "invalid package comprehension item");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parse_keyword(parser, IVY_KW_IN)) {
|
||||
parse_trace(
|
||||
parser,
|
||||
"expected `in` after package comprehension item");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parse_expr(parser, EXPR_PARSE_NORMAL, &pkg->n_item)) {
|
||||
parse_trace(parser, "invalid package comprehension container");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!parse_symbol(parser, IVY_SYM_RIGHT_BRACE)) {
|
||||
parse_trace(
|
||||
parser,
|
||||
"expected `}` after package comprehension container");
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = generic_node(pkg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_package(struct ivy_parser *parser, struct ivy_ast_node **out)
|
||||
{
|
||||
if (!parse_symbol(parser, IVY_SYM_LEFT_BRACE)) {
|
||||
parse_trace(parser, "expected `{`");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ivy_ast_node *item = NULL;
|
||||
if (!parse_expr(
|
||||
parser, EXPR_PARSE_STOP_COMMA | EXPR_PARSE_STOP_KW_CONTROL,
|
||||
&item)) {
|
||||
parse_trace(parser, "invalid package item");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (peek_keyword(parser, IVY_KW_FOR)) {
|
||||
return parse_dynamic_package(parser, item, out);
|
||||
}
|
||||
|
||||
struct ivy_ast_pkg_static_node *pkg = create_node(IVY_AST_PKG_STATIC);
|
||||
if (item) {
|
||||
fx_queue_push_back(&pkg->n_items, &item->n_entry);
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
while (ok) {
|
||||
parse_linefeed(parser);
|
||||
|
||||
if (parse_symbol(parser, IVY_SYM_RIGHT_BRACE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parse_symbol(parser, IVY_SYM_COMMA)) {
|
||||
parse_trace(
|
||||
parser,
|
||||
"expected `,` or `}` after package item");
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parse_expr(
|
||||
parser,
|
||||
EXPR_PARSE_STOP_COMMA | EXPR_PARSE_STOP_KW_CONTROL,
|
||||
&item)) {
|
||||
parse_trace(parser, "invalid package item");
|
||||
return false;
|
||||
}
|
||||
|
||||
fx_queue_push_back(&pkg->n_items, &item->n_entry);
|
||||
}
|
||||
|
||||
*out = generic_node(pkg);
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user