lang: replace stack-based parser with a recursive parser
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
#include "ctx.h"
|
||||
|
||||
#include <ivy/lang/ast.h>
|
||||
|
||||
bool is_tuple_terminator(struct ivy_token *tok)
|
||||
{
|
||||
const struct ivy_operator *op = get_operator_from_token(tok);
|
||||
switch (tok->t_type) {
|
||||
case IVY_TOK_SYMBOL:
|
||||
switch (tok->t_symbol) {
|
||||
case IVY_SYM_DOT:
|
||||
case IVY_SYM_RIGHT_PAREN:
|
||||
case IVY_SYM_RIGHT_BRACE:
|
||||
case IVY_SYM_RIGHT_BRACKET:
|
||||
return true;
|
||||
default:
|
||||
op = get_operator_from_token(tok);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (op && op->op_precedence < IVY_PRECEDENCE_KEYWORD_MSG) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool parse_tuple(
|
||||
struct ivy_parser *parser, struct ivy_ast_node *first_item,
|
||||
struct ivy_ast_node **out)
|
||||
{
|
||||
struct ivy_ast_tuple_node *tuple = create_node(IVY_AST_TUPLE);
|
||||
fx_queue_push_back(&tuple->n_members, &first_item->n_entry);
|
||||
|
||||
bool ok = true;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
struct ivy_token *tok = peek_token(parser);
|
||||
if (!tok) {
|
||||
parse_trace(
|
||||
parser, "unexpected EOF while parsing tuple");
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_tuple_terminator(tok)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parse_symbol(parser, IVY_SYM_COMMA)) {
|
||||
parse_trace(parser, "expected `,` after tuple item");
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
struct ivy_ast_node *value = NULL;
|
||||
if (!parse_expr(
|
||||
parser,
|
||||
EXPR_PARSE_STOP_COMMA | EXPR_PARSE_STOP_TUPLE_TERMINATOR,
|
||||
&value)) {
|
||||
parse_trace(parser, "invalid tuple item");
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
fx_queue_push_back(&tuple->n_members, &value->n_entry);
|
||||
}
|
||||
|
||||
*out = generic_node(tuple);
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user