herb 0.8.10-arm-linux-gnu → 0.9.0-arm-linux-gnu

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 (209) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +11 -3
  3. data/README.md +64 -34
  4. data/Rakefile +48 -40
  5. data/config.yml +317 -34
  6. data/ext/herb/error_helpers.c +367 -140
  7. data/ext/herb/error_helpers.h +1 -0
  8. data/ext/herb/extconf.rb +67 -28
  9. data/ext/herb/extension.c +317 -51
  10. data/ext/herb/extension.h +1 -0
  11. data/ext/herb/extension_helpers.c +23 -14
  12. data/ext/herb/extension_helpers.h +2 -2
  13. data/ext/herb/nodes.c +537 -270
  14. data/ext/herb/nodes.h +1 -0
  15. data/herb.gemspec +3 -2
  16. data/lib/herb/3.0/herb.so +0 -0
  17. data/lib/herb/3.1/herb.so +0 -0
  18. data/lib/herb/3.2/herb.so +0 -0
  19. data/lib/herb/3.3/herb.so +0 -0
  20. data/lib/herb/3.4/herb.so +0 -0
  21. data/lib/herb/4.0/herb.so +0 -0
  22. data/lib/herb/ast/helpers.rb +3 -3
  23. data/lib/herb/ast/node.rb +15 -2
  24. data/lib/herb/ast/nodes.rb +1132 -157
  25. data/lib/herb/bootstrap.rb +87 -0
  26. data/lib/herb/cli.rb +341 -31
  27. data/lib/herb/configuration.rb +248 -0
  28. data/lib/herb/defaults.yml +32 -0
  29. data/lib/herb/engine/compiler.rb +78 -11
  30. data/lib/herb/engine/debug_visitor.rb +13 -3
  31. data/lib/herb/engine/error_formatter.rb +13 -9
  32. data/lib/herb/engine/parser_error_overlay.rb +10 -6
  33. data/lib/herb/engine/validator.rb +8 -3
  34. data/lib/herb/engine/validators/nesting_validator.rb +2 -2
  35. data/lib/herb/engine.rb +82 -35
  36. data/lib/herb/errors.rb +563 -88
  37. data/lib/herb/lex_result.rb +1 -0
  38. data/lib/herb/location.rb +7 -3
  39. data/lib/herb/parse_result.rb +12 -2
  40. data/lib/herb/parser_options.rb +57 -0
  41. data/lib/herb/position.rb +1 -0
  42. data/lib/herb/prism_inspect.rb +116 -0
  43. data/lib/herb/project.rb +923 -331
  44. data/lib/herb/range.rb +1 -0
  45. data/lib/herb/token.rb +7 -1
  46. data/lib/herb/version.rb +1 -1
  47. data/lib/herb/visitor.rb +37 -2
  48. data/lib/herb/warnings.rb +6 -1
  49. data/lib/herb.rb +35 -3
  50. data/sig/herb/ast/helpers.rbs +2 -2
  51. data/sig/herb/ast/node.rbs +12 -2
  52. data/sig/herb/ast/nodes.rbs +641 -128
  53. data/sig/herb/bootstrap.rbs +31 -0
  54. data/sig/herb/configuration.rbs +89 -0
  55. data/sig/herb/engine/compiler.rbs +9 -1
  56. data/sig/herb/engine/debug_visitor.rbs +2 -0
  57. data/sig/herb/engine/validator.rbs +5 -1
  58. data/sig/herb/engine.rbs +17 -3
  59. data/sig/herb/errors.rbs +258 -63
  60. data/sig/herb/location.rbs +4 -0
  61. data/sig/herb/parse_result.rbs +4 -2
  62. data/sig/herb/parser_options.rbs +42 -0
  63. data/sig/herb/position.rbs +1 -0
  64. data/sig/herb/prism_inspect.rbs +28 -0
  65. data/sig/herb/range.rbs +1 -0
  66. data/sig/herb/token.rbs +6 -0
  67. data/sig/herb/visitor.rbs +25 -4
  68. data/sig/herb/warnings.rbs +6 -1
  69. data/sig/herb.rbs +14 -0
  70. data/sig/herb_c_extension.rbs +5 -2
  71. data/sig/serialized_ast_errors.rbs +54 -6
  72. data/sig/serialized_ast_nodes.rbs +60 -6
  73. data/src/analyze/action_view/attribute_extraction_helpers.c +290 -0
  74. data/src/analyze/action_view/content_tag.c +70 -0
  75. data/src/analyze/action_view/link_to.c +143 -0
  76. data/src/analyze/action_view/registry.c +60 -0
  77. data/src/analyze/action_view/tag.c +64 -0
  78. data/src/analyze/action_view/tag_helper_node_builders.c +305 -0
  79. data/src/analyze/action_view/tag_helpers.c +748 -0
  80. data/src/analyze/action_view/turbo_frame_tag.c +88 -0
  81. data/src/analyze/analyze.c +882 -0
  82. data/src/{analyzed_ruby.c → analyze/analyzed_ruby.c} +13 -11
  83. data/src/analyze/builders.c +343 -0
  84. data/src/analyze/conditional_elements.c +594 -0
  85. data/src/analyze/conditional_open_tags.c +640 -0
  86. data/src/analyze/control_type.c +250 -0
  87. data/src/{analyze_helpers.c → analyze/helpers.c} +48 -23
  88. data/src/analyze/invalid_structures.c +193 -0
  89. data/src/{analyze_missing_end.c → analyze/missing_end.c} +33 -22
  90. data/src/analyze/parse_errors.c +84 -0
  91. data/src/analyze/prism_annotate.c +397 -0
  92. data/src/{analyze_transform.c → analyze/transform.c} +17 -3
  93. data/src/ast_node.c +17 -7
  94. data/src/ast_nodes.c +662 -387
  95. data/src/ast_pretty_print.c +190 -6
  96. data/src/errors.c +1076 -520
  97. data/src/extract.c +145 -49
  98. data/src/herb.c +52 -34
  99. data/src/html_util.c +241 -12
  100. data/src/include/analyze/action_view/attribute_extraction_helpers.h +36 -0
  101. data/src/include/analyze/action_view/tag_helper_handler.h +41 -0
  102. data/src/include/analyze/action_view/tag_helper_node_builders.h +70 -0
  103. data/src/include/analyze/action_view/tag_helpers.h +38 -0
  104. data/src/include/{analyze.h → analyze/analyze.h} +14 -4
  105. data/src/include/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
  106. data/src/include/analyze/builders.h +27 -0
  107. data/src/include/analyze/conditional_elements.h +9 -0
  108. data/src/include/analyze/conditional_open_tags.h +9 -0
  109. data/src/include/analyze/control_type.h +14 -0
  110. data/src/include/{analyze_helpers.h → analyze/helpers.h} +4 -2
  111. data/src/include/analyze/invalid_structures.h +11 -0
  112. data/src/include/analyze/prism_annotate.h +16 -0
  113. data/src/include/ast_node.h +11 -5
  114. data/src/include/ast_nodes.h +117 -38
  115. data/src/include/ast_pretty_print.h +5 -0
  116. data/src/include/element_source.h +3 -8
  117. data/src/include/errors.h +148 -55
  118. data/src/include/extract.h +21 -5
  119. data/src/include/herb.h +18 -6
  120. data/src/include/herb_prism_node.h +13 -0
  121. data/src/include/html_util.h +7 -2
  122. data/src/include/io.h +3 -1
  123. data/src/include/lex_helpers.h +29 -0
  124. data/src/include/lexer.h +1 -1
  125. data/src/include/lexer_peek_helpers.h +87 -13
  126. data/src/include/lexer_struct.h +2 -0
  127. data/src/include/location.h +2 -1
  128. data/src/include/parser.h +27 -2
  129. data/src/include/parser_helpers.h +19 -3
  130. data/src/include/pretty_print.h +10 -5
  131. data/src/include/prism_context.h +45 -0
  132. data/src/include/prism_helpers.h +10 -7
  133. data/src/include/prism_serialized.h +12 -0
  134. data/src/include/token.h +16 -4
  135. data/src/include/token_struct.h +10 -3
  136. data/src/include/utf8.h +2 -1
  137. data/src/include/util/hb_allocator.h +78 -0
  138. data/src/include/util/hb_arena.h +6 -1
  139. data/src/include/util/hb_arena_debug.h +12 -1
  140. data/src/include/util/hb_array.h +7 -3
  141. data/src/include/util/hb_buffer.h +6 -4
  142. data/src/include/util/hb_foreach.h +79 -0
  143. data/src/include/util/hb_narray.h +8 -4
  144. data/src/include/util/hb_string.h +56 -9
  145. data/src/include/util.h +6 -3
  146. data/src/include/version.h +1 -1
  147. data/src/io.c +3 -2
  148. data/src/lexer.c +42 -30
  149. data/src/lexer_peek_helpers.c +12 -74
  150. data/src/location.c +2 -2
  151. data/src/main.c +53 -28
  152. data/src/parser.c +783 -247
  153. data/src/parser_helpers.c +110 -23
  154. data/src/parser_match_tags.c +109 -48
  155. data/src/pretty_print.c +29 -24
  156. data/src/prism_helpers.c +30 -27
  157. data/src/ruby_parser.c +2 -0
  158. data/src/token.c +151 -66
  159. data/src/token_matchers.c +0 -1
  160. data/src/utf8.c +7 -6
  161. data/src/util/hb_allocator.c +341 -0
  162. data/src/util/hb_arena.c +81 -56
  163. data/src/util/hb_arena_debug.c +32 -17
  164. data/src/util/hb_array.c +30 -15
  165. data/src/util/hb_buffer.c +17 -21
  166. data/src/util/hb_narray.c +22 -7
  167. data/src/util/hb_string.c +49 -35
  168. data/src/util.c +21 -11
  169. data/src/visitor.c +47 -0
  170. data/templates/ext/herb/error_helpers.c.erb +24 -11
  171. data/templates/ext/herb/error_helpers.h.erb +1 -0
  172. data/templates/ext/herb/nodes.c.erb +50 -16
  173. data/templates/ext/herb/nodes.h.erb +1 -0
  174. data/templates/java/error_helpers.c.erb +1 -1
  175. data/templates/java/nodes.c.erb +30 -8
  176. data/templates/java/org/herb/ast/Errors.java.erb +24 -1
  177. data/templates/java/org/herb/ast/Nodes.java.erb +80 -21
  178. data/templates/javascript/packages/core/src/errors.ts.erb +16 -3
  179. data/templates/javascript/packages/core/src/node-type-guards.ts.erb +3 -1
  180. data/templates/javascript/packages/core/src/nodes.ts.erb +109 -32
  181. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +13 -4
  182. data/templates/javascript/packages/node/extension/nodes.cpp.erb +43 -4
  183. data/templates/lib/herb/ast/nodes.rb.erb +88 -31
  184. data/templates/lib/herb/errors.rb.erb +15 -3
  185. data/templates/lib/herb/visitor.rb.erb +2 -2
  186. data/templates/rust/src/ast/nodes.rs.erb +97 -44
  187. data/templates/rust/src/errors.rs.erb +2 -1
  188. data/templates/rust/src/nodes.rs.erb +167 -15
  189. data/templates/rust/src/union_types.rs.erb +60 -0
  190. data/templates/rust/src/visitor.rs.erb +81 -0
  191. data/templates/src/{analyze_missing_end.c.erb → analyze/missing_end.c.erb} +9 -6
  192. data/templates/src/{analyze_transform.c.erb → analyze/transform.c.erb} +2 -2
  193. data/templates/src/ast_nodes.c.erb +34 -26
  194. data/templates/src/ast_pretty_print.c.erb +24 -5
  195. data/templates/src/errors.c.erb +60 -54
  196. data/templates/src/include/ast_nodes.h.erb +6 -2
  197. data/templates/src/include/ast_pretty_print.h.erb +5 -0
  198. data/templates/src/include/errors.h.erb +15 -11
  199. data/templates/src/include/util/hb_foreach.h.erb +20 -0
  200. data/templates/src/parser_match_tags.c.erb +10 -4
  201. data/templates/src/visitor.c.erb +2 -2
  202. data/templates/template.rb +204 -29
  203. data/templates/wasm/error_helpers.cpp.erb +9 -5
  204. data/templates/wasm/nodes.cpp.erb +41 -4
  205. metadata +57 -16
  206. data/src/analyze.c +0 -1608
  207. data/src/element_source.c +0 -12
  208. data/src/include/util/hb_system.h +0 -9
  209. data/src/util/hb_system.c +0 -30
