herb 0.9.2-arm-linux-gnu → 0.9.4-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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/config.yml +125 -0
  4. data/ext/herb/error_helpers.c +172 -2
  5. data/ext/herb/extconf.rb +6 -0
  6. data/ext/herb/extension.c +16 -2
  7. data/ext/herb/extension_helpers.c +6 -5
  8. data/ext/herb/extension_helpers.h +4 -4
  9. data/ext/herb/nodes.c +89 -3
  10. data/lib/herb/3.0/herb.so +0 -0
  11. data/lib/herb/3.1/herb.so +0 -0
  12. data/lib/herb/3.2/herb.so +0 -0
  13. data/lib/herb/3.3/herb.so +0 -0
  14. data/lib/herb/3.4/herb.so +0 -0
  15. data/lib/herb/4.0/herb.so +0 -0
  16. data/lib/herb/ast/erb_content_node.rb +32 -0
  17. data/lib/herb/ast/nodes.rb +244 -3
  18. data/lib/herb/cli.rb +12 -2
  19. data/lib/herb/engine/compiler.rb +166 -75
  20. data/lib/herb/engine/validators/security_validator.rb +40 -0
  21. data/lib/herb/engine.rb +3 -0
  22. data/lib/herb/errors.rb +268 -0
  23. data/lib/herb/parser_options.rb +7 -2
  24. data/lib/herb/project.rb +58 -17
  25. data/lib/herb/version.rb +1 -1
  26. data/lib/herb/visitor.rb +82 -0
  27. data/lib/herb.rb +1 -0
  28. data/sig/herb/ast/erb_content_node.rbs +13 -0
  29. data/sig/herb/ast/nodes.rbs +98 -2
  30. data/sig/herb/engine/compiler.rbs +31 -2
  31. data/sig/herb/engine/validators/security_validator.rbs +4 -0
  32. data/sig/herb/engine.rbs +3 -0
  33. data/sig/herb/errors.rbs +122 -0
  34. data/sig/herb/parser_options.rbs +6 -2
  35. data/sig/herb/visitor.rbs +12 -0
  36. data/sig/serialized_ast_errors.rbs +29 -0
  37. data/sig/serialized_ast_nodes.rbs +19 -0
  38. data/src/analyze/action_view/attribute_extraction_helpers.c +420 -91
  39. data/src/analyze/action_view/image_tag.c +87 -0
  40. data/src/analyze/action_view/javascript_include_tag.c +22 -12
  41. data/src/analyze/action_view/registry.c +6 -3
  42. data/src/analyze/action_view/tag.c +19 -2
  43. data/src/analyze/action_view/tag_helper_node_builders.c +105 -36
  44. data/src/analyze/action_view/tag_helpers.c +792 -44
  45. data/src/analyze/analyze.c +167 -13
  46. data/src/analyze/{helpers.c → analyze_helpers.c} +1 -1
  47. data/src/analyze/analyzed_ruby.c +1 -1
  48. data/src/analyze/builders.c +11 -8
  49. data/src/analyze/conditional_elements.c +6 -7
  50. data/src/analyze/conditional_open_tags.c +6 -7
  51. data/src/analyze/control_type.c +4 -2
  52. data/src/analyze/invalid_structures.c +5 -5
  53. data/src/analyze/missing_end.c +2 -2
  54. data/src/analyze/parse_errors.c +47 -6
  55. data/src/analyze/prism_annotate.c +7 -7
  56. data/src/analyze/render_nodes.c +6 -26
  57. data/src/analyze/strict_locals.c +651 -0
  58. data/src/analyze/transform.c +7 -0
  59. data/src/{ast_node.c → ast/ast_node.c} +8 -8
  60. data/src/{ast_nodes.c → ast/ast_nodes.c} +82 -11
  61. data/src/{ast_pretty_print.c → ast/ast_pretty_print.c} +113 -9
  62. data/src/{pretty_print.c → ast/pretty_print.c} +9 -9
  63. data/src/errors.c +398 -8
  64. data/src/extract.c +5 -5
  65. data/src/herb.c +15 -5
  66. data/src/include/analyze/action_view/attribute_extraction_helpers.h +3 -1
  67. data/src/include/analyze/action_view/tag_helper_handler.h +3 -3
  68. data/src/include/analyze/action_view/tag_helper_node_builders.h +34 -5
  69. data/src/include/analyze/action_view/tag_helpers.h +4 -3
  70. data/src/include/analyze/analyze.h +12 -5
  71. data/src/include/analyze/analyzed_ruby.h +2 -2
  72. data/src/include/analyze/builders.h +4 -4
  73. data/src/include/analyze/conditional_elements.h +2 -2
  74. data/src/include/analyze/conditional_open_tags.h +2 -2
  75. data/src/include/analyze/control_type.h +1 -1
  76. data/src/include/analyze/helpers.h +2 -2
  77. data/src/include/analyze/invalid_structures.h +1 -1
  78. data/src/include/analyze/prism_annotate.h +2 -2
  79. data/src/include/analyze/render_nodes.h +1 -1
  80. data/src/include/analyze/strict_locals.h +11 -0
  81. data/src/include/{ast_node.h → ast/ast_node.h} +4 -4
  82. data/src/include/{ast_nodes.h → ast/ast_nodes.h} +38 -14
  83. data/src/include/{ast_pretty_print.h → ast/ast_pretty_print.h} +3 -3
  84. data/src/include/{pretty_print.h → ast/pretty_print.h} +4 -4
  85. data/src/include/errors.h +65 -7
  86. data/src/include/extract.h +2 -2
  87. data/src/include/herb.h +5 -5
  88. data/src/include/{lex_helpers.h → lexer/lex_helpers.h} +5 -5
  89. data/src/include/{lexer.h → lexer/lexer.h} +1 -1
  90. data/src/include/{lexer_peek_helpers.h → lexer/lexer_peek_helpers.h} +2 -2
  91. data/src/include/{lexer_struct.h → lexer/lexer_struct.h} +2 -2
  92. data/src/include/{token.h → lexer/token.h} +3 -3
  93. data/src/include/{token_matchers.h → lexer/token_matchers.h} +1 -1
  94. data/src/include/{token_struct.h → lexer/token_struct.h} +3 -3
  95. data/src/include/{util → lib}/hb_foreach.h +1 -1
  96. data/src/include/{util → lib}/hb_string.h +5 -1
  97. data/src/include/{location.h → location/location.h} +1 -1
  98. data/src/include/parser/dot_notation.h +12 -0
  99. data/src/include/{parser.h → parser/parser.h} +11 -4
  100. data/src/include/{parser_helpers.h → parser/parser_helpers.h} +6 -6
  101. data/src/include/{prism_context.h → prism/prism_context.h} +2 -2
  102. data/src/include/{prism_helpers.h → prism/prism_helpers.h} +6 -6
  103. data/src/include/{html_util.h → util/html_util.h} +1 -1
  104. data/src/include/util/ruby_util.h +9 -0
  105. data/src/include/{utf8.h → util/utf8.h} +1 -1
  106. data/src/include/{util.h → util/util.h} +1 -1
  107. data/src/include/version.h +1 -1
  108. data/src/include/visitor.h +3 -3
  109. data/src/{lexer_peek_helpers.c → lexer/lexer_peek_helpers.c} +3 -3
  110. data/src/{token.c → lexer/token.c} +8 -8
  111. data/src/{token_matchers.c → lexer/token_matchers.c} +2 -2
  112. data/src/lexer.c +6 -6
  113. data/src/{util → lib}/hb_allocator.c +2 -2
  114. data/src/{util → lib}/hb_arena.c +1 -1
  115. data/src/{util → lib}/hb_arena_debug.c +2 -2
  116. data/src/{util → lib}/hb_array.c +2 -2
  117. data/src/{util → lib}/hb_buffer.c +2 -2
  118. data/src/{util → lib}/hb_narray.c +1 -1
  119. data/src/{util → lib}/hb_string.c +2 -2
  120. data/src/{location.c → location/location.c} +2 -2
  121. data/src/{position.c → location/position.c} +2 -2
  122. data/src/{range.c → location/range.c} +1 -1
  123. data/src/main.c +11 -11
  124. data/src/parser/dot_notation.c +100 -0
  125. data/src/{parser_match_tags.c → parser/match_tags.c} +34 -5
  126. data/src/{parser_helpers.c → parser/parser_helpers.c} +10 -10
  127. data/src/parser.c +68 -32
  128. data/src/{prism_helpers.c → prism/prism_helpers.c} +7 -7
  129. data/src/{ruby_parser.c → prism/ruby_parser.c} +1 -1
  130. data/src/{html_util.c → util/html_util.c} +4 -4
  131. data/src/{io.c → util/io.c} +3 -3
  132. data/src/util/ruby_util.c +42 -0
  133. data/src/{utf8.c → util/utf8.c} +2 -2
  134. data/src/{util.c → util/util.c} +4 -4
  135. data/src/visitor.c +35 -3
  136. data/templates/ext/herb/error_helpers.c.erb +2 -2
  137. data/templates/ext/herb/nodes.c.erb +1 -1
  138. data/templates/java/error_helpers.c.erb +1 -1
  139. data/templates/java/error_helpers.h.erb +2 -2
  140. data/templates/java/nodes.c.erb +4 -4
  141. data/templates/java/nodes.h.erb +1 -1
  142. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +4 -4
  143. data/templates/javascript/packages/node/extension/nodes.cpp.erb +4 -4
  144. data/templates/lib/herb/visitor.rb.erb +14 -0
  145. data/templates/src/analyze/missing_end.c.erb +2 -2
  146. data/templates/src/{ast_nodes.c.erb → ast/ast_nodes.c.erb} +9 -9
  147. data/templates/src/{ast_pretty_print.c.erb → ast/ast_pretty_print.c.erb} +8 -8
  148. data/templates/src/errors.c.erb +8 -8
  149. data/templates/src/include/{ast_nodes.h.erb → ast/ast_nodes.h.erb} +11 -12
  150. data/templates/src/include/{ast_pretty_print.h.erb → ast/ast_pretty_print.h.erb} +2 -2
  151. data/templates/src/include/errors.h.erb +7 -7
  152. data/templates/src/{parser_match_tags.c.erb → parser/match_tags.c.erb} +4 -4
  153. data/templates/src/visitor.c.erb +3 -3
  154. data/templates/wasm/error_helpers.cpp.erb +4 -4
  155. data/templates/wasm/nodes.cpp.erb +5 -5
  156. metadata +76 -68
  157. data/src/include/element_source.h +0 -10
  158. /data/src/include/{util → lib}/hb_allocator.h +0 -0
  159. /data/src/include/{util → lib}/hb_arena.h +0 -0
  160. /data/src/include/{util → lib}/hb_arena_debug.h +0 -0
  161. /data/src/include/{util → lib}/hb_array.h +0 -0
  162. /data/src/include/{util → lib}/hb_buffer.h +0 -0
  163. /data/src/include/{util → lib}/hb_narray.h +0 -0
  164. /data/src/include/{util → lib}/string.h +0 -0
  165. /data/src/include/{position.h → location/position.h} +0 -0
  166. /data/src/include/{range.h → location/range.h} +0 -0
  167. /data/src/include/{herb_prism_node.h → prism/herb_prism_node.h} +0 -0
  168. /data/src/include/{prism_serialized.h → prism/prism_serialized.h} +0 -0
  169. /data/src/include/{ruby_parser.h → prism/ruby_parser.h} +0 -0
  170. /data/src/include/{io.h → util/io.h} +0 -0
  171. /data/templates/src/include/{util → lib}/hb_foreach.h.erb +0 -0
