691 lines
17 KiB
C
691 lines
17 KiB
C
#include "ctx.h"
|
|
#include "node.h"
|
|
|
|
#include <blue/object/string.h>
|
|
#include <ivy/lang/lex.h>
|
|
#include <ivy/lang/operator.h>
|
|
#include <stdio.h>
|
|
|
|
enum expr_end {
|
|
EXPR_END_NONE = 0,
|
|
/* arithmetic expressions, terminated with a dot (.) */
|
|
EXPR_END_DOT,
|
|
/* keyword expressions (if-else, while/for loops, match, etc), terminated with the end keyword. */
|
|
EXPR_END_KEYWORD,
|
|
};
|
|
|
|
enum expr_part {
|
|
EXPR_NONE = 0,
|
|
EXPR_OPERATOR,
|
|
EXPR_OPERAND,
|
|
};
|
|
|
|
struct expr_parser_state {
|
|
struct parser_state s_base;
|
|
enum expr_end s_end;
|
|
|
|
/* for a keyword-based expression (loops, conditionals, etc) this is the id of the keyword that started the expression.
|
|
if this is a return expression (i.e. prefixed with a caret), this will be IVY_SYM_CARET. */
|
|
unsigned int s_type;
|
|
unsigned int s_prev_tok;
|
|
enum expr_part s_prev_part;
|
|
b_queue s_output_queue;
|
|
b_queue s_operator_stack;
|
|
};
|
|
|
|
static enum ivy_status add_child(
|
|
struct ivy_ast_node *parent, struct ivy_ast_node *child)
|
|
{
|
|
struct ivy_ast_expr_node *expr = (struct ivy_ast_expr_node *)parent;
|
|
|
|
if (!expr->n_child) {
|
|
expr->n_child = child;
|
|
return IVY_OK;
|
|
}
|
|
|
|
return IVY_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
static void set_previous(struct expr_parser_state *state, struct ivy_token *tok)
|
|
{
|
|
switch (tok->t_type) {
|
|
case IVY_TOK_SYMBOL:
|
|
state->s_prev_tok = tok->t_symbol;
|
|
break;
|
|
case IVY_TOK_KEYWORD:
|
|
state->s_prev_tok = tok->t_keyword;
|
|
break;
|
|
default:
|
|
state->s_prev_tok = tok->t_type;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void print_operand(struct ivy_ast_node *node)
|
|
{
|
|
switch (node->n_type) {
|
|
case IVY_AST_IDENT: {
|
|
struct ivy_ast_ident_node *ident = (struct ivy_ast_ident_node *)node;
|
|
printf("%s", ident->n_content->t_str);
|
|
break;
|
|
}
|
|
case IVY_AST_INT: {
|
|
struct ivy_ast_int_node *v = (struct ivy_ast_int_node *)node;
|
|
printf("%llu", v->n_value->t_int);
|
|
break;
|
|
}
|
|
case IVY_AST_DOUBLE: {
|
|
struct ivy_ast_double_node *v = (struct ivy_ast_double_node *)node;
|
|
printf("%.2lf", v->n_value->t_double);
|
|
break;
|
|
}
|
|
case IVY_AST_OP: {
|
|
struct ivy_ast_op_node *v = (struct ivy_ast_op_node *)node;
|
|
printf("%s", ivy_operator_id_to_string(v->n_op->op_id));
|
|
break;
|
|
}
|
|
case IVY_AST_MSG: {
|
|
struct ivy_ast_msg_node *v = (struct ivy_ast_msg_node *)node;
|
|
printf("%s()", v->n_sel->n_msg_name->t_str);
|
|
break;
|
|
}
|
|
case IVY_AST_STRING: {
|
|
struct ivy_ast_string_node *v = (struct ivy_ast_string_node *)node;
|
|
printf("\"%s\"", v->n_value->t_str);
|
|
break;
|
|
}
|
|
default:
|
|
printf("<node>");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static enum ivy_status finalise_expr(struct expr_parser_state *state, struct ivy_ast_node **root)
|
|
{
|
|
b_queue_iterator it = {0};
|
|
while (true) {
|
|
b_queue_entry *entry = b_queue_pop_back(&state->s_operator_stack);
|
|
if (!entry) {
|
|
break;
|
|
}
|
|
|
|
struct ivy_ast_node *node = b_unbox(struct ivy_ast_node, entry, n_entry);
|
|
if (!node) {
|
|
/* this should never happen */
|
|
return IVY_ERR_INTERNAL_FAILURE;
|
|
}
|
|
|
|
if (node->n_type != IVY_AST_OP) {
|
|
b_queue_push_back(&state->s_output_queue, entry);
|
|
continue;
|
|
}
|
|
|
|
struct ivy_ast_op_node *op_node = (struct ivy_ast_op_node *)node;
|
|
|
|
if (op_node->n_op->op_id == IVY_OP_LEFT_PAREN) {
|
|
/* mismatched parentheses */
|
|
return IVY_ERR_BAD_SYNTAX;
|
|
}
|
|
|
|
b_queue_push_back(&state->s_output_queue, entry);
|
|
}
|
|
|
|
b_queue q = B_QUEUE_INIT;
|
|
b_queue_entry *tmp = NULL;
|
|
b_queue_iterator_begin(&state->s_output_queue, &it);
|
|
int i = 0;
|
|
|
|
while (b_queue_iterator_is_valid(&it)) {
|
|
struct ivy_ast_node *item
|
|
= b_unbox(struct ivy_ast_node, it.entry, n_entry);
|
|
b_queue_iterator_erase(&it);
|
|
|
|
if (item->n_type != IVY_AST_OP && item->n_type != IVY_AST_MSG) {
|
|
/* operand */
|
|
b_queue_push_back(&q, &item->n_entry);
|
|
continue;
|
|
}
|
|
|
|
const struct ivy_operator *op = NULL;
|
|
|
|
if (item->n_type == IVY_AST_MSG) {
|
|
struct ivy_ast_msg_node *msg = (struct ivy_ast_msg_node *)item;
|
|
tmp = b_queue_pop_back(&q);
|
|
msg->n_recipient = b_unbox(struct ivy_ast_node, tmp, n_entry);
|
|
b_queue_push_back(&q, &msg->n_base.n_entry);
|
|
continue;
|
|
}
|
|
|
|
struct ivy_ast_op_node *op_node = (struct ivy_ast_op_node *)item;
|
|
op = op_node->n_op;
|
|
tmp = b_queue_pop_back(&q);
|
|
op_node->n_right = b_unbox(struct ivy_ast_node, tmp, n_entry);
|
|
|
|
if (op->op_arity == IVY_OP_BINARY) {
|
|
tmp = b_queue_pop_back(&q);
|
|
op_node->n_left = b_unbox(struct ivy_ast_node, tmp, n_entry);
|
|
}
|
|
|
|
b_queue_push_back(&q, &op_node->n_base.n_entry);
|
|
}
|
|
|
|
tmp = b_queue_pop_back(&q);
|
|
*root = b_unbox(struct ivy_ast_node, tmp, n_entry);
|
|
printf("\n");
|
|
return IVY_OK;
|
|
}
|
|
|
|
static const struct ivy_operator *get_operator(struct ivy_token *tok)
|
|
{
|
|
switch (tok->t_type) {
|
|
case IVY_TOK_IDENT:
|
|
return ivy_operator_get(tok->t_type);
|
|
case IVY_TOK_KEYWORD:
|
|
return ivy_operator_get(tok->t_keyword);
|
|
case IVY_TOK_SYMBOL:
|
|
return ivy_operator_get(tok->t_symbol);
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static struct ivy_ast_selector_node *create_unary_selector_from_ident(struct ivy_token *tok)
|
|
{
|
|
struct ivy_ast_selector_node *sel = (struct ivy_ast_selector_node *)ast_node_create(IVY_AST_SELECTOR);
|
|
if (!sel) {
|
|
return NULL;
|
|
}
|
|
|
|
sel->n_msg_name = tok;
|
|
sel->n_recipient = IVY_SELECTOR_RECIPIENT_NONE;
|
|
|
|
return sel;
|
|
}
|
|
|
|
static enum ivy_status push_operator(
|
|
struct expr_parser_state *state, struct ivy_token *tok, const struct ivy_operator *op)
|
|
{
|
|
if (!op) {
|
|
op = get_operator(tok);
|
|
}
|
|
|
|
if (!op) {
|
|
return IVY_ERR_BAD_SYNTAX;
|
|
}
|
|
|
|
if ((op->op_location == IVY_OP_INFIX || op->op_location == IVY_OP_POSTFIX)
|
|
&& state->s_prev_part != EXPR_OPERAND) {
|
|
return IVY_ERR_BAD_SYNTAX;
|
|
}
|
|
|
|
if (op->op_location == IVY_OP_PREFIX
|
|
&& state->s_prev_part == EXPR_OPERAND) {
|
|
return IVY_ERR_BAD_SYNTAX;
|
|
}
|
|
|
|
while (true) {
|
|
b_queue_entry *top_entry = b_queue_last(&state->s_operator_stack);
|
|
|
|
if (!top_entry) {
|
|
break;
|
|
}
|
|
|
|
struct ivy_ast_node *top
|
|
= b_unbox(struct ivy_ast_node, top_entry, n_entry);
|
|
|
|
const struct ivy_operator *top_op = NULL;
|
|
if (top->n_type == IVY_AST_OP) {
|
|
struct ivy_ast_op_node *op_node = (struct ivy_ast_op_node *)top;
|
|
top_op = op_node->n_op;
|
|
} else if (top->n_type == IVY_AST_MSG) {
|
|
top_op = ivy_operator_get(IVY_TOK_IDENT);
|
|
}
|
|
|
|
if (top_op->op_id == IVY_OP_LEFT_PAREN) {
|
|
break;
|
|
}
|
|
|
|
if (top_op->op_precedence < op->op_precedence) {
|
|
break;
|
|
}
|
|
|
|
if (top_op->op_precedence == op->op_precedence
|
|
&& op->op_associativity != IVY_ASSOCIATIVITY_LEFT) {
|
|
break;
|
|
}
|
|
|
|
b_queue_delete(&state->s_operator_stack, top_entry);
|
|
b_queue_push_back(&state->s_output_queue, top_entry);
|
|
}
|
|
|
|
if (tok->t_type == IVY_TOK_IDENT) {
|
|
struct ivy_ast_msg_node *msg_node = (struct ivy_ast_msg_node *)ast_node_create(IVY_AST_MSG);
|
|
msg_node->n_sel = create_unary_selector_from_ident(tok);
|
|
b_queue_push_back(&state->s_operator_stack, &msg_node->n_base.n_entry);
|
|
} else {
|
|
struct ivy_ast_op_node *op_node = (struct ivy_ast_op_node *)ast_node_create(IVY_AST_OP);
|
|
op_node->n_op = op;
|
|
b_queue_push_back(&state->s_operator_stack, &op_node->n_base.n_entry);
|
|
}
|
|
|
|
return IVY_OK;
|
|
}
|
|
|
|
|
|
static enum ivy_status push_operand(
|
|
struct expr_parser_state *state, struct ivy_token *tok)
|
|
{
|
|
struct ivy_ast_node *node = NULL;
|
|
|
|
switch (tok->t_type) {
|
|
case IVY_TOK_INT: {
|
|
struct ivy_ast_int_node *v = (struct ivy_ast_int_node *)ast_node_create(IVY_AST_INT);
|
|
v->n_value = tok;
|
|
node = (struct ivy_ast_node *)v;
|
|
break;
|
|
}
|
|
case IVY_TOK_DOUBLE: {
|
|
struct ivy_ast_double_node *v = (struct ivy_ast_double_node *)ast_node_create(IVY_AST_DOUBLE);
|
|
v->n_value = tok;
|
|
node = (struct ivy_ast_node *)v;
|
|
break;
|
|
}
|
|
case IVY_TOK_STRING: {
|
|
struct ivy_ast_string_node *v = (struct ivy_ast_string_node *)ast_node_create(IVY_AST_STRING);
|
|
v->n_value = tok;
|
|
node = (struct ivy_ast_node *)v;
|
|
break;
|
|
}
|
|
case IVY_TOK_IDENT: {
|
|
struct ivy_ast_ident_node *v = (struct ivy_ast_ident_node *)ast_node_create(IVY_AST_IDENT);
|
|
v->n_content = tok;
|
|
node = (struct ivy_ast_node *)v;
|
|
break;
|
|
}
|
|
default:
|
|
return IVY_ERR_INTERNAL_FAILURE;
|
|
}
|
|
|
|
b_queue_push_back(&state->s_output_queue, &node->n_entry);
|
|
return IVY_OK;
|
|
}
|
|
|
|
static struct token_parse_result parse_ident(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end == EXPR_END_NONE) {
|
|
state->s_end = EXPR_END_DOT;
|
|
}
|
|
|
|
if (state->s_prev_part == EXPR_OPERAND) {
|
|
push_operator(state, tok, NULL);
|
|
} else {
|
|
push_operand(state, tok);
|
|
}
|
|
|
|
set_previous(state, tok);
|
|
state->s_prev_part = EXPR_OPERAND;
|
|
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_atom(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end == EXPR_END_NONE) {
|
|
state->s_end = EXPR_END_DOT;
|
|
}
|
|
|
|
push_operand(state, tok);
|
|
set_previous(state, tok);
|
|
state->s_prev_part = EXPR_OPERAND;
|
|
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_string(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end == EXPR_END_NONE) {
|
|
state->s_end = EXPR_END_DOT;
|
|
}
|
|
|
|
push_operand(state, tok);
|
|
set_previous(state, tok);
|
|
state->s_prev_part = EXPR_OPERAND;
|
|
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_str_start(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_str_end(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_label(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_int(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end == EXPR_END_NONE) {
|
|
state->s_end = EXPR_END_DOT;
|
|
}
|
|
|
|
if (state->s_prev_part == EXPR_OPERAND) {
|
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
|
}
|
|
|
|
push_operand(state, tok);
|
|
set_previous(state, tok);
|
|
state->s_prev_part = EXPR_OPERAND;
|
|
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_double(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end == EXPR_END_NONE) {
|
|
state->s_end = EXPR_END_DOT;
|
|
}
|
|
|
|
if (state->s_prev_part == EXPR_OPERAND) {
|
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
|
}
|
|
|
|
push_operand(state, tok);
|
|
set_previous(state, tok);
|
|
state->s_prev_part = EXPR_OPERAND;
|
|
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_symbol(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end != EXPR_END_DOT) {
|
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
|
}
|
|
|
|
enum ivy_status status = push_operator(state, tok, NULL);
|
|
set_previous(state, tok);
|
|
state->s_prev_part = EXPR_OPERATOR;
|
|
|
|
return PARSE_RESULT(status, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_left_paren(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end == EXPR_END_NONE) {
|
|
state->s_end = EXPR_END_DOT;
|
|
}
|
|
|
|
if (state->s_prev_tok == IVY_TOK_IDENT) {
|
|
/* this is the openning parenthesis of a complex message. */
|
|
}
|
|
|
|
if (state->s_prev_part == EXPR_OPERAND) {
|
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
|
}
|
|
|
|
struct ivy_ast_op_node *paren_node = (struct ivy_ast_op_node *)ast_node_create(IVY_AST_OP);
|
|
paren_node->n_op = ivy_operator_get(tok->t_symbol);
|
|
b_queue_push_back(&state->s_operator_stack, &paren_node->n_base.n_entry);
|
|
set_previous(state, tok);
|
|
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_right_paren(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_if(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end == EXPR_END_NONE) {
|
|
state->s_end = EXPR_END_KEYWORD;
|
|
}
|
|
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_else(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_end(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_while(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_for(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_match(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_try(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_catch(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_throw(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_understands(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_in(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_do(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_is(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_and(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_or(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
return PARSE_RESULT(IVY_ERR_IO_FAILURE, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_not(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end != EXPR_END_DOT) {
|
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
|
}
|
|
|
|
enum ivy_status status = push_operator(state, tok, NULL);
|
|
set_previous(state, tok);
|
|
|
|
return PARSE_RESULT(status, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_bang(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end != EXPR_END_DOT) {
|
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
|
}
|
|
|
|
struct ivy_ast_node *expr_tree = NULL;
|
|
enum ivy_status status = finalise_expr(state, &expr_tree);
|
|
|
|
if (status != IVY_OK) {
|
|
return PARSE_RESULT(status, 0);
|
|
}
|
|
|
|
parser_replace_current_node(ctx, expr_tree);
|
|
parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT);
|
|
return PARSE_RESULT(IVY_OK, PARSE_REPEAT_TOKEN);
|
|
}
|
|
|
|
static struct token_parse_result parse_dot(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end != EXPR_END_DOT) {
|
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
|
}
|
|
|
|
struct ivy_ast_node *expr_tree = NULL;
|
|
enum ivy_status status = finalise_expr(state, &expr_tree);
|
|
|
|
if (status != IVY_OK) {
|
|
return PARSE_RESULT(status, 0);
|
|
}
|
|
|
|
parser_replace_current_node(ctx, expr_tree);
|
|
parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT);
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
static struct token_parse_result parse_caret(
|
|
struct ivy_parser *ctx, struct ivy_token *tok)
|
|
{
|
|
struct expr_parser_state *state
|
|
= parser_get_state(ctx, struct expr_parser_state);
|
|
|
|
if (state->s_end != EXPR_END_NONE || state->s_type != IVY_KW_NONE) {
|
|
return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0);
|
|
}
|
|
|
|
state->s_type = IVY_SYM_CARET;
|
|
|
|
return PARSE_RESULT(IVY_OK, 0);
|
|
}
|
|
|
|
struct ast_node_type expr_node_ops = {
|
|
.n_add_child = add_child,
|
|
.n_state_size = sizeof(struct expr_parser_state),
|
|
.n_node_size = sizeof(struct ivy_ast_expr_node),
|
|
.n_token_parsers = {
|
|
TOK_PARSER(IDENT, parse_ident),
|
|
TOK_PARSER(ATOM, parse_atom),
|
|
TOK_PARSER(STRING, parse_string),
|
|
TOK_PARSER(STR_START, parse_str_start),
|
|
TOK_PARSER(STR_END, parse_str_end),
|
|
TOK_PARSER(LABEL, parse_label),
|
|
TOK_PARSER(INT, parse_int),
|
|
TOK_PARSER(DOUBLE, parse_double),
|
|
TOK_PARSER(SYMBOL, parse_symbol),
|
|
},
|
|
.n_symbol_parsers = {
|
|
SYM_PARSER(BANG, parse_bang),
|
|
SYM_PARSER(DOT, parse_dot),
|
|
SYM_PARSER(CARET, parse_caret),
|
|
SYM_PARSER(LEFT_PAREN, parse_left_paren),
|
|
SYM_PARSER(RIGHT_PAREN, parse_right_paren),
|
|
},
|
|
.n_keyword_parsers = {
|
|
KW_PARSER(IF, parse_if),
|
|
KW_PARSER(ELSE, parse_else),
|
|
KW_PARSER(END, parse_end),
|
|
KW_PARSER(WHILE, parse_while),
|
|
KW_PARSER(FOR, parse_for),
|
|
KW_PARSER(MATCH, parse_match),
|
|
KW_PARSER(TRY, parse_try),
|
|
KW_PARSER(CATCH, parse_catch),
|
|
KW_PARSER(THROW, parse_throw),
|
|
KW_PARSER(UNDERSTANDS, parse_understands),
|
|
KW_PARSER(IN, parse_in),
|
|
KW_PARSER(DO, parse_do),
|
|
KW_PARSER(IS, parse_is),
|
|
KW_PARSER(AND, parse_and),
|
|
KW_PARSER(OR, parse_or),
|
|
KW_PARSER(NOT, parse_not),
|
|
},
|
|
};
|