diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index c98a80d9f..0247f01d4 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -88,7 +88,7 @@ static bool analyze_erb_content(const AST_NODE_T* node, void* data) { erb_content_node->base.location.start, erb_content_node->base.location.end, allocator, - erb_content_node->base.errors + &erb_content_node->base.errors ); } @@ -97,7 +97,7 @@ static bool analyze_erb_content(const AST_NODE_T* node, void* data) { erb_content_node->base.location.start, erb_content_node->base.location.end, allocator, - erb_content_node->base.errors + &erb_content_node->base.errors ); } } else { diff --git a/src/analyze/conditional_elements.c b/src/analyze/conditional_elements.c index db5d90577..1a7af8452 100644 --- a/src/analyze/conditional_elements.c +++ b/src/analyze/conditional_elements.c @@ -13,7 +13,7 @@ #include typedef struct { - hb_array_T* document_errors; + hb_array_T** document_errors; hb_allocator_T* allocator; } conditional_elements_context_T; @@ -182,9 +182,8 @@ typedef struct { bool is_if; } conditional_open_tag_T; -static void rewrite_conditional_elements(hb_array_T* nodes, hb_array_T* document_errors, hb_allocator_T* allocator) { +static void rewrite_conditional_elements(hb_array_T* nodes, hb_array_T** document_errors, hb_allocator_T* allocator) { if (!nodes || hb_array_size(nodes) == 0) { return; } - if (!document_errors) { return; } for (size_t open_index = 0; open_index < hb_array_size(nodes); open_index++) { AST_NODE_T* open_node = (AST_NODE_T*) hb_array_get(nodes, open_index); @@ -235,7 +234,7 @@ static void rewrite_conditional_elements(hb_array_T* nodes, hb_array_T* document allocator ); - hb_array_append(document_errors, multiple_tags_error); + hb_array_append_lazy(document_errors, multiple_tags_error, allocator); break; } } @@ -339,7 +338,7 @@ static void rewrite_conditional_elements(hb_array_T* nodes, hb_array_T* document allocator ); - hb_array_append(document_errors, mismatch_error); + hb_array_append_lazy(document_errors, mismatch_error, allocator); continue; } @@ -355,7 +354,7 @@ static void rewrite_conditional_elements(hb_array_T* nodes, hb_array_T* document position_T start_position = matched_open->open_conditional->location.start; position_T end_position = node->location.end; - hb_array_T* errors = hb_array_init(0, allocator); + hb_array_T* errors = NULL; AST_HTML_CONDITIONAL_ELEMENT_NODE_T* conditional_element = ast_html_conditional_element_node_init( matched_open->condition, @@ -589,6 +588,6 @@ static bool transform_conditional_elements_visitor(const AST_NODE_T* node, void* } void herb_transform_conditional_elements(AST_DOCUMENT_NODE_T* document, hb_allocator_T* allocator) { - conditional_elements_context_T context = { .document_errors = document->base.errors, .allocator = allocator }; + conditional_elements_context_T context = { .document_errors = &document->base.errors, .allocator = allocator }; herb_visit_node((AST_NODE_T*) document, transform_conditional_elements_visitor, &context); } diff --git a/src/analyze/conditional_open_tags.c b/src/analyze/conditional_open_tags.c index 8b5264593..a15df0710 100644 --- a/src/analyze/conditional_open_tags.c +++ b/src/analyze/conditional_open_tags.c @@ -265,9 +265,7 @@ static void add_multiple_tags_error_to_erb_node( allocator ); - if (!erb_node->errors) { erb_node->errors = hb_array_init(0, allocator); } - - hb_array_append(erb_node->errors, error); + hb_array_append_lazy(&erb_node->errors, error, allocator); } static void check_and_report_multiple_tags_in_if(AST_ERB_IF_NODE_T* if_node, hb_allocator_T* allocator) { diff --git a/src/analyze/invalid_structures.c b/src/analyze/invalid_structures.c index 0a765f62a..34c8d4515 100644 --- a/src/analyze/invalid_structures.c +++ b/src/analyze/invalid_structures.c @@ -89,7 +89,7 @@ bool detect_invalid_erb_structures(const AST_NODE_T* node, void* data) { node->location.start, node->location.end, context->allocator, - node->errors + &((AST_NODE_T*) node)->errors ); } } @@ -124,7 +124,7 @@ bool detect_invalid_erb_structures(const AST_NODE_T* node, void* data) { subsequent->location.start, subsequent->location.end, context->allocator, - subsequent->errors + &((AST_NODE_T*) subsequent)->errors ); } } diff --git a/src/analyze/parse_errors.c b/src/analyze/parse_errors.c index 040a63b5e..f73bdad56 100644 --- a/src/analyze/parse_errors.c +++ b/src/analyze/parse_errors.c @@ -36,7 +36,7 @@ static void parse_erb_content_errors(AST_NODE_T* erb_node, const char* source, h allocator ); - hb_array_append(erb_node->errors, parse_error); + hb_array_append_lazy(&erb_node->errors, parse_error, allocator); } pm_node_destroy(&parser, root); @@ -74,7 +74,7 @@ void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source RUBY_PARSE_ERROR_T* parse_error = ruby_parse_error_from_prism_error(error, (AST_NODE_T*) document, source, &parser, allocator); - hb_array_append(document->base.errors, parse_error); + hb_array_append_lazy(&document->base.errors, parse_error, allocator); } pm_node_destroy(&parser, root); diff --git a/src/analyze/render_nodes.c b/src/analyze/render_nodes.c index 3e9977e8c..f0b5dce62 100644 --- a/src/analyze/render_nodes.c +++ b/src/analyze/render_nodes.c @@ -465,7 +465,7 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call( if (!locals) { locals = hb_array_init(0, allocator); } - hb_array_T* errors = hb_array_init(0, allocator); + hb_array_T* errors = NULL; if (!has_keyword_partial && partial && keyword_hash) { keyword_result_T locals_keyword = find_keyword_value(keyword_hash, "locals", allocator); @@ -478,7 +478,7 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call( erb_node->base.location.start, erb_node->base.location.end, allocator, - errors + &errors ); hb_allocator_dealloc(allocator, locals_keyword.value); @@ -551,7 +551,7 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call( erb_node->base.location.start, erb_node->base.location.end, allocator, - errors + &errors ); hb_allocator_dealloc(allocator, keywords_buffer); @@ -560,7 +560,7 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call( if (!partial && !template_path && !layout && !file && !inline_template && !body && !plain && !html && !renderable && !has_positional_partial && !object) { - append_render_no_arguments_error(erb_node->base.location.start, erb_node->base.location.end, allocator, errors); + append_render_no_arguments_error(erb_node->base.location.start, erb_node->base.location.end, allocator, &errors); } if (has_positional_partial && has_keyword_partial && keyword_hash) { @@ -572,7 +572,7 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call( erb_node->base.location.start, erb_node->base.location.end, allocator, - errors + &errors ); if (keyword_partial.value) { hb_allocator_dealloc(allocator, keyword_partial.value); } @@ -600,7 +600,7 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call( erb_node->base.location.start, erb_node->base.location.end, allocator, - errors + &errors ); } } @@ -610,7 +610,7 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call( erb_node->base.location.start, erb_node->base.location.end, allocator, - errors + &errors ); } @@ -620,7 +620,7 @@ static AST_ERB_RENDER_NODE_T* create_render_node_from_call( erb_node->base.location.start, erb_node->base.location.end, allocator, - errors + &errors ); } diff --git a/src/analyze/strict_locals.c b/src/analyze/strict_locals.c index 7969c848e..9d7a637e0 100644 --- a/src/analyze/strict_locals.c +++ b/src/analyze/strict_locals.c @@ -194,7 +194,7 @@ static hb_array_T* extract_strict_locals( ); hb_array_T* node_errors = hb_array_init(1, allocator); - append_strict_locals_positional_argument_error(hb_string_from_c_string(name), start, end, allocator, node_errors); + append_strict_locals_positional_argument_error(hb_string_from_c_string(name), start, end, allocator, &node_errors); AST_RUBY_STRICT_LOCAL_NODE_T* local = ast_ruby_strict_local_node_init(name_token, value_node, false, false, start, value_end, node_errors, allocator); @@ -229,7 +229,7 @@ static hb_array_T* extract_strict_locals( position_T end = name_token ? name_token->location.end : start; hb_array_T* node_errors = hb_array_init(1, allocator); - append_strict_locals_positional_argument_error(hb_string_from_c_string(name), start, end, allocator, node_errors); + append_strict_locals_positional_argument_error(hb_string_from_c_string(name), start, end, allocator, &node_errors); AST_RUBY_STRICT_LOCAL_NODE_T* local = ast_ruby_strict_local_node_init(name_token, NULL, true, false, start, end, node_errors, allocator); @@ -262,7 +262,7 @@ static hb_array_T* extract_strict_locals( position_T end = name_token ? name_token->location.end : start; hb_array_T* node_errors = hb_array_init(1, allocator); - append_strict_locals_block_argument_error(hb_string_from_c_string(name), start, end, allocator, node_errors); + append_strict_locals_block_argument_error(hb_string_from_c_string(name), start, end, allocator, &node_errors); AST_RUBY_STRICT_LOCAL_NODE_T* local = ast_ruby_strict_local_node_init(name_token, NULL, false, false, start, end, node_errors, allocator); @@ -296,7 +296,7 @@ static hb_array_T* extract_strict_locals( position_T end = name_token ? name_token->location.end : start; hb_array_T* node_errors = hb_array_init(1, allocator); - append_strict_locals_splat_argument_error(hb_string_from_c_string(name), start, end, allocator, node_errors); + append_strict_locals_splat_argument_error(hb_string_from_c_string(name), start, end, allocator, &node_errors); AST_RUBY_STRICT_LOCAL_NODE_T* local = ast_ruby_strict_local_node_init(name_token, NULL, false, false, start, end, node_errors, allocator); @@ -486,7 +486,7 @@ static AST_ERB_STRICT_LOCALS_NODE_T* create_strict_locals_node( error_start, error_end, allocator, - errors + &errors ); hb_allocator_dealloc(allocator, rest); @@ -609,7 +609,7 @@ static void transform_strict_locals_in_array(hb_array_T* array, analyze_ruby_con strict_locals_node->base.location.start, strict_locals_node->base.location.end, context->allocator, - strict_locals_node->base.errors + &strict_locals_node->base.errors ); } diff --git a/src/ast_node.c b/src/ast_node.c index 410810857..6a123e220 100644 --- a/src/ast_node.c +++ b/src/ast_node.c @@ -29,8 +29,10 @@ void ast_node_init( node->location.start = start; node->location.end = end; + (void) allocator; + if (errors == NULL) { - node->errors = hb_array_init(0, allocator); + node->errors = NULL; } else { node->errors = errors; } diff --git a/src/include/parser_helpers.h b/src/include/parser_helpers.h index 2d721cd29..7a7517536 100644 --- a/src/include/parser_helpers.h +++ b/src/include/parser_helpers.h @@ -15,7 +15,7 @@ token_T* parser_pop_open_tag(const parser_T* parser); void parser_append_unexpected_error_impl( parser_T* parser, - hb_array_T* errors, + hb_array_T** errors, const char* description, token_type_T first_token, ... @@ -25,11 +25,11 @@ void parser_append_unexpected_error_impl( void parser_append_unexpected_error_string( parser_T* parser, - hb_array_T* errors, + hb_array_T** errors, const char* description, const char* expected ); -void parser_append_unexpected_token_error(parser_T* parser, token_type_T expected_type, hb_array_T* errors); +void parser_append_unexpected_token_error(parser_T* parser, token_type_T expected_type, hb_array_T** errors); void parser_append_literal_node_from_buffer( const parser_T* parser, @@ -51,21 +51,21 @@ bool parser_is_expected_closing_tag_name(hb_string_T tag_name, foreign_content_t token_T* parser_advance(parser_T* parser); token_T* parser_consume_if_present(parser_T* parser, token_type_T type); -token_T* parser_consume_expected(parser_T* parser, token_type_T type, hb_array_T* array); +token_T* parser_consume_expected(parser_T* parser, token_type_T type, hb_array_T** array); AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag( parser_T* parser, AST_HTML_OPEN_TAG_NODE_T* open_tag, hb_array_T* body, - hb_array_T* errors + hb_array_T** errors ); void parser_handle_mismatched_tags( const parser_T* parser, const AST_HTML_CLOSE_TAG_NODE_T* close_tag, - hb_array_T* errors + hb_array_T** errors ); -void parser_synchronize(parser_T* parser, hb_array_T* errors); +void parser_synchronize(parser_T* parser, hb_array_T** errors); bool parser_can_close_ancestor(const parser_T* parser, hb_string_T tag_name); size_t parser_find_ancestor_depth(const parser_T* parser, hb_string_T tag_name); diff --git a/src/include/util/hb_array.h b/src/include/util/hb_array.h index bca066c97..f173d1241 100644 --- a/src/include/util/hb_array.h +++ b/src/include/util/hb_array.h @@ -20,6 +20,7 @@ void* hb_array_first(hb_array_T* array); void* hb_array_last(hb_array_T* array); bool hb_array_append(hb_array_T* array, void* item); +bool hb_array_append_lazy(hb_array_T** array, void* item, struct hb_allocator* allocator); void hb_array_set(const hb_array_T* array, size_t index, void* item); void hb_array_free(hb_array_T** array); void hb_array_remove(hb_array_T* array, size_t index); diff --git a/src/parser.c b/src/parser.c index c6dff3b8a..a34283fe4 100644 --- a/src/parser.c +++ b/src/parser.c @@ -22,8 +22,8 @@ #define MAX_CONSECUTIVE_ERRORS 10 -static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T* errors); -static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_array_T* errors); +static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T** errors); +static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_array_T** errors); static AST_ERB_CONTENT_NODE_T* parser_parse_erb_tag(parser_T* parser); static void parser_handle_whitespace(parser_T* parser, token_T* whitespace_token, hb_array_T* children); static void parser_consume_whitespace(parser_T* parser, hb_array_T* children); @@ -60,12 +60,12 @@ void herb_parser_init(parser_T* parser, lexer_T* lexer, parser_options_T options } static AST_CDATA_NODE_T* parser_parse_cdata(parser_T* parser) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; hb_array_T* children = hb_array_init(8, parser->allocator); hb_buffer_T content; hb_buffer_init(&content, 128, parser->allocator); - token_T* tag_opening = parser_consume_expected(parser, TOKEN_CDATA_START, errors); + token_T* tag_opening = parser_consume_expected(parser, TOKEN_CDATA_START, &errors); position_T start = parser->current_token->location.start; while (token_is_none_of(parser, TOKEN_CDATA_END, TOKEN_EOF)) { @@ -83,7 +83,7 @@ static AST_CDATA_NODE_T* parser_parse_cdata(parser_T* parser) { } parser_append_literal_node_from_buffer(parser, &content, children, start); - token_T* tag_closing = parser_consume_expected(parser, TOKEN_CDATA_END, errors); + token_T* tag_closing = parser_consume_expected(parser, TOKEN_CDATA_END, &errors); AST_CDATA_NODE_T* cdata = ast_cdata_node_init( tag_opening, @@ -103,9 +103,9 @@ static AST_CDATA_NODE_T* parser_parse_cdata(parser_T* parser) { } static AST_HTML_COMMENT_NODE_T* parser_parse_html_comment(parser_T* parser) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; hb_array_T* children = hb_array_init(8, parser->allocator); - token_T* comment_start = parser_consume_expected(parser, TOKEN_HTML_COMMENT_START, errors); + token_T* comment_start = parser_consume_expected(parser, TOKEN_HTML_COMMENT_START, &errors); position_T start = parser->current_token->location.start; hb_buffer_T comment; @@ -139,10 +139,10 @@ static AST_HTML_COMMENT_NODE_T* parser_parse_html_comment(parser_T* parser) { comment_end->location.start, comment_end->location.end, parser->allocator, - errors + &errors ); } else { - comment_end = parser_consume_expected(parser, TOKEN_HTML_COMMENT_END, errors); + comment_end = parser_consume_expected(parser, TOKEN_HTML_COMMENT_END, &errors); } AST_HTML_COMMENT_NODE_T* comment_node = ast_html_comment_node_init( @@ -163,12 +163,12 @@ static AST_HTML_COMMENT_NODE_T* parser_parse_html_comment(parser_T* parser) { } static AST_HTML_DOCTYPE_NODE_T* parser_parse_html_doctype(parser_T* parser) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; hb_array_T* children = hb_array_init(8, parser->allocator); hb_buffer_T content; hb_buffer_init(&content, 64, parser->allocator); - token_T* tag_opening = parser_consume_expected(parser, TOKEN_HTML_DOCTYPE, errors); + token_T* tag_opening = parser_consume_expected(parser, TOKEN_HTML_DOCTYPE, &errors); position_T start = parser->current_token->location.start; @@ -182,14 +182,14 @@ static AST_HTML_DOCTYPE_NODE_T* parser_parse_html_doctype(parser_T* parser) { continue; } - token_T* token = parser_consume_expected(parser, parser->current_token->type, errors); + token_T* token = parser_consume_expected(parser, parser->current_token->type, &errors); hb_buffer_append_string(&content, token->value); token_free(token, parser->allocator); } parser_append_literal_node_from_buffer(parser, &content, children, start); - token_T* tag_closing = parser_consume_expected(parser, TOKEN_HTML_TAG_END, errors); + token_T* tag_closing = parser_consume_expected(parser, TOKEN_HTML_TAG_END, &errors); AST_HTML_DOCTYPE_NODE_T* doctype = ast_html_doctype_node_init( tag_opening, @@ -209,12 +209,12 @@ static AST_HTML_DOCTYPE_NODE_T* parser_parse_html_doctype(parser_T* parser) { } static AST_XML_DECLARATION_NODE_T* parser_parse_xml_declaration(parser_T* parser) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; hb_array_T* children = hb_array_init(8, parser->allocator); hb_buffer_T content; hb_buffer_init(&content, 64, parser->allocator); - token_T* tag_opening = parser_consume_expected(parser, TOKEN_XML_DECLARATION, errors); + token_T* tag_opening = parser_consume_expected(parser, TOKEN_XML_DECLARATION, &errors); position_T start = parser->current_token->location.start; @@ -237,7 +237,7 @@ static AST_XML_DECLARATION_NODE_T* parser_parse_xml_declaration(parser_T* parser parser_append_literal_node_from_buffer(parser, &content, children, start); - token_T* tag_closing = parser_consume_expected(parser, TOKEN_XML_DECLARATION_END, errors); + token_T* tag_closing = parser_consume_expected(parser, TOKEN_XML_DECLARATION_END, &errors); AST_XML_DECLARATION_NODE_T* xml_declaration = ast_xml_declaration_node_init( tag_opening, @@ -256,7 +256,7 @@ static AST_XML_DECLARATION_NODE_T* parser_parse_xml_declaration(parser_T* parser return xml_declaration; } -static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_array_T* document_errors) { +static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_array_T** document_errors) { position_T start = parser->current_token->location.start; hb_buffer_T content; @@ -309,7 +309,7 @@ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_arra token_free(token, parser->allocator); } - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; AST_HTML_TEXT_NODE_T* text_node = NULL; @@ -328,7 +328,7 @@ static AST_HTML_TEXT_NODE_T* parser_parse_text_content(parser_T* parser, hb_arra } static AST_HTML_ATTRIBUTE_NAME_NODE_T* parser_parse_html_attribute_name(parser_T* parser) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; hb_array_T* children = hb_array_init(8, parser->allocator); hb_buffer_T buffer; hb_buffer_init(&buffer, 128, parser->allocator); @@ -395,7 +395,7 @@ static AST_HTML_ATTRIBUTE_NAME_NODE_T* parser_parse_html_attribute_name(parser_T static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value( parser_T* parser, hb_array_T* children, - hb_array_T* errors + hb_array_T** errors ) { hb_buffer_T buffer; hb_buffer_init(&buffer, 512, parser->allocator); @@ -456,7 +456,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value true, opening_quote->location.start, parser->current_token->location.start, - errors, + *errors, parser->allocator ); @@ -501,7 +501,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value true, opening_quote->location.start, parser->current_token->location.start, - errors, + *errors, parser->allocator ); @@ -594,7 +594,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value true, opening_quote->location.start, closing_quote->location.end, - errors, + *errors, parser->allocator ); @@ -606,7 +606,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser_T* parser) { hb_array_T* children = hb_array_init(8, parser->allocator); - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; //
> if (token_is(parser, TOKEN_ERB_START)) { @@ -627,7 +627,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser //
if (token_is(parser, TOKEN_IDENTIFIER)) { - token_T* identifier = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors); + token_T* identifier = parser_consume_expected(parser, TOKEN_IDENTIFIER, &errors); AST_LITERAL_NODE_T* literal = ast_literal_node_init_from_token(identifier, parser->allocator); token_free(identifier, parser->allocator); @@ -646,7 +646,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser } //
- if (token_is(parser, TOKEN_QUOTE)) { return parser_parse_quoted_html_attribute_value(parser, children, errors); } + if (token_is(parser, TOKEN_QUOTE)) { return parser_parse_quoted_html_attribute_value(parser, children, &errors); } if (token_is(parser, TOKEN_BACKTICK)) { token_T* token = parser_advance(parser); @@ -660,7 +660,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser start, end, parser->allocator, - errors + &errors ); AST_HTML_ATTRIBUTE_VALUE_NODE_T* value = @@ -680,7 +680,7 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser parser->current_token->location.start, parser->current_token->location.end, parser->allocator, - errors + &errors ); hb_allocator_dealloc(parser->allocator, expected); @@ -808,7 +808,7 @@ static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute(parser_T* parser) //
if (token_is(parser, TOKEN_HTML_TAG_END) || token_is(parser, TOKEN_HTML_TAG_SELF_CLOSE)) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; hb_string_T attribute_name_string = hb_string("unknown"); if (hb_array_size(attribute_name->children) > 0) { @@ -822,7 +822,7 @@ static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute(parser_T* parser) equals->location.start, parser->current_token->location.start, parser->allocator, - errors + &errors ); AST_HTML_ATTRIBUTE_VALUE_NODE_T* empty_value = ast_html_attribute_value_node_init( @@ -1000,11 +1000,11 @@ static void parser_handle_whitespace_in_open_tag(parser_T* parser, hb_array_T* c } static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; hb_array_T* children = hb_array_init(8, parser->allocator); - token_T* tag_start = parser_consume_expected(parser, TOKEN_HTML_TAG_START, errors); - token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors); + token_T* tag_start = parser_consume_expected(parser, TOKEN_HTML_TAG_START, &errors); + token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, &errors); while (token_is_none_of(parser, TOKEN_HTML_TAG_END, TOKEN_HTML_TAG_SELF_CLOSE, TOKEN_EOF)) { if (token_is_any_of(parser, TOKEN_HTML_TAG_START, TOKEN_HTML_TAG_START_CLOSE)) { @@ -1013,7 +1013,7 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) { tag_name->location.start, parser->current_token->location.start, parser->allocator, - errors + &errors ); AST_HTML_OPEN_TAG_NODE_T* open_tag_node = ast_html_open_tag_node_init( @@ -1077,7 +1077,7 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) { position_T stray_end = peek_token->location.end; token_free(peek_token, parser->allocator); - append_stray_erb_closing_tag_error(stray_start, stray_end, parser->allocator, errors); + append_stray_erb_closing_tag_error(stray_start, stray_end, parser->allocator, &errors); token_T* percent = parser_advance(parser); token_T* gt = parser_advance(parser); @@ -1097,7 +1097,7 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) { parser_append_unexpected_error( parser, - errors, + &errors, "Unexpected Token", TOKEN_IDENTIFIER, TOKEN_AT, @@ -1113,7 +1113,7 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) { tag_name->location.start, parser->current_token->location.start, parser->allocator, - errors + &errors ); AST_HTML_OPEN_TAG_NODE_T* open_tag_node = ast_html_open_tag_node_init( @@ -1139,7 +1139,7 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) { token_T* tag_end = parser_consume_if_present(parser, TOKEN_HTML_TAG_END); if (tag_end == NULL) { - tag_end = parser_consume_expected(parser, TOKEN_HTML_TAG_SELF_CLOSE, errors); + tag_end = parser_consume_expected(parser, TOKEN_HTML_TAG_SELF_CLOSE, &errors); if (tag_end == NULL) { token_free(tag_start, parser->allocator); @@ -1174,14 +1174,14 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) { } static AST_HTML_CLOSE_TAG_NODE_T* parser_parse_html_close_tag(parser_T* parser) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; hb_array_T* children = hb_array_init(8, parser->allocator); - token_T* tag_opening = parser_consume_expected(parser, TOKEN_HTML_TAG_START_CLOSE, errors); + token_T* tag_opening = parser_consume_expected(parser, TOKEN_HTML_TAG_START_CLOSE, &errors); parser_consume_whitespace(parser, children); - token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors); + token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, &errors); parser_consume_whitespace(parser, children); @@ -1193,7 +1193,7 @@ static AST_HTML_CLOSE_TAG_NODE_T* parser_parse_html_close_tag(parser_T* parser) tag_opening->location.start, tag_name->location.end, parser->allocator, - errors + &errors ); } @@ -1209,7 +1209,7 @@ static AST_HTML_CLOSE_TAG_NODE_T* parser_parse_html_close_tag(parser_T* parser) tag_opening->location.start, tag_closing->location.end, parser->allocator, - errors + &errors ); hb_allocator_dealloc(parser->allocator, expected.data); @@ -1259,7 +1259,7 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_regular_element( parser_T* parser, AST_HTML_OPEN_TAG_NODE_T* open_tag ) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; hb_array_T* body = hb_array_init(8, parser->allocator); parser_push_open_tag(parser, open_tag->tag_name); @@ -1267,20 +1267,20 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_regular_element( if (!hb_string_is_empty(open_tag->tag_name->value) && parser_is_foreign_content_tag(open_tag->tag_name->value)) { foreign_content_type_T content_type = parser_get_foreign_content_type(open_tag->tag_name->value); parser_enter_foreign_content(parser, content_type); - parser_parse_foreign_content(parser, body, errors); + parser_parse_foreign_content(parser, body, &errors); } else { - parser_parse_in_data_state(parser, body, errors); + parser_parse_in_data_state(parser, body, &errors); } if (!token_is(parser, TOKEN_HTML_TAG_START_CLOSE)) { - return parser_handle_missing_close_tag(parser, open_tag, body, errors); + return parser_handle_missing_close_tag(parser, open_tag, body, &errors); } AST_HTML_CLOSE_TAG_NODE_T* close_tag = parser_parse_html_close_tag(parser); if (parser_in_svg_context(parser) == false && is_void_element(close_tag->tag_name->value)) { hb_array_push(body, close_tag); - parser_parse_in_data_state(parser, body, errors); + parser_parse_in_data_state(parser, body, &errors); close_tag = parser_parse_html_close_tag(parser); } @@ -1301,7 +1301,7 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_regular_element( unclosed->location.start, unclosed->location.end, parser->allocator, - errors + &errors ); token_free(unclosed, parser->allocator); } @@ -1310,7 +1310,7 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_regular_element( token_T* popped_token = parser_pop_open_tag(parser); token_free(popped_token, parser->allocator); } else { - parser_handle_mismatched_tags(parser, close_tag, errors); + parser_handle_mismatched_tags(parser, close_tag, &errors); } return ast_html_element_node_init( @@ -1350,16 +1350,16 @@ static AST_NODE_T* parser_parse_html_element(parser_T* parser) { } static AST_ERB_CONTENT_NODE_T* parser_parse_erb_tag(parser_T* parser) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; - token_T* opening_tag = parser_consume_expected(parser, TOKEN_ERB_START, errors); - token_T* content = parser_consume_expected(parser, TOKEN_ERB_CONTENT, errors); + token_T* opening_tag = parser_consume_expected(parser, TOKEN_ERB_START, &errors); + token_T* content = parser_consume_expected(parser, TOKEN_ERB_CONTENT, &errors); token_T* closing_tag = NULL; position_T end_position; if (token_is(parser, TOKEN_ERB_END)) { - closing_tag = parser_consume_expected(parser, TOKEN_ERB_END, errors); + closing_tag = parser_consume_expected(parser, TOKEN_ERB_END, &errors); end_position = closing_tag->location.end; } else if (token_is(parser, TOKEN_ERB_START)) { append_nested_erb_tag_error( @@ -1369,7 +1369,7 @@ static AST_ERB_CONTENT_NODE_T* parser_parse_erb_tag(parser_T* parser) { parser->current_token->location.start, parser->current_token->location.end, parser->allocator, - errors + &errors ); end_position = parser->current_token->location.start; } else { @@ -1378,7 +1378,7 @@ static AST_ERB_CONTENT_NODE_T* parser_parse_erb_tag(parser_T* parser) { opening_tag->location.start, parser->current_token->location.start, parser->allocator, - errors + &errors ); end_position = parser->current_token->location.start; } @@ -1404,7 +1404,7 @@ static AST_ERB_CONTENT_NODE_T* parser_parse_erb_tag(parser_T* parser) { return erb_node; } -static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_array_T* errors) { +static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_array_T** errors) { hb_buffer_T content; hb_buffer_init(&content, 1024, parser->allocator); position_T start = parser->current_token->location.start; @@ -1463,7 +1463,7 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children, hb_buffer_free(&content); } -static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T* errors) { +static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T** errors) { while (token_is_not(parser, TOKEN_EOF)) { if (token_is(parser, TOKEN_ERB_START)) { @@ -1657,7 +1657,7 @@ static hb_array_T* parser_build_elements_from_tags( if (last_body_node != NULL) { end_position = last_body_node->location.end; } } - hb_array_T* element_errors = hb_array_init(8, allocator); + hb_array_T* element_errors = NULL; if (strict) { append_omitted_closing_tag_error( @@ -1666,17 +1666,12 @@ static hb_array_T* parser_build_elements_from_tags( open_tag->base.location.start, open_tag->base.location.end, allocator, - element_errors + &element_errors ); } - AST_HTML_OMITTED_CLOSE_TAG_NODE_T* omitted_close_tag = ast_html_omitted_close_tag_node_init( - open_tag->tag_name, - end_position, - end_position, - hb_array_init(8, allocator), - allocator - ); + AST_HTML_OMITTED_CLOSE_TAG_NODE_T* omitted_close_tag = + ast_html_omitted_close_tag_node_init(open_tag->tag_name, end_position, end_position, NULL, allocator); AST_HTML_ELEMENT_NODE_T* element = ast_html_element_node_init( (AST_NODE_T*) open_tag, @@ -1701,7 +1696,7 @@ static hb_array_T* parser_build_elements_from_tags( open_tag->base.location.start, open_tag->base.location.end, allocator, - open_tag->base.errors + &open_tag->base.errors ); } @@ -1719,7 +1714,7 @@ static hb_array_T* parser_build_elements_from_tags( hb_array_T* processed_body = parser_build_elements_from_tags(body, errors, options, allocator); hb_array_free(&body); - hb_array_T* element_errors = hb_array_init(8, allocator); + hb_array_T* element_errors = NULL; AST_HTML_ELEMENT_NODE_T* element = ast_html_element_node_init( (AST_NODE_T*) open_tag, @@ -1748,7 +1743,7 @@ static hb_array_T* parser_build_elements_from_tags( close_tag->base.location.start, close_tag->base.location.end, allocator, - close_tag->base.errors + &close_tag->base.errors ); } } @@ -1764,12 +1759,12 @@ static hb_array_T* parser_build_elements_from_tags( static AST_DOCUMENT_NODE_T* parser_parse_document(parser_T* parser) { hb_array_T* children = hb_array_init(8, parser->allocator); - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; position_T start = parser->current_token->location.start; - parser_parse_in_data_state(parser, children, errors); + parser_parse_in_data_state(parser, children, &errors); - token_T* eof = parser_consume_expected(parser, TOKEN_EOF, errors); + token_T* eof = parser_consume_expected(parser, TOKEN_EOF, &errors); AST_DOCUMENT_NODE_T* document_node = ast_document_node_init(children, NULL, HERB_PRISM_NODE_EMPTY, start, eof->location.end, errors, parser->allocator); @@ -1785,7 +1780,7 @@ AST_DOCUMENT_NODE_T* herb_parser_parse(parser_T* parser) { static void parser_handle_whitespace(parser_T* parser, token_T* whitespace_token, hb_array_T* children) { if (parser->options.track_whitespace) { - hb_array_T* errors = hb_array_init(8, parser->allocator); + hb_array_T* errors = NULL; AST_WHITESPACE_NODE_T* whitespace_node = ast_whitespace_node_init( whitespace_token, whitespace_token->location.start, diff --git a/src/parser_helpers.c b/src/parser_helpers.c index 26b1ba25a..bd904069c 100644 --- a/src/parser_helpers.c +++ b/src/parser_helpers.c @@ -92,7 +92,7 @@ void parser_exit_foreign_content(parser_T* parser) { void parser_append_unexpected_error_impl( parser_T* parser, - hb_array_T* errors, + hb_array_T** errors, const char* description, token_type_T first_token, ... @@ -120,7 +120,7 @@ void parser_append_unexpected_error_impl( void parser_append_unexpected_error_string( parser_T* parser, - hb_array_T* errors, + hb_array_T** errors, const char* description, const char* expected ) { @@ -139,7 +139,7 @@ void parser_append_unexpected_error_string( token_free(token, parser->allocator); } -void parser_append_unexpected_token_error(parser_T* parser, token_type_T expected_type, hb_array_T* errors) { +void parser_append_unexpected_token_error(parser_T* parser, token_type_T expected_type, hb_array_T** errors) { append_unexpected_token_error( expected_type, parser->current_token, @@ -180,7 +180,7 @@ token_T* parser_consume_if_present(parser_T* parser, const token_type_T type) { return parser_advance(parser); } -token_T* parser_consume_expected(parser_T* parser, const token_type_T expected_type, hb_array_T* array) { +token_T* parser_consume_expected(parser_T* parser, const token_type_T expected_type, hb_array_T** array) { token_T* token = parser_consume_if_present(parser, expected_type); if (token == NULL) { @@ -203,7 +203,7 @@ AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag( parser_T* parser, AST_HTML_OPEN_TAG_NODE_T* open_tag, hb_array_T* body, - hb_array_T* errors + hb_array_T** errors ) { append_missing_closing_tag_error( open_tag->tag_name, @@ -222,7 +222,7 @@ AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag( ELEMENT_SOURCE_HTML, open_tag->base.location.start, open_tag->base.location.end, - errors, + *errors, parser->allocator ); } @@ -230,7 +230,7 @@ AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag( void parser_handle_mismatched_tags( const parser_T* parser, const AST_HTML_CLOSE_TAG_NODE_T* close_tag, - hb_array_T* errors + hb_array_T** errors ) { if (hb_array_size(parser->open_tags_stack) > 0) { token_T* expected_tag = hb_array_last(parser->open_tags_stack); @@ -263,7 +263,7 @@ bool parser_is_expected_closing_tag_name(hb_string_T tag_name, foreign_content_t return hb_string_equals_case_insensitive(expected_tag_name, tag_name); } -void parser_synchronize(parser_T* parser, hb_array_T* errors) { +void parser_synchronize(parser_T* parser, hb_array_T** errors) { (void) errors; while (parser->current_token->type != TOKEN_EOF) { diff --git a/src/util/hb_array.c b/src/util/hb_array.c index 2bbeddf6b..c46ffa3b3 100644 --- a/src/util/hb_array.c +++ b/src/util/hb_array.c @@ -116,6 +116,15 @@ void hb_array_remove_item(hb_array_T* array, void* item) { if (index != SIZE_MAX) { hb_array_remove(array, index); } } +bool hb_array_append_lazy(hb_array_T** array, void* item, hb_allocator_T* allocator) { + if (*array == NULL) { + *array = hb_array_init(8, allocator); + if (!*array) { return false; } + } + + return hb_array_append(*array, item); +} + // Alias for hb_array_append bool hb_array_push(hb_array_T* array, void* item) { return hb_array_append(array, item); diff --git a/templates/src/analyze/missing_end.c.erb b/templates/src/analyze/missing_end.c.erb index 51c7d4aa7..9598a0379 100644 --- a/templates/src/analyze/missing_end.c.erb +++ b/templates/src/analyze/missing_end.c.erb @@ -26,7 +26,7 @@ void check_erb_node_for_missing_end(const AST_NODE_T* node, hb_allocator_T* allo <%= node.human %>->tag_opening->location.start, <%= node.human %>->tag_closing->location.end, allocator, - node->errors + &((AST_NODE_T*) node)->errors ); } diff --git a/templates/src/errors.c.erb b/templates/src/errors.c.erb index 9e6514017..1b2fe4158 100644 --- a/templates/src/errors.c.erb +++ b/templates/src/errors.c.erb @@ -90,8 +90,8 @@ void error_init(ERROR_T* error, const error_type_T type, position_T start, posit return <%= error.human %>; } -void append_<%= error.human %>(<%= (arguments + ["hb_array_T* errors"]).join(", ") %>) { - hb_array_append(errors, <%= error.human %>_init(<%= arguments.map { |argument| argument.split(" ").last.strip }.join(", ") %>)); +void append_<%= error.human %>(<%= (arguments + ["hb_array_T** errors"]).join(", ") %>) { + hb_array_append_lazy(errors, <%= error.human %>_init(<%= arguments.map { |argument| argument.split(" ").last.strip }.join(", ") %>), allocator); } <%- end -%> diff --git a/templates/src/include/errors.h.erb b/templates/src/include/errors.h.erb index 5b01db595..5a7c470b4 100644 --- a/templates/src/include/errors.h.erb +++ b/templates/src/include/errors.h.erb @@ -35,7 +35,7 @@ typedef struct { <%- error_arguments = error.fields.any? ? error.fields.map { |field| [field.c_type, " ", field.name].join } : [] -%> <%- arguments = error_arguments + ["position_T start", "position_T end", "hb_allocator_T* allocator"] -%> <%= error.struct_type %>* <%= error.human %>_init(<%= arguments.join(", ") %>); -void append_<%= error.human %>(<%= (arguments << "hb_array_T* errors").join(", ") %>); +void append_<%= error.human %>(<%= (arguments << "hb_array_T** errors").join(", ") %>); <%- end -%> void error_init(ERROR_T* error, error_type_T type, position_T start, position_T end);