@herb-tools/node 0.8.10 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/binding.gyp +26 -8
  3. package/dist/herb-node.cjs +41 -12
  4. package/dist/herb-node.cjs.map +1 -1
  5. package/dist/herb-node.esm.js +8 -1
  6. package/dist/herb-node.esm.js.map +1 -1
  7. package/dist/types/node-backend.d.ts +3 -1
  8. package/extension/error_helpers.cpp +395 -73
  9. package/extension/error_helpers.h +13 -3
  10. package/extension/extension_helpers.cpp +38 -35
  11. package/extension/extension_helpers.h +2 -2
  12. package/extension/herb.cpp +183 -64
  13. package/extension/libherb/analyze/action_view/attribute_extraction_helpers.c +290 -0
  14. package/extension/libherb/analyze/action_view/attribute_extraction_helpers.h +36 -0
  15. package/extension/libherb/analyze/action_view/content_tag.c +70 -0
  16. package/extension/libherb/analyze/action_view/link_to.c +143 -0
  17. package/extension/libherb/analyze/action_view/registry.c +60 -0
  18. package/extension/libherb/analyze/action_view/tag.c +64 -0
  19. package/extension/libherb/analyze/action_view/tag_helper_handler.h +41 -0
  20. package/extension/libherb/analyze/action_view/tag_helper_node_builders.c +305 -0
  21. package/extension/libherb/analyze/action_view/tag_helper_node_builders.h +70 -0
  22. package/extension/libherb/analyze/action_view/tag_helpers.c +748 -0
  23. package/extension/libherb/analyze/action_view/tag_helpers.h +38 -0
  24. package/extension/libherb/analyze/action_view/turbo_frame_tag.c +88 -0
  25. package/extension/libherb/analyze/analyze.c +882 -0
  26. package/extension/libherb/{include → analyze}/analyze.h +14 -4
  27. package/extension/libherb/{analyzed_ruby.c → analyze/analyzed_ruby.c} +13 -11
  28. package/extension/libherb/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
  29. package/extension/libherb/analyze/builders.c +343 -0
  30. package/extension/libherb/analyze/builders.h +27 -0
  31. package/extension/libherb/analyze/conditional_elements.c +594 -0
  32. package/extension/libherb/analyze/conditional_elements.h +9 -0
  33. package/extension/libherb/analyze/conditional_open_tags.c +640 -0
  34. package/extension/libherb/analyze/conditional_open_tags.h +9 -0
  35. package/extension/libherb/analyze/control_type.c +250 -0
  36. package/extension/libherb/analyze/control_type.h +14 -0
  37. package/extension/libherb/{analyze_helpers.c → analyze/helpers.c} +48 -23
  38. package/extension/libherb/{analyze_helpers.h → analyze/helpers.h} +4 -2
  39. package/extension/libherb/analyze/invalid_structures.c +193 -0
  40. package/extension/libherb/analyze/invalid_structures.h +11 -0
  41. package/extension/libherb/{analyze_missing_end.c → analyze/missing_end.c} +33 -22
  42. package/extension/libherb/analyze/parse_errors.c +84 -0
  43. package/extension/libherb/analyze/prism_annotate.c +397 -0
  44. package/extension/libherb/analyze/prism_annotate.h +16 -0
  45. package/extension/libherb/{analyze_transform.c → analyze/transform.c} +17 -3
  46. package/extension/libherb/ast_node.c +17 -7
  47. package/extension/libherb/ast_node.h +11 -5
  48. package/extension/libherb/ast_nodes.c +663 -388
  49. package/extension/libherb/ast_nodes.h +118 -39
  50. package/extension/libherb/ast_pretty_print.c +191 -7
  51. package/extension/libherb/ast_pretty_print.h +6 -1
  52. package/extension/libherb/element_source.h +3 -8
  53. package/extension/libherb/errors.c +1077 -521
  54. package/extension/libherb/errors.h +149 -56
  55. package/extension/libherb/extract.c +145 -49
  56. package/extension/libherb/extract.h +21 -5
  57. package/extension/libherb/herb.c +52 -34
  58. package/extension/libherb/herb.h +18 -6
  59. package/extension/libherb/herb_prism_node.h +13 -0
  60. package/extension/libherb/html_util.c +241 -12
  61. package/extension/libherb/html_util.h +7 -2
  62. package/extension/libherb/include/analyze/action_view/attribute_extraction_helpers.h +36 -0
  63. package/extension/libherb/include/analyze/action_view/tag_helper_handler.h +41 -0
  64. package/extension/libherb/include/analyze/action_view/tag_helper_node_builders.h +70 -0
  65. package/extension/libherb/include/analyze/action_view/tag_helpers.h +38 -0
  66. package/extension/libherb/{analyze.h → include/analyze/analyze.h} +14 -4
  67. package/extension/libherb/include/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
  68. package/extension/libherb/include/analyze/builders.h +27 -0
  69. package/extension/libherb/include/analyze/conditional_elements.h +9 -0
  70. package/extension/libherb/include/analyze/conditional_open_tags.h +9 -0
  71. package/extension/libherb/include/analyze/control_type.h +14 -0
  72. package/extension/libherb/include/{analyze_helpers.h → analyze/helpers.h} +4 -2
  73. package/extension/libherb/include/analyze/invalid_structures.h +11 -0
  74. package/extension/libherb/include/analyze/prism_annotate.h +16 -0
  75. package/extension/libherb/include/ast_node.h +11 -5
  76. package/extension/libherb/include/ast_nodes.h +118 -39
  77. package/extension/libherb/include/ast_pretty_print.h +6 -1
  78. package/extension/libherb/include/element_source.h +3 -8
  79. package/extension/libherb/include/errors.h +149 -56
  80. package/extension/libherb/include/extract.h +21 -5
  81. package/extension/libherb/include/herb.h +18 -6
  82. package/extension/libherb/include/herb_prism_node.h +13 -0
  83. package/extension/libherb/include/html_util.h +7 -2
  84. package/extension/libherb/include/io.h +3 -1
  85. package/extension/libherb/include/lex_helpers.h +29 -0
  86. package/extension/libherb/include/lexer.h +1 -1
  87. package/extension/libherb/include/lexer_peek_helpers.h +87 -13
  88. package/extension/libherb/include/lexer_struct.h +2 -0
  89. package/extension/libherb/include/location.h +2 -1
  90. package/extension/libherb/include/parser.h +27 -2
  91. package/extension/libherb/include/parser_helpers.h +19 -3
  92. package/extension/libherb/include/pretty_print.h +10 -5
  93. package/extension/libherb/include/prism_context.h +45 -0
  94. package/extension/libherb/include/prism_helpers.h +10 -7
  95. package/extension/libherb/include/prism_serialized.h +12 -0
  96. package/extension/libherb/include/token.h +16 -4
  97. package/extension/libherb/include/token_struct.h +10 -3
  98. package/extension/libherb/include/utf8.h +2 -1
  99. package/extension/libherb/include/util/hb_allocator.h +78 -0
  100. package/extension/libherb/include/util/hb_arena.h +6 -1
  101. package/extension/libherb/include/util/hb_arena_debug.h +12 -1
  102. package/extension/libherb/include/util/hb_array.h +7 -3
  103. package/extension/libherb/include/util/hb_buffer.h +6 -4
  104. package/extension/libherb/include/util/hb_foreach.h +79 -0
  105. package/extension/libherb/include/util/hb_narray.h +8 -4
  106. package/extension/libherb/include/util/hb_string.h +56 -9
  107. package/extension/libherb/include/util.h +6 -3
  108. package/extension/libherb/include/version.h +1 -1
  109. package/extension/libherb/io.c +3 -2
  110. package/extension/libherb/io.h +3 -1
  111. package/extension/libherb/lex_helpers.h +29 -0
  112. package/extension/libherb/lexer.c +42 -30
  113. package/extension/libherb/lexer.h +1 -1
  114. package/extension/libherb/lexer_peek_helpers.c +12 -74
  115. package/extension/libherb/lexer_peek_helpers.h +87 -13
  116. package/extension/libherb/lexer_struct.h +2 -0
  117. package/extension/libherb/location.c +2 -2
  118. package/extension/libherb/location.h +2 -1
  119. package/extension/libherb/main.c +53 -28
  120. package/extension/libherb/parser.c +783 -247
  121. package/extension/libherb/parser.h +27 -2
  122. package/extension/libherb/parser_helpers.c +110 -23
  123. package/extension/libherb/parser_helpers.h +19 -3
  124. package/extension/libherb/parser_match_tags.c +110 -49
  125. package/extension/libherb/pretty_print.c +29 -24
  126. package/extension/libherb/pretty_print.h +10 -5
  127. package/extension/libherb/prism_context.h +45 -0
  128. package/extension/libherb/prism_helpers.c +30 -27
  129. package/extension/libherb/prism_helpers.h +10 -7
  130. package/extension/libherb/prism_serialized.h +12 -0
  131. package/extension/libherb/ruby_parser.c +2 -0
  132. package/extension/libherb/token.c +151 -66
  133. package/extension/libherb/token.h +16 -4
  134. package/extension/libherb/token_matchers.c +0 -1
  135. package/extension/libherb/token_struct.h +10 -3
  136. package/extension/libherb/utf8.c +7 -6
  137. package/extension/libherb/utf8.h +2 -1
  138. package/extension/libherb/util/hb_allocator.c +341 -0
  139. package/extension/libherb/util/hb_allocator.h +78 -0
  140. package/extension/libherb/util/hb_arena.c +81 -56
  141. package/extension/libherb/util/hb_arena.h +6 -1
  142. package/extension/libherb/util/hb_arena_debug.c +32 -17
  143. package/extension/libherb/util/hb_arena_debug.h +12 -1
  144. package/extension/libherb/util/hb_array.c +30 -15
  145. package/extension/libherb/util/hb_array.h +7 -3
  146. package/extension/libherb/util/hb_buffer.c +17 -21
  147. package/extension/libherb/util/hb_buffer.h +6 -4
  148. package/extension/libherb/util/hb_foreach.h +79 -0
  149. package/extension/libherb/util/hb_narray.c +22 -7
  150. package/extension/libherb/util/hb_narray.h +8 -4
  151. package/extension/libherb/util/hb_string.c +49 -35
  152. package/extension/libherb/util/hb_string.h +56 -9
  153. package/extension/libherb/util.c +21 -11
  154. package/extension/libherb/util.h +6 -3
  155. package/extension/libherb/version.h +1 -1
  156. package/extension/libherb/visitor.c +48 -1
  157. package/extension/nodes.cpp +451 -6
  158. package/extension/nodes.h +8 -1
  159. package/package.json +12 -8
  160. package/src/node-backend.ts +11 -1
  161. package/dist/types/index-cjs.d.cts +0 -1
  162. package/extension/libherb/analyze.c +0 -1608
  163. package/extension/libherb/element_source.c +0 -12
  164. package/extension/libherb/include/util/hb_system.h +0 -9
  165. package/extension/libherb/util/hb_system.c +0 -30
  166. package/extension/libherb/util/hb_system.h +0 -9
  167. package/src/index-cjs.cts +0 -22
  168. /package/dist/types/{index-esm.d.mts → index.d.ts} +0 -0
  169. /package/src/{index-esm.mts → index.ts} +0 -0
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "ast_node.h"
5
5
  #include "lexer.h"