@@ -0,0 +1,9 @@
1
+ #ifndef HERB_RUBY_UTIL_H
2
+ #define HERB_RUBY_UTIL_H
3
+
4
+ #include "../lib/hb_string.h"
5
+ #include <stdbool.h>
6
+
7
+ bool is_ruby_introspection_method(hb_string_T method_name);
8
+
9
+ #endif
@@ -1,7 +1,7 @@
1
1
  #ifndef HERB_UTF8_H
2
2
  #define HERB_UTF8_H
3
3
 
4
- #include "util/hb_string.h"
4
+ #include "../lib/hb_string.h"
5
5
  #include <stdbool.h>
6
6
  #include <stdint.h>
7
7
  #include <stdlib.h>
@@ -1,7 +1,7 @@
1
1
  #ifndef HERB_UTIL_H
2
2
  #define HERB_UTIL_H
3
3
 
4
- #include "util/hb_string.h"
4
+ #include "../lib/hb_string.h"
5
5
  #include <stdbool.h>
6
6
  #include <stdlib.h>
7
7
 
@@ -1,6 +1,6 @@
1
1
  #ifndef HERB_VERSION_H
2
2
  #define HERB_VERSION_H
3
3
 
4
- #define HERB_VERSION "0.9.2"
4
+ #define HERB_VERSION "0.9.4"
5
5
 
