herb 0.7.1-arm-linux-gnu → 0.7.3-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.
- checksums.yaml +4 -4
- data/Makefile +2 -0
- data/README.md +1 -1
- data/Rakefile +46 -1
- data/config.yml +714 -0
- data/ext/herb/error_helpers.c +27 -27
- data/ext/herb/extconf.rb +2 -1
- data/ext/herb/extension.c +6 -6
- data/ext/herb/extension_helpers.c +3 -3
- data/ext/herb/nodes.c +35 -35
- data/herb.gemspec +3 -0
- 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/engine/debug_visitor.rb +41 -21
- data/lib/herb/engine.rb +20 -6
- data/lib/herb/version.rb +1 -1
- data/sig/herb/engine/debug_visitor.rbs +3 -3
- data/sig/herb/engine.rbs +5 -0
- data/src/analyze.c +5 -9
- data/src/analyze_helpers.c +17 -6
- data/src/include/pretty_print.h +1 -1
- data/src/include/version.h +1 -1
- data/src/parser.c +6 -9
- data/src/pretty_print.c +1 -1
- data/templates/ext/herb/error_helpers.c.erb +85 -0
- data/templates/ext/herb/error_helpers.h.erb +12 -0
- data/templates/ext/herb/nodes.c.erb +90 -0
- data/templates/ext/herb/nodes.h.erb +9 -0
- data/templates/javascript/packages/core/src/errors.ts.erb +193 -0
- data/templates/javascript/packages/core/src/node-type-guards.ts.erb +325 -0
- data/templates/javascript/packages/core/src/nodes.ts.erb +414 -0
- data/templates/javascript/packages/core/src/visitor.ts.erb +29 -0
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +113 -0
- data/templates/javascript/packages/node/extension/error_helpers.h.erb +17 -0
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +111 -0
- data/templates/javascript/packages/node/extension/nodes.h.erb +17 -0
- data/templates/lib/herb/ast/nodes.rb.erb +117 -0
- data/templates/lib/herb/errors.rb.erb +106 -0
- data/templates/lib/herb/visitor.rb.erb +28 -0
- data/templates/sig/serialized_ast_errors.rbs.erb +10 -0
- data/templates/sig/serialized_ast_nodes.rbs.erb +10 -0
- data/templates/src/ast_nodes.c.erb +145 -0
- data/templates/src/ast_pretty_print.c.erb +97 -0
- data/templates/src/errors.c.erb +245 -0
- data/templates/src/include/ast_nodes.h.erb +46 -0
- data/templates/src/include/ast_pretty_print.h.erb +14 -0
- data/templates/src/include/errors.h.erb +58 -0
- data/templates/src/visitor.c.erb +47 -0
- data/templates/template.rb +406 -0
- data/templates/wasm/error_helpers.cpp.erb +93 -0
- data/templates/wasm/error_helpers.h.erb +15 -0
- data/templates/wasm/nodes.cpp.erb +79 -0
- data/templates/wasm/nodes.h.erb +15 -0
- data/vendor/prism/Rakefile +75 -0
- data/vendor/prism/config.yml +4713 -0
- data/vendor/prism/include/prism/ast.h +8190 -0
- data/vendor/prism/include/prism/defines.h +260 -0
- data/vendor/prism/include/prism/diagnostic.h +455 -0
- data/vendor/prism/include/prism/encoding.h +283 -0
- data/vendor/prism/include/prism/node.h +129 -0
- data/vendor/prism/include/prism/options.h +482 -0
- data/vendor/prism/include/prism/pack.h +163 -0
- data/vendor/prism/include/prism/parser.h +933 -0
- data/vendor/prism/include/prism/prettyprint.h +34 -0
- data/vendor/prism/include/prism/regexp.h +43 -0
- data/vendor/prism/include/prism/static_literals.h +121 -0
- data/vendor/prism/include/prism/util/pm_buffer.h +236 -0
- data/vendor/prism/include/prism/util/pm_char.h +204 -0
- data/vendor/prism/include/prism/util/pm_constant_pool.h +218 -0
- data/vendor/prism/include/prism/util/pm_integer.h +130 -0
- data/vendor/prism/include/prism/util/pm_list.h +103 -0
- data/vendor/prism/include/prism/util/pm_memchr.h +29 -0
- data/vendor/prism/include/prism/util/pm_newline_list.h +113 -0
- data/vendor/prism/include/prism/util/pm_string.h +200 -0
- data/vendor/prism/include/prism/util/pm_strncasecmp.h +32 -0
- data/vendor/prism/include/prism/util/pm_strpbrk.h +46 -0
- data/vendor/prism/include/prism/version.h +29 -0
- data/vendor/prism/include/prism.h +408 -0
- data/vendor/prism/src/diagnostic.c +848 -0
- data/vendor/prism/src/encoding.c +5235 -0
- data/vendor/prism/src/node.c +8676 -0
- data/vendor/prism/src/options.c +328 -0
- data/vendor/prism/src/pack.c +509 -0
- data/vendor/prism/src/prettyprint.c +8941 -0
- data/vendor/prism/src/prism.c +23302 -0
- data/vendor/prism/src/regexp.c +790 -0
- data/vendor/prism/src/serialize.c +2268 -0
- data/vendor/prism/src/static_literals.c +617 -0
- data/vendor/prism/src/token_type.c +703 -0
- data/vendor/prism/src/util/pm_buffer.c +357 -0
- data/vendor/prism/src/util/pm_char.c +318 -0
- data/vendor/prism/src/util/pm_constant_pool.c +342 -0
- data/vendor/prism/src/util/pm_integer.c +670 -0
- data/vendor/prism/src/util/pm_list.c +49 -0
- data/vendor/prism/src/util/pm_memchr.c +35 -0
- data/vendor/prism/src/util/pm_newline_list.c +125 -0
- data/vendor/prism/src/util/pm_string.c +383 -0
- data/vendor/prism/src/util/pm_strncasecmp.c +36 -0
- data/vendor/prism/src/util/pm_strpbrk.c +206 -0
- data/vendor/prism/templates/ext/prism/api_node.c.erb +282 -0
- data/vendor/prism/templates/include/prism/ast.h.erb +226 -0
- data/vendor/prism/templates/include/prism/diagnostic.h.erb +130 -0
- data/vendor/prism/templates/java/org/prism/AbstractNodeVisitor.java.erb +22 -0
- data/vendor/prism/templates/java/org/prism/Loader.java.erb +434 -0
- data/vendor/prism/templates/java/org/prism/Nodes.java.erb +403 -0
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +448 -0
- data/vendor/prism/templates/javascript/src/nodes.js.erb +197 -0
- data/vendor/prism/templates/javascript/src/visitor.js.erb +78 -0
- data/vendor/prism/templates/lib/prism/compiler.rb.erb +43 -0
- data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +103 -0
- data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +189 -0
- data/vendor/prism/templates/lib/prism/dsl.rb.erb +133 -0
- data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +131 -0
- data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +19 -0
- data/vendor/prism/templates/lib/prism/node.rb.erb +515 -0
- data/vendor/prism/templates/lib/prism/reflection.rb.erb +136 -0
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +602 -0
- data/vendor/prism/templates/lib/prism/visitor.rb.erb +55 -0
- data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +68 -0
- data/vendor/prism/templates/rbi/prism/node.rbi.erb +164 -0
- data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +18 -0
- data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +45 -0
- data/vendor/prism/templates/sig/prism/dsl.rbs.erb +31 -0
- data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +7 -0
- data/vendor/prism/templates/sig/prism/node.rbs.erb +132 -0
- data/vendor/prism/templates/sig/prism/visitor.rbs.erb +17 -0
- data/vendor/prism/templates/sig/prism.rbs.erb +89 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +523 -0
- data/vendor/prism/templates/src/node.c.erb +333 -0
- data/vendor/prism/templates/src/prettyprint.c.erb +166 -0
- data/vendor/prism/templates/src/serialize.c.erb +406 -0
- data/vendor/prism/templates/src/token_type.c.erb +369 -0
- data/vendor/prism/templates/template.rb +689 -0
- metadata +112 -2
data/lib/herb/engine.rb
CHANGED
@@ -17,7 +17,7 @@ require_relative "engine/validators/accessibility_validator"
|
|
17
17
|
module Herb
|
18
18
|
class Engine
|
19
19
|
attr_reader :src, :filename, :project_path, :relative_file_path, :bufvar, :debug, :content_for_head,
|
20
|
-
:validation_error_template
|
20
|
+
:validation_error_template, :visitors
|
21
21
|
|
22
22
|
ESCAPE_TABLE = {
|
23
23
|
"&" => "&",
|
@@ -51,6 +51,16 @@ module Herb
|
|
51
51
|
@content_for_head = properties[:content_for_head]
|
52
52
|
@validation_error_template = nil
|
53
53
|
@validation_mode = properties.fetch(:validation_mode, :raise)
|
54
|
+
@visitors = properties.fetch(:visitors, default_visitors)
|
55
|
+
|
56
|
+
if @debug && @visitors.empty?
|
57
|
+
debug_visitor = DebugVisitor.new(
|
58
|
+
file_path: @filename,
|
59
|
+
project_path: @project_path
|
60
|
+
)
|
61
|
+
|
62
|
+
@visitors << debug_visitor
|
63
|
+
end
|
54
64
|
|
55
65
|
unless [:raise, :overlay, :none].include?(@validation_mode)
|
56
66
|
raise ArgumentError,
|
@@ -109,12 +119,12 @@ module Herb
|
|
109
119
|
|
110
120
|
add_validation_overlay(validation_errors, input) if @validation_mode == :overlay && validation_errors&.any?
|
111
121
|
|
112
|
-
|
113
|
-
|
114
|
-
ast.accept(debug_visitor)
|
122
|
+
@visitors.each do |visitor|
|
123
|
+
ast.accept(visitor)
|
115
124
|
end
|
116
125
|
|
117
126
|
compiler = Compiler.new(self, properties)
|
127
|
+
|
118
128
|
ast.accept(compiler)
|
119
129
|
|
120
130
|
compiler.generate_output
|
@@ -359,8 +369,12 @@ module Herb
|
|
359
369
|
)
|
360
370
|
|
361
371
|
error_html = overlay_generator.generate_html
|
362
|
-
|
363
|
-
|
372
|
+
@validation_error_template = "<template data-herb-parser-error>#{error_html}</template>"
|
373
|
+
end
|
374
|
+
|
375
|
+
#: () -> Array[Herb::Visitor]
|
376
|
+
def default_visitors
|
377
|
+
[]
|
364
378
|
end
|
365
379
|
end
|
366
380
|
end
|
data/lib/herb/version.rb
CHANGED
@@ -3,9 +3,7 @@
|
|
3
3
|
module Herb
|
4
4
|
class Engine
|
5
5
|
class DebugVisitor < Herb::Visitor
|
6
|
-
def initialize: (untyped
|
7
|
-
|
8
|
-
def debug_enabled?: () -> untyped
|
6
|
+
def initialize: (?file_path: untyped, ?project_path: untyped) -> untyped
|
9
7
|
|
10
8
|
def visit_document_node: (untyped node) -> untyped
|
11
9
|
|
@@ -23,6 +21,8 @@ module Herb
|
|
23
21
|
|
24
22
|
private
|
25
23
|
|
24
|
+
def calculate_relative_path: () -> untyped
|
25
|
+
|
26
26
|
def wrap_all_erb_nodes: (untyped node) -> untyped
|
27
27
|
|
28
28
|
# Creates a dummy location for AST nodes that don't need real location info
|
data/sig/herb/engine.rbs
CHANGED
@@ -18,6 +18,8 @@ module Herb
|
|
18
18
|
|
19
19
|
attr_reader validation_error_template: untyped
|
20
20
|
|
21
|
+
attr_reader visitors: untyped
|
22
|
+
|
21
23
|
ESCAPE_TABLE: untyped
|
22
24
|
|
23
25
|
class CompilationError < StandardError
|
@@ -68,5 +70,8 @@ module Herb
|
|
68
70
|
def escape_attr: (untyped text) -> untyped
|
69
71
|
|
70
72
|
def add_parser_error_overlay: (untyped parser_errors, untyped input) -> untyped
|
73
|
+
|
74
|
+
# : () -> Array[Herb::Visitor]
|
75
|
+
def default_visitors: () -> Array[Herb::Visitor]
|
71
76
|
end
|
72
77
|
end
|
data/src/analyze.c
CHANGED
@@ -54,7 +54,7 @@ static bool analyze_erb_content(const AST_NODE_T* node, void* data) {
|
|
54
54
|
if (strcmp(opening, "<%%") != 0 && strcmp(opening, "<%%=") != 0 && strcmp(opening, "<%#") != 0) {
|
55
55
|
analyzed_ruby_T* analyzed = herb_analyze_ruby(erb_content_node->content->value);
|
56
56
|
|
57
|
-
if (false) {
|
57
|
+
if (false) { pretty_print_analyzed_ruby(analyzed, erb_content_node->content->value); }
|
58
58
|
|
59
59
|
erb_content_node->parsed = true;
|
60
60
|
erb_content_node->valid = analyzed->valid;
|
@@ -1107,7 +1107,8 @@ void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source
|
|
1107
1107
|
char* extracted_ruby = herb_extract_ruby_with_semicolons(source);
|
1108
1108
|
|
1109
1109
|
pm_parser_t parser;
|
1110
|
-
|
1110
|
+
pm_options_t options = { 0, .partial_script = true };
|
1111
|
+
pm_parser_init(&parser, (const uint8_t*) extracted_ruby, strlen(extracted_ruby), &options);
|
1111
1112
|
|
1112
1113
|
pm_node_t* root = pm_parse(&parser);
|
1113
1114
|
|
@@ -1115,16 +1116,11 @@ void herb_analyze_parse_errors(AST_DOCUMENT_NODE_T* document, const char* source
|
|
1115
1116
|
error = (const pm_diagnostic_t*) error->node.next) {
|
1116
1117
|
|
1117
1118
|
RUBY_PARSE_ERROR_T* parse_error = ruby_parse_error_from_prism_error(error, (AST_NODE_T*) document, source, &parser);
|
1118
|
-
|
1119
|
-
// TODO: ideally this shouldn't be hard-coded
|
1120
|
-
if (strcmp(parse_error->diagnostic_id, "invalid_yield") == 0) {
|
1121
|
-
error_free((ERROR_T*) parse_error);
|
1122
|
-
} else {
|
1123
|
-
array_append(document->base.errors, parse_error);
|
1124
|
-
}
|
1119
|
+
array_append(document->base.errors, parse_error);
|
1125
1120
|
}
|
1126
1121
|
|
1127
1122
|
pm_node_destroy(&parser, root);
|
1128
1123
|
pm_parser_free(&parser);
|
1124
|
+
pm_options_free(&options);
|
1129
1125
|
free(extracted_ruby);
|
1130
1126
|
}
|
data/src/analyze_helpers.c
CHANGED
@@ -91,9 +91,12 @@ bool search_if_nodes(const pm_node_t* node, void* data) {
|
|
91
91
|
if (node->type == PM_IF_NODE) {
|
92
92
|
const pm_if_node_t* if_node = (const pm_if_node_t*) node;
|
93
93
|
|
94
|
-
|
95
|
-
|
94
|
+
bool has_if_keyword = if_node->if_keyword_loc.start != NULL && if_node->if_keyword_loc.end != NULL;
|
95
|
+
bool has_end_keyword = if_node->end_keyword_loc.start != NULL && if_node->end_keyword_loc.end != NULL;
|
96
|
+
|
97
|
+
if (has_if_keyword && has_end_keyword) {
|
96
98
|
analyzed->has_if_node = true;
|
99
|
+
|
97
100
|
return true;
|
98
101
|
}
|
99
102
|
}
|
@@ -198,12 +201,20 @@ bool search_unless_nodes(const pm_node_t* node, void* data) {
|
|
198
201
|
analyzed_ruby_T* analyzed = (analyzed_ruby_T*) data;
|
199
202
|
|
200
203
|
if (node->type == PM_UNLESS_NODE) {
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
204
|
+
const pm_unless_node_t* unless_node = (const pm_unless_node_t*) node;
|
205
|
+
|
206
|
+
bool has_if_keyword = unless_node->keyword_loc.start != NULL && unless_node->keyword_loc.end != NULL;
|
207
|
+
bool has_end_keyword = unless_node->end_keyword_loc.start != NULL && unless_node->end_keyword_loc.end != NULL;
|
208
|
+
|
209
|
+
if (has_if_keyword && has_end_keyword) {
|
210
|
+
analyzed->has_unless_node = true;
|
211
|
+
|
212
|
+
return true;
|
213
|
+
}
|
205
214
|
}
|
206
215
|
|
216
|
+
pm_visit_child_nodes(node, search_unless_nodes, analyzed);
|
217
|
+
|
207
218
|
return false;
|
208
219
|
}
|
209
220
|
|
data/src/include/pretty_print.h
CHANGED
@@ -88,6 +88,6 @@ void pretty_print_array(
|
|
88
88
|
|
89
89
|
void pretty_print_errors(AST_NODE_T* node, size_t indent, size_t relative_indent, bool last_property, buffer_T* buffer);
|
90
90
|
|
91
|
-
void
|
91
|
+
void pretty_print_analyzed_ruby(analyzed_ruby_T* analyzed, const char* source);
|
92
92
|
|
93
93
|
#endif
|
data/src/include/version.h
CHANGED
data/src/parser.c
CHANGED
@@ -555,14 +555,12 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser
|
|
555
555
|
return value;
|
556
556
|
}
|
557
557
|
|
558
|
-
token_T* token = parser_advance(parser);
|
559
|
-
|
560
558
|
append_unexpected_error(
|
561
559
|
"Unexpected Token",
|
562
560
|
"TOKEN_IDENTIFIER, TOKEN_QUOTE, TOKEN_ERB_START",
|
563
|
-
token_type_to_string(
|
564
|
-
|
565
|
-
|
561
|
+
token_type_to_string(parser->current_token->type),
|
562
|
+
parser->current_token->location->start,
|
563
|
+
parser->current_token->location->end,
|
566
564
|
errors
|
567
565
|
);
|
568
566
|
|
@@ -571,13 +569,11 @@ static AST_HTML_ATTRIBUTE_VALUE_NODE_T* parser_parse_html_attribute_value(parser
|
|
571
569
|
children,
|
572
570
|
NULL,
|
573
571
|
false,
|
574
|
-
|
575
|
-
|
572
|
+
parser->current_token->location->start,
|
573
|
+
parser->current_token->location->end,
|
576
574
|
errors
|
577
575
|
);
|
578
576
|
|
579
|
-
token_free(token);
|
580
|
-
|
581
577
|
return value;
|
582
578
|
}
|
583
579
|
|
@@ -1135,6 +1131,7 @@ static void parser_parse_in_data_state(parser_T* parser, array_T* children, arra
|
|
1135
1131
|
parser,
|
1136
1132
|
TOKEN_AMPERSAND,
|
1137
1133
|
TOKEN_AT,
|
1134
|
+
TOKEN_BACKTICK,
|
1138
1135
|
TOKEN_CHARACTER,
|
1139
1136
|
TOKEN_COLON,
|
1140
1137
|
TOKEN_DASH,
|
data/src/pretty_print.c
CHANGED
@@ -254,7 +254,7 @@ void pretty_print_string_property(
|
|
254
254
|
}
|
255
255
|
}
|
256
256
|
|
257
|
-
void
|
257
|
+
void pretty_print_analyzed_ruby(analyzed_ruby_T* analyzed, const char* source) {
|
258
258
|
printf(
|
259
259
|
"------------------------\nanalyzed (%p)\n------------------------\n%s\n------------------------\n if: %i\n "
|
260
260
|
" elsif: %i\n else: %i\n end: %i\n block: %i\n block_closing: %i\n case: %i\n when: %i\n for: "
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#include "extension.h"
|
4
|
+
#include "extension_helpers.h"
|
5
|
+
#include "error_helpers.h"
|
6
|
+
|
7
|
+
#include "../../src/include/errors.h"
|
8
|
+
#include "../../src/include/herb.h"
|
9
|
+
#include "../../src/include/token.h"
|
10
|
+
|
11
|
+
VALUE rb_error_from_c_struct(ERROR_T* error);
|
12
|
+
|
13
|
+
<%- errors.each do |error| -%>
|
14
|
+
static VALUE rb_<%= error.human %>_from_c_struct(<%= error.struct_type %>* <%= error.human %>) {
|
15
|
+
if (<%= error.human %> == NULL) { return Qnil; }
|
16
|
+
|
17
|
+
ERROR_T* error = &<%= error.human %>->base;
|
18
|
+
|
19
|
+
VALUE Herb = rb_define_module("Herb");
|
20
|
+
VALUE Errors = rb_define_module_under(Herb, "Errors");
|
21
|
+
VALUE Error = rb_define_class_under(Errors, "Error", rb_cObject);
|
22
|
+
VALUE <%= error.name %> = rb_define_class_under(Errors, "<%= error.name %>", Error);
|
23
|
+
|
24
|
+
VALUE type = rb_utf8_str_new_cstr(error_type_to_string(error));
|
25
|
+
VALUE location = rb_location_from_c_struct(error->location);
|
26
|
+
VALUE message = rb_utf8_str_new_cstr(error->message);
|
27
|
+
|
28
|
+
<%- error.fields.each do |field| -%>
|
29
|
+
<%- case field -%>
|
30
|
+
<%- when Herb::Template::PositionField -%>
|
31
|
+
VALUE <%= error.human %>_<%= field.name %> = rb_position_from_c_struct(<%= error.human %>-><%= field.name %>);
|
32
|
+
<%- when Herb::Template::TokenField -%>
|
33
|
+
VALUE <%= error.human %>_<%= field.name %> = rb_token_from_c_struct(<%= error.human %>-><%= field.name %>);
|
34
|
+
<%- when Herb::Template::TokenTypeField -%>
|
35
|
+
VALUE <%= error.human %>_<%= field.name %> = rb_utf8_str_new_cstr(token_type_to_string(<%= error.human %>-><%= field.name %>));
|
36
|
+
<%- when Herb::Template::StringField -%>
|
37
|
+
VALUE <%= error.human %>_<%= field.name %> = rb_utf8_str_new_cstr(<%= error.human %>-><%= field.name %>);
|
38
|
+
<%- else -%>
|
39
|
+
/* <%= field.inspect %> */
|
40
|
+
VALUE <%= error.human %>_<%= field.name %> = Qnil;
|
41
|
+
<%- end -%>
|
42
|
+
<%- end -%>
|
43
|
+
|
44
|
+
VALUE args[<%= 3 + error.fields.count %>] = {
|
45
|
+
type,
|
46
|
+
location,
|
47
|
+
message<% if error.fields.any? %>,<% end %>
|
48
|
+
<%- error.fields.each do |field| -%>
|
49
|
+
<%= error.human %>_<%= field.name %><% if error.fields.last != field %>,<% end %>
|
50
|
+
<%- end -%>
|
51
|
+
};
|
52
|
+
|
53
|
+
return rb_class_new_instance(<%= 3 + error.fields.count %>, args, <%= error.name %>);
|
54
|
+
};
|
55
|
+
|
56
|
+
<%- end -%>
|
57
|
+
|
58
|
+
VALUE rb_error_from_c_struct(ERROR_T* error) {
|
59
|
+
if (!error) { return Qnil; }
|
60
|
+
|
61
|
+
switch (error->type) {
|
62
|
+
<%- errors.each do |error| -%>
|
63
|
+
case <%= error.type %>: return rb_<%= error.human %>_from_c_struct((<%= error.struct_type %>*) error); break;
|
64
|
+
<%- end -%>
|
65
|
+
}
|
66
|
+
|
67
|
+
return Qnil;
|
68
|
+
}
|
69
|
+
|
70
|
+
VALUE rb_errors_array_from_c_array(array_T* array) {
|
71
|
+
VALUE rb_array = rb_ary_new();
|
72
|
+
|
73
|
+
if (array) {
|
74
|
+
for (size_t i = 0; i < array_size(array); i++) {
|
75
|
+
ERROR_T* child_node = (ERROR_T*) array_get(array, i);
|
76
|
+
|
77
|
+
if (child_node) {
|
78
|
+
VALUE rb_child = rb_error_from_c_struct(child_node);
|
79
|
+
rb_ary_push(rb_array, rb_child);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
return rb_array;
|
85
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#ifndef HERB_EXTENSION_ERROR_HELPERS_H
|
2
|
+
#define HERB_EXTENSION_ERROR_HELPERS_H
|
3
|
+
|
4
|
+
#include "../../src/include/errors.h"
|
5
|
+
#include "../../src/include/herb.h"
|
6
|
+
|
7
|
+
#include <ruby.h>
|
8
|
+
|
9
|
+
VALUE rb_error_from_c_struct(ERROR_T* error);
|
10
|
+
VALUE rb_errors_array_from_c_array(array_T* array);
|
11
|
+
|
12
|
+
#endif
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#include "error_helpers.h"
|
4
|
+
#include "extension_helpers.h"
|
5
|
+
#include "extension.h"
|
6
|
+
#include "nodes.h"
|
7
|
+
|
8
|
+
#include "../../src/include/herb.h"
|
9
|
+
#include "../../src/include/token.h"
|
10
|
+
|
11
|
+
VALUE rb_node_from_c_struct(AST_NODE_T* node);
|
12
|
+
static VALUE rb_nodes_array_from_c_array(array_T* array);
|
13
|
+
|
14
|
+
<%- nodes.each do |node| -%>
|
15
|
+
static VALUE rb_<%= node.human %>_from_c_struct(<%= node.struct_type %>* <%= node.human %>) {
|
16
|
+
if (<%= node.human %> == NULL) { return Qnil; }
|
17
|
+
|
18
|
+
AST_NODE_T* node = &<%= node.human %>->base;
|
19
|
+
|
20
|
+
VALUE Herb = rb_define_module("Herb");
|
21
|
+
VALUE AST = rb_define_module_under(Herb, "AST");
|
22
|
+
VALUE Node = rb_define_class_under(AST, "Node", rb_cObject);
|
23
|
+
VALUE <%= node.name %> = rb_define_class_under(AST, "<%= node.name %>", Node);
|
24
|
+
|
25
|
+
VALUE type = rb_utf8_str_new_cstr(ast_node_type_to_string(node));
|
26
|
+
VALUE location = rb_location_from_c_struct(node->location);
|
27
|
+
VALUE errors = rb_errors_array_from_c_array(node->errors);
|
28
|
+
|
29
|
+
<%- node.fields.each do |field| -%>
|
30
|
+
<%- case field -%>
|
31
|
+
<%- when Herb::Template::StringField -%>
|
32
|
+
VALUE <%= node.human %>_<%= field.name %> = rb_utf8_str_new_cstr(<%= node.human %>-><%= field.name %>);
|
33
|
+
<%- when Herb::Template::NodeField -%>
|
34
|
+
VALUE <%= node.human %>_<%= field.name %> = rb_node_from_c_struct((AST_NODE_T*) <%= node.human %>-><%= field.name %>);
|
35
|
+
<%- when Herb::Template::TokenField -%>
|
36
|
+
VALUE <%= node.human %>_<%= field.name %> = rb_token_from_c_struct(<%= node.human %>-><%= field.name %>);
|
37
|
+
<%- when Herb::Template::BooleanField -%>
|
38
|
+
VALUE <%= node.human %>_<%= field.name %> = (<%= node.human %>-><%= field.name %>) ? Qtrue : Qfalse;
|
39
|
+
<%- when Herb::Template::ArrayField -%>
|
40
|
+
VALUE <%= node.human %>_<%= field.name %> = rb_nodes_array_from_c_array(<%= node.human %>-><%= field.name %>);
|
41
|
+
<%- when Herb::Template::ElementSourceField -%>
|
42
|
+
VALUE <%= node.human %>_<%= field.name %> = rb_utf8_str_new_cstr(element_source_to_string(<%= node.human %>-><%= field.name %>));
|
43
|
+
<%- else -%>
|
44
|
+
/* <%= field.inspect %> */
|
45
|
+
VALUE <%= node.human %>_<%= field.name %> = Qnil;
|
46
|
+
<%- end -%>
|
47
|
+
<%- end -%>
|
48
|
+
|
49
|
+
VALUE args[<%= 3 + node.fields.count %>] = {
|
50
|
+
type,
|
51
|
+
location,
|
52
|
+
errors<% if node.fields.any? %>,<% end %>
|
53
|
+
<%- node.fields.each do |field| -%>
|
54
|
+
<%= node.human %>_<%= field.name %><% if node.fields.last != field %>,<% end %>
|
55
|
+
<%- end -%>
|
56
|
+
};
|
57
|
+
|
58
|
+
return rb_class_new_instance(<%= 3 + node.fields.count %>, args, <%= node.name %>);
|
59
|
+
};
|
60
|
+
|
61
|
+
<%- end -%>
|
62
|
+
|
63
|
+
VALUE rb_node_from_c_struct(AST_NODE_T* node) {
|
64
|
+
if (!node) { return Qnil; }
|
65
|
+
|
66
|
+
switch (node->type) {
|
67
|
+
<%- nodes.each do |node| -%>
|
68
|
+
case <%= node.type %>: return rb_<%= node.human %>_from_c_struct((<%= node.struct_type %>*) node); break;
|
69
|
+
<%- end -%>
|
70
|
+
}
|
71
|
+
|
72
|
+
return Qnil;
|
73
|
+
}
|
74
|
+
|
75
|
+
static VALUE rb_nodes_array_from_c_array(array_T* array) {
|
76
|
+
VALUE rb_array = rb_ary_new();
|
77
|
+
|
78
|
+
if (array) {
|
79
|
+
for (size_t i = 0; i < array_size(array); i++) {
|
80
|
+
AST_NODE_T* child_node = (AST_NODE_T*) array_get(array, i);
|
81
|
+
|
82
|
+
if (child_node) {
|
83
|
+
VALUE rb_child = rb_node_from_c_struct(child_node);
|
84
|
+
rb_ary_push(rb_array, rb_child);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
return rb_array;
|
90
|
+
}
|
@@ -0,0 +1,193 @@
|
|
1
|
+
import { Location, SerializedLocation } from "./location.js"
|
2
|
+
import { Token, SerializedToken } from "./token.js"
|
3
|
+
import { Diagnostic, MonacoDiagnostic } from "./diagnostic.js"
|
4
|
+
|
5
|
+
export type HerbErrorType =
|
6
|
+
<%- errors.each_with_index.map do |error, index| -%>
|
7
|
+
| "<%= error.type %>"
|
8
|
+
<%- end -%>
|
9
|
+
|
10
|
+
export type SerializedErrorType = string
|
11
|
+
|
12
|
+
export interface SerializedHerbError {
|
13
|
+
type: string
|
14
|
+
message: string
|
15
|
+
location: SerializedLocation
|
16
|
+
}
|
17
|
+
|
18
|
+
export abstract class HerbError implements Diagnostic {
|
19
|
+
readonly type: string
|
20
|
+
readonly message: string
|
21
|
+
readonly location: Location
|
22
|
+
readonly severity: "error" | "warning" | "info" | "hint" = "error"
|
23
|
+
readonly source: string = "parser"
|
24
|
+
|
25
|
+
get code(): string {
|
26
|
+
return this.type
|
27
|
+
}
|
28
|
+
|
29
|
+
static from(error: SerializedHerbError): HerbError {
|
30
|
+
return fromSerializedError(error)
|
31
|
+
}
|
32
|
+
|
33
|
+
constructor(type: string, message: string, location: Location) {
|
34
|
+
this.type = type
|
35
|
+
this.message = message
|
36
|
+
this.location = location
|
37
|
+
}
|
38
|
+
|
39
|
+
toJSON(): SerializedHerbError {
|
40
|
+
return {
|
41
|
+
type: this.type,
|
42
|
+
message: this.message,
|
43
|
+
location: this.location.toJSON(),
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
inspect(): string {
|
48
|
+
return this.treeInspect(0)
|
49
|
+
}
|
50
|
+
|
51
|
+
abstract treeInspect(indent?: number): string
|
52
|
+
}
|
53
|
+
|
54
|
+
<%- errors.each do |error| -%>
|
55
|
+
export interface Serialized<%= error.name %> {
|
56
|
+
type: "<%= error.type %>";
|
57
|
+
message: string;
|
58
|
+
location: SerializedLocation;
|
59
|
+
<%- error.fields.each do |field| -%>
|
60
|
+
<%- case field -%>
|
61
|
+
<%- when Herb::Template::StringField -%>
|
62
|
+
<%= field.name %>: string;
|
63
|
+
<%- when Herb::Template::TokenField -%>
|
64
|
+
<%= field.name %>: SerializedToken | null;
|
65
|
+
<%- when Herb::Template::TokenTypeField -%>
|
66
|
+
<%= field.name %>: string | null;
|
67
|
+
<%- else -%>
|
68
|
+
<%= field.name %>: any; // <%= field.inspect %>
|
69
|
+
<%- end -%>
|
70
|
+
<%- end -%>
|
71
|
+
}
|
72
|
+
|
73
|
+
export interface <%= error.name %>Props {
|
74
|
+
type: string;
|
75
|
+
message: string;
|
76
|
+
location: Location;
|
77
|
+
<%- error.fields.each do |field| -%>
|
78
|
+
<%- case field -%>
|
79
|
+
<%- when Herb::Template::StringField -%>
|
80
|
+
<%= field.name %>: string;
|
81
|
+
<%- when Herb::Template::TokenField -%>
|
82
|
+
<%= field.name %>: Token | null;
|
83
|
+
<%- when Herb::Template::TokenTypeField -%>
|
84
|
+
<%= field.name %>: string | null;
|
85
|
+
<%- else -%>
|
86
|
+
<%= field.name %>: any; // <%= field.inspect %>
|
87
|
+
<%- end -%>
|
88
|
+
<%- end -%>
|
89
|
+
}
|
90
|
+
|
91
|
+
export class <%= error.name %> extends HerbError {
|
92
|
+
<%- error.fields.each do |field| -%>
|
93
|
+
<%- case field -%>
|
94
|
+
<%- when Herb::Template::StringField -%>
|
95
|
+
readonly <%= field.name %>: string;
|
96
|
+
<%- when Herb::Template::TokenField -%>
|
97
|
+
readonly <%= field.name %>: Token | null;
|
98
|
+
<%- when Herb::Template::TokenTypeField -%>
|
99
|
+
readonly <%= field.name %>: string | null;
|
100
|
+
<%- else -%>
|
101
|
+
readonly <%= field.name %>: any;
|
102
|
+
<%- end -%>
|
103
|
+
<%- end -%>
|
104
|
+
|
105
|
+
static from(data: Serialized<%= error.name %>): <%= error.name %> {
|
106
|
+
return new <%= error.name %>({
|
107
|
+
type: data.type,
|
108
|
+
message: data.message,
|
109
|
+
location: Location.from(data.location),
|
110
|
+
<%- error.fields.each do |field| -%>
|
111
|
+
<%- case field -%>
|
112
|
+
<%- when Herb::Template::StringField, Herb::Template::TokenTypeField, Herb::Template::SizeTField -%>
|
113
|
+
<%= field.name %>: data.<%= field.name %>,
|
114
|
+
<%- when Herb::Template::TokenField -%>
|
115
|
+
<%= field.name %>: data.<%= field.name %> ? Token.from(data.<%= field.name %>) : null,
|
116
|
+
<%- else -%>
|
117
|
+
<% raise "Unexpetected type: #{field.class}" %>
|
118
|
+
<%- end -%>
|
119
|
+
<%- end -%>
|
120
|
+
})
|
121
|
+
}
|
122
|
+
|
123
|
+
constructor(props: <%= error.name %>Props) {
|
124
|
+
super(props.type, props.message, props.location);
|
125
|
+
|
126
|
+
<%- error.fields.each do |field| -%>
|
127
|
+
this.<%= field.name %> = props.<%= field.name %>;
|
128
|
+
<%- end -%>
|
129
|
+
}
|
130
|
+
|
131
|
+
toJSON(): Serialized<%= error.name %> {
|
132
|
+
return {
|
133
|
+
...super.toJSON(),
|
134
|
+
type: "<%= error.type %>",
|
135
|
+
<%- error.fields.each do |field| -%>
|
136
|
+
<%- case field -%>
|
137
|
+
<%- when Herb::Template::StringField, Herb::Template::TokenTypeField, Herb::Template::SizeTField -%>
|
138
|
+
<%= field.name %>: this.<%= field.name %>,
|
139
|
+
<%- when Herb::Template::TokenField -%>
|
140
|
+
<%= field.name %>: this.<%= field.name %> ? this.<%= field.name %>.toJSON() : null,
|
141
|
+
<%- else -%>
|
142
|
+
<% raise "Unexpetected type: #{field.class}" %>
|
143
|
+
<%- end -%>
|
144
|
+
<%- end -%>
|
145
|
+
};
|
146
|
+
}
|
147
|
+
|
148
|
+
toMonacoDiagnostic(): MonacoDiagnostic {
|
149
|
+
return {
|
150
|
+
line: this.location.start.line,
|
151
|
+
column: this.location.start.column,
|
152
|
+
endLine: this.location.end.line,
|
153
|
+
endColumn: this.location.end.column,
|
154
|
+
message: this.message,
|
155
|
+
severity: 'error'
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
treeInspect(): string {
|
160
|
+
let output = "";
|
161
|
+
|
162
|
+
output += `@ <%= error.name %> ${this.location.treeInspectWithLabel()}\n`;
|
163
|
+
<%- symbol = error.fields.any? ? "├──" : "└──" -%>
|
164
|
+
output += `<%= symbol %> message: "${this.message}"\n`;
|
165
|
+
<%- error.fields.each do |field| -%>
|
166
|
+
<%- symbol = error.fields.last == field ? "└──" : "├──" -%>
|
167
|
+
<%- name = "#{symbol} #{field.name}: " -%>
|
168
|
+
<%- case field -%>
|
169
|
+
<%- when Herb::Template::StringField, Herb::Template::TokenTypeField, Herb::Template::SizeTField -%>
|
170
|
+
output += `<%= name %>${JSON.stringify(this.<%= field.name %>)}\n`;
|
171
|
+
<%- when Herb::Template::TokenField -%>
|
172
|
+
output += `<%= name %>${this.<%= field.name %> ? this.<%= field.name %>.treeInspect() : "∅"}\n`;
|
173
|
+
<%- else -%>
|
174
|
+
<% raise "Unexpetected type: #{field.class}" %>
|
175
|
+
<%- end -%>
|
176
|
+
<%- end -%>
|
177
|
+
|
178
|
+
return output;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
<%- end -%>
|
183
|
+
|
184
|
+
export function fromSerializedError(error: SerializedHerbError): HerbError {
|
185
|
+
switch (error.type) {
|
186
|
+
<%- errors.each do |error| -%>
|
187
|
+
case "<%= error.type %>": return <%= error.name %>.from(error as Serialized<%= error.name %>);
|
188
|
+
<%- end -%>
|
189
|
+
|
190
|
+
default:
|
191
|
+
throw new Error(`Unknown node type: ${error.type}`);
|
192
|
+
}
|
193
|
+
}
|