herb 0.7.4-aarch64-linux-gnu → 0.8.0-aarch64-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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +8 -5
  3. data/config.yml +40 -20
  4. data/ext/herb/error_helpers.c +57 -3
  5. data/ext/herb/error_helpers.h +1 -1
  6. data/ext/herb/extconf.rb +1 -0
  7. data/ext/herb/extension.c +10 -24
  8. data/ext/herb/extension_helpers.c +12 -18
  9. data/ext/herb/extension_helpers.h +4 -4
  10. data/ext/herb/nodes.c +72 -37
  11. data/herb.gemspec +0 -2
  12. data/lib/herb/3.0/herb.so +0 -0
  13. data/lib/herb/3.1/herb.so +0 -0
  14. data/lib/herb/3.2/herb.so +0 -0
  15. data/lib/herb/3.3/herb.so +0 -0
  16. data/lib/herb/3.4/herb.so +0 -0
  17. data/lib/herb/ast/helpers.rb +11 -0
  18. data/lib/herb/ast/node.rb +15 -6
  19. data/lib/herb/ast/nodes.rb +609 -392
  20. data/lib/herb/cli.rb +31 -0
  21. data/lib/herb/colors.rb +82 -0
  22. data/lib/herb/engine/compiler.rb +140 -14
  23. data/lib/herb/engine/debug_visitor.rb +1 -5
  24. data/lib/herb/engine/parser_error_overlay.rb +1 -1
  25. data/lib/herb/engine.rb +18 -20
  26. data/lib/herb/errors.rb +166 -56
  27. data/lib/herb/location.rb +2 -2
  28. data/lib/herb/project.rb +86 -21
  29. data/lib/herb/token.rb +14 -2
  30. data/lib/herb/version.rb +1 -1
  31. data/lib/herb.rb +1 -0
  32. data/sig/herb/ast/helpers.rbs +3 -0
  33. data/sig/herb/ast/node.rbs +12 -5
  34. data/sig/herb/ast/nodes.rbs +124 -62
  35. data/sig/herb/colors.rbs +35 -0
  36. data/sig/herb/engine/compiler.rbs +23 -1
  37. data/sig/herb/errors.rbs +74 -20
  38. data/sig/herb/token.rbs +8 -0
  39. data/sig/herb_c_extension.rbs +1 -1
  40. data/sig/serialized_ast_errors.rbs +8 -0
  41. data/src/analyze.c +461 -249
  42. data/src/analyze_helpers.c +5 -0
  43. data/src/analyze_missing_end.c +147 -0
  44. data/src/analyze_transform.c +196 -0
  45. data/src/analyzed_ruby.c +23 -2
  46. data/src/ast_node.c +14 -17
  47. data/src/ast_nodes.c +179 -181
  48. data/src/ast_pretty_print.c +232 -232
  49. data/src/element_source.c +7 -6
  50. data/src/errors.c +272 -152
  51. data/src/extract.c +92 -34
  52. data/src/herb.c +37 -49
  53. data/src/html_util.c +34 -96
  54. data/src/include/analyze.h +10 -2
  55. data/src/include/analyze_helpers.h +3 -0
  56. data/src/include/analyzed_ruby.h +4 -2
  57. data/src/include/ast_node.h +4 -4
  58. data/src/include/ast_nodes.h +68 -67
  59. data/src/include/ast_pretty_print.h +2 -2
  60. data/src/include/element_source.h +3 -1
  61. data/src/include/errors.h +42 -26
  62. data/src/include/extract.h +4 -4
  63. data/src/include/herb.h +6 -7
  64. data/src/include/html_util.h +4 -5
  65. data/src/include/lexer.h +1 -3
  66. data/src/include/lexer_peek_helpers.h +21 -19
  67. data/src/include/lexer_struct.h +12 -10
  68. data/src/include/location.h +10 -13
  69. data/src/include/macros.h +4 -0
  70. data/src/include/parser.h +12 -6
  71. data/src/include/parser_helpers.h +26 -16
  72. data/src/include/position.h +3 -14
  73. data/src/include/pretty_print.h +38 -28
  74. data/src/include/prism_helpers.h +1 -1
  75. data/src/include/range.h +4 -13
  76. data/src/include/token.h +5 -11
  77. data/src/include/token_struct.h +2 -2
  78. data/src/include/utf8.h +3 -2
  79. data/src/include/util/hb_arena.h +31 -0
  80. data/src/include/util/hb_arena_debug.h +8 -0
  81. data/src/include/util/hb_array.h +33 -0
  82. data/src/include/util/hb_buffer.h +34 -0
  83. data/src/include/util/hb_string.h +29 -0
  84. data/src/include/util/hb_system.h +9 -0
  85. data/src/include/util.h +3 -14
  86. data/src/include/version.h +1 -1
  87. data/src/include/visitor.h +1 -1
  88. data/src/io.c +7 -4
  89. data/src/lexer.c +62 -88
  90. data/src/lexer_peek_helpers.c +42 -38
  91. data/src/location.c +9 -37
  92. data/src/main.c +19 -23
  93. data/src/parser.c +373 -313
  94. data/src/parser_helpers.c +60 -54
  95. data/src/parser_match_tags.c +316 -0
  96. data/src/pretty_print.c +88 -117
  97. data/src/prism_helpers.c +7 -7
  98. data/src/range.c +2 -35
  99. data/src/token.c +36 -87
  100. data/src/utf8.c +4 -4
  101. data/src/util/hb_arena.c +179 -0
  102. data/src/util/hb_arena_debug.c +237 -0
  103. data/src/{array.c → util/hb_array.c} +26 -27
  104. data/src/util/hb_buffer.c +203 -0
  105. data/src/util/hb_string.c +85 -0
  106. data/src/util/hb_system.c +30 -0
  107. data/src/util.c +29 -99
  108. data/src/visitor.c +54 -54
  109. data/templates/ext/herb/error_helpers.c.erb +3 -3
  110. data/templates/ext/herb/error_helpers.h.erb +1 -1
  111. data/templates/ext/herb/nodes.c.erb +11 -6
  112. data/templates/java/error_helpers.c.erb +75 -0
  113. data/templates/java/error_helpers.h.erb +20 -0
  114. data/templates/java/nodes.c.erb +97 -0
  115. data/templates/java/nodes.h.erb +23 -0
  116. data/templates/java/org/herb/ast/Errors.java.erb +121 -0
  117. data/templates/java/org/herb/ast/NodeVisitor.java.erb +14 -0
  118. data/templates/java/org/herb/ast/Nodes.java.erb +220 -0
  119. data/templates/java/org/herb/ast/Visitor.java.erb +56 -0
  120. data/templates/javascript/packages/core/src/visitor.ts.erb +29 -1
  121. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +8 -8
  122. data/templates/javascript/packages/node/extension/error_helpers.h.erb +1 -1
  123. data/templates/javascript/packages/node/extension/nodes.cpp.erb +9 -9
  124. data/templates/javascript/packages/node/extension/nodes.h.erb +1 -1
  125. data/templates/lib/herb/ast/nodes.rb.erb +28 -16
  126. data/templates/lib/herb/errors.rb.erb +17 -12
  127. data/templates/rust/src/ast/nodes.rs.erb +220 -0
  128. data/templates/rust/src/errors.rs.erb +216 -0
  129. data/templates/rust/src/nodes.rs.erb +374 -0
  130. data/templates/src/analyze_missing_end.c.erb +36 -0
  131. data/templates/src/analyze_transform.c.erb +24 -0
  132. data/templates/src/ast_nodes.c.erb +14 -16
  133. data/templates/src/ast_pretty_print.c.erb +36 -36
  134. data/templates/src/errors.c.erb +36 -38
  135. data/templates/src/include/ast_nodes.h.erb +11 -10
  136. data/templates/src/include/ast_pretty_print.h.erb +2 -2
  137. data/templates/src/include/errors.h.erb +9 -9
  138. data/templates/src/parser_match_tags.c.erb +38 -0
  139. data/templates/src/visitor.c.erb +4 -4
  140. data/templates/template.rb +22 -3
  141. data/templates/wasm/error_helpers.cpp.erb +9 -9
  142. data/templates/wasm/error_helpers.h.erb +1 -1
  143. data/templates/wasm/nodes.cpp.erb +9 -9
  144. data/templates/wasm/nodes.h.erb +1 -1
  145. data/vendor/prism/Rakefile +4 -1
  146. data/vendor/prism/config.yml +2 -1
  147. data/vendor/prism/include/prism/ast.h +31 -1
  148. data/vendor/prism/include/prism/diagnostic.h +1 -0
  149. data/vendor/prism/include/prism/version.h +3 -3
  150. data/vendor/prism/src/diagnostic.c +3 -1
  151. data/vendor/prism/src/prism.c +130 -71
  152. data/vendor/prism/src/util/pm_string.c +6 -8
  153. data/vendor/prism/templates/include/prism/ast.h.erb +2 -0
  154. data/vendor/prism/templates/java/org/prism/Loader.java.erb +2 -2
  155. data/vendor/prism/templates/javascript/src/deserialize.js.erb +2 -2
  156. data/vendor/prism/templates/lib/prism/serialize.rb.erb +2 -2
  157. data/vendor/prism/templates/sig/prism.rbs.erb +4 -0
  158. data/vendor/prism/templates/src/diagnostic.c.erb +1 -0
  159. metadata +34 -21
  160. data/lib/herb/libherb/array.rb +0 -51
  161. data/lib/herb/libherb/ast_node.rb +0 -50
  162. data/lib/herb/libherb/buffer.rb +0 -56
  163. data/lib/herb/libherb/extract_result.rb +0 -20
  164. data/lib/herb/libherb/lex_result.rb +0 -32
  165. data/lib/herb/libherb/libherb.rb +0 -52
  166. data/lib/herb/libherb/parse_result.rb +0 -20
  167. data/lib/herb/libherb/token.rb +0 -46
  168. data/lib/herb/libherb.rb +0 -35
  169. data/src/buffer.c +0 -232
  170. data/src/include/array.h +0 -33
  171. data/src/include/buffer.h +0 -39
  172. data/src/include/json.h +0 -28
  173. data/src/include/memory.h +0 -12
  174. data/src/json.c +0 -205
  175. data/src/memory.c +0 -53
  176. data/src/position.c +0 -33