6
6
  #endif
@@ -1,9 +1,9 @@
1
1
  #ifndef HERB_VISITOR_H
2
2
  #define HERB_VISITOR_H
3
3
 
4
- #include "ast_node.h"
5
- #include "ast_nodes.h"
6
- #include "util/hb_array.h"
4
+ #include "ast/ast_node.h"
5
+ #include "ast/ast_nodes.h"
6
+ #include "lib/hb_array.h"
7
7
 
8
8
  void herb_visit_node(const AST_NODE_T* node, bool (*visitor)(const AST_NODE_T*, void*), void* data);
9
9
  void herb_visit_child_nodes(const AST_NODE_T* node, bool (*visitor)(const AST_NODE_T* node, void* data), void* data);
@@ -1,6 +1,6 @@
1
- #include "include/lexer_peek_helpers.h"
2
- #include "include/lexer.h"
3
- #include "include/token.h"
1
+ #include "../include/lexer/lexer_peek_helpers.h"
2
+ #include "../include/lexer/lexer.h"
3
+ #include "../include/lexer/token.h"
4
4
 
5
5
  #include <ctype.h>
6
6
 
@@ -1,11 +1,11 @@
1
- #include "include/token.h"
2
- #include "include/position.h"
3
- #include "include/range.h"
4
- #include "include/token_struct.h"
5
- #include "include/util.h"
6
- #include "include/util/hb_allocator.h"
7
- #include "include/util/hb_buffer.h"
8
- #include "include/util/hb_string.h"
1
+ #include "../include/lexer/token.h"
2
+ #include "../include/lexer/token_struct.h"
3
+ #include "../include/lib/hb_allocator.h"
4
+ #include "../include/lib/hb_buffer.h"
5
+ #include "../include/lib/hb_string.h"
6
+ #include "../include/location/position.h"
7
+ #include "../include/location/range.h"
8
+ #include "../include/util/util.h"
9
9
 
10
10
  #include <stdarg.h>
11
11
  #include <stdbool.h>
@@ -1,5 +1,5 @@
1
- #include "include/token_matchers.h"
2
- #include "include/parser.h"
1
+ #include "../include/lexer/token_matchers.h"
2
+ #include "../include/parser/parser.h"
3
3
 
4
4
  #include <stdarg.h>
5
5
  #include <stdbool.h>
data/src/lexer.c CHANGED
@@ -1,9 +1,9 @@
1
- #include "include/lexer_peek_helpers.h"
1
+ #include "include/lexer/lexer_peek_helpers.h"
2
+ #include "include/lexer/token.h"
3
+ #include "include/lib/hb_string.h"
2
4
  #include "include/macros.h"
