From 1c5b23d968bf37949a531a26dec9e7bef9a39212 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Mon, 2 Dec 2024 07:56:27 +0000 Subject: [PATCH] lang: ast: re-write expression parser to support keyword messages also adjust some parser state callbackss to better support sub-parsers returning results to their parents. --- lang/ast/block.c | 15 +- lang/ast/class.c | 9 +- lang/ast/ctx.c | 42 +- lang/ast/ctx.h | 5 +- lang/ast/expr.c | 1042 +++++++++++++++++++-------------------- lang/ast/msgh.c | 4 +- lang/ast/node.c | 18 - lang/ast/node.h | 60 +-- lang/ast/unit-import.c | 10 +- lang/ast/unit-package.c | 9 +- lang/ast/unit.c | 4 +- 11 files changed, 605 insertions(+), 613 deletions(-) diff --git a/lang/ast/block.c b/lang/ast/block.c index a2704eb..ae66747 100644 --- a/lang/ast/block.c +++ b/lang/ast/block.c @@ -1,11 +1,11 @@ -#include "ctx.h" -#include "node.h" #include "block.h" + +#include "ctx.h" #include "iterate.h" +#include "node.h" #include #include -#include static struct token_parse_result parse_end( struct ivy_parser *ctx, struct ivy_token *tok) @@ -21,7 +21,7 @@ static struct token_parse_result parse_end( } static struct token_parse_result parse_bang( - struct ivy_parser* ctx, struct ivy_token* tok) + struct ivy_parser *ctx, struct ivy_token *tok) { struct block_parser_state *state = parser_get_state(ctx, struct block_parser_state); @@ -51,9 +51,10 @@ static struct token_parse_result parse_expr_begin( } static enum ivy_status add_child( - struct ivy_ast_node *parent, struct ivy_ast_node *child) + struct parser_state *parent, struct ivy_ast_node *child) { - struct ivy_ast_block_node *block = (struct ivy_ast_block_node *)parent; + struct ivy_ast_block_node *block + = (struct ivy_ast_block_node *)parent->s_node; b_queue_push_back(&block->n_expr, &child->n_entry); @@ -70,7 +71,7 @@ static void collect_children( { struct ivy_ast_block_node *block = (struct ivy_ast_block_node *)node; b_queue_iterator it = {0}; - b_queue_foreach(&it, &block->n_expr) { + b_queue_foreach (&it, &block->n_expr) { struct ivy_ast_node *expr = b_unbox(struct ivy_ast_node, it.entry, n_entry); ast_node_iterator_enqueue_node(iterator, node, expr); diff --git a/lang/ast/class.c b/lang/ast/class.c index 872c5e4..c44e6be 100644 --- a/lang/ast/class.c +++ b/lang/ast/class.c @@ -1,6 +1,6 @@ #include "ctx.h" -#include "node.h" #include "iterate.h" +#include "node.h" #include #include @@ -15,7 +15,8 @@ struct class_parser_state { int s_prev_token; }; -static struct token_parse_result parse_dollar(struct ivy_parser *ctx, struct ivy_token *tok) +static struct token_parse_result parse_dollar( + struct ivy_parser *ctx, struct ivy_token *tok) { struct class_parser_state *state = parser_get_state(ctx, struct class_parser_state); @@ -123,9 +124,9 @@ static struct token_parse_result parse_linefeed( } static enum ivy_status add_child( - struct ivy_ast_node *parent, struct ivy_ast_node *child) + struct parser_state *state, struct ivy_ast_node *child) { - struct ivy_ast_class_node *c = (struct ivy_ast_class_node *)parent; + struct ivy_ast_class_node *c = (struct ivy_ast_class_node *)state->s_node; switch (child->n_type) { case IVY_AST_MSGH: diff --git a/lang/ast/ctx.c b/lang/ast/ctx.c index c66c4d8..b478523 100644 --- a/lang/ast/ctx.c +++ b/lang/ast/ctx.c @@ -5,9 +5,21 @@ #include #include #include +#include #include #include +static void print_state_stack(struct ivy_parser *parser) +{ + b_queue_iterator it = {0}; + b_queue_foreach (&it, &parser->p_state) { + struct parser_state *state + = b_unbox(struct parser_state, it.entry, s_entry); + printf(" %s\n", + ivy_ast_node_type_to_string(state->s_node->n_type)); + } +} + enum ivy_status ivy_parser_create(struct ivy_parser **parser) { struct ivy_parser *out = malloc(sizeof *out); @@ -48,6 +60,9 @@ enum ivy_status ivy_parser_push_token( struct token_parse_result result = func(parser, tok); parser->p_status = result.r_status; + printf("states (after token)\n"); + print_state_stack(parser); + if (result.r_flags & PARSE_REPEAT_TOKEN) { continue; } @@ -108,6 +123,8 @@ struct parser_state *parser_push_state( node_type->n_init_state(parser, state); } + printf("states (after push)\n"); + print_state_stack(parser); return state; } @@ -122,13 +139,17 @@ void parser_pop_state(struct ivy_parser *parser, enum pop_state_flags flags) b_queue_pop_back(&parser->p_state); if (state && (flags & STATE_ADD_NODE_TO_PARENT)) { - ast_node_add_child(state->s_parent, state->s_node); + parser_add_child(parser, state->s_node); } free(state); + + printf("states (after pop)\n"); + print_state_stack(parser); } -void parser_replace_current_node(struct ivy_parser *parser, struct ivy_ast_node *new_node) +void parser_replace_current_node( + struct ivy_parser *parser, struct ivy_ast_node *new_node) { struct parser_state *state = parser_get_state_generic(parser); if (!state) { @@ -139,6 +160,23 @@ void parser_replace_current_node(struct ivy_parser *parser, struct ivy_ast_node state->s_node = new_node; } +enum ivy_status parser_add_child( + struct ivy_parser *parser, struct ivy_ast_node *new_node) +{ + struct parser_state *state = parser_get_state_generic(parser); + if (!state) { + return IVY_ERR_NOT_SUPPORTED; + } + + const struct ast_node_type *node_type + = get_ast_node_type(state->s_node->n_type); + if (!node_type || !node_type->n_add_child) { + return IVY_ERR_NOT_SUPPORTED; + } + + return node_type->n_add_child(state, new_node); +} + bool ivy_parser_is_node_complete(struct ivy_parser *parser) { return (parser->p_state.q_first == parser->p_state.q_last); diff --git a/lang/ast/ctx.h b/lang/ast/ctx.h index 3634e98..2e008c9 100644 --- a/lang/ast/ctx.h +++ b/lang/ast/ctx.h @@ -30,6 +30,9 @@ extern struct parser_state *parser_push_state( extern void parser_pop_state(struct ivy_parser *parser, enum pop_state_flags flags); extern struct parser_state *parser_get_state_generic(struct ivy_parser *parser); -extern void parser_replace_current_node(struct ivy_parser *parser, struct ivy_ast_node *new_node); +extern void parser_replace_current_node( + struct ivy_parser *parser, struct ivy_ast_node *new_node); +extern enum ivy_status parser_add_child( + struct ivy_parser *parser, struct ivy_ast_node *new_node); #endif diff --git a/lang/ast/expr.c b/lang/ast/expr.c index f8ea62f..4b8f6e2 100644 --- a/lang/ast/expr.c +++ b/lang/ast/expr.c @@ -6,61 +6,56 @@ #include #include -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_type { + EXPR_TYPE_NONE = 0, + /* if-else, while/for, match, etc (any expression that ends with an + * 'end' keyword */ + EXPR_TYPE_STMT, + /* arithmetic and message-sending expressions (any expression that ends + * implicitly or with an expression separator */ + EXPR_TYPE_ARITH, }; -enum expr_part { - EXPR_NONE = 0, - EXPR_OPERATOR, - EXPR_OPERAND, +enum expr_component { + EXPR_CMP_NONE = 0, + EXPR_CMP_OPERATOR, + EXPR_CMP_OPERAND, + EXPR_CMP_MSG, }; struct expr_parser_state { struct parser_state s_base; - enum expr_end s_end; + enum expr_type s_type; + /* for arithmetic expressions, this records whether the previous + * component (either a token or parenthesised group of tokens) is an + * operator, operand, or message */ + enum expr_component s_prev_component; + /* the token type/keyword type/symbol type of the last token that was + * encountered */ + unsigned int s_prev_token; + /* if this is an arithmetic expression, this variable is the depth + * of parentheses that this sub-expression is at */ + unsigned int s_paren_depth; + + /* when this is set, the expression will be terminated when the + * specified token is encountered. the token that terminated the + * expression will not be consumed. */ + unsigned int s_terminator; + + /* all sub-expressions (i.e. those conatained within brackets, + * keyword-messages and keyword-message args, etc) will have this set + * to true */ + bool s_subexpr; - /* 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; + + /* these variables are for keyword-message expressions */ + struct ivy_ast_node *s_recipient; + b_queue s_labels; + b_queue s_args; }; -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) { @@ -87,7 +82,11 @@ static void print_operand(struct ivy_ast_node *node) } 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); + if (v->n_sel->n_msg_name) { + printf("%s()", v->n_sel->n_msg_name->t_str); + } else { + printf(""); + } break; } case IVY_AST_STRING: { @@ -101,10 +100,171 @@ static void print_operand(struct ivy_ast_node *node) } } -static enum ivy_status finalise_expr( - struct expr_parser_state *state, struct ivy_ast_node **root) +static void push_operand(struct expr_parser_state *state, struct ivy_token *tok) +{ + switch (tok->t_type) { + 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; + b_queue_push_back(&state->s_output_queue, &v->n_base.n_entry); + break; + } + 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; + b_queue_push_back(&state->s_output_queue, &v->n_base.n_entry); + 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; + b_queue_push_back(&state->s_output_queue, &v->n_base.n_entry); + 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; + b_queue_push_back(&state->s_output_queue, &v->n_base.n_entry); + break; + } + default: + break; + } +} + +static const struct ivy_operator *get_operator(struct ivy_token *tok) +{ + switch (tok->t_type) { + case IVY_TOK_SYMBOL: + return ivy_operator_get_by_token(tok->t_symbol); + case IVY_TOK_KEYWORD: + return ivy_operator_get_by_token(tok->t_keyword); + default: + return ivy_operator_get_by_token(tok->t_type); + } +} + +static struct ivy_ast_selector_node *unary_selector_from_token(struct ivy_token *tok) +{ + struct ivy_ast_selector_node *sel + = (struct ivy_ast_selector_node *)ast_node_create(IVY_AST_SELECTOR); + sel->n_msg_name = tok; + return sel; +} + +static void push_operator(struct expr_parser_state *state, struct ivy_token *tok) +{ + const struct ivy_operator *op = get_operator(tok); + + while (true) { + b_queue_entry *top = b_queue_last(&state->s_operator_stack); + if (!top) { + break; + } + + struct ivy_ast_node *top_node + = b_unbox(struct ivy_ast_node, top, n_entry); + const struct ivy_operator *top_op = NULL; + + switch (top_node->n_type) { + case IVY_AST_OP: { + struct ivy_ast_op_node *op_node + = (struct ivy_ast_op_node *)top_node; + top_op = op_node->n_op; + break; + } + case IVY_AST_MSG: { + struct ivy_ast_msg_node *msg_node + = (struct ivy_ast_msg_node *)top_node; + top_op = ivy_operator_get_by_id(IVY_OP_MSG); + break; + } + default: + return; + } + + if (top_op->op_precedence < op->op_precedence + || (top_op->op_precedence == op->op_precedence + && op->op_associativity != IVY_ASSOCIATIVITY_LEFT)) { + break; + } + + b_queue_delete(&state->s_operator_stack, top); + b_queue_push_back(&state->s_output_queue, top); + } + + if (op->op_id == IVY_OP_MSG) { + struct ivy_ast_msg_node *new_msg_node + = (struct ivy_ast_msg_node *)ast_node_create(IVY_AST_MSG); + new_msg_node->n_sel = unary_selector_from_token(tok); + b_queue_push_back( + &state->s_operator_stack, &new_msg_node->n_base.n_entry); + } else { + struct ivy_ast_op_node *new_op_node + = (struct ivy_ast_op_node *)ast_node_create(IVY_AST_OP); + new_op_node->n_op = op; + b_queue_push_back( + &state->s_operator_stack, &new_op_node->n_base.n_entry); + } +} + +static void print_expr_queues(struct expr_parser_state *state) { b_queue_iterator it = {0}; + + printf("operators:"); + b_queue_foreach (&it, &state->s_operator_stack) { + struct ivy_ast_node *n + = b_unbox(struct ivy_ast_node, it.entry, n_entry); + fputc(' ', stdout); + print_operand(n); + } + + printf("\noperands:"); + b_queue_foreach (&it, &state->s_output_queue) { + struct ivy_ast_node *n + = b_unbox(struct ivy_ast_node, it.entry, n_entry); + fputc(' ', stdout); + print_operand(n); + } + + printf("\n"); +} + +static bool op_node_is_complete(struct ivy_ast_op_node *node) +{ + if (!node->n_op) { + return false; + } + + switch (node->n_op->op_arity) { + case IVY_OP_UNARY: + return node->n_right != NULL; + case IVY_OP_BINARY: + return (node->n_left != NULL && node->n_right != NULL); + default: + return false; + } +} + +static enum ivy_status finalise_expr( + struct expr_parser_state *state, struct ivy_ast_node **expr_tree, + enum ivy_operator_precedence minimum_precedence) +{ + b_queue_iterator it = {0}; + + /* first, take all the operators still left on the operator stack and + * add them to the output queue. + * + * since each set of parentheses has its own expression context, + * we don't have to handle parentheses here */ while (true) { b_queue_entry *entry = b_queue_pop_back(&state->s_operator_stack); if (!entry) { @@ -118,21 +278,43 @@ static enum ivy_status finalise_expr( return IVY_ERR_INTERNAL_FAILURE; } - if (node->n_type != IVY_AST_OP) { - b_queue_push_back(&state->s_output_queue, entry); - continue; + const struct ivy_operator *op = NULL; + + switch (node->n_type) { + case IVY_AST_OP: { + struct ivy_ast_op_node *n = (struct ivy_ast_op_node *)node; + op = n->n_op; + break; + } + case IVY_AST_MSG: + /* all unary message operators have the same pre-defined + * precedence */ + op = ivy_operator_get_by_id(IVY_OP_MSG); + break; + default: + return IVY_ERR_INTERNAL_FAILURE; } - 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; + /* if we aren't processing operators below a certain precedence + * then leave them on the stack and stop here. */ + if (op->op_precedence < minimum_precedence) { + b_queue_push_back(&state->s_operator_stack, entry); + break; } b_queue_push_back(&state->s_output_queue, entry); } +#if 0 + printf("** after linearisation:\n"); + print_expr_queues(state); +#endif + + /* next, step through the output queue and build a tree of ast nodes + * representing the expression. the queue is in RPM, where operators + * always follow their operands, so a queue of operands is needed + * for the conversion. */ + b_queue q = B_QUEUE_INIT; b_queue_entry *tmp = NULL; b_queue_iterator_begin(&state->s_output_queue, &it); @@ -143,6 +325,8 @@ static enum ivy_status finalise_expr( = b_unbox(struct ivy_ast_node, it.entry, n_entry); b_queue_iterator_erase(&it); + /* if the node is an operand, just push it to a temporary queue + * and come back to it later. */ if (item->n_type != IVY_AST_OP && item->n_type != IVY_AST_MSG) { /* operand */ b_queue_push_back(&q, &item->n_entry); @@ -154,14 +338,32 @@ static enum ivy_status finalise_expr( 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); + /* if the message has no recipient, it is a unary message, + * and the recipient is located on the operand stack. + * + * if the message DOES have a recipient, it is a + * self-contained keyword message, and can be pushed to + * the operand queue as-is. */ + if (!msg->n_recipient) { + 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; + /* if an operator node is already complete (i.e. it already has + * all the operands it needs, it can be pushed to the operand + * queue as-is */ + if (op_node_is_complete(op_node)) { + b_queue_push_back(&q, &item->n_entry); + continue; + } + + /* otherwise, pop the relevant operands from the operand + * queue... */ op = op_node->n_op; tmp = b_queue_pop_back(&q); op_node->n_right = b_unbox(struct ivy_ast_node, tmp, n_entry); @@ -172,161 +374,100 @@ static enum ivy_status finalise_expr( = b_unbox(struct ivy_ast_node, tmp, n_entry); } + /* ...and push the newly-completed operator node to the operand + * queue */ b_queue_push_back(&q, &op_node->n_base.n_entry); } +#if 0 + printf("** after hierarchisation:\n"); + print_expr_queues(state); +#endif + + /* if we are not processing operators below a certain precedence, + * i.e. when determining the recipient of a keyword-message), these + * operators will still be on the parser state's operator stack, but + * their operands have just been moved to the temporary operand stack + * used above. move them back to the parser state's output queue here + * so they can be used later. */ + b_queue_foreach (&it, &state->s_operator_stack) { + b_queue_entry *entry = b_queue_pop_front(&q); + if (!entry) { + return IVY_ERR_INTERNAL_FAILURE; + } + + b_queue_push_back(&state->s_output_queue, entry); + } + +#if 0 + printf("** after de-linearisation:\n"); + print_expr_queues(state); + ivy_ast_node_print(*expr_tree); + printf("------\n"); +#endif + + /* the final node remaining on the temp operand stack is the root node + * of the new expression tree */ tmp = b_queue_pop_back(&q); - *root = b_unbox(struct ivy_ast_node, tmp, n_entry); - printf("\n"); + *expr_tree = b_unbox(struct ivy_ast_node, tmp, n_entry); + return IVY_OK; } -static const struct ivy_operator *get_operator(struct ivy_token *tok) +static struct token_parse_result parse_operand( + struct ivy_parser *ctx, struct ivy_token *tok) { + struct expr_parser_state *state + = parser_get_state(ctx, struct expr_parser_state); + + if (state->s_type == EXPR_TYPE_STMT) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + if (state->s_prev_component == EXPR_CMP_OPERAND) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + + state->s_type = EXPR_TYPE_ARITH; + + push_operand(state, tok); + // print_expr_queues(state); + state->s_prev_component = EXPR_CMP_OPERAND; + + return PARSE_RESULT(IVY_OK, 0); +} + +static struct token_parse_result parse_operator( + struct ivy_parser *ctx, struct ivy_token *tok) +{ + struct expr_parser_state *state + = parser_get_state(ctx, struct expr_parser_state); + + if (state->s_type != EXPR_TYPE_ARITH) { + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + switch (tok->t_type) { - case IVY_TOK_IDENT: - return ivy_operator_get_by_token(tok->t_type); - case IVY_TOK_KEYWORD: - return ivy_operator_get_by_token(tok->t_keyword); case IVY_TOK_SYMBOL: - return ivy_operator_get_by_token(tok->t_symbol); + state->s_prev_token = tok->t_symbol; + break; + case IVY_TOK_KEYWORD: + state->s_prev_token = tok->t_keyword; + break; 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; + break; } - 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) -{ + const struct ivy_operator *op = get_operator(tok); if (!op) { - op = get_operator(tok); + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } - if (!op) { - return IVY_ERR_BAD_SYNTAX; - } + push_operator(state, tok); + state->s_prev_component = EXPR_CMP_OPERATOR; - 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_by_token(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; + print_expr_queues(state); + return PARSE_RESULT(IVY_OK, 0); } static struct token_parse_result parse_ident( @@ -335,131 +476,16 @@ static struct token_parse_result parse_ident( 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; - } + struct token_parse_result result; - if (state->s_prev_part == EXPR_OPERAND) { - push_operator(state, tok, NULL); + if (state->s_prev_component == EXPR_CMP_OPERAND) { + result = parse_operator(ctx, tok); + state->s_prev_component = EXPR_CMP_MSG; } else { - push_operand(state, tok); + result = parse_operand(ctx, 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); + return result; } static struct token_parse_result parse_left_paren( @@ -468,210 +494,102 @@ static struct token_parse_result parse_left_paren( 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_type == EXPR_TYPE_NONE) { + state->s_type = EXPR_TYPE_ARITH; } - if (state->s_prev_tok == IVY_TOK_IDENT) { - /* this is the openning parenthesis of a complex message. */ - } - - if (state->s_prev_part == EXPR_OPERAND) { + if (state->s_type != EXPR_TYPE_ARITH) { 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_by_token(tok->t_symbol); - b_queue_push_back(&state->s_operator_stack, &paren_node->n_base.n_entry); - set_previous(state, tok); + /* a sub-expression surrounded by parentheses is parsed by creating + * a sub-expression parser state */ + struct expr_parser_state *sub_expr + = (struct expr_parser_state *)parser_push_state(ctx, IVY_AST_EXPR); + sub_expr->s_paren_depth = state->s_paren_depth + 1; return PARSE_RESULT(IVY_OK, 0); } +static struct ivy_ast_selector_node *keyword_selector_from_label_list(b_queue *labels) +{ + struct ivy_ast_selector_node *sel + = (struct ivy_ast_selector_node *)ast_node_create(IVY_AST_SELECTOR); + + b_queue_iterator it = {0}; + + b_queue_iterator_begin(labels, &it); + while (b_queue_iterator_is_valid(&it)) { + struct ivy_token *label + = b_unbox(struct ivy_token, it.entry, t_entry); + b_queue_iterator_erase(&it); + b_queue_push_back(&sel->n_arg_labels, &label->t_entry); + } + + return sel; +} + +static struct ivy_ast_msg_node *finalise_keyword_msg(struct expr_parser_state *state) +{ + struct ivy_ast_msg_node *msg + = (struct ivy_ast_msg_node *)ast_node_create(IVY_AST_MSG); + + msg->n_recipient = state->s_recipient; + msg->n_sel = keyword_selector_from_label_list(&state->s_labels); + + b_queue_iterator it = {0}; + + b_queue_iterator_begin(&state->s_args, &it); + while (b_queue_iterator_is_valid(&it)) { + struct ivy_ast_node *arg + = b_unbox(struct ivy_ast_node, it.entry, n_entry); + b_queue_iterator_erase(&it); + + b_queue_push_back(&msg->n_arg, &arg->n_entry); + } + + return msg; +} + static struct token_parse_result parse_right_paren( struct ivy_parser *ctx, struct ivy_token *tok) { struct expr_parser_state *state = parser_get_state(ctx, struct expr_parser_state); - b_queue_entry *entry = NULL; - - while (true) { - entry = b_queue_last(&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 PARSE_RESULT(IVY_ERR_INTERNAL_FAILURE, 0); - } - - if (node->n_type != IVY_AST_OP) { - b_queue_delete(&state->s_operator_stack, entry); - 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) { - break; - } - - b_queue_delete(&state->s_operator_stack, entry); - b_queue_push_back(&state->s_output_queue, entry); - entry = NULL; - } - - if (!entry) { - /* mismatched parentheses */ + if (state->s_type != EXPR_TYPE_ARITH) { return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } - struct ivy_ast_node *paren = b_unbox(struct ivy_ast_node, entry, n_entry); - b_queue_delete(&state->s_operator_stack, entry); - ivy_ast_node_destroy(paren); - - 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) { + if (state->s_paren_depth == 0 && !state->s_subexpr) { 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); + if (state->s_recipient) { + /* this is the end of a keyword-message */ + struct ivy_ast_msg_node *msg = finalise_keyword_msg(state); + parser_replace_current_node(ctx, (struct ivy_ast_node *)msg); + parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT); + return PARSE_RESULT(IVY_OK, PARSE_REPEAT_TOKEN); } - struct ivy_ast_node *expr_tree = NULL; - enum ivy_status status = finalise_expr(state, &expr_tree); - + /* this is the end of a regular parentheses-surrounded sub-expression. */ + struct ivy_ast_node *expr = NULL; + enum ivy_status status + = finalise_expr(state, &expr, IVY_PRECEDENCE_ASSIGN); if (status != IVY_OK) { return PARSE_RESULT(status, 0); } - parser_replace_current_node(ctx, expr_tree); + parser_replace_current_node(ctx, expr); + + int flags = 0; + if (state->s_paren_depth == 0 && state->s_subexpr) { + flags = PARSE_REPEAT_TOKEN; + } + parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT); - return PARSE_RESULT(IVY_OK, PARSE_REPEAT_TOKEN); + return PARSE_RESULT(IVY_OK, flags); } static struct token_parse_result parse_dot( @@ -680,75 +598,137 @@ static struct token_parse_result parse_dot( struct expr_parser_state *state = parser_get_state(ctx, struct expr_parser_state); - if (state->s_end != EXPR_END_DOT) { + if (state->s_type != EXPR_TYPE_ARITH) { 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 (state->s_paren_depth > 0) { + /* end-of-expression with mismatched parentheses */ + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); + } + if (state->s_recipient) { + /* this is the end of a keyword-message */ + struct ivy_ast_msg_node *msg = finalise_keyword_msg(state); + parser_replace_current_node(ctx, (struct ivy_ast_node *)msg); + parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT); + return PARSE_RESULT(IVY_OK, PARSE_REPEAT_TOKEN); + } + + /* this is the end of a regular expression or sub-expression */ + struct ivy_ast_node *expr = NULL; + enum ivy_status status + = finalise_expr(state, &expr, IVY_PRECEDENCE_ASSIGN); if (status != IVY_OK) { return PARSE_RESULT(status, 0); } - parser_replace_current_node(ctx, expr_tree); + parser_replace_current_node(ctx, expr); + + int flags = 0; + if (state->s_subexpr) { + /* if we are currently parsing a subexpression (such as a + * keyword-message argument), the dot needs to be propagated to + * the parent expression context so that it can be terminated + * too. */ + flags = PARSE_REPEAT_TOKEN; + } + parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT); - return PARSE_RESULT(IVY_OK, 0); + return PARSE_RESULT(IVY_OK, flags); } -static struct token_parse_result parse_caret( +static struct token_parse_result parse_label( 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) { + if (state->s_type != EXPR_TYPE_ARITH) { return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, 0); } - state->s_type = IVY_SYM_CARET; + if (state->s_terminator == IVY_TOK_LABEL) { + /* we are currently parsing a keyword-message argument, and + * have just encountered the label denoting the next argument. + * terminate here and propagate this label to the parent + * keyword-message parser context. */ + parser_pop_state(ctx, STATE_ADD_NODE_TO_PARENT); + return PARSE_RESULT(IVY_ERR_BAD_SYNTAX, PARSE_REPEAT_TOKEN); + } + + if (!state->s_recipient) { + /* this is the beginning of a new keyword-message */ + struct expr_parser_state *msg_expr + = (struct expr_parser_state *)parser_push_state( + ctx, IVY_AST_EXPR); + + /* the only operator with a lower precedence than + * keyword-messages is assignment. everything in the preceding + * expression, up to but not including any un-parenthesised + * assignments, is the recipient of the message. */ + struct ivy_ast_node *expr = NULL; + enum ivy_status status + = finalise_expr(state, &expr, IVY_PRECEDENCE_KEYWORD_MSG); + if (status != IVY_OK) { + return PARSE_RESULT(status, 0); + } + + msg_expr->s_recipient = expr; + msg_expr->s_subexpr = true; + msg_expr->s_type = EXPR_TYPE_ARITH; + state = msg_expr; + } + + /* we have just finished parsing a keyword-message argument, and this + * label marks the start of a new one. store the label and create a + * new argument parsing context. */ + b_queue_push_back(&state->s_labels, &tok->t_entry); + + struct expr_parser_state *arg_expr + = (struct expr_parser_state *)parser_push_state(ctx, IVY_AST_EXPR); + arg_expr->s_terminator = IVY_TOK_LABEL; + arg_expr->s_subexpr = true; return PARSE_RESULT(IVY_OK, 0); } +static enum ivy_status add_child( + struct parser_state *parent, struct ivy_ast_node *child) +{ + struct expr_parser_state *state = (struct expr_parser_state *)parent; + if (state->s_type == EXPR_TYPE_STMT) { + return IVY_ERR_NOT_SUPPORTED; + } + + if (state->s_recipient) { + /* treat the child node as a keyword-message argument */ + b_queue_push_back(&state->s_args, &child->n_entry); + } else { + /* treat the child node as a sub-expression enclosed in + * parentheses (i.e. an operand). */ + b_queue_push_back(&state->s_output_queue, &child->n_entry); + state->s_prev_component = EXPR_CMP_OPERAND; + } + + return IVY_OK; +} + 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 = { + .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(INT, parse_operand), + TOK_PARSER(DOUBLE, parse_operand), + TOK_PARSER(STRING, parse_operand), + TOK_PARSER(SYMBOL, parse_operator), 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), + SYM_PARSER(DOT, parse_dot), }, }; diff --git a/lang/ast/msgh.c b/lang/ast/msgh.c index 390f611..c4456f9 100644 --- a/lang/ast/msgh.c +++ b/lang/ast/msgh.c @@ -80,9 +80,9 @@ static struct token_parse_result parse_pipe( } static enum ivy_status add_child( - struct ivy_ast_node *parent, struct ivy_ast_node *child) + struct parser_state *parent, struct ivy_ast_node *child) { - struct ivy_ast_msgh_node *msgh = (struct ivy_ast_msgh_node *)parent; + struct ivy_ast_msgh_node *msgh = (struct ivy_ast_msgh_node *)parent->s_node; if (child->n_type == IVY_AST_SELECTOR && !msgh->n_sel) { msgh->n_sel = (struct ivy_ast_selector_node *)child; diff --git a/lang/ast/node.c b/lang/ast/node.c index e48fc86..a134525 100644 --- a/lang/ast/node.c +++ b/lang/ast/node.c @@ -170,24 +170,6 @@ struct ivy_ast_node *ast_node_create(enum ivy_ast_node_type type) return node; } -enum ivy_status ast_node_add_child( - struct ivy_ast_node *parent, struct ivy_ast_node *child) -{ - const struct ast_node_type *ops = get_ast_node_type(parent->n_type); - if (!ops) { - return IVY_ERR_NOT_SUPPORTED; - } - - enum ivy_status (*add_child)(struct ivy_ast_node *, struct ivy_ast_node *) - = ops->n_add_child; - - if (!add_child) { - return IVY_ERR_NOT_SUPPORTED; - } - - return add_child(parent, child); -} - static enum ivy_status node_print( struct ivy_ast_node *node, struct ivy_ast_node_iterator *it) { diff --git a/lang/ast/node.h b/lang/ast/node.h index 1f89f0f..3ff108b 100644 --- a/lang/ast/node.h +++ b/lang/ast/node.h @@ -6,8 +6,8 @@ struct parser_state; -#define PARSE_RESULT(status, flags) \ - ((struct token_parse_result) {.r_status = (status), .r_flags = (flags)}) +#define PARSE_RESULT(status, flags) \ + ((struct token_parse_result) { .r_status = (status), .r_flags = (flags) }) #define __TOK_PARSER_INDEX(x) ((x) - __IVY_TOK_INDEX_BASE) #define __SYM_PARSER_INDEX(x) ((x) - __IVY_SYM_INDEX_BASE) @@ -26,51 +26,51 @@ struct parser_state; #define KW_PARSER_FALLBACK(func) [__KW_PARSER_FALLBACK_INDEX] = func enum token_parse_flags { - PARSE_REPEAT_TOKEN = 0x01u, + PARSE_REPEAT_TOKEN = 0x01u, }; enum token_expr_type { - TOK_EXPR_NONE = 0, - TOK_EXPR_BEGIN, - TOK_EXPR_ANY, + TOK_EXPR_NONE = 0, + TOK_EXPR_BEGIN, + TOK_EXPR_ANY, }; struct token_parse_result { - enum ivy_status r_status; - enum token_parse_flags r_flags; + enum ivy_status r_status; + enum token_parse_flags r_flags; }; typedef struct token_parse_result (*token_parse_function)( - struct ivy_parser *, struct ivy_token *); + struct ivy_parser*, struct ivy_token*); struct ast_node_type { - enum ivy_status (*n_add_child)( - struct ivy_ast_node *, struct ivy_ast_node *); - void (*n_print)(struct ivy_ast_node *); - void (*n_init_state)(struct ivy_parser *, struct parser_state *); - void (*n_collect_children)( - struct ivy_ast_node *, struct ivy_ast_node_iterator *); + enum ivy_status (*n_add_child)( + struct parser_state*, struct ivy_ast_node*); + void (*n_print)(struct ivy_ast_node*); + void (*n_init_state)(struct ivy_parser*, struct parser_state*); + void (*n_collect_children)( + struct ivy_ast_node*, struct ivy_ast_node_iterator*); - size_t n_state_size; - size_t n_node_size; + size_t n_state_size; + size_t n_node_size; - token_parse_function n_token_parsers[__TOK_PARSER_INDEX(__IVY_TOK_INDEX_LIMIT)]; - token_parse_function n_keyword_parsers[__KW_PARSER_INDEX(__IVY_KW_INDEX_LIMIT)]; - token_parse_function n_symbol_parsers[__SYM_PARSER_INDEX(__IVY_SYM_INDEX_LIMIT)]; + token_parse_function n_token_parsers[__TOK_PARSER_INDEX(__IVY_TOK_INDEX_LIMIT)]; + token_parse_function n_keyword_parsers[__KW_PARSER_INDEX(__IVY_KW_INDEX_LIMIT)]; + token_parse_function n_symbol_parsers[__SYM_PARSER_INDEX(__IVY_SYM_INDEX_LIMIT)]; - struct { - token_parse_function expr_begin; - token_parse_function expr_other; - token_parse_function expr_all; - } n_expr_parser; + struct { + token_parse_function expr_begin; + token_parse_function expr_other; + token_parse_function expr_all; + } n_expr_parser; }; -extern const struct ast_node_type *get_ast_node_type(enum ivy_ast_node_type type); +extern const struct ast_node_type* get_ast_node_type(enum ivy_ast_node_type type); extern token_parse_function get_token_parser( - struct ivy_ast_node *context, struct ivy_token *tok); -extern enum token_expr_type get_token_expr_type(struct ivy_token *tok); -extern struct ivy_ast_node *ast_node_create(enum ivy_ast_node_type type); + struct ivy_ast_node* context, struct ivy_token* tok); +extern enum token_expr_type get_token_expr_type(struct ivy_token* tok); +extern struct ivy_ast_node* ast_node_create(enum ivy_ast_node_type type); extern enum ivy_status ast_node_add_child( - struct ivy_ast_node *parent, struct ivy_ast_node *child); + struct ivy_ast_node* parent, struct ivy_ast_node* child); #endif diff --git a/lang/ast/unit-import.c b/lang/ast/unit-import.c index 289db2c..49779ac 100644 --- a/lang/ast/unit-import.c +++ b/lang/ast/unit-import.c @@ -10,7 +10,8 @@ struct unit_import_parser_state { int s_prev_token; }; -static struct token_parse_result parse_dot(struct ivy_parser *ctx, struct ivy_token *tok) +static struct token_parse_result parse_dot( + struct ivy_parser *ctx, struct ivy_token *tok) { struct unit_import_parser_state *state = parser_get_state(ctx, struct unit_import_parser_state); @@ -56,12 +57,6 @@ static struct token_parse_result parse_linefeed( return PARSE_RESULT(IVY_OK, 0); } -static enum ivy_status add_child( - struct ivy_ast_node *parent, struct ivy_ast_node *child) -{ - return IVY_ERR_NOT_SUPPORTED; -} - static void print(struct ivy_ast_node *node) { struct ivy_ast_unit_import_node *unit_import @@ -93,7 +88,6 @@ static void init_state(struct ivy_parser *ctx, struct parser_state *sp) } struct ast_node_type unit_import_node_ops = { - .n_add_child = add_child, .n_print = print, .n_init_state = init_state, .n_state_size = sizeof(struct unit_import_parser_state), diff --git a/lang/ast/unit-package.c b/lang/ast/unit-package.c index 9fb1873..1071aa7 100644 --- a/lang/ast/unit-package.c +++ b/lang/ast/unit-package.c @@ -57,12 +57,6 @@ static struct token_parse_result parse_linefeed( return PARSE_RESULT(IVY_OK, 0); } -static enum ivy_status add_child( - struct ivy_ast_node *parent, struct ivy_ast_node *child) -{ - return IVY_ERR_NOT_SUPPORTED; -} - static void print(struct ivy_ast_node *node) { struct ivy_ast_unit_package_node *unit_package @@ -94,7 +88,6 @@ static void init_state(struct ivy_parser *ctx, struct parser_state *sp) } struct ast_node_type unit_package_node_ops = { - .n_add_child = add_child, .n_print = print, .n_init_state = init_state, .n_state_size = sizeof(struct unit_package_parser_state), @@ -107,4 +100,4 @@ struct ast_node_type unit_package_node_ops = { TOK_PARSER(LINEFEED, parse_linefeed), } -}; \ No newline at end of file +}; diff --git a/lang/ast/unit.c b/lang/ast/unit.c index 6f50891..8895c9d 100644 --- a/lang/ast/unit.c +++ b/lang/ast/unit.c @@ -33,9 +33,9 @@ static struct token_parse_result parse_expr_begin( } static enum ivy_status add_child( - struct ivy_ast_node *parent, struct ivy_ast_node *child) + struct parser_state *parent, struct ivy_ast_node *child) { - struct ivy_ast_unit_node *unit = (struct ivy_ast_unit_node *)parent; + struct ivy_ast_unit_node *unit = (struct ivy_ast_unit_node *)parent->s_node; b_queue_push_back(&unit->n_children, &child->n_entry); return IVY_OK; }