diff --git a/lang/ast/ctx.c b/lang/ast/ctx.c index f1c53a0..4b603d2 100644 --- a/lang/ast/ctx.c +++ b/lang/ast/ctx.c @@ -4,6 +4,7 @@ #include "node.h" #include +#include #include #include #include @@ -67,6 +68,13 @@ void ivy_parser_destroy(struct ivy_parser *parser, struct ivy_ast_node **result) free(parser); } +enum ivy_status ivy_parser_set_diag_ctx( + struct ivy_parser *parser, struct ivy_diag_ctx *ctx) +{ + parser->p_diag_ctx = ctx; + return IVY_OK; +} + enum ivy_status ivy_parser_get_status(struct ivy_parser *parser) { return parser->p_status; @@ -266,3 +274,30 @@ struct ivy_ast_node *ivy_parser_dequeue_node(struct ivy_parser *parser) return b_unbox(struct ivy_ast_node, entry, n_entry); } + +struct ivy_diag *parser_push_diag( + struct ivy_parser *parser, unsigned long diag_class, unsigned long msg, + struct ivy_token *tok) +{ + struct ivy_diag *diag + = ivy_diag_ctx_create_diag(parser->p_diag_ctx, diag_class); + + if (msg != 0) { + ivy_diag_push_msg(diag, msg); + } + + if (tok) { + const struct ivy_diag_highlight hl[] = { + IVY_DIAG_HL( + ERROR, tok->t_start.c_row, tok->t_start.c_col, + tok->t_end.c_row, tok->t_end.c_col), + }; + const size_t nr_hl = sizeof hl / sizeof hl[0]; + + ivy_diag_push_snippet( + diag, tok->t_start.c_row, tok->t_end.c_row, NULL, 0, hl, + nr_hl); + }; + + return diag; +} diff --git a/lang/ast/ctx.h b/lang/ast/ctx.h index 9e96379..475563d 100644 --- a/lang/ast/ctx.h +++ b/lang/ast/ctx.h @@ -2,7 +2,9 @@ #define _AST_CTX_H_ #include +#include #include +#include #include #define parser_get_state(parser, state_type) \ @@ -19,6 +21,7 @@ struct parser_state { struct ivy_parser { enum ivy_status p_status; + struct ivy_diag_ctx *p_diag_ctx; b_queue p_state; b_queue p_token_queue; b_queue p_node_queue; @@ -40,4 +43,8 @@ extern void parser_replace_current_node( extern enum ivy_status parser_add_child( struct ivy_parser *parser, struct ivy_ast_node *new_node); +extern struct ivy_diag *parser_push_diag( + struct ivy_parser *parser, unsigned long diag_class, unsigned long msg, + struct ivy_token *tok); + #endif diff --git a/lang/ast/node.c b/lang/ast/node.c index 9b59c61..c25a6dc 100644 --- a/lang/ast/node.c +++ b/lang/ast/node.c @@ -250,6 +250,39 @@ void ivy_ast_node_to_string(struct ivy_ast_node *node, struct b_string *out) } } +void ivy_ast_node_set_bounds_from_token( + struct ivy_ast_node *parent, const struct ivy_token *tok) +{ + parent->n_start = tok->t_start; + parent->n_end = tok->t_end; +} + +void ivy_ast_node_extend_bounds( + struct ivy_ast_node *parent, const struct ivy_ast_node *child) +{ + if (child->n_start.c_row < parent->n_start.c_row) { + parent->n_start = child->n_start; + } else if (child->n_start.c_col < parent->n_start.c_col) { + parent->n_start.c_col = child->n_start.c_col; + } + + if (child->n_end.c_row > parent->n_end.c_row) { + parent->n_end = child->n_end; + } else if (child->n_end.c_col > parent->n_end.c_col) { + parent->n_end.c_col = child->n_end.c_col; + } +} + +void ivy_ast_node_extend_bounds_recursive( + struct ivy_ast_node *parent, const struct ivy_ast_node *child) +{ + while (parent) { + ivy_ast_node_extend_bounds(parent, child); + child = parent; + parent = parent->n_parent; + } +} + void ivy_ast_node_destroy(struct ivy_ast_node *node) { struct ivy_ast_node_iterator it = {}; diff --git a/lang/include/ivy/lang/ast.h b/lang/include/ivy/lang/ast.h index cabe5d5..2cfd8e7 100644 --- a/lang/include/ivy/lang/ast.h +++ b/lang/include/ivy/lang/ast.h @@ -7,6 +7,7 @@ #include #include +struct ivy_diag_ctx; struct ivy_token; struct ivy_parser; struct b_string; @@ -72,6 +73,8 @@ struct ivy_ast_node_iterator_entry { struct ivy_ast_node { enum ivy_ast_node_type n_type; + struct ivy_ast_node *n_parent; + struct ivy_char_cell n_start, n_end; b_queue_entry n_entry; struct ivy_ast_node_iterator_entry n_it; }; @@ -332,6 +335,8 @@ IVY_API enum ivy_status ivy_parser_create(struct ivy_parser **parser); IVY_API void ivy_parser_destroy( struct ivy_parser *parser, struct ivy_ast_node **result); +IVY_API enum ivy_status ivy_parser_set_diag_ctx( + struct ivy_parser *parser, struct ivy_diag_ctx *ctx); IVY_API enum ivy_status ivy_parser_get_status(struct ivy_parser *parser); IVY_API bool ivy_parser_is_node_complete(struct ivy_parser *parser); IVY_API struct ivy_ast_node *ivy_parser_root_node(struct ivy_parser *parser); @@ -345,6 +350,12 @@ IVY_API enum ivy_status ivy_ast_node_iterate( struct ivy_ast_node *node, struct ivy_ast_node_iterator *it, ivy_ast_node_iteration_callback callback, void *arg); IVY_API void ivy_ast_node_to_string(struct ivy_ast_node *node, struct b_string *out); +IVY_API void ivy_ast_node_set_bounds_from_token( + struct ivy_ast_node *parent, const struct ivy_token *tok); +IVY_API void ivy_ast_node_extend_bounds( + struct ivy_ast_node *parent, const struct ivy_ast_node *child); +IVY_API void ivy_ast_node_extend_bounds_recursive( + struct ivy_ast_node *parent, const struct ivy_ast_node *child); IVY_API void ivy_ast_node_destroy(struct ivy_ast_node *node); IVY_API const char *ivy_ast_node_type_to_string(enum ivy_ast_node_type v);