3
- #include "include/token.h"
4
- #include "include/utf8.h"
5
- #include "include/util.h"
6
- #include "include/util/hb_string.h"
5
+ #include "include/util/utf8.h"
6
+ #include "include/util/util.h"
7
7
 
8
8
  #include <ctype.h>
9
9
  #include <stdint.h>
@@ -75,7 +75,7 @@ token_T* lexer_error(lexer_T* lexer, const char* message) {
75
75
  size_t length = strlen(buffer);
76
76
  char* error_message = hb_allocator_strndup(lexer->allocator, buffer, length);
77
77
 
78
- return token_init((hb_string_T) { .data = error_message, .length = (uint32_t) length }, TOKEN_ERROR, lexer);
78
+ return token_init(hb_string_from_data(error_message, length), TOKEN_ERROR, lexer);
79
79
  }
80
80
 
81
81
  static void lexer_advance(lexer_T* lexer) {
@@ -1,5 +1,5 @@
1
- #include "../include/util/hb_allocator.h"
2
- #include "../include/util/hb_arena.h"
1
+ #include "../include/lib/hb_allocator.h"
2
+ #include "../include/lib/hb_arena.h"
3
3
 
4
4
  #include <stdio.h>
5
5
  #include <stdlib.h>
@@ -1,4 +1,4 @@
1
- #include "../include/util/hb_arena.h"
1
+ #include "../include/lib/hb_arena.h"
2
2
  #include "../include/macros.h"
3
3
 
4
4
  #include <assert.h>
@@ -2,8 +2,8 @@
2
2
  #include <stdio.h>
3
3
  #include <string.h>
4
4
 
5
- #include "../include/util/hb_arena.h"
6
- #include "../include/util/hb_arena_debug.h"
5
+ #include "../include/lib/hb_arena.h"
6
+ #include "../include/lib/hb_arena_debug.h"
7
7
 
8
8
  #define ANSI_COLOR_GREEN "\033[32m"
9
9
  #define ANSI_COLOR_YELLOW "\033[33m"
@@ -1,9 +1,9 @@
1
1
  #include <stdint.h>
2
2
  #include <stdio.h>
3
3
 
4
+ #include "../include/lib/hb_allocator.h"
5
+ #include "../include/lib/hb_array.h"
4
6
  #include "../include/macros.h"
5
- #include "../include/util/hb_allocator.h"
6
- #include "../include/util/hb_array.h"
7
7
 
8
8
  size_t hb_array_sizeof(void) {
9
9
  return sizeof(hb_array_T);
@@ -2,9 +2,9 @@
2
2
  #include <stdio.h>
3
3
  #include <string.h>
4
4
 
5
+ #include "../include/lib/hb_allocator.h"
6
+ #include "../include/lib/hb_buffer.h"
5
7
  #include "../include/macros.h"
6
- #include "../include/util/hb_allocator.h"
7
- #include "../include/util/hb_buffer.h"
8
8
 
9
9
  static bool hb_buffer_has_capacity(hb_buffer_T* buffer, const size_t required_length) {
10
10
  return (buffer->length + required_length <= buffer->capacity);
@@ -1,4 +1,4 @@
1
- #include "../include/util/hb_narray.h"
1
+ #include "../include/lib/hb_narray.h"
2
2
 
3
3
  #include <assert.h>
4
4
  #include <stdbool.h>
@@ -1,6 +1,6 @@
1
- #include "../include/util/hb_string.h"
1
+ #include "../include/lib/hb_string.h"
2
2
  #include "../include/macros.h"
3
- #include "../include/util.h"
3
+ #include "../include/util/util.h"
4
4
 
5
5
  #include <stdlib.h>
6
6
  #include <string.h>
@@ -1,5 +1,5 @@
1
- #include "include/location.h"
2
- #include "include/position.h"
1
+ #include "../include/location/location.h"
2
+ #include "../include/location/position.h"
3
3
 
4
4
  void location_from(
5
5
  location_T* location,
@@ -1,5 +1,5 @@
1
- #include "include/position.h"
2
- #include "include/util.h"
1
+ #include "../include/location/position.h"
2
+ #include "../include/util/util.h"
3
3
 
4
4
  position_T position_from_source_with_offset(const char* source, size_t offset) {
5
5
  position_T position = { .line = 1, .column = 0 };
@@ -1,4 +1,4 @@
1
- #include "include/range.h"
1
+ #include "../include/location/range.h"
2
2
 
3
3
  uint32_t range_length(range_T range) {
4
4
  return range.to - range.from;
data/src/main.c CHANGED
@@ -1,23 +1,23 @@
1
1
  #define _POSIX_C_SOURCE 199309L // Enables `clock_gettime()`
2
2
 
3
- #include "include/ast_node.h"
4
- #include "include/ast_nodes.h"
3
+ #include "include/ast/ast_node.h"
4
+ #include "include/ast/ast_nodes.h"
5
5
 
6
6
  #ifndef HERB_EXCLUDE_PRETTYPRINT
7
- # include "include/ast_pretty_print.h"
7
+ # include "include/ast/ast_pretty_print.h"
8
8
  #endif
9
9
 
10
10
  #include "include/extract.h"
11
11
  #include "include/herb.h"
12
- #include "include/io.h"
13
- #include "include/lex_helpers.h"
12
+ #include "include/lexer/lex_helpers.h"
13
+ #include "include/lib/hb_allocator.h"
14
+ #include "include/lib/hb_arena.h"
15
+ #include "include/lib/hb_arena_debug.h"
16
+ #include "include/lib/hb_buffer.h"
17
+ #include "include/lib/string.h"
14
18
  #include "include/macros.h"
15
- #include "include/ruby_parser.h"
16
- #include "include/util/hb_allocator.h"
17
- #include "include/util/hb_arena.h"
18
- #include "include/util/hb_arena_debug.h"
19
- #include "include/util/hb_buffer.h"
20
- #include "include/util/string.h"
19
+ #include "include/prism/ruby_parser.h"
20
+ #include "include/util/io.h"
21
21
 
22
22
  #include <stdio.h>
23
23
  #include <stdlib.h>
@@ -0,0 +1,100 @@
1
+ #include "../include/parser/dot_notation.h"
2
+ #include "../include/errors.h"
3
+ #include "../include/lexer/lexer.h"
4
+ #include "../include/lexer/token.h"
5
+ #include "../include/parser/parser_helpers.h"
6
+
7
+ #include <ctype.h>
8
+
9
+ static bool token_is_dot(token_T* token) {
10
+ return token->type == TOKEN_CHARACTER && token->value.length == 1 && token->value.data[0] == '.';
11
+ }
12
+
13
+ static bool current_token_is_dot(parser_T* parser) {
14
+ return token_is_dot(parser->current_token);
15
+ }
16
+
17
+ static void consume_dot_notation_loop(parser_T* parser, token_T* tag_name, hb_array_T* errors) {
18
+ while (current_token_is_dot(parser)) {
19
+ token_T* dot = parser_advance(parser);
20
+ token_T* segment = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors);
21
+
22
+ if (segment == NULL || segment->value.length == 0) {
23
+ if (segment) { token_free(segment, parser->allocator); }
24
+ token_free(dot, parser->allocator);
25
+ break;
26
+ }
27
+
28
+ uint32_t new_length = (uint32_t) (segment->value.data + segment->value.length - tag_name->value.data);
29
+ tag_name->value.length = new_length;
30
+ tag_name->location.end = segment->location.end;
31
+ tag_name->range.to = segment->range.to;
32
+
33
+ token_free(segment, parser->allocator);
34
+ token_free(dot, parser->allocator);
35
+ }
36
+ }
37
+
38
+ bool parser_lookahead_is_valid_dot_notation_open_tag(parser_T* parser) {
39
+ lexer_T lexer_copy = *parser->lexer;
40
+ token_T* name = lexer_next_token(&lexer_copy);
41
+
42
+ if (name == NULL || name->type != TOKEN_IDENTIFIER) {
43
+ if (name) { token_free(name, parser->allocator); }
44
+ return false;
45
+ }
46
+
47
+ bool first_is_upper = name->value.length > 0 && isupper((unsigned char) name->value.data[0]);
48
+ token_free(name, parser->allocator);
49
+ token_T* next = lexer_next_token(&lexer_copy);
50
+
51
+ if (next == NULL) { return true; }
52
+
53
+ bool is_dot = token_is_dot(next);
54
+ token_free(next, parser->allocator);
55
+
56
+ if (!is_dot) { return true; }
57
+ if (!parser->options.dot_notation_tags) { return true; }
58
+ if (!first_is_upper) { return true; }
59
+
60
+ next = lexer_next_token(&lexer_copy);
61
+
62
+ while (next != NULL) {
63
+ if (next->type != TOKEN_IDENTIFIER || next->value.length == 0) {
64
+ token_free(next, parser->allocator);
65
+ return true;
66
+ }
67
+
68
+ token_free(next, parser->allocator);
69
+ next = lexer_next_token(&lexer_copy);
70
+
71
+ if (next == NULL) { return true; }
72
+
73
+ is_dot = token_is_dot(next);
74
+ token_free(next, parser->allocator);
75
+
76
+ if (!is_dot) { return true; }
77
+
78
+ next = lexer_next_token(&lexer_copy);
79
+ }
80
+
81
+ return true;
82
+ }
83
+
84
+ void parser_consume_dot_notation_segments(parser_T* parser, token_T* tag_name, hb_array_T* errors) {
85
+ if (!parser->options.dot_notation_tags) { return; }
86
+ if (tag_name == NULL || tag_name->value.length == 0) { return; }
87
+ if (!current_token_is_dot(parser)) { return; }
88
+
89
+ if (!isupper((unsigned char) tag_name->value.data[0])) {
90
+ append_dot_notation_casing_error(
91
+ tag_name,
92
+ tag_name->location.start,
93
+ tag_name->location.end,
94
+ parser->allocator,
95
+ errors
96
+ );
97
+ }
98
+
99
+ consume_dot_notation_loop(parser, tag_name, errors);
100
+ }
@@ -1,10 +1,10 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /home/runner/work/herb/herb/templates/src/parser_match_tags.c.erb
2
+ // be modified manually. See /home/runner/work/herb/herb/templates/src/parser/match_tags.c.erb
3
3
 
4
- #include "include/parser.h"
5
- #include "include/ast_nodes.h"
6
- #include "include/util/hb_array.h"
7
- #include "include/visitor.h"
4
+ #include "../include/parser/parser.h"
5
+ #include "../include/ast/ast_nodes.h"
6
+ #include "../include/lib/hb_array.h"
7
+ #include "../include/visitor.h"
8
8
 
9
9
  bool match_tags_visitor(const AST_NODE_T* node, void* data) {
10
10
  match_tags_context_T* context = (match_tags_context_T*) data;
@@ -205,6 +205,15 @@ bool match_tags_visitor(const AST_NODE_T* node, void* data) {
205
205
  if (erb_block_node->body != NULL) {
206
206
  match_tags_in_node_array(erb_block_node->body, context->errors, context->options, context->allocator);
207
207
  }
208
+ if (erb_block_node->rescue_clause != NULL) {
209
+ herb_visit_node((AST_NODE_T*) erb_block_node->rescue_clause, match_tags_visitor, context);
210
+ }
211
+ if (erb_block_node->else_clause != NULL) {
212
+ herb_visit_node((AST_NODE_T*) erb_block_node->else_clause, match_tags_visitor, context);
213
+ }
214
+ if (erb_block_node->ensure_clause != NULL) {
215
+ herb_visit_node((AST_NODE_T*) erb_block_node->ensure_clause, match_tags_visitor, context);
216
+ }
208
217
  if (erb_block_node->end_node != NULL) {
209
218
  herb_visit_node((AST_NODE_T*) erb_block_node->end_node, match_tags_visitor, context);
210
219
  }
@@ -380,6 +389,26 @@ bool match_tags_visitor(const AST_NODE_T* node, void* data) {
380
389
 
381
390
 
382
391
 
392
+ case AST_RUBY_STRICT_LOCAL_NODE: {
393
+ const AST_RUBY_STRICT_LOCAL_NODE_T* ruby_strict_local_node = (const AST_RUBY_STRICT_LOCAL_NODE_T*) node;
394
+
395
+ if (ruby_strict_local_node->default_value != NULL) {
396
+ herb_visit_node((AST_NODE_T*) ruby_strict_local_node->default_value, match_tags_visitor, context);
397
+ }
398
+ } break;
399
+
400
+
401
+
402
+ case AST_ERB_STRICT_LOCALS_NODE: {
403
+ const AST_ERB_STRICT_LOCALS_NODE_T* erb_strict_locals_node = (const AST_ERB_STRICT_LOCALS_NODE_T*) node;
404
+
405
+ if (erb_strict_locals_node->locals != NULL) {
406
+ match_tags_in_node_array(erb_strict_locals_node->locals, context->errors, context->options, context->allocator);
407
+ }
408
+ } break;
409
+
410
+
411
+
383
412
 
384
413
 
385
414
  case AST_ERB_IN_NODE: {
@@ -1,12 +1,12 @@
1
- #include "include/parser_helpers.h"
2
- #include "include/ast_nodes.h"
3
- #include "include/errors.h"
4
- #include "include/lexer.h"
5
- #include "include/parser.h"
6
- #include "include/token.h"
7
- #include "include/util/hb_array.h"
8
- #include "include/util/hb_buffer.h"
9
- #include "include/util/hb_string.h"
1
+ #include "../include/parser/parser_helpers.h"
2
+ #include "../include/ast/ast_nodes.h"
3
+ #include "../include/errors.h"
4
+ #include "../include/lexer/lexer.h"
5
+ #include "../include/lexer/token.h"
6
+ #include "../include/lib/hb_array.h"
7
+ #include "../include/lib/hb_buffer.h"
8
+ #include "../include/lib/hb_string.h"
9
+ #include "../include/parser/parser.h"
10
10
 
11
11
  #include <stdarg.h>
12
12
  #include <stdio.h>
@@ -219,7 +219,7 @@ AST_HTML_ELEMENT_NODE_T* parser_handle_missing_close_tag(
219
219
  body,
220
220
  NULL,
221
221
  false,
222
- ELEMENT_SOURCE_HTML,
222
+ hb_string("HTML"),
223
223
  open_tag->base.location.start,
224
224
  open_tag->base.location.end,
225
225
  errors,
data/src/parser.c CHANGED
@@ -1,18 +1,19 @@
1
- #include "include/parser.h"
2
- #include "include/ast_node.h"
3
- #include "include/ast_nodes.h"
1
+ #include "include/parser/parser.h"
2
+ #include "include/ast/ast_node.h"
3
+ #include "include/ast/ast_nodes.h"
4
4
  #include "include/errors.h"
5
- #include "include/html_util.h"
6
- #include "include/lexer.h"
7
- #include "include/lexer_peek_helpers.h"
8
- #include "include/parser_helpers.h"
9
- #include "include/token.h"
10
- #include "include/token_matchers.h"
11
- #include "include/util.h"
12
- #include "include/util/hb_array.h"
13
- #include "include/util/hb_buffer.h"
14
- #include "include/util/hb_string.h"
15
- #include "include/util/string.h"
5
+ #include "include/lexer/lexer.h"
6
+ #include "include/lexer/lexer_peek_helpers.h"
7
+ #include "include/lexer/token.h"
8
+ #include "include/lexer/token_matchers.h"
9
+ #include "include/lib/hb_array.h"
10
+ #include "include/lib/hb_buffer.h"
11
+ #include "include/lib/hb_string.h"
12
+ #include "include/lib/string.h"
13
+ #include "include/parser/dot_notation.h"
14
+ #include "include/parser/parser_helpers.h"
15
+ #include "include/util/html_util.h"
16
+ #include "include/util/util.h"
16
17
  #include "include/visitor.h"
17
18
 
18
19
  #include <stdio.h>
@@ -38,9 +39,14 @@ const parser_options_T HERB_DEFAULT_PARSER_OPTIONS = { .track_whitespace = false
38
39
  .strict = true,
39
40
  .action_view_helpers = false,
40
41
  .render_nodes = false,
42
+ .strict_locals = false,
41
43
  .prism_nodes_deep = false,
42
44
  .prism_nodes = false,
43
- .prism_program = false };
45
+ .prism_program = false,
46
+ .dot_notation_tags = false,
47
+ .html = true,
48
+ .start_line = 0,
49
+ .start_column = 0 };
44
50
 
45
51
  size_t parser_sizeof(void) {
46
52
  return sizeof(struct PARSER_STRUCT);
@@ -473,7 +479,9 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_quoted_html_attribute_value
473
479
 
474
480
  if (equals_token && equals_token->type == TOKEN_EQUALS) {
475
481
  token_T* after_equals = lexer_next_token(parser->lexer);
476
- looks_like_new_attribute = (after_equals && after_equals->type == TOKEN_QUOTE);
482
+ looks_like_new_attribute =
483
+ (after_equals && after_equals->type == TOKEN_QUOTE && opening_quote != NULL
484
+ && hb_string_equals(after_equals->value, opening_quote->value));
477
485
 
478
486
  if (after_equals) { token_free(after_equals, parser->allocator); }
479
487
  }
@@ -767,7 +775,7 @@ static AST_HTML_ATTRIBUTE_NODE_T* parser_parse_html_attribute(parser_T* parser)
767
775
  equals_with_whitespace->type = TOKEN_EQUALS;
768
776
 
769
777
  char* arena_copy = hb_allocator_strndup(parser->allocator, equals_buffer.value, equals_buffer.length);
770
- equals_with_whitespace->value = (hb_string_T) { .data = arena_copy, .length = (uint32_t) equals_buffer.length };
778
+ equals_with_whitespace->value = hb_string_from_data(arena_copy, equals_buffer.length);
771
779
 
772
780
  hb_buffer_free(&equals_buffer);
773
781
 
@@ -884,7 +892,7 @@ static void parser_skip_erb_content(lexer_T* lexer) {
884
892
  do {
885
893
  token = lexer_next_token(lexer);
886
894
 
887
- if (token->type == TOKEN_ERB_END) {
895
+ if (token->type == TOKEN_ERB_END || token->type == TOKEN_EOF) {
888
896
  token_free(token, lexer->allocator);
889
897
  break;
890
898
  }
@@ -899,6 +907,11 @@ static bool parser_lookahead_erb_is_attribute(lexer_T* lexer) {
899
907
  do {
900
908
  after = lexer_next_token(lexer);
901
909
 
910
+ if (after->type == TOKEN_EOF) {
911
+ token_free(after, lexer->allocator);
912
+ return false;
913
+ }
914
+
902
915
  if (after->type == TOKEN_EQUALS) {
903
916
  token_free(after, lexer->allocator);
904
917
  return true;
@@ -929,14 +942,30 @@ static bool parser_lookahead_erb_is_attribute(lexer_T* lexer) {
929
942
 
930
943
  static bool starts_with_keyword(hb_string_T string, const char* keyword) {
931
944
  hb_string_T prefix = hb_string(keyword);
945
+
932
946
  if (string.length < prefix.length) { return false; }
933
947
  if (strncmp(string.data, prefix.data, prefix.length) != 0) { return false; }
934
-
935
948
  if (string.length == prefix.length) { return true; }
936
949
 
937
950
  return is_whitespace(string.data[prefix.length]);
938
951
  }
939
952
 
953
+ static AST_HTML_TEXT_NODE_T* parser_advance_as_text(parser_T* parser) {
954
+ token_T* token = parser_advance(parser);
955
+
956
+ AST_HTML_TEXT_NODE_T* text = ast_html_text_node_init(
957
+ token->value,
958
+ token->location.start,
959
+ token->location.end,
960
+ hb_array_init(0, parser->allocator),
961
+ parser->allocator
962
+ );
963
+
964
+ token_free(token, parser->allocator);
965
+
966
+ return text;
967
+ }
968
+
940
969
  // TODO: ideally we could avoid basing this off of strings, and use the step in analyze.c
941
970
  static bool parser_lookahead_erb_is_control_flow(parser_T* parser) {
942
971
  lexer_T lexer_copy = *parser->lexer;
@@ -1005,6 +1034,8 @@ static AST_HTML_OPEN_TAG_NODE_T* parser_parse_html_open_tag(parser_T* parser) {
1005
1034
  token_T* tag_start = parser_consume_expected(parser, TOKEN_HTML_TAG_START, errors);
1006
1035
  token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors);
1007
1036
 
1037
+ parser_consume_dot_notation_segments(parser, tag_name, errors);
1038
+
1008
1039
  while (token_is_none_of(parser, TOKEN_HTML_TAG_END, TOKEN_HTML_TAG_SELF_CLOSE, TOKEN_EOF)) {
1009
1040
  if (token_is_any_of(parser, TOKEN_HTML_TAG_START, TOKEN_HTML_TAG_START_CLOSE)) {
1010
1041
  append_unclosed_open_tag_error(
@@ -1182,6 +1213,8 @@ static AST_HTML_CLOSE_TAG_NODE_T* parser_parse_html_close_tag(parser_T* parser)
1182
1213
 
1183
1214
  token_T* tag_name = parser_consume_expected(parser, TOKEN_IDENTIFIER, errors);
1184
1215
 
1216
+ parser_consume_dot_notation_segments(parser, tag_name, errors);
1217
+
1185
1218
  parser_consume_whitespace(parser, children);
1186
1219
 
1187
1220
  token_T* tag_closing = parser_consume_if_present(parser, TOKEN_HTML_TAG_END);
@@ -1246,7 +1279,7 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_self_closing_element(
1246
1279
  NULL,
1247
1280
  NULL,
1248
1281
  true,
1249
- ELEMENT_SOURCE_HTML,
1282
+ hb_string("HTML"),
1250
1283
  open_tag->base.location.start,
1251
1284
  open_tag->base.location.end,
1252
1285
  NULL,
@@ -1318,7 +1351,7 @@ static AST_HTML_ELEMENT_NODE_T* parser_parse_html_regular_element(
1318
1351
  body,
1319
1352
  (AST_NODE_T*) close_tag,
1320
1353
  false,
1321
- ELEMENT_SOURCE_HTML,
1354
+ hb_string("HTML"),
1322
1355
  open_tag->base.location.start,
1323
1356
  close_tag->base.location.end,
1324
1357
  errors,
@@ -1408,13 +1441,7 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children,
1408
1441
  hb_buffer_init(&content, 1024, parser->allocator);
1409
1442
  position_T start = parser->current_token->location.start;
1410
1443
  hb_string_T expected_closing_tag = parser_get_foreign_content_closing_tag(parser->foreign_content_type);
1411
-
1412
- if (hb_string_is_empty(expected_closing_tag)) {
1413
- parser_exit_foreign_content(parser);
1414
- hb_buffer_free(&content);
1415
-
1416
- return;
1417
- }
1444
+ bool has_closing_tag = !hb_string_is_empty(expected_closing_tag);
1418
1445
 
1419
1446
  while (!token_is(parser, TOKEN_EOF)) {
1420
1447
  if (token_is(parser, TOKEN_ERB_START)) {
@@ -1428,7 +1455,7 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children,
1428
1455
  continue;
1429
1456
  }
1430
1457
 
1431
- if (token_is(parser, TOKEN_HTML_TAG_START_CLOSE)) {
1458
+ if (has_closing_tag && token_is(parser, TOKEN_HTML_TAG_START_CLOSE)) {
1432
1459
  lexer_state_snapshot_T saved_state = lexer_save_state(parser->lexer);
1433
1460
 
1434
1461
  token_T* next_token = lexer_next_token(parser->lexer);
@@ -1463,6 +1490,11 @@ static void parser_parse_foreign_content(parser_T* parser, hb_array_T* children,
1463
1490
  }
1464
1491
 
1465
1492
  static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, hb_array_T* errors) {
1493
+ if (!parser->options.html) {
1494
+ parser_parse_foreign_content(parser, children, errors);
1495
+ return;
1496
+ }
1497
+
1466
1498
  while (token_is_not(parser, TOKEN_EOF)) {
1467
1499
 
1468
1500
  if (token_is(parser, TOKEN_ERB_START)) {
@@ -1496,7 +1528,11 @@ static void parser_parse_in_data_state(parser_T* parser, hb_array_T* children, h
1496
1528
  }
1497
1529
 
1498
1530
  if (token_is(parser, TOKEN_HTML_TAG_START)) {
1499
- hb_array_append(children, parser_parse_html_element(parser));
1531
+ if (parser_lookahead_is_valid_dot_notation_open_tag(parser)) {
1532
+ hb_array_append(children, parser_parse_html_element(parser));
1533
+ } else {
1534
+ hb_array_append(children, parser_advance_as_text(parser));
1535
+ }
1500
1536
  parser->consecutive_error_count = 0;
1501
1537
  continue;
1502
1538
  }
@@ -1683,7 +1719,7 @@ static hb_array_T* parser_build_elements_from_tags(
1683
1719
  processed_body,
1684
1720
  (AST_NODE_T*) omitted_close_tag,
1685
1721
  false,
1686
- ELEMENT_SOURCE_HTML,
1722
+ hb_string("HTML"),
1687
1723
  open_tag->base.location.start,
1688
1724
  end_position,
1689
1725
  element_errors,
@@ -1726,7 +1762,7 @@ static hb_array_T* parser_build_elements_from_tags(
1726
1762
  processed_body,
1727
1763
  (AST_NODE_T*) close_tag,
1728
1764
  false,
1729
- ELEMENT_SOURCE_HTML,
1765
+ hb_string("HTML"),
1730
1766
  open_tag->base.location.start,
1731
1767
  close_tag->base.location.end,
1732
1768
  element_errors,