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
@@ -0,0 +1,78 @@
1
+ #ifndef HERB_ALLOCATOR_H
2
+ #define HERB_ALLOCATOR_H
3
+
4
+ #include <stdbool.h>
5
+ #include <stddef.h>
6
+
7
+ #include "hb_arena.h"
8
+
9
+ #ifndef HB_ALLOCATOR_DEFAULT_ARENA_SIZE
10
+ # define HB_ALLOCATOR_DEFAULT_ARENA_SIZE (1024 * 16)
11
+ #endif
12
+
13
+ typedef enum {
14
+ HB_ALLOCATOR_MALLOC,
15
+ HB_ALLOCATOR_ARENA,
16
+ HB_ALLOCATOR_TRACKING,
17
+ } hb_allocator_type_T;
18
+
19
+ typedef struct {
20
+ void* pointer;
21
+ size_t size;
22
+ } hb_allocator_tracking_entry_T;
23
+
24
+ typedef struct {
25
+ size_t allocation_count;
26
+ size_t deallocation_count;
27
+ size_t untracked_deallocation_count;
28
+ size_t bytes_allocated;
29
+ size_t bytes_deallocated;
30
+ hb_allocator_tracking_entry_T* buckets;
31
+ size_t buckets_capacity;
32
+ size_t buckets_used;
33
+ void** untracked_pointers;
34
+ size_t untracked_pointers_size;
35
+ size_t untracked_pointers_capacity;
36
+ } hb_allocator_tracking_stats_T;
37
+
38
+ typedef struct hb_allocator {
39
+ void* (*alloc)(struct hb_allocator* self, size_t size);
40
+ void* (*realloc)(struct hb_allocator* self, void* pointer, size_t old_size, size_t new_size);
41
+ void (*dealloc)(struct hb_allocator* self, void* pointer);
42
+ char* (*strdup)(struct hb_allocator* self, const char* string);
43
+ char* (*strndup)(struct hb_allocator* self, const char* string, size_t length);
44
+ void (*destroy)(struct hb_allocator* self);
45
+ void* context;
46
+ } hb_allocator_T;
47
+
48
+ bool hb_allocator_init(hb_allocator_T* allocator, hb_allocator_type_T type);
49
+ bool hb_allocator_init_with_size(hb_allocator_T* allocator, hb_allocator_type_T type, size_t initial_size);
50
+ void hb_allocator_destroy(hb_allocator_T* allocator);
51
+
52
+ hb_allocator_T hb_allocator_with_malloc(void);
53
+ hb_allocator_T hb_allocator_with_arena(hb_arena_T* arena);
54
+ hb_allocator_T hb_allocator_with_tracking(void);
55
+
56
+ hb_allocator_tracking_stats_T* hb_allocator_tracking_stats(hb_allocator_T* allocator);
57
+
58
+ static inline void* hb_allocator_alloc(hb_allocator_T* allocator, size_t size) {
59
+ return allocator->alloc(allocator, size);
60
+ }
61
+
62
+ static inline void* hb_allocator_realloc(hb_allocator_T* allocator, void* pointer, size_t old_size, size_t new_size) {
63
+ return allocator->realloc(allocator, pointer, old_size, new_size);
64
+ }
65
+
66
+ static inline void hb_allocator_dealloc(hb_allocator_T* allocator, void* pointer) {
67
+ allocator->dealloc(allocator, pointer);
68
+ }
69
+
70
+ static inline char* hb_allocator_strdup(hb_allocator_T* allocator, const char* string) {
71
+ return allocator->strdup(allocator, string);
72
+ }
73
+
74
+ static inline char* hb_allocator_strndup(hb_allocator_T* allocator, const char* string, size_t length) {
75
+ return allocator->strndup(allocator, string, length);
76
+ }
77
+
78
+ #endif
@@ -20,12 +20,17 @@ typedef struct HB_ARENA_STRUCT {
20
20
  size_t allocation_count;
21
21
  } hb_arena_T;
22
22
 
23
+ #define hb_arena_for_each_page(arena) for (hb_arena_page_T* page = (arena)->head; page != NULL; page = page->next)
24
+
25
+ #define hb_arena_for_each_page_const(arena) \
26
+ for (const hb_arena_page_T* page = (arena)->head; page != NULL; page = page->next)
27
+
23
28
  bool hb_arena_init(hb_arena_T* allocator, size_t initial_size);
24
29
  void* hb_arena_alloc(hb_arena_T* allocator, size_t size);
25
30
  size_t hb_arena_position(hb_arena_T* allocator);
26
31
  size_t hb_arena_capacity(hb_arena_T* allocator);