@@ -1,5 +1,5 @@
1
- #include "include/analyzed_ruby.h"
2
- #include "include/util/hb_string.h"
1
+ #include "../include/analyze/analyzed_ruby.h"
2
+ #include "../include/util/hb_string.h"
3
3
 
4
4
  #include <prism.h>
5
5
  #include <string.h>
@@ -7,6 +7,8 @@
7
7
  analyzed_ruby_T* init_analyzed_ruby(hb_string_T source) {
8
8
  analyzed_ruby_T* analyzed = malloc(sizeof(analyzed_ruby_T));
9
9
 
10
+ if (!analyzed) { return NULL; }
11
+
10
12
  pm_parser_init(&analyzed->parser, (const uint8_t*) source.data, source.length, NULL);
11
13
 
12
14
  analyzed->root = pm_parse(&analyzed->parser);
@@ -46,22 +48,22 @@ void free_analyzed_ruby(analyzed_ruby_T* analyzed) {
46
48
  free(analyzed);
47
49
  }
48
50
 
49
- const char* erb_keyword_from_analyzed_ruby(const analyzed_ruby_T* analyzed) {
51
+ hb_string_T erb_keyword_from_analyzed_ruby(const analyzed_ruby_T* analyzed) {
50
52
  if (analyzed->end_count > 0) {
51
- return "`<% end %>`";
53
+ return hb_string("`<% end %>`");
52
54
  } else if (analyzed->else_node_count > 0) {
53
- return "`<% else %>`";
55
+ return hb_string("`<% else %>`");
54
56
  } else if (analyzed->elsif_node_count > 0) {
55
- return "`<% elsif %>`";
57
+ return hb_string("`<% elsif %>`");
56
58
  } else if (analyzed->when_node_count > 0) {
57
- return "`<% when %>`";
59
+ return hb_string("`<% when %>`");
58
60
  } else if (analyzed->in_node_count > 0) {
59
- return "`<% in %>`";
61
+ return hb_string("`<% in %>`");
60
62
  } else if (analyzed->rescue_node_count > 0) {
61
- return "`<% rescue %>`";
63
+ return hb_string("`<% rescue %>`");
62
64
  } else if (analyzed->ensure_node_count > 0) {
63
- return "`<% ensure %>`";
65
+ return hb_string("`<% ensure %>`");
64
66
  }
65
67
 
66
- return NULL;
68
+ return HB_STRING_NULL;
67
69
  }
@@ -0,0 +1,343 @@
1
+ #include "../include/analyze/builders.h"
2
+ #include "../include/analyze/analyze.h"
3
+ #include "../include/ast_nodes.h"
4
+ #include "../include/location.h"
5
+ #include "../include/position.h"
6
+ #include "../include/prism_helpers.h"
7
+ #include "../include/token_struct.h"
8
+ #include "../include/util/hb_allocator.h"
9
+ #include "../include/util/hb_array.h"
10
+ #include "../include/util/hb_string.h"
11
+
12
+ #include <stddef.h>
13
+ #include <string.h>
14
+
15
+ position_T erb_content_end_position(const AST_ERB_CONTENT_NODE_T* erb_node) {
16
+ if (erb_node->tag_closing != NULL) {
17
+ return erb_node->tag_closing->location.end;
18
+ } else if (erb_node->content != NULL) {
19
+ return erb_node->content->location.end;
20
+ } else {
21
+ return erb_node->tag_opening->location.end;
22
+ }
23
+ }
24
+
25
+ location_T* compute_then_keyword(
26
+ AST_ERB_CONTENT_NODE_T* erb_node,
27
+ control_type_t control_type,
28
+ hb_allocator_T* allocator
29
+ ) {
30
+ if (control_type != CONTROL_TYPE_IF && control_type != CONTROL_TYPE_ELSIF && control_type != CONTROL_TYPE_UNLESS
31
+ && control_type != CONTROL_TYPE_WHEN && control_type != CONTROL_TYPE_IN) {
32
+ return NULL;
33
+ }
34
+
35
+ token_T* content = erb_node->content;
36
+ const char* source = (content && !hb_string_is_empty(content->value))
37
+ ? hb_allocator_strndup(allocator, content->value.data, content->value.length)
38
+ : NULL;
39
+ location_T* then_keyword = NULL;
40
+
41
+ if (control_type == CONTROL_TYPE_WHEN || control_type == CONTROL_TYPE_IN) {
42
+ if (source != NULL && strstr(source, "then") != NULL) {
43
+ then_keyword = get_then_keyword_location_wrapped(source, control_type == CONTROL_TYPE_IN, allocator);
44
+ }
45
+ } else if (control_type == CONTROL_TYPE_ELSIF) {
46
+ if (source != NULL && strstr(source, "then") != NULL) {
47
+ then_keyword = get_then_keyword_location_elsif_wrapped(source, allocator);
48
+ }
49
+ } else {
50
+ then_keyword = get_then_keyword_location(erb_node->analyzed_ruby, source, allocator);
51
+ }
52
+
53
+ if (then_keyword != NULL && content != NULL) {
54
+ position_T content_start = content->location.start;
55
+
56
+ then_keyword->start.line = content_start.line + then_keyword->start.line - 1;
57
+ then_keyword->start.column = content_start.column + then_keyword->start.column;
58
+ then_keyword->end.line = content_start.line + then_keyword->end.line - 1;
59
+ then_keyword->end.column = content_start.column + then_keyword->end.column;
60
+ }
61
+
62
+ return then_keyword;
63
+ }
64
+
65
+ typedef struct {
66
+ AST_ERB_CONTENT_NODE_T* erb;
67
+ hb_array_T* children;
68
+ AST_NODE_T* subsequent;
69
+ AST_ERB_END_NODE_T* end_node;
70
+ token_T* tag_opening;
71
+ token_T* content;
72
+ token_T* tag_closing;
73
+ location_T* then_keyword;
74
+ position_T start_position;
75
+ position_T end_position;
76
+ hb_array_T* errors;
77
+ control_type_t control_type;
78
+ hb_allocator_T* allocator;
79
+ } control_builder_context_T;
80
+
81
+ typedef AST_NODE_T* (*control_builder_fn)(control_builder_context_T* context);
82
+
83
+ typedef struct {
84
+ control_type_t type;
85
+ control_builder_fn builder;
86
+ } control_builder_entry_T;
87
+
88
+ static AST_NODE_T* build_if_node(control_builder_context_T* context);
89
+ static AST_NODE_T* build_else_node(control_builder_context_T* context);
90
+ static AST_NODE_T* build_when_node(control_builder_context_T* context);
91
+ static AST_NODE_T* build_in_node(control_builder_context_T* context);
92
+ static AST_NODE_T* build_rescue_node(control_builder_context_T* context);
93
+ static AST_NODE_T* build_ensure_node(control_builder_context_T* context);
94
+ static AST_NODE_T* build_unless_node(control_builder_context_T* context);
95
+ static AST_NODE_T* build_while_node(control_builder_context_T* context);
96
+ static AST_NODE_T* build_until_node(control_builder_context_T* context);
97
+ static AST_NODE_T* build_for_node(control_builder_context_T* context);
98
+ static AST_NODE_T* build_block_node(control_builder_context_T* context);
99
+ static AST_NODE_T* build_yield_node(control_builder_context_T* context);
100
+
101
+ static const control_builder_entry_T CONTROL_BUILDERS[] = {
102
+ { CONTROL_TYPE_IF, build_if_node }, { CONTROL_TYPE_ELSIF, build_if_node },
103
+ { CONTROL_TYPE_ELSE, build_else_node }, { CONTROL_TYPE_WHEN, build_when_node },
104
+ { CONTROL_TYPE_IN, build_in_node }, { CONTROL_TYPE_RESCUE, build_rescue_node },
105
+ { CONTROL_TYPE_ENSURE, build_ensure_node }, { CONTROL_TYPE_UNLESS, build_unless_node },
106
+ { CONTROL_TYPE_WHILE, build_while_node }, { CONTROL_TYPE_UNTIL, build_until_node },
107
+ { CONTROL_TYPE_FOR, build_for_node }, { CONTROL_TYPE_BLOCK, build_block_node },
108
+ { CONTROL_TYPE_YIELD, build_yield_node },
109
+ };
110
+
111
+ static control_builder_fn lookup_control_builder(control_type_t type) {
112
+ for (size_t i = 0; i < sizeof(CONTROL_BUILDERS) / sizeof(CONTROL_BUILDERS[0]); i++) {
113
+ if (CONTROL_BUILDERS[i].type == type) { return CONTROL_BUILDERS[i].builder; }
114
+ }
115
+
116
+ return NULL;
117
+ }
118
+
119
+ AST_NODE_T* create_control_node(
120
+ AST_ERB_CONTENT_NODE_T* erb_node,
121
+ hb_array_T* children,
122
+ AST_NODE_T* subsequent,
123
+ AST_ERB_END_NODE_T* end_node,
124
+ control_type_t control_type,
125
+ hb_allocator_T* allocator
126
+ ) {
127
+ control_builder_context_T context = { .erb = erb_node,
128
+ .children = children,
129
+ .subsequent = subsequent,
130
+ .end_node = end_node,
131
+ .tag_opening = erb_node->tag_opening,
132
+ .content = erb_node->content,
133
+ .tag_closing = erb_node->tag_closing,
134
+ .then_keyword = compute_then_keyword(erb_node, control_type, allocator),
135
+ .start_position = erb_node->tag_opening->location.start,
136
+ .end_position = erb_content_end_position(erb_node),
137
+ .errors = erb_node->base.errors,
138
+ .control_type = control_type,
139
+ .allocator = allocator };
140
+
141
+ erb_node->base.errors = NULL;
142
+
143
+ if (context.end_node) {
144
+ context.end_position = context.end_node->base.location.end;
145
+ } else if (hb_array_size(context.children) > 0) {
146
+ AST_NODE_T* last_child = hb_array_last(context.children);
147
+ context.end_position = last_child->location.end;
148
+ } else if (context.subsequent) {
149
+ context.end_position = context.subsequent->location.end;
150
+ }
151
+
152
+ control_builder_fn builder = lookup_control_builder(control_type);
153
+
154
+ if (!builder) { return NULL; }
155
+
156
+ return builder(&context);
157
+ }
158
+
159
+ static AST_NODE_T* build_if_node(control_builder_context_T* context) {
160
+ return (AST_NODE_T*) ast_erb_if_node_init(
161
+ context->tag_opening,
162
+ context->content,
163
+ context->tag_closing,
164
+ context->then_keyword,
165
+ HERB_PRISM_NODE_EMPTY,
166
+ context->children,
167
+ context->subsequent,
168
+ context->end_node,
169
+ context->start_position,
170
+ context->end_position,
171
+ context->errors,
172
+ context->allocator
173
+ );
174
+ }
175
+
176
+ static AST_NODE_T* build_else_node(control_builder_context_T* context) {
177
+ return (AST_NODE_T*) ast_erb_else_node_init(
178
+ context->tag_opening,
179
+ context->content,
180
+ context->tag_closing,
181
+ context->children,
182
+ context->start_position,
183
+ context->end_position,
184
+ context->errors,
185
+ context->allocator
186
+ );
187
+ }
188
+
189
+ static AST_NODE_T* build_when_node(control_builder_context_T* context) {
190
+ return (AST_NODE_T*) ast_erb_when_node_init(
191
+ context->tag_opening,
192
+ context->content,
193
+ context->tag_closing,
194
+ context->then_keyword,
195
+ context->children,
196
+ context->start_position,
197
+ context->end_position,
198
+ context->errors,
199
+ context->allocator
200
+ );
201
+ }
202
+
203
+ static AST_NODE_T* build_in_node(control_builder_context_T* context) {
204
+ return (AST_NODE_T*) ast_erb_in_node_init(
205
+ context->tag_opening,
206
+ context->content,
207
+ context->tag_closing,
208
+ context->then_keyword,
209
+ context->children,
210
+ context->start_position,
211
+ context->end_position,
212
+ context->errors,
213
+ context->allocator
214
+ );
215
+ }
216
+
217
+ static AST_NODE_T* build_rescue_node(control_builder_context_T* context) {
218
+ AST_ERB_RESCUE_NODE_T* rescue_node = NULL;
219
+
220
+ if (context->subsequent && context->subsequent->type == AST_ERB_RESCUE_NODE) {
221
+ rescue_node = (AST_ERB_RESCUE_NODE_T*) context->subsequent;
222
+ }
223
+
224
+ return (AST_NODE_T*) ast_erb_rescue_node_init(
225
+ context->tag_opening,
226
+ context->content,
227
+ context->tag_closing,
228
+ context->children,
229
+ rescue_node,
230
+ context->start_position,
231
+ context->end_position,
232
+ context->errors,
233
+ context->allocator
234
+ );
235
+ }
236
+
237
+ static AST_NODE_T* build_ensure_node(control_builder_context_T* context) {
238
+ return (AST_NODE_T*) ast_erb_ensure_node_init(
239
+ context->tag_opening,
240
+ context->content,
241
+ context->tag_closing,
242
+ context->children,
243
+ context->start_position,
244
+ context->end_position,
245
+ context->errors,
246
+ context->allocator
247
+ );
248
+ }
249
+
250
+ static AST_NODE_T* build_unless_node(control_builder_context_T* context) {
251
+ AST_ERB_ELSE_NODE_T* else_clause = NULL;
252
+
253
+ if (context->subsequent && context->subsequent->type == AST_ERB_ELSE_NODE) {
254
+ else_clause = (AST_ERB_ELSE_NODE_T*) context->subsequent;
255
+ }
256
+
257
+ return (AST_NODE_T*) ast_erb_unless_node_init(
258
+ context->tag_opening,
259
+ context->content,
260
+ context->tag_closing,
261
+ context->then_keyword,
262
+ HERB_PRISM_NODE_EMPTY,
263
+ context->children,
264
+ else_clause,
265
+ context->end_node,
266
+ context->start_position,
267
+ context->end_position,
268
+ context->errors,
269
+ context->allocator
270
+ );
271
+ }
272
+
273
+ static AST_NODE_T* build_while_node(control_builder_context_T* context) {
274
+ return (AST_NODE_T*) ast_erb_while_node_init(
275
+ context->tag_opening,
276
+ context->content,
277
+ context->tag_closing,
278
+ HERB_PRISM_NODE_EMPTY,
279
+ context->children,
280
+ context->end_node,
281
+ context->start_position,
282
+ context->end_position,
283
+ context->errors,
284
+ context->allocator
285
+ );
286
+ }
287
+
288
+ static AST_NODE_T* build_until_node(control_builder_context_T* context) {
289
+ return (AST_NODE_T*) ast_erb_until_node_init(
290
+ context->tag_opening,
291
+ context->content,
292
+ context->tag_closing,
293
+ HERB_PRISM_NODE_EMPTY,
294
+ context->children,
295
+ context->end_node,
296
+ context->start_position,
297
+ context->end_position,
298
+ context->errors,
299
+ context->allocator
300
+ );
301
+ }
302
+
303
+ static AST_NODE_T* build_for_node(control_builder_context_T* context) {
304
+ return (AST_NODE_T*) ast_erb_for_node_init(
305
+ context->tag_opening,
306
+ context->content,
307
+ context->tag_closing,
308
+ HERB_PRISM_NODE_EMPTY,
309
+ context->children,
310
+ context->end_node,
311
+ context->start_position,
312
+ context->end_position,
313
+ context->errors,
314
+ context->allocator
315
+ );
316
+ }
317
+
318
+ static AST_NODE_T* build_block_node(control_builder_context_T* context) {
319
+ return (AST_NODE_T*) ast_erb_block_node_init(
320
+ context->tag_opening,
321
+ context->content,
322
+ context->tag_closing,
323
+ HERB_PRISM_NODE_EMPTY,
324
+ context->children,
325
+ context->end_node,
326
+ context->start_position,
327
+ context->end_position,
328
+ context->errors,
329
+ context->allocator
330
+ );
331
+ }
332
+
333
+ static AST_NODE_T* build_yield_node(control_builder_context_T* context) {
334
+ return (AST_NODE_T*) ast_erb_yield_node_init(
335
+ context->tag_opening,
336
+ context->content,
337
+ context->tag_closing,
338
+ context->start_position,
339
+ context->end_position,
340
+ context->errors,
341
+ context->allocator
342
+ );
343
+ }