lang: replace stack-based parser with a recursive parser
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
#include "ctx.h"
|
||||
|
||||
#include <ivy/lang/ast.h>
|
||||
|
||||
bool parse_unary_msg(
|
||||
struct ivy_parser *parser, struct ivy_ast_node *recipient,
|
||||
struct ivy_ast_node **out)
|
||||
{
|
||||
struct ivy_token *selector_tok = NULL;
|
||||
if (!parse_word(parser, &selector_tok)) {
|
||||
parse_trace(parser, "expected unary message selector");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ivy_ast_selector_node *sel = create_node(IVY_AST_SELECTOR);
|
||||
sel->n_msg_name = selector_tok;
|
||||
|
||||
struct ivy_ast_msg_node *msg = create_node(IVY_AST_MSG);
|
||||
msg->n_sel = sel;
|
||||
msg->n_recipient = recipient;
|
||||
|
||||
*out = generic_node(msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_keyword_msg(
|
||||
struct ivy_parser *parser, struct ivy_ast_node *recipient,
|
||||
enum expr_parse_flags flags, struct ivy_ast_node **out)
|
||||
{
|
||||
#if 0
|
||||
if (!recipient) {
|
||||
recipient = pop_operand(expr, IVY_PRECEDENCE_KEYWORD_MSG);
|
||||
}
|
||||
|
||||
if (!recipient) {
|
||||
parse_trace(parser, "no valid recipient for keyword msg");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct ivy_ast_selector_node *sel = create_node(IVY_AST_SELECTOR);
|
||||
struct ivy_ast_msg_node *msg = create_node(IVY_AST_MSG);
|
||||
msg->n_recipient = recipient;
|
||||
msg->n_sel = sel;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
while (1) {
|
||||
struct ivy_token *label = NULL;
|
||||
if (!parse_label(parser, &label)) {
|
||||
break;
|
||||
}
|
||||
|
||||
struct ivy_ast_node *value = NULL;
|
||||
flags |= EXPR_PARSE_STOP_LABEL;
|
||||
flags |= EXPR_PARSE_STOP_SEMICOLON;
|
||||
flags |= EXPR_PARSE_STOP_KW_CONTROL;
|
||||
flags &= ~EXPR_PARSE_CONSUME_TERMINATOR;
|
||||
|
||||
if (!parse_expr(parser, flags, &value)) {
|
||||
parse_trace(parser, "invalid keyword msg arg value");
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
fx_queue_push_back(&sel->n_arg_labels, &label->t_entry);
|
||||
fx_queue_push_back(&msg->n_arg, &value->n_entry);
|
||||
}
|
||||
|
||||
*out = generic_node(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_complex_msg(
|
||||
struct ivy_parser *parser, struct ivy_ast_node *msg_node,
|
||||
struct ivy_ast_node **out)
|
||||
{
|
||||
if (!parse_symbol(parser, IVY_SYM_LEFT_PAREN)) {
|
||||
parse_trace(parser, "expected `(` before complex msg arg list");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!msg) {
|
||||
fx_queue_entry *entry = fx_queue_pop_back(&expr->expr_out_queue);
|
||||
if (!entry) {
|
||||
parse_trace(
|
||||
parser, "no valid recipient for complex msg");
|
||||
return false;
|
||||
}
|
||||
|
||||
msg = fx_unbox(struct ivy_ast_msg_node, entry, n_base.n_entry);
|
||||
if (msg->n_base.n_type != IVY_AST_MSG) {
|
||||
parse_trace(
|
||||
parser,
|
||||
"previous expression is not a unary message");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct ivy_ast_msg_node *msg = (struct ivy_ast_msg_node *)msg_node;
|
||||
struct ivy_ast_selector_node *sel = msg->n_sel;
|
||||
msg->n_sel = sel;
|
||||
|
||||
bool ok = true;
|
||||
|
||||
while (1) {
|
||||
struct ivy_token *label = NULL;
|
||||
if (parse_symbol(parser, IVY_SYM_RIGHT_PAREN)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fx_queue_empty(&msg->n_arg)
|
||||
&& !parse_symbol(parser, IVY_SYM_COMMA)) {
|
||||
parse_trace(
|
||||
parser, "expected `,` after complex msg arg");
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (parse_label(parser, &label)) {
|
||||
fx_queue_push_back(&sel->n_arg_labels, &label->t_entry);
|
||||
} else {
|
||||
label = ivy_token_create_discard();
|
||||
fx_queue_push_back(&sel->n_arg_labels, &label->t_entry);
|
||||
}
|
||||
|
||||
struct ivy_ast_node *value = NULL;
|
||||
if (!parse_expr(parser, EXPR_PARSE_STOP_COMMA, &value)) {
|
||||
parse_trace(parser, "invalid complex msg arg value");
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
fx_queue_push_back(&msg->n_arg, &value->n_entry);
|
||||
}
|
||||
|
||||
*out = generic_node(msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user