27
32
  void hb_arena_reset(hb_arena_T* allocator);
28
- void hb_arena_reset_to(hb_arena_T* allocator, size_t new_position);
33
+ void hb_arena_reset_to(hb_arena_T* allocator, size_t target_position);
29
34
  void hb_arena_free(hb_arena_T* allocator);
30
35
 
31
36
  #endif
@@ -3,6 +3,17 @@
3
3
 
4
4
  #include "hb_arena.h"
5
5
 
6
- void hb_arena_print_stats(const hb_arena_T* allocator);
6
+ typedef struct {
7
+ size_t pages;
8
+ size_t total_capacity;
9
+ size_t total_used;
10
+ size_t total_available;
11
+ size_t allocations;
12
+ size_t fragmentation;
13
+ size_t default_page_size;
14
+ } hb_arena_stats_T;
15
+
16
+ hb_arena_stats_T hb_arena_get_stats(const hb_arena_T* arena);
17
+ void hb_arena_print_stats(const hb_arena_T* arena);
7
18
 
8
19
  #endif
@@ -1,21 +1,25 @@
1
1
  #ifndef HERB_ARRAY_H
2
2
  #define HERB_ARRAY_H
3
3
 
4
+ #include <stdbool.h>
4
5
  #include <stdlib.h>
5
6
 
7
+ struct hb_allocator;
8
+
6
9
  typedef struct HB_ARRAY_STRUCT {
7
10
  void** items;
8
11
  size_t size;
9
12
  size_t capacity;
13
+ struct hb_allocator* allocator;
10
14
  } hb_array_T;
11
15
 
12
- hb_array_T* hb_array_init(size_t capacity);
16
+ hb_array_T* hb_array_init(size_t capacity, struct hb_allocator* allocator);
13
17
 
14
18
  void* hb_array_get(const hb_array_T* array, size_t index);
15
19
  void* hb_array_first(hb_array_T* array);
16
20
  void* hb_array_last(hb_array_T* array);
17
21
 
18
- void hb_array_append(hb_array_T* array, void* item);
22
+ bool hb_array_append(hb_array_T* array, void* item);
19
23
  void hb_array_set(const hb_array_T* array, size_t index, void* item);
20
24
  void hb_array_free(hb_array_T** array);
21
25
  void hb_array_remove(hb_array_T* array, size_t index);
@@ -23,7 +27,7 @@ void hb_array_remove(hb_array_T* array, size_t index);
23
27
  size_t hb_array_index_of(hb_array_T* array, void* item);
24
28
  void hb_array_remove_item(hb_array_T* array, void* item);
25
29
 
26
- void hb_array_push(hb_array_T* array, void* item);
30
+ bool hb_array_push(hb_array_T* array, void* item);
27
31
  void* hb_array_pop(hb_array_T* array);
28
32
 
29
33
  size_t hb_array_capacity(const hb_array_T* array);
@@ -1,21 +1,21 @@
1
1
  #ifndef HERB_BUFFER_H
2
2
  #define HERB_BUFFER_H
3
3
 
4
- #include "hb_arena.h"
5
4
  #include "hb_string.h"
6
5
 
7
6
  #include <stdbool.h>
8
7
  #include <stdlib.h>
9
8
 
9
+ struct hb_allocator;
10
+
10
11
  typedef struct HB_BUFFER_STRUCT {
11
- hb_arena_T* allocator;
12
+ struct hb_allocator* allocator;
12
13
  char* value;
13
14
  size_t length;
14
15
  size_t capacity;
15
16
  } hb_buffer_T;
16
17
 
17
- bool hb_buffer_init(hb_buffer_T* buffer, size_t capacity);
18
- bool hb_buffer_init_arena(hb_buffer_T* buffer, hb_arena_T* allocator, size_t capacity);
18
+ bool hb_buffer_init(hb_buffer_T* buffer, size_t capacity, struct hb_allocator* allocator);
19
19
 
20
20
  void hb_buffer_append(hb_buffer_T* buffer, const char* text);
21
21
  void hb_buffer_append_with_length(hb_buffer_T* buffer, const char* text, size_t length);
@@ -28,9 +28,11 @@ void hb_buffer_concat(hb_buffer_T* destination, hb_buffer_T* source);
28
28
  char* hb_buffer_value(const hb_buffer_T* buffer);
29
29
 
30
30
  size_t hb_buffer_length(const hb_buffer_T* buffer);
31
+ bool hb_buffer_is_empty(const hb_buffer_T* buffer);
31
32
  size_t hb_buffer_capacity(const hb_buffer_T* buffer);
32
33
  size_t hb_buffer_sizeof(void);
33
34
 