@@ -37,14 +37,16 @@ module Herb
37
37
  to_hash.to_json(state)
38
38
  end
39
39
 
40
- #: (?Integer) -> String
41
- def tree_inspect(_indent = 0)
40
+ #: (?indent: Integer, ?depth: Integer, ?depth_limit: Integer) -> String
41
+ def tree_inspect(indent: 0, depth: 0, depth_limit: 25)
42
42
  raise NotImplementedError
43
43
  end
44
44
  end
45
45
 
46
46
  <%- errors.each do |error| -%>
47
47
  class <%= error.name -%> < Error
48
+ include Colors
49
+
48
50
  <%- error.fields.each do |field| -%>
49
51
  attr_reader :<%= field.name %> #: <%= field.ruby_type %>
50
52
  <%- end -%>
@@ -72,27 +74,30 @@ module Herb
72
74
  }) #: Herb::serialized_<%= error.human %>
73
75
  end
74
76
 
75
- #: (?Integer) -> String
76
- def tree_inspect(indent = 0)
77
+ #: (?indent: Integer, ?depth: Integer, ?depth_limit: Integer) -> String
78
+ def tree_inspect(indent: 0, depth: 0, depth_limit: 25)
77
79
  output = +""
78
80
 
79
- output += %(@ #{error_name} #{location.tree_inspect}\n)
81
+ output += white("@ #{bold(red(error_name))} #{dimmed("(location: #{location.tree_inspect})\n")}")
80
82
  <%- symbol = error.fields.none? ? "└──" : "├──" -%>
81
- output += %(<%= symbol %> message: #{message.inspect}\n)
83
+ output += white("<%= symbol %> message: #{green(message.inspect)}\n")
82
84
  <%- error.fields.each do |field| -%>
83
85
  <%- symbol = error.fields.last == field ? "└──" : "├──" -%>
84
- <%- name = "#{symbol} #{field.name}: " -%>
85
86
  <%- case field -%>
86
87
  <%- when Herb::Template::PositionField -%>
87
- output += %(<%= name %>#{<%= field.name %> ? <%= field.name %>.tree_inspect : "∅"}\n)
88
+ output += white("<%= symbol %> <%= field.name %>: ")
89
+ output += <%= field.name %> ? <%= field.name %>.tree_inspect : magenta("∅")
90
+ output += "\n"
88
91
  <%- when Herb::Template::TokenField -%>
89
- output += %(<%= name %>#{<%= field.name %> ? <%= field.name %>.tree_inspect : "∅"}\n)
92
+ output += white("<%= symbol %> <%= field.name %>: ")
93
+ output += <%= field.name %> ? <%= field.name %>.tree_inspect : magenta("∅")
94
+ output += "\n"
90
95
  <%- when Herb::Template::TokenTypeField -%>
91
- output += %(<%= name %>#{<%= field.name %>.inspect}\n)
96
+ output += white("<%= symbol %> <%= field.name %>: #{green(<%= field.name %>.inspect)}\n")
92
97
  <%- when Herb::Template::StringField -%>
93
- output += %(<%= name %>#{<%= field.name %>.inspect}\n)
98
+ output += white("<%= symbol %> <%= field.name %>: #{green(<%= field.name %>.inspect)}\n")
94
99
  <%- else -%>
95
- output += "<%= name %>'#{<%= field.name %>.class}'\n"
100
+ output += white("<%= symbol %> <%= field.name %>: ") + '#{<%= field.name %>.class}'\n"
96
101
  <%- end -%>
97
102
  <%- end -%>
98
103
  output += %(\n)
@@ -0,0 +1,220 @@
1
+ use crate::bindings::*;
2
+ use crate::convert::token_from_c;
3
+ use crate::errors::*;
4
+ use crate::nodes::*;
5
+ use crate::{Location, Position};
6
+ use std::ffi::CStr;
7
+ use std::os::raw::{c_char, c_void};
8
+
9
+ unsafe fn convert_location(c_location: location_T) -> Location {
10
+ Location::new(
11
+ Position::new(c_location.start.line, c_location.start.column),
12
+ Position::new(c_location.end.line, c_location.end.column),
13
+ )
14
+ }
15
+
16
+ <%- errors.each do |error| -%>
17
+ <%- snake_name = error.name.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase -%>
18
+ unsafe fn convert_<%= snake_name %>(error_ptr: *const <%= error.c_type %>) -> <%= error.name %> {
19
+ let error_ref = &*error_ptr;
20
+ let message = if error_ref.base.message.is_null() {
21
+ String::new()
22
+ } else {
23
+ CStr::from_ptr(error_ref.base.message).to_string_lossy().into_owned()
24
+ };
25
+ let location = convert_location(error_ref.base.location);
26
+
27
+ <%= error.name %>::new(
28
+ message,
29
+ location,
30
+ <%- error.fields.each do |field| -%>
31
+ <%- case field -%>
32
+ <%- when Herb::Template::StringField -%>
33
+ get_string_field(error_ref.<%= field.name %>),
34
+ <%- when Herb::Template::TokenField -%>
35
+ convert_token_field(error_ref.<%= field.name %>),
36
+ <%- when Herb::Template::TokenTypeField -%>
37
+ if error_ref.<%= field.name %> == u32::MAX {
38
+ None
39
+ } else {
40
+ Some(CStr::from_ptr(crate::ffi::token_type_to_string(error_ref.<%= field.name %>)).to_string_lossy().into_owned())
41
+ },
42
+ <%- end -%>
43
+ <%- end -%>
44
+ )
45
+ }
46
+
47
+ <%- end -%>
48
+
49
+ unsafe fn convert_errors(errors_array: *mut hb_array_T) -> Vec<AnyError> {
50
+ if errors_array.is_null() {
51
+ return Vec::new();
52
+ }
53
+
54
+ let count = hb_array_size(errors_array);
55
+ let mut errors = Vec::with_capacity(count);
56
+
57
+ for index in 0..count {
58
+ let error_base_ptr = hb_array_get(errors_array, index) as *const ERROR_T;
59
+ if error_base_ptr.is_null() {
60
+ continue;
61
+ }
62
+
63
+ let error_base = &*error_base_ptr;
64
+
65
+ let error = match error_base.type_ {
66
+ <%- errors.each do |error| -%>
67
+ <%- snake_name = error.name.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase -%>
68
+ <%= error.type %> => {
69
+ let error_ptr = error_base_ptr as *const <%= error.c_type %>;
70
+ AnyError::<%= error.name %>(convert_<%= snake_name %>(error_ptr))
71
+ }
72
+ <%- end -%>
73
+ _ => continue,
74
+ };
75
+
76
+ errors.push(error);
77
+ }
78
+
79
+ errors
80
+ }
81
+
82
+ unsafe fn get_string_field(string_ptr: *const c_char) -> String {
83
+ if string_ptr.is_null() {
84
+ String::new()
85
+ } else {
86
+ CStr::from_ptr(string_ptr).to_string_lossy().into_owned()
87
+ }
88
+ }
89
+
90
+ unsafe fn convert_element_source(source: u32) -> String {
91
+ let hb_string = crate::ffi::element_source_to_string(source);
92
+ if hb_string.data.is_null() {
93
+ String::new()
94
+ } else {
95
+ let slice = std::slice::from_raw_parts(hb_string.data as *const u8, hb_string.length as usize);
96
+ String::from_utf8_lossy(slice).into_owned()
97
+ }
98
+ }
99
+
100
+ unsafe fn convert_token_field(token_ptr: *mut token_T) -> Option<crate::Token> {
101
+ if token_ptr.is_null() {
102
+ None
103
+ } else {
104
+ Some(token_from_c(token_ptr))
105
+ }
106
+ }
107
+
108
+ unsafe fn convert_children(children_array: *mut hb_array_T) -> Vec<AnyNode> {
109
+ if children_array.is_null() {
110
+ return Vec::new();
111
+ }
112
+
113
+ let count = hb_array_size(children_array);
114
+ let mut children = Vec::with_capacity(count);
115
+
116
+ for index in 0..count {
117
+ let child_ptr = hb_array_get(children_array, index);
118
+ if !child_ptr.is_null() {
119
+ if let Some(node) = convert_node(child_ptr as *const c_void) {
120
+ children.push(node);
121
+ }
122
+ }
123
+ }
124
+
125
+ children
126
+ }
127
+
128
+ unsafe fn convert_node_field(node_ptr: *mut c_void) -> Option<Box<AnyNode>> {
129
+ if node_ptr.is_null() {
130
+ None
131
+ } else {
132
+ convert_node(node_ptr).map(Box::new)
133
+ }
134
+ }
135
+
136
+ macro_rules! convert_specific_node_field {
137
+ ($node_ptr:expr, $expected_type:expr, $convert_fn:ident, $node_type:ty) => {
138
+ if $node_ptr.is_null() {
139
+ None
140
+ } else {
141
+ let ast_base_ptr = $node_ptr as *const AST_NODE_T;
142
+ let ast_base_ref = &*ast_base_ptr;
143
+ let node_type = ast_base_ref.type_;
144
+
145
+ if node_type != $expected_type {
146
+ eprintln!("Warning: Expected node type {} but got {}", $expected_type, node_type);
147
+ None
148
+ } else {
149
+ $convert_fn($node_ptr as *const c_void).map(Box::new)
150
+ }
151
+ }
152
+ };
153
+ }
154
+
155
+ unsafe fn convert_node(node_ptr: *const c_void) -> Option<AnyNode> {
156
+ if node_ptr.is_null() {
157
+ return None;
158
+ }
159
+
160
+ let ast_base_ptr = node_ptr as *const AST_NODE_T;
161
+ let ast_base_ref = &*ast_base_ptr;
162
+ let node_type = ast_base_ref.type_;
163
+
164
+ match node_type {
165
+ <%- nodes.each do |node| -%>
166
+ <%= node.type %> => convert_<%= node.human %>(node_ptr).map(AnyNode::<%= node.name %>),
167
+ <%- end -%>
168
+ _ => {
169
+ eprintln!("Warning: Unknown node type {}", node_type);
170
+ None
171
+ }
172
+ }
173
+ }
174
+
175
+ <%- nodes.each do |node| -%>
176
+ <%- if node.name == "DocumentNode" -%>
177
+ /// Converts a C document node pointer to a Rust DocumentNode.
178
+ ///
179
+ /// # Safety
180
+ ///
181
+ /// The caller must ensure that `node_ptr` is a valid pointer to a C document node
182
+ /// structure with properly initialized fields.
183
+ <%- end -%>
184
+ <%= node.name == "DocumentNode" ? "pub " : "" %>unsafe fn convert_<%= node.human %>(node_ptr: *const c_void) -> Option<<%= node.name %>> {
185
+ if node_ptr.is_null() {
186
+ return None;
187
+ }
188
+
189
+ let c_node_ptr = node_ptr as *const <%= node.c_type %>;
190
+ let node_base_ref = &(*c_node_ptr).base;
191
+
192
+ Some(<%= node.name %> {
193
+ node_type: "<%= node.name %>".to_string(),
194
+ location: convert_location(node_base_ref.location),
195
+ errors: convert_errors(node_base_ref.errors),
196
+ <%- node.fields.each do |field| -%>
197
+ <%- case field -%>
198
+ <%- when Herb::Template::StringField -%>
199
+ <%= field.name %>: get_string_field((*c_node_ptr).<%= field.name %>),
200
+ <%- when Herb::Template::ElementSourceField -%>
201
+ <%= field.name %>: convert_element_source((*c_node_ptr).<%= field.name %>),
202
+ <%- when Herb::Template::TokenField -%>
203
+ <%= field.name %>: convert_token_field((*c_node_ptr).<%= field.name %>),
204
+ <%- when Herb::Template::BooleanField -%>
205
+ <%= field.name %>: (*c_node_ptr).<%= field.name %>,
206
+ <%- when Herb::Template::ArrayField -%>
207
+ <%= field.name %>: convert_children((*c_node_ptr).<%= field.name %>),
208
+ <%- when Herb::Template::NodeField -%>
209
+ <%- if field.specific_kind && field.specific_kind != "Node" -%>
210
+ <%- specific_node = nodes.find { |n| n.name == field.specific_kind } -%>
211
+ <%= field.name %>: convert_specific_node_field!((*c_node_ptr).<%= field.name %>, <%= specific_node.type %>, convert_<%= specific_node.human %>, <%= field.specific_kind %>),
212
+ <%- else -%>
213
+ <%= field.name %>: convert_node_field((*c_node_ptr).<%= field.name %> as *mut c_void),
214
+ <%- end -%>
215
+ <%- end -%>
216
+ <%- end -%>
217
+ })
218
+ }
219
+
220
+ <%- end -%>
@@ -0,0 +1,216 @@
1
+ use crate::{Location, Token};
2
+ use colored::*;
3
+
4
+ fn escape_string(s: &str) -> String {
5
+ s.replace('\\', "\\\\")
6
+ .replace('\n', "\\n")
7
+ .replace('\r', "\\r")
8
+ .replace('\t', "\\t")
9
+ .replace('"', "\\\"")
10
+ }
11
+
12
+ fn format_string_value(value: &str) -> String {
13
+ format!("\"{}\"", escape_string(value)).green().to_string()
14
+ }
15
+
16
+ fn format_token_value(token: &Option<Token>) -> String {
17
+ token.as_ref().map(|t| t.tree_inspect()).unwrap_or_else(|| "∅".magenta().to_string())
18
+ }
19
+
20
+ fn format_token_type_value(token_type: &Option<String>) -> String {
21
+ token_type.as_ref().map(|t| format!("\"{}\"", t).green().to_string()).unwrap_or_else(|| "∅".magenta().to_string())
22
+ }
23
+
24
+ #[allow(dead_code)]
25
+ fn format_position_value(position: &Option<crate::Position>) -> String {
26
+ position.as_ref().map(|p| p.to_string()).unwrap_or_else(|| "∅".magenta().to_string())
27
+ }
28
+
29
+ #[allow(dead_code)]
30
+ fn format_size_value(value: usize) -> String {
31
+ value.to_string().magenta().bold().to_string()
32
+ }
33
+
34
+ #[derive(Debug, Clone, PartialEq)]
35
+ pub enum ErrorType {
36
+ <%- errors.each do |error| -%>
37
+ <%= error.name %>,
38
+ <%- end -%>
39
+ }
40
+
41
+ impl ErrorType {
42
+ pub fn as_str(&self) -> &str {
43
+ match self {
44
+ <%- errors.each do |error| -%>
45
+ ErrorType::<%= error.name %> => "<%= error.type %>",
46
+ <%- end -%>
47
+ }
48
+ }
49
+ }
50
+
51
+ pub trait ErrorNode {
52
+ fn error_type(&self) -> &str;
53
+ fn message(&self) -> &str;
54
+ fn location(&self) -> &Location;
55
+ fn tree_inspect(&self) -> String;
56
+ }
57
+
58
+ #[derive(Debug, Clone)]
59
+ pub enum AnyError {
60
+ <%- errors.each do |error| -%>
61
+ <%= error.name %>(<%= error.name %>),
62
+ <%- end -%>
63
+ }
64
+
65
+ impl AnyError {
66
+ pub fn error_type(&self) -> &str {
67
+ match self {
68
+ <%- errors.each do |error| -%>
69
+ AnyError::<%= error.name %>(e) => &e.error_type,
70
+ <%- end -%>
71
+ }
72
+ }
73
+
74
+ pub fn message(&self) -> &str {
75
+ match self {
76
+ <%- errors.each do |error| -%>
77
+ AnyError::<%= error.name %>(e) => &e.message,
78
+ <%- end -%>
79
+ }
80
+ }
81
+
82
+ pub fn location(&self) -> &Location {
83
+ match self {
84
+ <%- errors.each do |error| -%>
85
+ AnyError::<%= error.name %>(e) => &e.location,
86
+ <%- end -%>
87
+ }
88
+ }
89
+
90
+ pub fn tree_inspect(&self) -> String {
91
+ match self {
92
+ <%- errors.each do |error| -%>
93
+ AnyError::<%= error.name %>(e) => e.tree_inspect(),
94
+ <%- end -%>
95
+ }
96
+ }
97
+ }
98
+
99
+ impl ErrorNode for AnyError {
100
+ fn error_type(&self) -> &str {
101
+ self.error_type()
102
+ }
103
+
104
+ fn message(&self) -> &str {
105
+ self.message()
106
+ }
107
+
108
+ fn location(&self) -> &Location {
109
+ self.location()
110
+ }
111
+
112
+ fn tree_inspect(&self) -> String {
113
+ self.tree_inspect()
114
+ }
115
+ }
116
+
117
+ <%- errors.each do |error| -%>
118
+ #[derive(Debug, Clone)]
119
+ pub struct <%= error.name %> {
120
+ pub error_type: String,
121
+ pub message: String,
122
+ pub location: Location,
123
+ <%- error.fields.each do |field| -%>
124
+ <%- case field -%>
125
+ <%- when Herb::Template::StringField -%>
126
+ pub <%= field.name %>: String,
127
+ <%- when Herb::Template::TokenField -%>
128
+ pub <%= field.name %>: Option<Token>,
129
+ <%- when Herb::Template::TokenTypeField -%>
130
+ pub <%= field.name %>: Option<String>,
131
+ <%- when Herb::Template::PositionField -%>
132
+ pub <%= field.name %>: Option<Position>,
133
+ <%- when Herb::Template::SizeTField -%>
134
+ pub <%= field.name %>: usize,
135
+ <%- end -%>
136
+ <%- end -%>
137
+ }
138
+
139
+ impl <%= error.name %> {
140
+ pub fn new(
141
+ message: String,
142
+ location: Location,
143
+ <%- error.fields.each do |field| -%>
144
+ <%- case field -%>
145
+ <%- when Herb::Template::StringField -%>
146
+ <%= field.name %>: String,
147
+ <%- when Herb::Template::TokenField -%>
148
+ <%= field.name %>: Option<Token>,
149
+ <%- when Herb::Template::TokenTypeField -%>
150
+ <%= field.name %>: Option<String>,
151
+ <%- when Herb::Template::PositionField -%>
152
+ <%= field.name %>: Option<Position>,
153
+ <%- when Herb::Template::SizeTField -%>
154
+ <%= field.name %>: usize,
155
+ <%- end -%>
156
+ <%- end -%>
157
+ ) -> Self {
158
+ Self {
159
+ error_type: "<%= error.type %>".to_string(),
160
+ message,
161
+ location,
162
+ <%- error.fields.each do |field| -%>
163
+ <%= field.name %>,
164
+ <%- end -%>
165
+ }
166
+ }
167
+
168
+ pub fn tree_inspect(&self) -> String {
169
+ let mut output = String::new();
170
+
171
+ output.push_str(&format!("{} {} {}\n",
172
+ "@".white(),
173
+ "<%= error.name %>".red().bold(),
174
+ format!("(location: {})", self.location).dimmed()
175
+ ));
176
+ <%- symbol = error.fields.any? ? "├──" : "└──" -%>
177
+ output.push_str(&format!("{} {}: {}\n", "<%= symbol %>".white(), "message".white(), format_string_value(&self.message)));
178
+ <%- error.fields.each do |field| -%>
179
+ <%- symbol = error.fields.last == field ? "└──" : "├──" -%>
180
+ <%- case field -%>
181
+ <%- when Herb::Template::StringField -%>
182
+ output.push_str(&format!("{} {}: {}\n", "<%= symbol %>".white(), "<%= field.name %>".white(), format_string_value(&self.<%= field.name %>)));
183
+ <%- when Herb::Template::TokenField -%>
184
+ output.push_str(&format!("{} {}: {}\n", "<%= symbol %>".white(), "<%= field.name %>".white(), format_token_value(&self.<%= field.name %>)));
185
+ <%- when Herb::Template::TokenTypeField -%>
186
+ output.push_str(&format!("{} {}: {}\n", "<%= symbol %>".white(), "<%= field.name %>".white(), format_token_type_value(&self.<%= field.name %>)));
187
+ <%- when Herb::Template::PositionField -%>
188
+ output.push_str(&format!("{} {}: {}\n", "<%= symbol %>".white(), "<%= field.name %>".white(), format_position_value(&self.<%= field.name %>)));
189
+ <%- when Herb::Template::SizeTField -%>
190
+ output.push_str(&format!("{} {}: {}\n", "<%= symbol %>".white(), "<%= field.name %>".white(), format_size_value(self.<%= field.name %>)));
191
+ <%- end -%>
192
+ <%- end -%>
193
+
194
+ output
195
+ }
196
+ }
197
+
198
+ impl ErrorNode for <%= error.name %> {
199
+ fn error_type(&self) -> &str {
200
+ &self.error_type
201
+ }
202
+
203
+ fn message(&self) -> &str {
204
+ &self.message
205
+ }
206
+
207
+ fn location(&self) -> &Location {
208
+ &self.location
209
+ }
210
+
211
+ fn tree_inspect(&self) -> String {
212
+ <%= error.name %>::tree_inspect(self)
213
+ }
214
+ }
215
+
216
+ <%- end -%>