80 lines
1.7 KiB
C
80 lines
1.7 KiB
C
|
|
#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;
|
||
|
|
}
|