35
+ void hb_buffer_free(hb_buffer_T* buffer);
34
36
  void hb_buffer_clear(hb_buffer_T* buffer);
35
37
 
36
38
  #endif
@@ -0,0 +1,79 @@
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/include/util/hb_foreach.h.erb
3
+
4
+ #ifndef HB_FOREACH_H
5
+ #define HB_FOREACH_H
6
+
7
+ #define HB_ARG64(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,count,...) count
8
+ #define HB_NARGS(...) HB_ARG64(__VA_ARGS__,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
9
+
10
+ #define HB_FOR_EACH_1(macro, head) macro(head)
11
+ #define HB_FOR_EACH_2(macro, head, ...) macro(head), HB_FOR_EACH_1(macro, __VA_ARGS__)
12
+ #define HB_FOR_EACH_3(macro, head, ...) macro(head), HB_FOR_EACH_2(macro, __VA_ARGS__)
13
+ #define HB_FOR_EACH_4(macro, head, ...) macro(head), HB_FOR_EACH_3(macro, __VA_ARGS__)
14
+ #define HB_FOR_EACH_5(macro, head, ...) macro(head), HB_FOR_EACH_4(macro, __VA_ARGS__)
15
+ #define HB_FOR_EACH_6(macro, head, ...) macro(head), HB_FOR_EACH_5(macro, __VA_ARGS__)
16
+ #define HB_FOR_EACH_7(macro, head, ...) macro(head), HB_FOR_EACH_6(macro, __VA_ARGS__)
17
+ #define HB_FOR_EACH_8(macro, head, ...) macro(head), HB_FOR_EACH_7(macro, __VA_ARGS__)
18
+ #define HB_FOR_EACH_9(macro, head, ...) macro(head), HB_FOR_EACH_8(macro, __VA_ARGS__)
19
+ #define HB_FOR_EACH_10(macro, head, ...) macro(head), HB_FOR_EACH_9(macro, __VA_ARGS__)
20
+ #define HB_FOR_EACH_11(macro, head, ...) macro(head), HB_FOR_EACH_10(macro, __VA_ARGS__)
21
+ #define HB_FOR_EACH_12(macro, head, ...) macro(head), HB_FOR_EACH_11(macro, __VA_ARGS__)
22
+ #define HB_FOR_EACH_13(macro, head, ...) macro(head), HB_FOR_EACH_12(macro, __VA_ARGS__)
23
+ #define HB_FOR_EACH_14(macro, head, ...) macro(head), HB_FOR_EACH_13(macro, __VA_ARGS__)
24
+ #define HB_FOR_EACH_15(macro, head, ...) macro(head), HB_FOR_EACH_14(macro, __VA_ARGS__)
25
+ #define HB_FOR_EACH_16(macro, head, ...) macro(head), HB_FOR_EACH_15(macro, __VA_ARGS__)
26
+ #define HB_FOR_EACH_17(macro, head, ...) macro(head), HB_FOR_EACH_16(macro, __VA_ARGS__)
27
+ #define HB_FOR_EACH_18(macro, head, ...) macro(head), HB_FOR_EACH_17(macro, __VA_ARGS__)
28
+ #define HB_FOR_EACH_19(macro, head, ...) macro(head), HB_FOR_EACH_18(macro, __VA_ARGS__)
29
+ #define HB_FOR_EACH_20(macro, head, ...) macro(head), HB_FOR_EACH_19(macro, __VA_ARGS__)
30
+ #define HB_FOR_EACH_21(macro, head, ...) macro(head), HB_FOR_EACH_20(macro, __VA_ARGS__)
31
+ #define HB_FOR_EACH_22(macro, head, ...) macro(head), HB_FOR_EACH_21(macro, __VA_ARGS__)
32
+ #define HB_FOR_EACH_23(macro, head, ...) macro(head), HB_FOR_EACH_22(macro, __VA_ARGS__)
33
+ #define HB_FOR_EACH_24(macro, head, ...) macro(head), HB_FOR_EACH_23(macro, __VA_ARGS__)
34
+ #define HB_FOR_EACH_25(macro, head, ...) macro(head), HB_FOR_EACH_24(macro, __VA_ARGS__)
35
+ #define HB_FOR_EACH_26(macro, head, ...) macro(head), HB_FOR_EACH_25(macro, __VA_ARGS__)
36
+ #define HB_FOR_EACH_27(macro, head, ...) macro(head), HB_FOR_EACH_26(macro, __VA_ARGS__)
37
+ #define HB_FOR_EACH_28(macro, head, ...) macro(head), HB_FOR_EACH_27(macro, __VA_ARGS__)
38
+ #define HB_FOR_EACH_29(macro, head, ...) macro(head), HB_FOR_EACH_28(macro, __VA_ARGS__)
39
+ #define HB_FOR_EACH_30(macro, head, ...) macro(head), HB_FOR_EACH_29(macro, __VA_ARGS__)
40
+ #define HB_FOR_EACH_31(macro, head, ...) macro(head), HB_FOR_EACH_30(macro, __VA_ARGS__)
41
+ #define HB_FOR_EACH_32(macro, head, ...) macro(head), HB_FOR_EACH_31(macro, __VA_ARGS__)
42
+ #define HB_FOR_EACH_33(macro, head, ...) macro(head), HB_FOR_EACH_32(macro, __VA_ARGS__)
43
+ #define HB_FOR_EACH_34(macro, head, ...) macro(head), HB_FOR_EACH_33(macro, __VA_ARGS__)
44
+ #define HB_FOR_EACH_35(macro, head, ...) macro(head), HB_FOR_EACH_34(macro, __VA_ARGS__)
45
+ #define HB_FOR_EACH_36(macro, head, ...) macro(head), HB_FOR_EACH_35(macro, __VA_ARGS__)
46
+ #define HB_FOR_EACH_37(macro, head, ...) macro(head), HB_FOR_EACH_36(macro, __VA_ARGS__)
47
+ #define HB_FOR_EACH_38(macro, head, ...) macro(head), HB_FOR_EACH_37(macro, __VA_ARGS__)
48
+ #define HB_FOR_EACH_39(macro, head, ...) macro(head), HB_FOR_EACH_38(macro, __VA_ARGS__)
49
+ #define HB_FOR_EACH_40(macro, head, ...) macro(head), HB_FOR_EACH_39(macro, __VA_ARGS__)
50
+ #define HB_FOR_EACH_41(macro, head, ...) macro(head), HB_FOR_EACH_40(macro, __VA_ARGS__)
51
+ #define HB_FOR_EACH_42(macro, head, ...) macro(head), HB_FOR_EACH_41(macro, __VA_ARGS__)
52
+ #define HB_FOR_EACH_43(macro, head, ...) macro(head), HB_FOR_EACH_42(macro, __VA_ARGS__)
53
+ #define HB_FOR_EACH_44(macro, head, ...) macro(head), HB_FOR_EACH_43(macro, __VA_ARGS__)
54
+ #define HB_FOR_EACH_45(macro, head, ...) macro(head), HB_FOR_EACH_44(macro, __VA_ARGS__)
55
+ #define HB_FOR_EACH_46(macro, head, ...) macro(head), HB_FOR_EACH_45(macro, __VA_ARGS__)
56
+ #define HB_FOR_EACH_47(macro, head, ...) macro(head), HB_FOR_EACH_46(macro, __VA_ARGS__)
57
+ #define HB_FOR_EACH_48(macro, head, ...) macro(head), HB_FOR_EACH_47(macro, __VA_ARGS__)
58
+ #define HB_FOR_EACH_49(macro, head, ...) macro(head), HB_FOR_EACH_48(macro, __VA_ARGS__)
59
+ #define HB_FOR_EACH_50(macro, head, ...) macro(head), HB_FOR_EACH_49(macro, __VA_ARGS__)
60
+ #define HB_FOR_EACH_51(macro, head, ...) macro(head), HB_FOR_EACH_50(macro, __VA_ARGS__)
61
+ #define HB_FOR_EACH_52(macro, head, ...) macro(head), HB_FOR_EACH_51(macro, __VA_ARGS__)
62
+ #define HB_FOR_EACH_53(macro, head, ...) macro(head), HB_FOR_EACH_52(macro, __VA_ARGS__)
63
+ #define HB_FOR_EACH_54(macro, head, ...) macro(head), HB_FOR_EACH_53(macro, __VA_ARGS__)
64
+ #define HB_FOR_EACH_55(macro, head, ...) macro(head), HB_FOR_EACH_54(macro, __VA_ARGS__)
65
+ #define HB_FOR_EACH_56(macro, head, ...) macro(head), HB_FOR_EACH_55(macro, __VA_ARGS__)
66
+ #define HB_FOR_EACH_57(macro, head, ...) macro(head), HB_FOR_EACH_56(macro, __VA_ARGS__)
67
+ #define HB_FOR_EACH_58(macro, head, ...) macro(head), HB_FOR_EACH_57(macro, __VA_ARGS__)
68
+ #define HB_FOR_EACH_59(macro, head, ...) macro(head), HB_FOR_EACH_58(macro, __VA_ARGS__)
69
+ #define HB_FOR_EACH_60(macro, head, ...) macro(head), HB_FOR_EACH_59(macro, __VA_ARGS__)
70
+ #define HB_FOR_EACH_61(macro, head, ...) macro(head), HB_FOR_EACH_60(macro, __VA_ARGS__)
71
+ #define HB_FOR_EACH_62(macro, head, ...) macro(head), HB_FOR_EACH_61(macro, __VA_ARGS__)
72
+ #define HB_FOR_EACH_63(macro, head, ...) macro(head), HB_FOR_EACH_62(macro, __VA_ARGS__)
73
+ #define HB_FOR_EACH_64(macro, head, ...) macro(head), HB_FOR_EACH_63(macro, __VA_ARGS__)
74
+
75
+ #define HB_CONCAT(left, right) left ## right
76
+ #define HB_FOR_EACH_N(count) HB_CONCAT(HB_FOR_EACH_, count)
77
+ #define HB_FOR_EACH(macro, ...) HB_FOR_EACH_N(HB_NARGS(__VA_ARGS__))(macro, __VA_ARGS__)
78
+
79
+ #endif
@@ -1,26 +1,30 @@
1
1
  #ifndef HERB_NARRAY_H
