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.
- checksums.yaml +4 -4
- data/Makefile +8 -5
- data/config.yml +40 -20
- data/ext/herb/error_helpers.c +57 -3
- data/ext/herb/error_helpers.h +1 -1
- data/ext/herb/extconf.rb +1 -0
- data/ext/herb/extension.c +10 -24
- data/ext/herb/extension_helpers.c +12 -18
- data/ext/herb/extension_helpers.h +4 -4
- data/ext/herb/nodes.c +72 -37
- data/herb.gemspec +0 -2
- data/lib/herb/3.0/herb.so +0 -0
- data/lib/herb/3.1/herb.so +0 -0
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +0 -0
- data/lib/herb/ast/helpers.rb +11 -0
- data/lib/herb/ast/node.rb +15 -6
- data/lib/herb/ast/nodes.rb +609 -392
- data/lib/herb/cli.rb +31 -0
- data/lib/herb/colors.rb +82 -0
- data/lib/herb/engine/compiler.rb +140 -14
- data/lib/herb/engine/debug_visitor.rb +1 -5
- data/lib/herb/engine/parser_error_overlay.rb +1 -1
- data/lib/herb/engine.rb +18 -20
- data/lib/herb/errors.rb +166 -56
- data/lib/herb/location.rb +2 -2
- data/lib/herb/project.rb +86 -21
- data/lib/herb/token.rb +14 -2
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +1 -0
- data/sig/herb/ast/helpers.rbs +3 -0
- data/sig/herb/ast/node.rbs +12 -5
- data/sig/herb/ast/nodes.rbs +124 -62
- data/sig/herb/colors.rbs +35 -0
- data/sig/herb/engine/compiler.rbs +23 -1
- data/sig/herb/errors.rbs +74 -20
- data/sig/herb/token.rbs +8 -0
- data/sig/herb_c_extension.rbs +1 -1
- data/sig/serialized_ast_errors.rbs +8 -0
- data/src/analyze.c +461 -249
- data/src/analyze_helpers.c +5 -0
- data/src/analyze_missing_end.c +147 -0
- data/src/analyze_transform.c +196 -0
- data/src/analyzed_ruby.c +23 -2
- data/src/ast_node.c +14 -17
- data/src/ast_nodes.c +179 -181
- data/src/ast_pretty_print.c +232 -232
- data/src/element_source.c +7 -6
- data/src/errors.c +272 -152
- data/src/extract.c +92 -34
- data/src/herb.c +37 -49
- data/src/html_util.c +34 -96
- data/src/include/analyze.h +10 -2
- data/src/include/analyze_helpers.h +3 -0
- data/src/include/analyzed_ruby.h +4 -2
- data/src/include/ast_node.h +4 -4
- data/src/include/ast_nodes.h +68 -67
- data/src/include/ast_pretty_print.h +2 -2
- data/src/include/element_source.h +3 -1
- data/src/include/errors.h +42 -26
- data/src/include/extract.h +4 -4
- data/src/include/herb.h +6 -7
- data/src/include/html_util.h +4 -5
- data/src/include/lexer.h +1 -3
- data/src/include/lexer_peek_helpers.h +21 -19
- data/src/include/lexer_struct.h +12 -10
- data/src/include/location.h +10 -13
- data/src/include/macros.h +4 -0
- data/src/include/parser.h +12 -6
- data/src/include/parser_helpers.h +26 -16
- data/src/include/position.h +3 -14
- data/src/include/pretty_print.h +38 -28
- data/src/include/prism_helpers.h +1 -1
- data/src/include/range.h +4 -13
- data/src/include/token.h +5 -11
- data/src/include/token_struct.h +2 -2
- data/src/include/utf8.h +3 -2
- data/src/include/util/hb_arena.h +31 -0
- data/src/include/util/hb_arena_debug.h +8 -0
- data/src/include/util/hb_array.h +33 -0
- data/src/include/util/hb_buffer.h +34 -0
- data/src/include/util/hb_string.h +29 -0
- data/src/include/util/hb_system.h +9 -0
- data/src/include/util.h +3 -14
- data/src/include/version.h +1 -1
- data/src/include/visitor.h +1 -1
- data/src/io.c +7 -4
- data/src/lexer.c +62 -88
- data/src/lexer_peek_helpers.c +42 -38
- data/src/location.c +9 -37
- data/src/main.c +19 -23
- data/src/parser.c +373 -313
- data/src/parser_helpers.c +60 -54
- data/src/parser_match_tags.c +316 -0
- data/src/pretty_print.c +88 -117
- data/src/prism_helpers.c +7 -7
- data/src/range.c +2 -35
- data/src/token.c +36 -87
- data/src/utf8.c +4 -4
- data/src/util/hb_arena.c +179 -0
- data/src/util/hb_arena_debug.c +237 -0
- data/src/{array.c → util/hb_array.c} +26 -27
- data/src/util/hb_buffer.c +203 -0
- data/src/util/hb_string.c +85 -0
- data/src/util/hb_system.c +30 -0
- data/src/util.c +29 -99
- data/src/visitor.c +54 -54
- data/templates/ext/herb/error_helpers.c.erb +3 -3
- data/templates/ext/herb/error_helpers.h.erb +1 -1
- data/templates/ext/herb/nodes.c.erb +11 -6
- data/templates/java/error_helpers.c.erb +75 -0
- data/templates/java/error_helpers.h.erb +20 -0
- data/templates/java/nodes.c.erb +97 -0
- data/templates/java/nodes.h.erb +23 -0
- data/templates/java/org/herb/ast/Errors.java.erb +121 -0
- data/templates/java/org/herb/ast/NodeVisitor.java.erb +14 -0
- data/templates/java/org/herb/ast/Nodes.java.erb +220 -0
- data/templates/java/org/herb/ast/Visitor.java.erb +56 -0
- data/templates/javascript/packages/core/src/visitor.ts.erb +29 -1
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +8 -8
- data/templates/javascript/packages/node/extension/error_helpers.h.erb +1 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +9 -9
- data/templates/javascript/packages/node/extension/nodes.h.erb +1 -1
- data/templates/lib/herb/ast/nodes.rb.erb +28 -16
- data/templates/lib/herb/errors.rb.erb +17 -12
- data/templates/rust/src/ast/nodes.rs.erb +220 -0
- data/templates/rust/src/errors.rs.erb +216 -0
- data/templates/rust/src/nodes.rs.erb +374 -0
- data/templates/src/analyze_missing_end.c.erb +36 -0
- data/templates/src/analyze_transform.c.erb +24 -0
- data/templates/src/ast_nodes.c.erb +14 -16
- data/templates/src/ast_pretty_print.c.erb +36 -36
- data/templates/src/errors.c.erb +36 -38
- data/templates/src/include/ast_nodes.h.erb +11 -10
- data/templates/src/include/ast_pretty_print.h.erb +2 -2
- data/templates/src/include/errors.h.erb +9 -9
- data/templates/src/parser_match_tags.c.erb +38 -0
- data/templates/src/visitor.c.erb +4 -4
- data/templates/template.rb +22 -3
- data/templates/wasm/error_helpers.cpp.erb +9 -9
- data/templates/wasm/error_helpers.h.erb +1 -1
- data/templates/wasm/nodes.cpp.erb +9 -9
- data/templates/wasm/nodes.h.erb +1 -1
- data/vendor/prism/Rakefile +4 -1
- data/vendor/prism/config.yml +2 -1
- data/vendor/prism/include/prism/ast.h +31 -1
- data/vendor/prism/include/prism/diagnostic.h +1 -0
- data/vendor/prism/include/prism/version.h +3 -3
- data/vendor/prism/src/diagnostic.c +3 -1
- data/vendor/prism/src/prism.c +130 -71
- data/vendor/prism/src/util/pm_string.c +6 -8
- data/vendor/prism/templates/include/prism/ast.h.erb +2 -0
- data/vendor/prism/templates/java/org/prism/Loader.java.erb +2 -2
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +2 -2
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +2 -2
- data/vendor/prism/templates/sig/prism.rbs.erb +4 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +1 -0
- metadata +34 -21
- data/lib/herb/libherb/array.rb +0 -51
- data/lib/herb/libherb/ast_node.rb +0 -50
- data/lib/herb/libherb/buffer.rb +0 -56
- data/lib/herb/libherb/extract_result.rb +0 -20
- data/lib/herb/libherb/lex_result.rb +0 -32
- data/lib/herb/libherb/libherb.rb +0 -52
- data/lib/herb/libherb/parse_result.rb +0 -20
- data/lib/herb/libherb/token.rb +0 -46
- data/lib/herb/libherb.rb +0 -35
- data/src/buffer.c +0 -232
- data/src/include/array.h +0 -33
- data/src/include/buffer.h +0 -39
- data/src/include/json.h +0 -28
- data/src/include/memory.h +0 -12
- data/src/json.c +0 -205
- data/src/memory.c +0 -53
- data/src/position.c +0 -33
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
package org.herb.ast;
|
|
2
|
+
|
|
3
|
+
import org.herb.Location;
|
|
4
|
+
import org.herb.Token;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Base class for all Herb parsing errors.
|
|
8
|
+
*/
|
|
9
|
+
abstract class HerbError {
|
|
10
|
+
private final String type;
|
|
11
|
+
private final String message;
|
|
12
|
+
private final Location location;
|
|
13
|
+
|
|
14
|
+
public HerbError(String type, String message, Location location) {
|
|
15
|
+
this.type = type;
|
|
16
|
+
this.message = message;
|
|
17
|
+
this.location = location;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public String getType() {
|
|
21
|
+
return type;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public String getMessage() {
|
|
25
|
+
return message;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public Location getLocation() {
|
|
29
|
+
return location;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@Override
|
|
33
|
+
public String toString() {
|
|
34
|
+
return String.format("HerbError{type='%s', message='%s', location=%s}", type, message, location);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public abstract String inspect();
|
|
38
|
+
|
|
39
|
+
protected String indent(String str, int level) {
|
|
40
|
+
if (level == 0) return str;
|
|
41
|
+
String prefix = " ".repeat(level);
|
|
42
|
+
return str.lines()
|
|
43
|
+
.map(line -> prefix + line)
|
|
44
|
+
.collect(java.util.stream.Collectors.joining("\n"));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
<%- errors.each do |error| -%>
|
|
49
|
+
/**
|
|
50
|
+
* <%= error.name %>: <%= error.message_template %>
|
|
51
|
+
*/
|
|
52
|
+
class <%= error.name %> extends HerbError {
|
|
53
|
+
<%- error.fields.each do |field| -%>
|
|
54
|
+
<%- case field -%>
|
|
55
|
+
<%- when Herb::Template::StringField -%>
|
|
56
|
+
private final String <%= field.name %>;
|
|
57
|
+
<%- when Herb::Template::TokenField -%>
|
|
58
|
+
private final Token <%= field.name %>;
|
|
59
|
+
<%- when Herb::Template::TokenTypeField -%>
|
|
60
|
+
private final String <%= field.name %>;
|
|
61
|
+
<%- else -%>
|
|
62
|
+
// Unsupported field type: <%= field.class %>
|
|
63
|
+
<%- end -%>
|
|
64
|
+
<%- end -%>
|
|
65
|
+
|
|
66
|
+
public <%= error.name %>(String type, String message, Location location<%- error.fields.each do |field| -%><%- case field -%><%- when Herb::Template::StringField -%>, String <%= field.name %><%- when Herb::Template::TokenField -%>, Token <%= field.name %><%- when Herb::Template::TokenTypeField -%>, String <%= field.name %><%- end -%><%- end -%>) {
|
|
67
|
+
super(type, message, location);
|
|
68
|
+
<%- error.fields.each do |field| -%>
|
|
69
|
+
this.<%= field.name %> = <%= field.name %>;
|
|
70
|
+
<%- end -%>
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
<%- error.fields.each do |field| -%>
|
|
74
|
+
<%- case field -%>
|
|
75
|
+
<%- when Herb::Template::StringField -%>
|
|
76
|
+
public String get<%= field.name.capitalize %>() {
|
|
77
|
+
return <%= field.name %>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
<%- when Herb::Template::TokenField -%>
|
|
81
|
+
public Token get<%= field.name.capitalize %>() {
|
|
82
|
+
return <%= field.name %>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
<%- when Herb::Template::TokenTypeField -%>
|
|
86
|
+
public String get<%= field.name.capitalize %>() {
|
|
87
|
+
return <%= field.name %>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
<%- end -%>
|
|
91
|
+
<%- end -%>
|
|
92
|
+
@Override
|
|
93
|
+
public String inspect() {
|
|
94
|
+
StringBuilder output = new StringBuilder();
|
|
95
|
+
|
|
96
|
+
output.append("@ <%= error.name %> ");
|
|
97
|
+
output.append(getLocation() != null ? "(location: " + getLocation().toString() + ")" : "no-location");
|
|
98
|
+
output.append("\n");
|
|
99
|
+
<%- symbol = error.fields.any? ? "├──" : "└──" -%>
|
|
100
|
+
output.append("<%= symbol %> message: ");
|
|
101
|
+
output.append("\"").append(getMessage()).append("\"");
|
|
102
|
+
output.append("\n");
|
|
103
|
+
<%- error.fields.each do |field| -%>
|
|
104
|
+
<%- symbol = error.fields.last == field ? "└──" : "├──" -%>
|
|
105
|
+
<%- case field -%>
|
|
106
|
+
<%- when Herb::Template::StringField, Herb::Template::TokenTypeField -%>
|
|
107
|
+
output.append("<%= symbol %> <%= field.name %>: ");
|
|
108
|
+
output.append("\"").append(<%= field.name %>).append("\"");
|
|
109
|
+
output.append("\n");
|
|
110
|
+
<%- when Herb::Template::TokenField -%>
|
|
111
|
+
output.append("<%= symbol %> <%= field.name %>: ");
|
|
112
|
+
output.append(<%= field.name %> != null ? <%= field.name %>.inspect() : "∅");
|
|
113
|
+
output.append("\n");
|
|
114
|
+
<%- end -%>
|
|
115
|
+
<%- end -%>
|
|
116
|
+
|
|
117
|
+
return output.toString();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
<%- end -%>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
package org.herb.ast;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Visitor interface for traversing AST nodes.
|
|
5
|
+
*
|
|
6
|
+
* @param <R> the return type
|
|
7
|
+
* @param <C> the context type
|
|
8
|
+
*/
|
|
9
|
+
public interface NodeVisitor<R, C> {
|
|
10
|
+
R visitNode(Node node, C context);
|
|
11
|
+
<%- nodes.each do |node| -%>
|
|
12
|
+
R visit<%= node.name %>(<%=node.name %> node, C context);
|
|
13
|
+
<%- end -%>
|
|
14
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
package org.herb.ast;
|
|
2
|
+
|
|
3
|
+
import org.herb.Location;
|
|
4
|
+
import org.herb.Token;
|
|
5
|
+
|
|
6
|
+
import java.util.ArrayList;
|
|
7
|
+
import java.util.List;
|
|
8
|
+
|
|
9
|
+
<%- nodes.each do |node| -%>
|
|
10
|
+
class <%= node.name %> extends BaseNode {
|
|
11
|
+
<%- if node.fields.any? -%>
|
|
12
|
+
<%- node.fields.each do |field| -%>
|
|
13
|
+
<%- if field.is_a?(Herb::Template::StringField) -%>
|
|
14
|
+
private final String <%= field.name %>;
|
|
15
|
+
<%- elsif field.is_a?(Herb::Template::TokenField) -%>
|
|
16
|
+
private final Token <%= field.name %>;
|
|
17
|
+
<%- elsif field.is_a?(Herb::Template::BooleanField) -%>
|
|
18
|
+
private final boolean <%= field.name %>;
|
|
19
|
+
<%- elsif field.is_a?(Herb::Template::ArrayField) -%>
|
|
20
|
+
private final List<Node> <%= field.name %>;
|
|
21
|
+
<%- elsif field.is_a?(Herb::Template::NodeField) -%>
|
|
22
|
+
<%- if field.specific_kind -%>
|
|
23
|
+
private final <%= field.specific_kind %> <%= field.name %>;
|
|
24
|
+
<%- else -%>
|
|
25
|
+
private final Node <%= field.name %>;
|
|
26
|
+
<%- end -%>
|
|
27
|
+
<%- elsif field.is_a?(Herb::Template::ElementSourceField) -%>
|
|
28
|
+
private final String <%= field.name %>;
|
|
29
|
+
<%- else -%>
|
|
30
|
+
// private final Object <%= field.name %>;
|
|
31
|
+
<%- end -%>
|
|
32
|
+
<%- end -%>
|
|
33
|
+
<%- end -%>
|
|
34
|
+
|
|
35
|
+
public <%= node.name %>(
|
|
36
|
+
String type,
|
|
37
|
+
Location location,
|
|
38
|
+
List<Node> errors<%- if node.fields.any? %>,<% end %>
|
|
39
|
+
<%- if node.fields.any? -%>
|
|
40
|
+
<%- node.fields.each do |field| -%>
|
|
41
|
+
<%- if field.is_a?(Herb::Template::StringField) -%>
|
|
42
|
+
String <%= field.name %><%- if node.fields.last != field %>,<% end %>
|
|
43
|
+
<%- elsif field.is_a?(Herb::Template::TokenField) -%>
|
|
44
|
+
Token <%= field.name %><%- if node.fields.last != field %>,<% end %>
|
|
45
|
+
<%- elsif field.is_a?(Herb::Template::BooleanField) -%>
|
|
46
|
+
boolean <%= field.name %><%- if node.fields.last != field %>,<% end %>
|
|
47
|
+
<%- elsif field.is_a?(Herb::Template::ArrayField) -%>
|
|
48
|
+
List<Node> <%= field.name %><%- if node.fields.last != field %>,<% end %>
|
|
49
|
+
<%- elsif field.is_a?(Herb::Template::NodeField) -%>
|
|
50
|
+
<%= field.specific_kind || 'Node' %> <%= field.name %><%- if node.fields.last != field %>,<% end %>
|
|
51
|
+
<%- elsif field.is_a?(Herb::Template::ElementSourceField) -%>
|
|
52
|
+
String <%= field.name %><%- if node.fields.last != field %>,<% end %>
|
|
53
|
+
<%- else -%>
|
|
54
|
+
// <%= field.c_type %> <%= field.name %>
|
|
55
|
+
<%- end -%>
|
|
56
|
+
<%- end -%>
|
|
57
|
+
<%- end -%>
|
|
58
|
+
) {
|
|
59
|
+
super(type, location, errors);
|
|
60
|
+
|
|
61
|
+
<%- if node.fields.any? -%>
|
|
62
|
+
<%- node.fields.each do |field| -%>
|
|
63
|
+
<%- unless field.is_a?(Herb::Template::AnalyzedRubyField) || field.is_a?(Herb::Template::PrismNodeField) -%>
|
|
64
|
+
this.<%= field.name %> = <%= field.name %>;
|
|
65
|
+
<%- else -%>
|
|
66
|
+
// this.<%= field.name %> = <%= field.name %>;
|
|
67
|
+
<%- end -%>
|
|
68
|
+
<%- end -%>
|
|
69
|
+
<%- end -%>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
<%- if node.fields.any? -%>
|
|
73
|
+
<%- node.fields.each do |field| -%>
|
|
74
|
+
<%- if field.is_a?(Herb::Template::StringField) -%>
|
|
75
|
+
public String get<%= field.name.split('_').map(&:capitalize).join %>() {
|
|
76
|
+
return <%= field.name %>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
<%- elsif field.is_a?(Herb::Template::TokenField) -%>
|
|
80
|
+
public Token get<%= field.name.split('_').map(&:capitalize).join %>() {
|
|
81
|
+
return <%= field.name %>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
<%- elsif field.is_a?(Herb::Template::BooleanField) -%>
|
|
85
|
+
public boolean is<%= field.name.split('_').map(&:capitalize).join %>() {
|
|
86
|
+
return <%= field.name %>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
<%- elsif field.is_a?(Herb::Template::ArrayField) -%>
|
|
90
|
+
public List<Node> get<%= field.name.split('_').map(&:capitalize).join %>() {
|
|
91
|
+
return <%= field.name %>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
<%- elsif field.is_a?(Herb::Template::NodeField) -%>
|
|
95
|
+
public <%= field.specific_kind || 'Node' %> get<%= field.name.split('_').map(&:capitalize).join %>() {
|
|
96
|
+
return <%= field.name %>;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
<%- elsif field.is_a?(Herb::Template::ElementSourceField) -%>
|
|
100
|
+
public String get<%= field.name.split('_').map(&:capitalize).join %>() {
|
|
101
|
+
return <%= field.name %>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
<%- else -%>
|
|
105
|
+
/*
|
|
106
|
+
public Object get<%= field.name.split('_').map(&:capitalize).join %>() {
|
|
107
|
+
return <%= field.name %>;
|
|
108
|
+
}
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
<%- end -%>
|
|
112
|
+
<%- end -%>
|
|
113
|
+
@Override
|
|
114
|
+
public <R, C> R accept(NodeVisitor<R, C> visitor, C context) {
|
|
115
|
+
return visitor.visit<%= node.name %>(this, context);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@Override
|
|
119
|
+
public <R, C> void visitChildren(NodeVisitor<R, C> visitor, C context) {
|
|
120
|
+
<%- if node.fields.any? -%>
|
|
121
|
+
<%- node.fields.each do |field| -%>
|
|
122
|
+
<%- if field.is_a?(Herb::Template::ArrayField) -%>
|
|
123
|
+
if (<%= field.name %> != null) {
|
|
124
|
+
for (Node child : <%= field.name %>) {
|
|
125
|
+
if (child != null) child.accept(visitor, context);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
<%- elsif field.is_a?(Herb::Template::NodeField) -%>
|
|
130
|
+
if (<%= field.name %> != null) <%= field.name %>.accept(visitor, context);
|
|
131
|
+
|
|
132
|
+
<%- end -%>
|
|
133
|
+
<%- end -%>
|
|
134
|
+
<%- else -%>
|
|
135
|
+
// No children to visit
|
|
136
|
+
<%- end -%>
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@Override
|
|
140
|
+
public String inspect() {
|
|
141
|
+
StringBuilder output = new StringBuilder();
|
|
142
|
+
|
|
143
|
+
output.append("@ <%= node.name %> ").append(location != null ? "(location: " + location.toString() + ")" : "no-location").append("\n");
|
|
144
|
+
<%- if node.fields.any? -%>
|
|
145
|
+
output.append(inspectErrors("│ "));
|
|
146
|
+
<%- else -%>
|
|
147
|
+
output.append(inspectErrors(" "));
|
|
148
|
+
<%- end -%>
|
|
149
|
+
<%- if node.fields.any? -%>
|
|
150
|
+
<%- node.fields.each_with_index do |field, index| -%>
|
|
151
|
+
<%- is_last = index == node.fields.length - 1 -%>
|
|
152
|
+
<%- symbol = is_last ? "└── " : "├── " -%>
|
|
153
|
+
<%- prefix = is_last ? " " : "│ " -%>
|
|
154
|
+
<%- if field.is_a?(Herb::Template::StringField) || field.is_a?(Herb::Template::ElementSourceField) -%>
|
|
155
|
+
output.append("<%= symbol %><%= field.name %>: ").append(<%= field.name %> != null ? "\"" + <%= field.name %>.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t").replace("\"", "\\\"") + "\"" : "∅").append("\n");
|
|
156
|
+
<%- elsif field.is_a?(Herb::Template::TokenField) -%>
|
|
157
|
+
output.append("<%= symbol %><%= field.name %>: ").append(<%= field.name %> != null ? <%= field.name %>.treeInspect() : "∅").append("\n");
|
|
158
|
+
<%- elsif field.is_a?(Herb::Template::BooleanField) -%>
|
|
159
|
+
output.append("<%= symbol %><%= field.name %>: ").append(<%= field.name %>).append("\n");
|
|
160
|
+
<%- elsif field.is_a?(Herb::Template::ArrayField) -%>
|
|
161
|
+
output.append("<%= symbol %><%= field.name %>: ").append(inspectArray(<%= field.name %>, "<%= prefix %>"));
|
|
162
|
+
<%- elsif field.is_a?(Herb::Template::NodeField) -%>
|
|
163
|
+
if (<%= field.name %> != null) {
|
|
164
|
+
output.append("<%= symbol %><%= field.name %>:\n");
|
|
165
|
+
output.append("<%= prefix %>").append(inspectNode(<%= field.name %>, "<%= prefix %>"));
|
|
166
|
+
<%- unless is_last -%>
|
|
167
|
+
output.append("<%= prefix %>").append("\n");
|
|
168
|
+
<%- end -%>
|
|
169
|
+
} else {
|
|
170
|
+
output.append("<%= symbol %><%= field.name %>: ∅\n");
|
|
171
|
+
}
|
|
172
|
+
<%- end -%>
|
|
173
|
+
<%- end -%>
|
|
174
|
+
<%- else -%>
|
|
175
|
+
output.append("└── (no fields)\n");
|
|
176
|
+
<%- end -%>
|
|
177
|
+
|
|
178
|
+
return output.toString();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@Override
|
|
182
|
+
public List<Node> recursiveErrors() {
|
|
183
|
+
List<Node> result = new ArrayList<>();
|
|
184
|
+
|
|
185
|
+
if (errors != null) {
|
|
186
|
+
result.addAll(errors);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
<%- if node.fields.any? -%>
|
|
190
|
+
<%- node.fields.each do |field| -%>
|
|
191
|
+
<%- if field.is_a?(Herb::Template::ArrayField) -%>
|
|
192
|
+
|
|
193
|
+
if (<%= field.name %> != null) {
|
|
194
|
+
for (Node child : <%= field.name %>) {
|
|
195
|
+
if (child != null) {
|
|
196
|
+
result.addAll(child.recursiveErrors());
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
<%- elsif field.is_a?(Herb::Template::NodeField) -%>
|
|
202
|
+
if (<%= field.name %> != null) {
|
|
203
|
+
result.addAll(<%= field.name %>.recursiveErrors());
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
<%- end -%>
|
|
207
|
+
<%- end -%>
|
|
208
|
+
<%- end -%>
|
|
209
|
+
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@Override
|
|
214
|
+
public String toString() {
|
|
215
|
+
return "<%= node.name %> {}";
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
<%- end -%>
|
|
220
|
+
<%- end -%>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package org.herb.ast;
|
|
2
|
+
|
|
3
|
+
import java.util.List;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Abstract base class for node visitors that provides default implementations.
|
|
7
|
+
* Subclasses can override specific visit methods to customize behavior.
|
|
8
|
+
*
|
|
9
|
+
* @param <R> the return type
|
|
10
|
+
* @param <C> the context type
|
|
11
|
+
*/
|
|
12
|
+
public abstract class Visitor<R, C> implements NodeVisitor<R, C> {
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Default visit method that can be overridden by subclasses.
|
|
16
|
+
*/
|
|
17
|
+
@Override
|
|
18
|
+
public R visitNode(Node node, C context) {
|
|
19
|
+
visitChildNodes(node, context);
|
|
20
|
+
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Visit all child nodes of a given node.
|
|
26
|
+
* Subclasses can call this to recursively visit children.
|
|
27
|
+
*/
|
|
28
|
+
protected void visitChildNodes(Node node, C context) {
|
|
29
|
+
if (node != null) {
|
|
30
|
+
node.visitChildren(this, context);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Visit a list of nodes.
|
|
36
|
+
*/
|
|
37
|
+
protected void visitAll(List<Node> nodes, C context) {
|
|
38
|
+
if (nodes == null) return;
|
|
39
|
+
|
|
40
|
+
for (Node node : nodes) {
|
|
41
|
+
if (node != null) node.accept(this, context);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
<%- nodes.each do |node| -%>
|
|
46
|
+
/**
|
|
47
|
+
* Default implementation for <%= node.name %>.
|
|
48
|
+
* Delegates to visitNode by default.
|
|
49
|
+
*/
|
|
50
|
+
@Override
|
|
51
|
+
public R visit<%= node.name %>(<%= node.name %> node, C context) {
|
|
52
|
+
return visitNode(node, context);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
<%- end -%>
|
|
56
|
+
}
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Node,
|
|
3
|
+
ERBNode,
|
|
3
4
|
<%- nodes.each do |node| -%>
|
|
4
5
|
<%= node.name %>,
|
|
5
6
|
<%- end -%>
|
|
6
7
|
} from "./nodes.js"
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Interface that enforces all node visit methods are implemented
|
|
11
|
+
* This ensures that any class implementing IVisitor must have a visit method for every node type
|
|
12
|
+
*/
|
|
13
|
+
export interface IVisitor {
|
|
14
|
+
visit(node: Node | null | undefined): void
|
|
15
|
+
visitAll(nodes: (Node | null | undefined)[]): void
|
|
16
|
+
visitChildNodes(node: Node): void
|
|
17
|
+
<%- nodes.each do |node| -%>
|
|
18
|
+
visit<%= node.name %>(node: <%= node.name %>): void
|
|
19
|
+
<%- end -%>
|
|
20
|
+
visitNode(node: Node): void
|
|
21
|
+
visitERBNode(node: ERBNode): void
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class Visitor implements IVisitor {
|
|
9
25
|
visit(node: Node | null | undefined): void {
|
|
10
26
|
if (!node) return
|
|
11
27
|
|
|
@@ -20,8 +36,20 @@ export class Visitor {
|
|
|
20
36
|
node.compactChildNodes().forEach(node => node.accept(this))
|
|
21
37
|
}
|
|
22
38
|
|
|
39
|
+
visitNode(_node: Node): void {
|
|
40
|
+
// Default implementation does nothing
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
visitERBNode(_node: ERBNode): void {
|
|
44
|
+
// Default implementation does nothing
|
|
45
|
+
}
|
|
46
|
+
|
|
23
47
|
<%- nodes.each do |node| -%>
|
|
24
48
|
visit<%= node.name %>(node: <%= node.name %>): void {
|
|
49
|
+
this.visitNode(node)
|
|
50
|
+
<%- if node.name.start_with?("ERB") -%>
|
|
51
|
+
this.visitERBNode(node)
|
|
52
|
+
<%- end -%>
|
|
25
53
|
this.visitChildNodes(node)
|
|
26
54
|
}
|
|
27
55
|
|
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
#include "nodes.h"
|
|
5
5
|
|
|
6
6
|
extern "C" {
|
|
7
|
-
#include "../extension/libherb/include/herb.h"
|
|
8
|
-
#include "../extension/libherb/include/token.h"
|
|
9
|
-
#include "../extension/libherb/include/array.h"
|
|
10
|
-
#include "../extension/libherb/include/errors.h"
|
|
11
7
|
#include "../extension/libherb/include/ast_node.h"
|
|
12
8
|
#include "../extension/libherb/include/ast_nodes.h"
|
|
9
|
+
#include "../extension/libherb/include/errors.h"
|
|
10
|
+
#include "../extension/libherb/include/herb.h"
|
|
11
|
+
#include "../extension/libherb/include/token.h"
|
|
12
|
+
#include "../extension/libherb/include/util/hb_array.h"
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
napi_value ErrorFromCStruct(napi_env env, ERROR_T* error);
|
|
16
|
-
napi_value ErrorsArrayFromCArray(napi_env env,
|
|
16
|
+
napi_value ErrorsArrayFromCArray(napi_env env, hb_array_T* array);
|
|
17
17
|
|
|
18
18
|
<%- errors.each do |error| -%>
|
|
19
19
|
napi_value <%= error.name %>FromCStruct(napi_env env, <%= error.struct_type %>* <%= error.human %>) {
|
|
@@ -75,13 +75,13 @@ napi_value <%= error.name %>FromCStruct(napi_env env, <%= error.struct_type %>*
|
|
|
75
75
|
|
|
76
76
|
<%- end -%>
|
|
77
77
|
|
|
78
|
-
napi_value ErrorsArrayFromCArray(napi_env env,
|
|
78
|
+
napi_value ErrorsArrayFromCArray(napi_env env, hb_array_T* array) {
|
|
79
79
|
napi_value result;
|
|
80
80
|
napi_create_array(env, &result);
|
|
81
81
|
|
|
82
82
|
if (array) {
|
|
83
|
-
for (size_t i = 0; i <
|
|
84
|
-
ERROR_T* error = (ERROR_T*)
|
|
83
|
+
for (size_t i = 0; i < hb_array_size(array); i++) {
|
|
84
|
+
ERROR_T* error = (ERROR_T*) hb_array_get(array, i);
|
|
85
85
|
if (error) {
|
|
86
86
|
napi_value js_error = ErrorFromCStruct(env, error);
|
|
87
87
|
napi_set_element(env, result, i, js_error);
|
|
@@ -8,7 +8,7 @@ extern "C" {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
napi_value ErrorFromCStruct(napi_env env, ERROR_T* error);
|
|
11
|
-
napi_value ErrorsArrayFromCArray(napi_env env,
|
|
11
|
+
napi_value ErrorsArrayFromCArray(napi_env env, hb_array_T* array);
|
|
12
12
|
|
|
13
13
|
<%- errors.each do |error| -%>
|
|
14
14
|
napi_value <%= error.name %>FromCStruct(napi_env env, <%= error.struct_type %>* <%= error.human %>);
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
#include "nodes.h"
|
|
5
5
|
|
|
6
6
|
extern "C" {
|
|
7
|
-
#include "../extension/libherb/include/herb.h"
|
|
8
|
-
#include "../extension/libherb/include/token.h"
|
|
9
|
-
#include "../extension/libherb/include/array.h"
|
|
10
7
|
#include "../extension/libherb/include/ast_node.h"
|
|
11
8
|
#include "../extension/libherb/include/ast_nodes.h"
|
|
9
|
+
#include "../extension/libherb/include/herb.h"
|
|
10
|
+
#include "../extension/libherb/include/token.h"
|
|
11
|
+
#include "../extension/libherb/include/util/hb_array.h"
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
napi_value NodeFromCStruct(napi_env env, AST_NODE_T* node);
|
|
15
|
-
napi_value NodesArrayFromCArray(napi_env env,
|
|
15
|
+
napi_value NodesArrayFromCArray(napi_env env, hb_array_T* array);
|
|
16
16
|
|
|
17
17
|
<%- nodes.each do |node| -%>
|
|
18
18
|
napi_value <%= node.human %>NodeFromCStruct(napi_env env, <%= node.struct_type %>* <%= node.human %>) {
|
|
@@ -25,7 +25,7 @@ napi_value <%= node.human %>NodeFromCStruct(napi_env env, <%= node.struct_type %
|
|
|
25
25
|
napi_value result;
|
|
26
26
|
napi_create_object(env, &result);
|
|
27
27
|
|
|
28
|
-
napi_value type =
|
|
28
|
+
napi_value type = CreateStringFromHbString(env, ast_node_type_to_string(&<%= node.human %>->base));
|
|
29
29
|
napi_set_named_property(env, result, "type", type);
|
|
30
30
|
|
|
31
31
|
napi_value location = CreateLocation(env, <%= node.human %>->base.location);
|
|
@@ -58,7 +58,7 @@ napi_value <%= node.human %>NodeFromCStruct(napi_env env, <%= node.struct_type %
|
|
|
58
58
|
napi_set_named_property(env, result, "<%= field.name %>", <%= field.name %>);
|
|
59
59
|
|
|
60
60
|
<%- when Herb::Template::ElementSourceField -%>
|
|
61
|
-
napi_value <%= field.name %> =
|
|
61
|
+
napi_value <%= field.name %> = CreateStringFromHbString(env, element_source_to_string(<%= node.human %>-><%= field.name %>));
|
|
62
62
|
napi_set_named_property(env, result, "<%= field.name %>", <%= field.name %>);
|
|
63
63
|
|
|
64
64
|
<%- else -%>
|
|
@@ -73,13 +73,13 @@ napi_value <%= node.human %>NodeFromCStruct(napi_env env, <%= node.struct_type %
|
|
|
73
73
|
}
|
|
74
74
|
<%- end -%>
|
|
75
75
|
|
|
76
|
-
napi_value NodesArrayFromCArray(napi_env env,
|
|
76
|
+
napi_value NodesArrayFromCArray(napi_env env, hb_array_T* array) {
|
|
77
77
|
napi_value result;
|
|
78
78
|
napi_create_array(env, &result);
|
|
79
79
|
|
|
80
80
|
if (array) {
|
|
81
|
-
for (size_t i = 0; i <
|
|
82
|
-
AST_NODE_T* child_node = (AST_NODE_T*)
|
|
81
|
+
for (size_t i = 0; i < hb_array_size(array); i++) {
|
|
82
|
+
AST_NODE_T* child_node = (AST_NODE_T*) hb_array_get(array, i);
|
|
83
83
|
if (child_node) {
|
|
84
84
|
napi_value js_child = NodeFromCStruct(env, child_node);
|
|
85
85
|
napi_set_element(env, result, i, js_child);
|
|
@@ -8,7 +8,7 @@ extern "C" {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
napi_value NodeFromCStruct(napi_env env, AST_NODE_T* node);
|
|
11
|
-
napi_value NodesArrayFromCArray(napi_env env,
|
|
11
|
+
napi_value NodesArrayFromCArray(napi_env env, hb_array_T* array);
|
|
12
12
|
|
|
13
13
|
<%- nodes.each do |node| -%>
|
|
14
14
|
napi_value <%= node.human %>NodeFromCStruct(napi_env env, <%= node.struct_type %>* <%= node.human %>);
|
|
@@ -2,6 +2,8 @@ module Herb
|
|
|
2
2
|
module AST
|
|
3
3
|
<%- nodes.each do |node| -%>
|
|
4
4
|
class <%= node.name -%> < Node
|
|
5
|
+
include Colors
|
|
6
|
+
|
|
5
7
|
<%- node.fields.each do |field| -%>
|
|
6
8
|
attr_reader :<%= field.name %> #: <%= field.ruby_type %>
|
|
7
9
|
<%- end -%>
|
|
@@ -55,38 +57,42 @@ module Herb
|
|
|
55
57
|
tree_inspect.rstrip.gsub(/\s+$/, "")
|
|
56
58
|
end
|
|
57
59
|
|
|
58
|
-
#: (?Integer) -> String
|
|
59
|
-
def tree_inspect(indent
|
|
60
|
+
#: (?indent: Integer, ?depth: Integer, ?depth_limit: Integer) -> String
|
|
61
|
+
def tree_inspect(indent: 0, depth: 0, depth_limit: 10)
|
|
60
62
|
output = +""
|
|
61
63
|
|
|
62
|
-
output += "@ #{node_name} "
|
|
63
|
-
output += location.tree_inspect
|
|
64
|
+
output += white("@ #{bold(yellow(node_name.to_s))} #{dimmed("(location: #{location.tree_inspect})")}")
|
|
64
65
|
output += "\n"
|
|
65
66
|
|
|
67
|
+
if depth >= depth_limit
|
|
68
|
+
output += dimmed("└── [depth limit reached ...]\n\n")
|
|
69
|
+
|
|
70
|
+
return output.gsub(/^/, " " * indent)
|
|
71
|
+
end
|
|
72
|
+
|
|
66
73
|
output += inspect_errors(prefix: "<%= node.fields.any? ? "│ " : " " %>")
|
|
67
74
|
|
|
68
75
|
<%- node.fields.each do |field| -%>
|
|
69
76
|
<%- symbol = node.fields.last == field ? "└──" : "├──" -%>
|
|
70
|
-
<%- name = "#{symbol} #{field.name}: " -%>
|
|
71
77
|
<%- case field -%>
|
|
72
78
|
<%- when Herb::Template::StringField -%>
|
|
73
|
-
output +=
|
|
79
|
+
output += white("<%= symbol %> <%= field.name %>: ") + green("#{<%= field.name %>.inspect}\n")
|
|
74
80
|
<%- when Herb::Template::TokenField -%>
|
|
75
|
-
output += "<%= name
|
|
76
|
-
output += <%= field.name %> ? <%= field.name %>.tree_inspect : "∅"
|
|
81
|
+
output += white("<%= symbol %> <%= field.name %>: ")
|
|
82
|
+
output += <%= field.name %> ? <%= field.name %>.tree_inspect : magenta("∅")
|
|
77
83
|
output += "\n"
|
|
78
84
|
<%- when Herb::Template::BooleanField -%>
|
|
79
|
-
output += "<%= name
|
|
80
|
-
output += [true, false].include?(<%= field.name %>) ? <%= field.name %>.to_s : "∅"
|
|
85
|
+
output += white("<%= symbol %> <%= field.name %>: ")
|
|
86
|
+
output += [true, false].include?(<%= field.name %>) ? bold(magenta(<%= field.name %>.to_s)) : magenta("∅")
|
|
81
87
|
output += "\n"
|
|
82
88
|
<%- when Herb::Template::ElementSourceField -%>
|
|
83
|
-
output +=
|
|
89
|
+
output += white("<%= symbol %> <%= field.name %>: #{green(<%= field.name %>.inspect)}\n")
|
|
84
90
|
<%- when Herb::Template::PrismNodeField -%>
|
|
85
91
|
# no-op for <%= field.name %>
|
|
86
92
|
<%- when Herb::Template::AnalyzedRubyField -%>
|
|
87
93
|
# no-op for <%= field.name %>
|
|
88
94
|
<%- when Herb::Template::NodeField -%>
|
|
89
|
-
output += "<%= name
|
|
95
|
+
output += white("<%= symbol %> <%= field.name %>: ")
|
|
90
96
|
if <%= field.name %>
|
|
91
97
|
<%- prefix = (node.fields.last == field) ? " " : "│ " -%>
|
|
92
98
|
output += "\n"
|
|
@@ -95,13 +101,19 @@ module Herb
|
|
|
95
101
|
<%- else -%>
|
|
96
102
|
output += "│ └── "
|
|
97
103
|
<%- end -%>
|
|
98
|
-
output += <%= field.name %>.tree_inspect(indent).gsub(/^/, " " * (indent + 1)).lstrip.gsub(/^/, "<%= prefix %>").delete_prefix("<%= prefix %>")
|
|
104
|
+
output += <%= field.name %>.tree_inspect(indent: indent, depth: depth + 1, depth_limit: depth_limit).gsub(/^/, " " * (indent + 1)).lstrip.gsub(/^/, "<%= prefix %>").delete_prefix("<%= prefix %>")
|
|
105
|
+
<%- if false -%>
|
|
106
|
+
<%- unless node.fields.last == field -%>
|
|
107
|
+
output += "\n"
|
|
108
|
+
output += white("<%= prefix %>\n")
|
|
109
|
+
<%- end -%>
|
|
110
|
+
<%- end -%>
|
|
99
111
|
else
|
|
100
|
-
output += "∅\n"
|
|
112
|
+
output += magenta("∅\n")
|
|
101
113
|
end
|
|
102
114
|
<%- when Herb::Template::ArrayField -%>
|
|
103
|
-
output += "<%= name
|
|
104
|
-
output += inspect_array(<%= field.name %>, prefix: "<%= (node.fields.last == field) ? " " : "│ " %>")
|
|
115
|
+
output += white("<%= symbol %> <%= field.name %>: ")
|
|
116
|
+
output += inspect_array(<%= field.name %>, prefix: "<%= (node.fields.last == field) ? " " : "│ " %>", indent: indent, depth: depth + 1, depth_limit: depth_limit)
|
|
105
117
|
<%- else -%>
|
|
106
118
|
<%- raise "Unhandled type: #{field.class}" -%>
|
|
107
119
|
<%- end -%>
|