lang: replace stack-based parser with a recursive parser
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
#include "ctx.h"
|
||||
|
||||
#include <ivy/lang/ast.h>
|
||||
|
||||
bool parse_cascade(
|
||||
struct ivy_parser *parser, struct ivy_ast_node *first_msg,
|
||||
struct ivy_ast_node **out)
|
||||
{
|
||||
if (!peek_symbol(parser, IVY_SYM_SEMICOLON)) {
|
||||
parse_trace(parser, "expected `;`");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ivy_ast_msg_node *first = (struct ivy_ast_msg_node *)first_msg;
|
||||
if (first->n_base.n_type != IVY_AST_MSG) {
|
||||
parse_trace(parser, "cascade operand is not a message");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ivy_ast_cascade_node *cascade = create_node(IVY_AST_CASCADE);
|
||||
cascade->n_recipient = first->n_recipient;
|
||||
first->n_recipient = NULL;
|
||||
fx_queue_push_back(&cascade->n_msg, &first->n_base.n_entry);
|
||||
|
||||
bool ok = true;
|
||||
while (ok) {
|
||||
parse_linefeed(parser);
|
||||
|
||||
if (!parse_symbol(parser, IVY_SYM_SEMICOLON)) {
|
||||
break;
|
||||
}
|
||||
|
||||
parse_linefeed(parser);
|
||||
fx_queue_entry *entry = NULL;
|
||||
struct ivy_ast_msg_node *msg = NULL;
|
||||
struct ivy_token *tok = peek_token(parser);
|
||||
if (!tok) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (tok->t_type) {
|
||||
case IVY_TOK_LABEL:
|
||||
ok = parse_keyword_msg(
|
||||
parser, cascade->n_recipient,
|
||||
EXPR_PARSE_STOP_SEMICOLON,
|
||||
(struct ivy_ast_node **)&msg);
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case IVY_TOK_IDENT:
|
||||
ok = parse_unary_msg(
|
||||
parser, cascade->n_recipient,
|
||||
(struct ivy_ast_node **)&msg);
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (peek_symbol(parser, IVY_SYM_LEFT_PAREN)) {
|
||||
ok = parse_complex_msg(
|
||||
parser, generic_node(msg),
|
||||
(struct ivy_ast_node **)&msg);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
parse_trace(parser, "expected message after `;`");
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
msg->n_recipient = NULL;
|
||||
fx_queue_push_back(&cascade->n_msg, &msg->n_base.n_entry);
|
||||
}
|
||||
|
||||
*out = generic_node(cascade);
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user