2
2
  #define HERB_NARRAY_H
3
3
 
4
+ #include <stdbool.h>
4
5
  #include <stdint.h>
5
6
  #include <stdlib.h>
6
- #include <stdbool.h>
7
+
8
+ #include "hb_allocator.h"
7
9
 
8
10
  typedef struct HB_NARRAY_STRUCT {
11
+ hb_allocator_T* allocator;
9
12
  uint8_t* items;
10
13
  size_t item_size;
11
14
  size_t size;
12
15
  size_t capacity;
13
16
  } hb_narray_T;
14
17
 
15
- void hb_narray_init(hb_narray_T* array, size_t item_size, size_t initial_capacity);
16
- #define hb_narray_pointer_init(array, initial_capacity) (hb_narray_init(array, sizeof(void*), initial_capacity))
18
+ bool hb_narray_init(hb_narray_T* array, size_t item_size, size_t initial_capacity, hb_allocator_T* allocator);
19
+ #define hb_narray_pointer_init(array, initial_capacity, allocator) \
20
+ (hb_narray_init(array, sizeof(void*), initial_capacity, allocator))
17
21
 
18
22
  void* hb_narray_get(const hb_narray_T* array, size_t index);
19
23
  void* hb_narray_first(hb_narray_T* array);
20
24
  void* hb_narray_last(hb_narray_T* array);