6
+ #include "util/hb_allocator.h"
6
7
  #include "util/hb_array.h"
7
8
 
8
9
  typedef enum {
@@ -17,17 +18,32 @@ typedef enum { PARSER_STATE_DATA, PARSER_STATE_FOREIGN_CONTENT } parser_state_T;
17
18
 
18
19
  typedef struct PARSER_OPTIONS_STRUCT {
19
20
  bool track_whitespace;
21
+ bool analyze;
22
+ bool strict;
23
+ bool action_view_helpers;
24
+ bool prism_program;
25
+ bool prism_nodes;
26
+ bool prism_nodes_deep;
20
27
  } parser_options_T;
21
28
 
29
+ typedef struct MATCH_TAGS_CONTEXT_STRUCT {
30
+ hb_array_T* errors;
31
+ const parser_options_T* options;
32
+ hb_allocator_T* allocator;
33
+ } match_tags_context_T;
34
+
22
35
  extern const parser_options_T HERB_DEFAULT_PARSER_OPTIONS;
23
36
 
24
37
  typedef struct PARSER_STRUCT {
38
+ hb_allocator_T* allocator;
25
39
  lexer_T* lexer;
26
40
  token_T* current_token;
27
41
  hb_array_T* open_tags_stack;
28
42
  parser_state_T state;
29
43
  foreign_content_type_T foreign_content_type;
30
44
  parser_options_T options;
45
+ size_t consecutive_error_count;
46
+ bool in_recovery_mode;
31
47
  } parser_T;
32
48
 
33
49
  size_t parser_sizeof(void);
@@ -36,10 +52,19 @@ void herb_parser_init(parser_T* parser, lexer_T* lexer, parser_options_T options
36
52
 
37
53
  AST_DOCUMENT_NODE_T* herb_parser_parse(parser_T* parser);
38
54
 
39
- void herb_parser_match_html_tags_post_analyze(AST_DOCUMENT_NODE_T* document);
55
+ void herb_parser_match_html_tags_post_analyze(
56
+ AST_DOCUMENT_NODE_T* document,
57
+ const parser_options_T* options,
58
+ hb_allocator_T* allocator
59
+ );
40
60
  void herb_parser_deinit(parser_T* parser);
41
61
 
42
- void match_tags_in_node_array(hb_array_T* nodes, hb_array_T* errors);
62
+ void match_tags_in_node_array(
63
+ hb_array_T* nodes,
64
+ hb_array_T* errors,
65
+ const parser_options_T* options,
66
+ hb_allocator_T* allocator
67
+ );
43
68
  bool match_tags_visitor(const AST_NODE_T* node, void* data);
44
69
 
45
70
  #endif
@@ -1,20 +1,18 @@
1
1
  #include "include/parser_helpers.h"
2
- #include "include/ast_node.h"
3
2
  #include "include/ast_nodes.h"
4
3
  #include "include/errors.h"
5
- #include "include/html_util.h"
6
4
  #include "include/lexer.h"
7
5
  #include "include/parser.h"
8
6
  #include "include/token.h"
9
- #include "include/token_matchers.h"
10
7
  #include "include/util/hb_array.h"
11
8
  #include "include/util/hb_buffer.h"
12
9
  #include "include/util/hb_string.h"
13
10
 
11
+ #include <stdarg.h>
14
12
  #include <stdio.h>
15
13
 
16
14
  void parser_push_open_tag(const parser_T* parser, token_T* tag_name) {
17
- token_T* copy = token_copy(tag_name);
15
+ token_T* copy = token_copy(tag_name, parser->allocator);
18
16
  hb_array_push(parser->open_tags_stack, copy);
19
17
  }
20
18
 
@@ -22,9 +20,9 @@ bool parser_check_matching_tag(const parser_T* parser, hb_string_T tag_name) {
22
20
  if (hb_array_size(parser->open_tags_stack) == 0) { return false; }
23
21
 
24
22
  token_T* top_token = hb_array_last(parser->open_tags_stack);
25
- if (top_token == NULL || top_token->value == NULL) { return false; };
23
+ if (top_token == NULL || hb_string_is_empty(top_token->value)) { return false; };
26
24
 
27
- return hb_string_equals_case_insensitive(hb_string(top_token->value), tag_name);
25
+ return hb_string_equals_case_insensitive(top_token->value, tag_name);
28
26
  }
29
27
 
30
28
  token_T* parser_pop_open_tag(const parser_T* parser) {
@@ -47,9 +45,8 @@ bool parser_in_svg_context(const parser_T* parser) {
47
45
  for (size_t i = 0; i < stack_size; i++) {
48
46
  token_T* tag = (token_T*) hb_array_get(parser->open_tags_stack, i);
49
47
 
50
- if (tag && tag->value) {
51
- hb_string_T tag_value_string = hb_string(tag->value);
52
- if (hb_string_equals_case_insensitive(tag_value_string, hb_string("svg"))) { return true; }
48
+ if (tag && !hb_string_is_empty(tag->value)) {
49
+ if (hb_string_equals_case_insensitive(tag->value, hb_string("svg"))) { return true; }
53
50
  }
54
51
  }
55
52
 
@@ -75,7 +72,7 @@ hb_string_T parser_get_foreign_content_closing_tag(foreign_content_type_T type)
75
72
  switch (type) {
76
73
  case FOREIGN_CONTENT_SCRIPT: return hb_string("script");
77
74
  case FOREIGN_CONTENT_STYLE: return hb_string("style");
78
- default: return hb_string("");
75
+ default: return HB_STRING_EMPTY;
79
76
  }
80
77
  }
81
78
 
@@ -93,24 +90,53 @@ void parser_exit_foreign_content(parser_T* parser) {
93
90
  parser->foreign_content_type = FOREIGN_CONTENT_UNKNOWN;
94
91
  }
95
92
 
96
- void parser_append_unexpected_error(
93
+ void parser_append_unexpected_error_impl(
97
94
  parser_T* parser,
95
+ hb_array_T* errors,
98
96
  const char* description,
99
- const char* expected,
100
- hb_array_T* errors
97
+ token_type_T first_token,
98
+ ...
99
+ ) {
100
+ token_T* token = parser_advance(parser);
101
+
102
+ va_list args;
103
+ va_start(args, first_token);
104
+ char* expected = token_types_to_friendly_string_valist(parser->allocator, first_token, args);
105
+ va_end(args);
106
+
107
+ append_unexpected_error(
108
+ hb_string(description),
109
+ hb_string(expected),
110
+ token_type_to_friendly_string(token->type),
111
+ token->location.start,
112
+ token->location.end,
113
+ parser->allocator,
114
+ errors
115
+ );
116
+
117
+ hb_allocator_dealloc(parser->allocator, expected);
118
+ token_free(token, parser->allocator);
119
+ }
120
+
121
+ void parser_append_unexpected_error_string(
122
+ parser_T* parser,
123
+ hb_array_T* errors,
124
+ const char* description,
125
+ const char* expected
101
126
  ) {
102
127
  token_T* token = parser_advance(parser);
103
128
 
104
129
  append_unexpected_error(
105
- description,
106
- expected,
107
- token_type_to_string(token->type),
130
+ hb_string(description),
131
+ hb_string(expected),
132
+ token_type_to_friendly_string(token->type),
108
133
  token->location.start,
109
134
  token->location.end,
135
+ parser->allocator,
110
136
  errors
111
137
  );
112
138
 
113
- token_free(token);
139
+ token_free(token, parser->allocator);
114
140
  }
115
141
 
116
142
  void parser_append_unexpected_token_error(parser_T* parser, token_type_T expected_type, hb_array_T* errors) {
@@ -119,6 +145,7 @@ void parser_append_unexpected_token_error(parser_T* parser, token_type_T expecte
119
145
  parser->current_token,
120
146
  parser->current_token->location.start,
121
147
  parser->current_token->location.end,
148
+ parser->allocator,
122
149
  errors
123
150
  );
124
151
  }
@@ -129,13 +156,17 @@ void parser_append_literal_node_from_buffer(
129
156
  hb_array_T* children,
130
157
  position_T start
131
158
  ) {
132
- if (hb_buffer_length(buffer) == 0) { return; }
159
+ if (buffer->length == 0) { return; }
160
+
161
+ hb_string_T content = { .data = buffer->value, .length = (uint32_t) buffer->length };
133
162
 
134
163
  AST_LITERAL_NODE_T* literal =
135
- ast_literal_node_init(hb_buffer_value(buffer), start, parser->current_token->location.start, NULL);
164
+ ast_literal_node_init(content, start, parser->current_token->location.start, NULL, parser->allocator);
136
165
 
137
166
  if (children != NULL) { hb_array_append(children, literal); }
138
- hb_buffer_clear(buffer);
167
+
168
+ hb_buffer_free(buffer);
169
+ hb_buffer_init(buffer, 128, parser->allocator);
139
170
  }
140
171
 
141
172
  token_T* parser_advance(parser_T* parser) {
@@ -155,13 +186,21 @@ token_T* parser_consume_expected(parser_T* parser, const token_type_T expected_t
155
186
  if (token == NULL) {
156
187
  token = parser_advance(parser);
157
188
 
158
- append_unexpected_token_error(expected_type, token, token->location.start, token->location.end, array);
189
+ append_unexpected_token_error(
190
+ expected_type,
191
+ token,
192
+ token->location.start,
193
+ token->location.end,
194
+ parser->allocator,
195
+ array
196
+ );
159
197
  }
160
198
 
161
199
  return token;
162
200
  }
163
201
 
164
202
  AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag(
203
+ parser_T* parser,
165
204
  AST_HTML_OPEN_TAG_NODE_T* open_tag,
166
205
  hb_array_T* body,
167
206
  hb_array_T* errors
@@ -170,11 +209,12 @@ AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag(
170
209
  open_tag->tag_name,
171
210
  open_tag->tag_name->location.start,
172
211
  open_tag->tag_name->location.end,
212
+ parser->allocator,
173
213
  errors
174
214
  );
175
215
 
176
216
  return ast_html_element_node_init(
177
- open_tag,
217
+ (AST_NODE_T*) open_tag,
178
218
  open_tag->tag_name,
179
219
  body,
180
220
  NULL,
@@ -182,7 +222,8 @@ AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag(
182
222
  ELEMENT_SOURCE_HTML,
183
223
  open_tag->base.location.start,
184
224
  open_tag->base.location.end,
185
- errors
225
+ errors,
226
+ parser->allocator
186
227
  );
187
228
  }
188
229
 
@@ -200,6 +241,7 @@ void parser_handle_mismatched_tags(
200
241
  actual_tag,
201
242
  actual_tag->location.start,
202
243
  actual_tag->location.end,
244
+ parser->allocator,
203
245
  errors
204
246
  );
205
247
  } else {
@@ -207,6 +249,7 @@ void parser_handle_mismatched_tags(
207
249
  close_tag->tag_name,
208
250
  close_tag->tag_name->location.start,
209
251
  close_tag->tag_name->location.end,
252
+ parser->allocator,
210
253
  errors
211
254
  );
212
255
  }
@@ -219,3 +262,47 @@ bool parser_is_expected_closing_tag_name(hb_string_T tag_name, foreign_content_t
219
262
 
220
263
  return hb_string_equals_case_insensitive(expected_tag_name, tag_name);
221
264
  }
265
+
266
+ void parser_synchronize(parser_T* parser, hb_array_T* errors) {
267
+ (void) errors;
268
+
269
+ while (parser->current_token->type != TOKEN_EOF) {
270
+ token_type_T type = parser->current_token->type;
271
+
272
+ if (type == TOKEN_HTML_TAG_START || type == TOKEN_HTML_TAG_START_CLOSE || type == TOKEN_ERB_START
273
+ || type == TOKEN_HTML_COMMENT_START || type == TOKEN_HTML_DOCTYPE) {
274
+ return;
275
+ }
276
+
277
+ token_T* skipped = parser_advance(parser);
278
+ token_free(skipped, parser->allocator);
279
+ }
280
+ }
281
+
282
+ bool parser_can_close_ancestor(const parser_T* parser, hb_string_T tag_name) {
283
+ size_t stack_size = hb_array_size(parser->open_tags_stack);
284
+
285
+ for (size_t i = stack_size; i > 0; i--) {
286
+ token_T* open = hb_array_get(parser->open_tags_stack, i - 1);
287
+
288
+ if (open && !hb_string_is_empty(open->value) && hb_string_equals_case_insensitive(open->value, tag_name)) {
289
+ return true;
290
+ }
291
+ }
292
+
293
+ return false;
294
+ }
295
+
296
+ size_t parser_find_ancestor_depth(const parser_T* parser, hb_string_T tag_name) {
297
+ size_t stack_size = hb_array_size(parser->open_tags_stack);
298
+
299
+ for (size_t i = stack_size; i > 0; i--) {
300
+ token_T* open = hb_array_get(parser->open_tags_stack, i - 1);
301
+
302
+ if (open && !hb_string_is_empty(open->value) && hb_string_equals_case_insensitive(open->value, tag_name)) {
303
+ return stack_size - i;
304
+ }
305
+ }
306
+
307
+ return (size_t) -1;
308
+ }
@@ -13,11 +13,21 @@ void parser_push_open_tag(const parser_T* parser, token_T* tag_name);
13
13
  bool parser_check_matching_tag(const parser_T* parser, hb_string_T tag_name);
14
14
  token_T* parser_pop_open_tag(const parser_T* parser);
15
15
 
16
- void parser_append_unexpected_error(
16
+ void parser_append_unexpected_error_impl(
17
17
  parser_T* parser,
18
+ hb_array_T* errors,
18
19
  const char* description,
19
- const char* expected,
20
- hb_array_T* errors
20
+ token_type_T first_token,
21
+ ...
22
+ );
23
+ #define parser_append_unexpected_error(parser, errors, description, ...) \
24
+ parser_append_unexpected_error_impl(parser, errors, description, __VA_ARGS__, TOKEN_SENTINEL)
25
+
26
+ void parser_append_unexpected_error_string(
27
+ parser_T* parser,
28
+ hb_array_T* errors,
29
+ const char* description,
30
+ const char* expected
21
31
  );
22
32
  void parser_append_unexpected_token_error(parser_T* parser, token_type_T expected_type, hb_array_T* errors);
23
33
 
@@ -44,6 +54,7 @@ token_T* parser_consume_if_present(parser_T* parser, token_type_T type);
44
54
  token_T* parser_consume_expected(parser_T* parser, token_type_T type, hb_array_T* array);
45
55
 
46
56
  AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag(
57
+ parser_T* parser,
47
58
  AST_HTML_OPEN_TAG_NODE_T* open_tag,
48
59
  hb_array_T* body,
49
60
  hb_array_T* errors
@@ -54,4 +65,9 @@ void parser_handle_mismatched_tags(
54
65
  hb_array_T* errors
55
66
  );
56
67
 
68
+ void parser_synchronize(parser_T* parser, hb_array_T* errors);
69
+
70
+ bool parser_can_close_ancestor(const parser_T* parser, hb_string_T tag_name);
71
+ size_t parser_find_ancestor_depth(const parser_T* parser, hb_string_T tag_name);
72
+
57
73
  #endif