21
25
  size_t hb_narray_size(const hb_narray_T* array);
22
26
 
23
- void hb_narray_append(hb_narray_T* array, void* item);
27
+ bool hb_narray_append(hb_narray_T* array, void* item);
24
28
  void hb_narray_remove(hb_narray_T* array, size_t index);
25
29
  void hb_narray_deinit(hb_narray_T* array);
26
30
 
@@ -4,26 +4,73 @@
4
4
  #include <stdbool.h>
5
5
  #include <stddef.h>
6
6
  #include <stdint.h>
7
+ #include <string.h>
8
+ #include <strings.h>
7
9
 
8
- #include "hb_arena.h"
10
+ #include "hb_allocator.h"
11
+ #include "hb_foreach.h"
9
12
 
10
13
  typedef struct HB_STRING_STRUCT {
11
14
  char* data;
12
15
  uint32_t length;
13
16
  } hb_string_T;
14
17
 
15
- hb_string_T hb_string(const char* null_terminated_c_string);
16
- hb_string_T hb_string_slice(hb_string_T string, uint32_t offset);
17
- bool hb_string_equals(hb_string_T a, hb_string_T b);
18
- bool hb_string_equals_case_insensitive(hb_string_T a, hb_string_T b);
19
- bool hb_string_starts_with(hb_string_T string, hb_string_T expected_prefix);
20
- bool hb_string_is_empty(hb_string_T string);
21
- hb_string_T hb_string_truncate(hb_string_T string, uint32_t max_length);
18
+ #define HB_STRING_EMPTY ((hb_string_T) { .data = "", .length = 0 })
19
+ #define HB_STRING_NULL ((hb_string_T) { .data = NULL, .length = 0 })
20
+
21
+ #define HB_STRING_LITERAL(string) { .data = (char*) (string), .length = (uint32_t) (sizeof(string) - 1) }
22
+
23
+ #define HB_STRING_LIST(...) { HB_FOR_EACH(HB_STRING_LITERAL, __VA_ARGS__) }
24
+
25
+ #define hb_string(string) \
26
+ (__builtin_constant_p(string) \
27
+ ? ((hb_string_T) { .data = (char*) (string), .length = (uint32_t) __builtin_strlen(string) }) \
28
+ : hb_string_from_c_string(string))
29
+
30
+ hb_string_T hb_string_from_c_string(const char* null_terminated_c_string);
31
+
32
+ static inline bool hb_string_is_null(hb_string_T string) {
33
+ return string.data == NULL;
34
+ }
35
+
36
+ static inline bool hb_string_is_empty(hb_string_T string) {
37
+ return string.data == NULL || string.length == 0;
38
+ }
39
+
40
+ static inline hb_string_T hb_string_slice(hb_string_T string, uint32_t offset) {
41
+ if (string.length < offset) { return HB_STRING_NULL; }
42
+
43
+ return (hb_string_T) { .data = string.data + offset, .length = string.length - offset };
44
+ }
22
45
 
46
+ static inline bool hb_string_equals(hb_string_T a, hb_string_T b) {
47
+ if (a.length != b.length) { return false; }
48
+
49
+ return strncmp(a.data, b.data, a.length) == 0;
50
+ }
51
+
52
+ static inline bool hb_string_equals_case_insensitive(hb_string_T a, hb_string_T b) {
53
+ if (a.length != b.length) { return false; }
54
+
55
+ return strncasecmp(a.data, b.data, a.length) == 0;
56
+ }
57
+
58
+ static inline bool hb_string_starts_with(hb_string_T string, hb_string_T expected_prefix) {
59
+ if (hb_string_is_empty(string) || hb_string_is_empty(expected_prefix)) { return false; }
60
+ if (string.length < expected_prefix.length) { return false; }
61
+
62
+ return strncmp(string.data, expected_prefix.data, expected_prefix.length) == 0;
63
+ }
64
+
65
+ hb_string_T hb_string_truncate(hb_string_T string, uint32_t max_length);
23
66
  hb_string_T hb_string_range(hb_string_T string, uint32_t from, uint32_t to);
67
+ hb_string_T hb_string_trim_start(hb_string_T string);
68
+ hb_string_T hb_string_trim_end(hb_string_T string);
69
+ hb_string_T hb_string_trim(hb_string_T string);
70
+ bool hb_string_is_blank(hb_string_T string);
71
+ hb_string_T hb_string_copy(hb_string_T string, hb_allocator_T* allocator);
24
72
 
25
73
  char* hb_string_to_c_string_using_malloc(hb_string_T string);
26
-
27
74
  char* hb_string_to_c_string(hb_arena_T* allocator, hb_string_T string);
28
75
 
29
76
  #endif
data/src/include/util.h CHANGED
@@ -5,10 +5,13 @@
5
5
  #include <stdbool.h>
6
6
  #include <stdlib.h>
7
7
 
8
+ struct hb_allocator;
9
+
8
10
  int is_newline(int character);
11
+ int is_whitespace(int character);
12
+ hb_string_T escape_newlines(struct hb_allocator* allocator, hb_string_T input);
13
+ hb_string_T quoted_string(struct hb_allocator* allocator, hb_string_T input);
9
14
 
10
- hb_string_T escape_newlines(hb_string_T input);
11
- hb_string_T quoted_string(hb_string_T input);
12
- char* herb_strdup(const char* s);
15
+ char* convert_underscores_to_dashes(const char* input);
13
16
 
14
17
  #endif
@@ -1,6 +1,6 @@
1
1
  #ifndef HERB_VERSION_H
2
2
  #define HERB_VERSION_H
3
3
 
4
- #define HERB_VERSION "0.8.10"
4
+ #define HERB_VERSION "0.9.0"
5
5
 
6
6
  #endif
data/src/io.c CHANGED
@@ -1,4 +1,5 @@
1
1
  #include "include/io.h"
2
+ #include "include/util/hb_allocator.h"
2
3
  #include "include/util/hb_buffer.h"
3
4
 
4
5
  #include <errno.h>
@@ -7,7 +8,7 @@
7
8
 
8
9
  #define FILE_READ_CHUNK 4096
9
10
 
10
- char* herb_read_file(const char* filename) {
11
+ char* herb_read_file(const char* filename, struct hb_allocator* allocator) {
11
12
  if (!filename) { return NULL; }
12
13
 
13
14
  FILE* fp = fopen(filename, "rb");
@@ -18,7 +19,7 @@ char* herb_read_file(const char* filename) {
18
19
  }
19
20
 
20
21
  hb_buffer_T buffer;
21
- hb_buffer_init(&buffer, 4096);
22
+ hb_buffer_init(&buffer, 4096, allocator);
22
23
 
23
24
  char chunk[FILE_READ_CHUNK];
24
25
  size_t bytes_read;
data/src/lexer.c CHANGED
@@ -1,15 +1,18 @@
1
1
  #include "include/lexer_peek_helpers.h"
2
+ #include "include/macros.h"
2
3
  #include "include/token.h"
3
4
  #include "include/utf8.h"
4
5
  #include "include/util.h"
5
- #include "include/util/hb_buffer.h"
6
6
  #include "include/util/hb_string.h"
7
7
 
8
8
  #include <ctype.h>
9
+ #include <stdint.h>
9
10
  #include <string.h>
10
11
 
11
12
  #define LEXER_STALL_LIMIT 5
12
13
 
14
+ static hb_string_T erb_open_patterns[] = HB_STRING_LIST("<%==", "<%%=", "<%graphql", "<%=", "<%#", "<%-", "<%%", "<%");
15
+
13
16
  static bool lexer_eof(const lexer_T* lexer) {
14
17
  return lexer->current_character == '\0' || lexer->stalled;
15
18
  }
@@ -31,11 +34,13 @@ static bool lexer_stalled(lexer_T* lexer) {
31
34
  return lexer->stalled;
32
35
  }
33
36
 
34
- void lexer_init(lexer_T* lexer, const char* source) {
37
+ void lexer_init(lexer_T* lexer, const char* source, hb_allocator_T* allocator) {
38
+ lexer->allocator = allocator;
39
+
35
40
  if (source != NULL) {
36
41
  lexer->source = hb_string(source);
37
42
  } else {
38
- lexer->source = hb_string("");
43
+ lexer->source = HB_STRING_EMPTY;
39
44
  }
40
45
 
41
46
  lexer->current_character = lexer->source.data[0];
@@ -55,11 +60,11 @@ void lexer_init(lexer_T* lexer, const char* source) {
55
60
  }
56
61
 
57
62
  token_T* lexer_error(lexer_T* lexer, const char* message) {
58
- char error_message[128];
63
+ char buffer[128];
59
64
 
60
65
  snprintf(
61
- error_message,
62
- sizeof(error_message),
66
+ buffer,
67
+ sizeof(buffer),
63
68
  "[Lexer] Error: %s (character '%c', line %u, col %u)\n",
64
69
  message,
65
70
  lexer->current_character,
@@ -67,7 +72,10 @@ token_T* lexer_error(lexer_T* lexer, const char* message) {
67
72
  lexer->current_column
68
73
  );
69
74
 
70
- return token_init(hb_string(error_message), TOKEN_ERROR, lexer);
75
+ size_t length = strlen(buffer);
76
+ char* error_message = hb_allocator_strndup(lexer->allocator, buffer, length);
77
+
78
+ return token_init((hb_string_T) { .data = error_message, .length = (uint32_t) length }, TOKEN_ERROR, lexer);
71
79
  }
72
80
 
73
81
  static void lexer_advance(lexer_T* lexer) {
@@ -79,8 +87,8 @@ static void lexer_advance(lexer_T* lexer) {
79
87
  }
80
88
  }
81
89
 
82
- static void lexer_advance_utf8_bytes(lexer_T* lexer, int byte_count) {
83
- if (byte_count <= 0) { return; }
90
+ static void lexer_advance_utf8_bytes(lexer_T* lexer, uint32_t byte_count) {
91
+ if (byte_count == 0) { return; }
84
92
 
85
93
  if (lexer_has_more_characters(lexer) && !lexer_eof(lexer)) {
86
94
  if (!is_newline(lexer->current_character)) { lexer->current_column++; }
@@ -120,19 +128,17 @@ static token_T* lexer_advance_with_next(lexer_T* lexer, size_t count, token_type
120
128
  }
121
129
 
122
130
  static token_T* lexer_advance_current(lexer_T* lexer, const token_type_T type) {
123
- char buffer[2];
124
- buffer[0] = lexer->current_character;
125
- buffer[1] = '\0';
126
-
127
- return lexer_advance_with(lexer, hb_string(buffer), type);
131
+ return lexer_advance_with_next(lexer, 1, type);
128
132
  }
129
133
 
130
134
  static token_T* lexer_advance_utf8_character(lexer_T* lexer, const token_type_T type) {
131
- int char_byte_length = utf8_sequence_length(lexer->source.data, lexer->current_position, lexer->source.length);
135
+ uint32_t char_byte_length = utf8_sequence_length(hb_string_slice(lexer->source, lexer->current_position));
136
+
132
137
  if (char_byte_length <= 1) { return lexer_advance_current(lexer, type); }
138
+
133
139
  uint32_t start_position = lexer->current_position;
134
140
 
135
- for (int i = 0; i < char_byte_length; i++) {
141
+ for (uint32_t i = 0; i < char_byte_length; i++) {
136
142
  if (lexer->current_position + i >= lexer->source.length) { return lexer_advance_current(lexer, type); }
137
143
  }
138
144
 
@@ -171,7 +177,8 @@ static token_T* lexer_parse_identifier(lexer_T* lexer) {
171
177
 
172
178
  while ((isalnum(lexer->current_character) || lexer->current_character == '-' || lexer->current_character == '_'
173
179
  || lexer->current_character == ':')
174
- && !lexer_peek_for_html_comment_end(lexer, 0) && !lexer_eof(lexer)) {
180
+ && !lexer_peek_for_html_comment_end(lexer, 0) && !lexer_peek_for_html_comment_invalid_end(lexer, 0)
181
+ && !lexer_eof(lexer)) {
175
182
 
176
183
  lexer_advance(lexer);
177
184
  }
@@ -185,13 +192,9 @@ static token_T* lexer_parse_identifier(lexer_T* lexer) {
185
192
  // ===== ERB Parsing
186
193
 
187
194
  static token_T* lexer_parse_erb_open(lexer_T* lexer) {
188
- hb_string_T erb_patterns[] = { hb_string("<%=="), hb_string("<%%="), hb_string("<%="), hb_string("<%#"),
189
- hb_string("<%-"), hb_string("<%%"), hb_string("<%graphql"), hb_string("<%") };
190
-
191
195
  lexer->state = STATE_ERB_CONTENT;
192
-
193
- for (size_t i = 0; i < sizeof(erb_patterns) / sizeof(erb_patterns[0]); i++) {
194
- token_T* match = lexer_match_and_advance(lexer, erb_patterns[i], TOKEN_ERB_START);
196
+ for (size_t i = 0; i < sizeof(erb_open_patterns) / sizeof(erb_open_patterns[0]); i++) {
197
+ token_T* match = lexer_match_and_advance(lexer, erb_open_patterns[i], TOKEN_ERB_START);
195
198
  if (match) { return match; }
196
199
  }
197
200
 
@@ -203,11 +206,17 @@ static token_T* lexer_parse_erb_content(lexer_T* lexer) {
203
206
 
204
207
  while (!lexer_peek_erb_end(lexer, 0)) {
205
208
  if (lexer_eof(lexer)) {
206
- token_T* token = token_init(
207
- hb_string_range(lexer->source, start_position, lexer->current_position),
208
- TOKEN_ERROR,
209
- lexer
210
- ); // Handle unexpected EOF
209
+ token_T* token =
210
+ token_init(hb_string_range(lexer->source, start_position, lexer->current_position), TOKEN_ERB_CONTENT, lexer);
211
+
212
+ return token;
213
+ }
214
+
215
+ if (lexer_peek_erb_start(lexer, 0)) {
216
+ lexer->state = STATE_DATA;
217
+
218
+ token_T* token =
219
+ token_init(hb_string_range(lexer->source, start_position, lexer->current_position), TOKEN_ERB_CONTENT, lexer);
211
220
 
212
221
  return token;
213
222
  }
@@ -244,7 +253,7 @@ static token_T* lexer_parse_erb_close(lexer_T* lexer) {
244
253
  // ===== Tokenizing Function
245
254
 
246
255
  token_T* lexer_next_token(lexer_T* lexer) {
247
- if (lexer_eof(lexer)) { return token_init(hb_string(""), TOKEN_EOF, lexer); }
256
+ if (lexer_eof(lexer)) { return token_init(HB_STRING_EMPTY, TOKEN_EOF, lexer); }
248
257
  if (lexer_stalled(lexer)) { return lexer_error(lexer, "Lexer stalled after 5 iterations"); }
249
258
 
250
259
  if (lexer->state == STATE_ERB_CONTENT) { return lexer_parse_erb_content(lexer); }
@@ -302,7 +311,10 @@ token_T* lexer_next_token(lexer_T* lexer) {
302
311
  }
303
312
 
304
313
  case '-': {
305
- token_T* token = lexer_match_and_advance(lexer, hb_string("-->"), TOKEN_HTML_COMMENT_END);
314
+ token_T* token = lexer_match_and_advance(lexer, hb_string("--!>"), TOKEN_HTML_COMMENT_INVALID_END);
315
+ if (token) { return token; }
316
+
317
+ token = lexer_match_and_advance(lexer, hb_string("-->"), TOKEN_HTML_COMMENT_END);
306
318
  return token ? token : lexer_advance_current(lexer, TOKEN_DASH);
307
319
  }
308
320