herb 0.7.2-aarch64-linux-musl → 0.7.3-aarch64-linux-musl
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/extconf.rb +2 -1
- data/ext/herb/nodes.c +1 -1
- 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/version.rb +1 -1
- 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 +1 -0
- 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
@@ -0,0 +1,206 @@
|
|
1
|
+
#include "prism/util/pm_strpbrk.h"
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Add an invalid multibyte character error to the parser.
|
5
|
+
*/
|
6
|
+
static inline void
|
7
|
+
pm_strpbrk_invalid_multibyte_character(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
|
8
|
+
pm_diagnostic_list_append_format(&parser->error_list, start, end, PM_ERR_INVALID_MULTIBYTE_CHARACTER, *start);
|
9
|
+
}
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Set the explicit encoding for the parser to the current encoding.
|
13
|
+
*/
|
14
|
+
static inline void
|
15
|
+
pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, const uint8_t *source, size_t width) {
|
16
|
+
if (parser->explicit_encoding != NULL) {
|
17
|
+
if (parser->explicit_encoding == parser->encoding) {
|
18
|
+
// Okay, we already locked to this encoding.
|
19
|
+
} else if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) {
|
20
|
+
// Not okay, we already found a Unicode escape sequence and this
|
21
|
+
// conflicts.
|
22
|
+
pm_diagnostic_list_append_format(&parser->error_list, source, source + width, PM_ERR_MIXED_ENCODING, parser->encoding->name);
|
23
|
+
} else {
|
24
|
+
// Should not be anything else.
|
25
|
+
assert(false && "unreachable");
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
parser->explicit_encoding = parser->encoding;
|
30
|
+
}
|
31
|
+
|
32
|
+
/**
|
33
|
+
* This is the default path.
|
34
|
+
*/
|
35
|
+
static inline const uint8_t *
|
36
|
+
pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
|
37
|
+
size_t index = 0;
|
38
|
+
|
39
|
+
while (index < maximum) {
|
40
|
+
if (strchr((const char *) charset, source[index]) != NULL) {
|
41
|
+
return source + index;
|
42
|
+
}
|
43
|
+
|
44
|
+
if (source[index] < 0x80) {
|
45
|
+
index++;
|
46
|
+
} else {
|
47
|
+
size_t width = pm_encoding_utf_8_char_width(source + index, (ptrdiff_t) (maximum - index));
|
48
|
+
|
49
|
+
if (width > 0) {
|
50
|
+
index += width;
|
51
|
+
} else if (!validate) {
|
52
|
+
index++;
|
53
|
+
} else {
|
54
|
+
// At this point we know we have an invalid multibyte character.
|
55
|
+
// We'll walk forward as far as we can until we find the next
|
56
|
+
// valid character so that we don't spam the user with a ton of
|
57
|
+
// the same kind of error.
|
58
|
+
const size_t start = index;
|
59
|
+
|
60
|
+
do {
|
61
|
+
index++;
|
62
|
+
} while (index < maximum && pm_encoding_utf_8_char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
|
63
|
+
|
64
|
+
pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
return NULL;
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* This is the path when the encoding is ASCII-8BIT.
|
74
|
+
*/
|
75
|
+
static inline const uint8_t *
|
76
|
+
pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
|
77
|
+
size_t index = 0;
|
78
|
+
|
79
|
+
while (index < maximum) {
|
80
|
+
if (strchr((const char *) charset, source[index]) != NULL) {
|
81
|
+
return source + index;
|
82
|
+
}
|
83
|
+
|
84
|
+
if (validate && source[index] >= 0x80) pm_strpbrk_explicit_encoding_set(parser, source, 1);
|
85
|
+
index++;
|
86
|
+
}
|
87
|
+
|
88
|
+
return NULL;
|
89
|
+
}
|
90
|
+
|
91
|
+
/**
|
92
|
+
* This is the slow path that does care about the encoding.
|
93
|
+
*/
|
94
|
+
static inline const uint8_t *
|
95
|
+
pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
|
96
|
+
size_t index = 0;
|
97
|
+
const pm_encoding_t *encoding = parser->encoding;
|
98
|
+
|
99
|
+
while (index < maximum) {
|
100
|
+
if (strchr((const char *) charset, source[index]) != NULL) {
|
101
|
+
return source + index;
|
102
|
+
}
|
103
|
+
|
104
|
+
if (source[index] < 0x80) {
|
105
|
+
index++;
|
106
|
+
} else {
|
107
|
+
size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index));
|
108
|
+
if (validate) pm_strpbrk_explicit_encoding_set(parser, source, width);
|
109
|
+
|
110
|
+
if (width > 0) {
|
111
|
+
index += width;
|
112
|
+
} else if (!validate) {
|
113
|
+
index++;
|
114
|
+
} else {
|
115
|
+
// At this point we know we have an invalid multibyte character.
|
116
|
+
// We'll walk forward as far as we can until we find the next
|
117
|
+
// valid character so that we don't spam the user with a ton of
|
118
|
+
// the same kind of error.
|
119
|
+
const size_t start = index;
|
120
|
+
|
121
|
+
do {
|
122
|
+
index++;
|
123
|
+
} while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
|
124
|
+
|
125
|
+
pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
return NULL;
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* This is the fast path that does not care about the encoding because we know
|
135
|
+
* the encoding only supports single-byte characters.
|
136
|
+
*/
|
137
|
+
static inline const uint8_t *
|
138
|
+
pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
|
139
|
+
size_t index = 0;
|
140
|
+
const pm_encoding_t *encoding = parser->encoding;
|
141
|
+
|
142
|
+
while (index < maximum) {
|
143
|
+
if (strchr((const char *) charset, source[index]) != NULL) {
|
144
|
+
return source + index;
|
145
|
+
}
|
146
|
+
|
147
|
+
if (source[index] < 0x80 || !validate) {
|
148
|
+
index++;
|
149
|
+
} else {
|
150
|
+
size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index));
|
151
|
+
pm_strpbrk_explicit_encoding_set(parser, source, width);
|
152
|
+
|
153
|
+
if (width > 0) {
|
154
|
+
index += width;
|
155
|
+
} else {
|
156
|
+
// At this point we know we have an invalid multibyte character.
|
157
|
+
// We'll walk forward as far as we can until we find the next
|
158
|
+
// valid character so that we don't spam the user with a ton of
|
159
|
+
// the same kind of error.
|
160
|
+
const size_t start = index;
|
161
|
+
|
162
|
+
do {
|
163
|
+
index++;
|
164
|
+
} while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
|
165
|
+
|
166
|
+
pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
return NULL;
|
172
|
+
}
|
173
|
+
|
174
|
+
/**
|
175
|
+
* Here we have rolled our own version of strpbrk. The standard library strpbrk
|
176
|
+
* has undefined behavior when the source string is not null-terminated. We want
|
177
|
+
* to support strings that are not null-terminated because pm_parse does not
|
178
|
+
* have the contract that the string is null-terminated. (This is desirable
|
179
|
+
* because it means the extension can call pm_parse with the result of a call to
|
180
|
+
* mmap).
|
181
|
+
*
|
182
|
+
* The standard library strpbrk also does not support passing a maximum length
|
183
|
+
* to search. We want to support this for the reason mentioned above, but we
|
184
|
+
* also don't want it to stop on null bytes. Ruby actually allows null bytes
|
185
|
+
* within strings, comments, regular expressions, etc. So we need to be able to
|
186
|
+
* skip past them.
|
187
|
+
*
|
188
|
+
* Finally, we want to support encodings wherein the charset could contain
|
189
|
+
* characters that are trailing bytes of multi-byte characters. For example, in
|
190
|
+
* Shift_JIS, the backslash character can be a trailing byte. In that case we
|
191
|
+
* need to take a slower path and iterate one multi-byte character at a time.
|
192
|
+
*/
|
193
|
+
const uint8_t *
|
194
|
+
pm_strpbrk(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, ptrdiff_t length, bool validate) {
|
195
|
+
if (length <= 0) {
|
196
|
+
return NULL;
|
197
|
+
} else if (!parser->encoding_changed) {
|
198
|
+
return pm_strpbrk_utf8(parser, source, charset, (size_t) length, validate);
|
199
|
+
} else if (parser->encoding == PM_ENCODING_ASCII_8BIT_ENTRY) {
|
200
|
+
return pm_strpbrk_ascii_8bit(parser, source, charset, (size_t) length, validate);
|
201
|
+
} else if (parser->encoding->multibyte) {
|
202
|
+
return pm_strpbrk_multi_byte(parser, source, charset, (size_t) length, validate);
|
203
|
+
} else {
|
204
|
+
return pm_strpbrk_single_byte(parser, source, charset, (size_t) length, validate);
|
205
|
+
}
|
206
|
+
}
|
@@ -0,0 +1,282 @@
|
|
1
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
2
|
+
#include "prism/extension.h"
|
3
|
+
|
4
|
+
extern VALUE rb_cPrism;
|
5
|
+
extern VALUE rb_cPrismNode;
|
6
|
+
extern VALUE rb_cPrismSource;
|
7
|
+
extern VALUE rb_cPrismToken;
|
8
|
+
extern VALUE rb_cPrismLocation;
|
9
|
+
|
10
|
+
<%- nodes.each do |node| -%>
|
11
|
+
static VALUE rb_cPrism<%= node.name %>;
|
12
|
+
<%- end -%>
|
13
|
+
|
14
|
+
static VALUE
|
15
|
+
pm_location_new(const pm_parser_t *parser, const uint8_t *start, const uint8_t *end, VALUE source, bool freeze) {
|
16
|
+
if (freeze) {
|
17
|
+
VALUE location_argv[] = {
|
18
|
+
source,
|
19
|
+
LONG2FIX(start - parser->start),
|
20
|
+
LONG2FIX(end - start)
|
21
|
+
};
|
22
|
+
|
23
|
+
return rb_obj_freeze(rb_class_new_instance(3, location_argv, rb_cPrismLocation));
|
24
|
+
} else {
|
25
|
+
uint64_t value = ((((uint64_t) (start - parser->start)) << 32) | ((uint32_t) (end - start)));
|
26
|
+
return ULL2NUM(value);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
VALUE
|
31
|
+
pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source, bool freeze) {
|
32
|
+
ID type = rb_intern(pm_token_type_name(token->type));
|
33
|
+
VALUE location = pm_location_new(parser, token->start, token->end, source, freeze);
|
34
|
+
|
35
|
+
VALUE slice = rb_enc_str_new((const char *) token->start, token->end - token->start, encoding);
|
36
|
+
if (freeze) rb_obj_freeze(slice);
|
37
|
+
|
38
|
+
VALUE argv[] = { source, ID2SYM(type), slice, location };
|
39
|
+
VALUE value = rb_class_new_instance(4, argv, rb_cPrismToken);
|
40
|
+
if (freeze) rb_obj_freeze(value);
|
41
|
+
|
42
|
+
return value;
|
43
|
+
}
|
44
|
+
|
45
|
+
static VALUE
|
46
|
+
pm_string_new(const pm_string_t *string, rb_encoding *encoding) {
|
47
|
+
return rb_obj_freeze(rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding));
|
48
|
+
}
|
49
|
+
|
50
|
+
VALUE
|
51
|
+
pm_integer_new(const pm_integer_t *integer) {
|
52
|
+
VALUE result;
|
53
|
+
if (integer->values == NULL) {
|
54
|
+
result = UINT2NUM(integer->value);
|
55
|
+
} else {
|
56
|
+
VALUE string = rb_str_new(NULL, integer->length * 8);
|
57
|
+
unsigned char *bytes = (unsigned char *) RSTRING_PTR(string);
|
58
|
+
|
59
|
+
size_t offset = integer->length * 8;
|
60
|
+
for (size_t value_index = 0; value_index < integer->length; value_index++) {
|
61
|
+
uint32_t value = integer->values[value_index];
|
62
|
+
|
63
|
+
for (int index = 0; index < 8; index++) {
|
64
|
+
int byte = (value >> (4 * index)) & 0xf;
|
65
|
+
bytes[--offset] = byte < 10 ? byte + '0' : byte - 10 + 'a';
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
result = rb_funcall(string, rb_intern("to_i"), 1, UINT2NUM(16));
|
70
|
+
}
|
71
|
+
|
72
|
+
if (integer->negative) {
|
73
|
+
result = rb_funcall(result, rb_intern("-@"), 0);
|
74
|
+
}
|
75
|
+
|
76
|
+
return result;
|
77
|
+
}
|
78
|
+
|
79
|
+
// Create a Prism::Source object from the given parser, after pm_parse() was called.
|
80
|
+
VALUE
|
81
|
+
pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze) {
|
82
|
+
VALUE source_string = rb_enc_str_new((const char *) parser->start, parser->end - parser->start, encoding);
|
83
|
+
|
84
|
+
VALUE offsets = rb_ary_new_capa(parser->newline_list.size);
|
85
|
+
for (size_t index = 0; index < parser->newline_list.size; index++) {
|
86
|
+
rb_ary_push(offsets, ULONG2NUM(parser->newline_list.offsets[index]));
|
87
|
+
}
|
88
|
+
|
89
|
+
if (freeze) {
|
90
|
+
rb_obj_freeze(source_string);
|
91
|
+
rb_obj_freeze(offsets);
|
92
|
+
}
|
93
|
+
|
94
|
+
VALUE source = rb_funcall(rb_cPrismSource, rb_intern("for"), 3, source_string, LONG2NUM(parser->start_line), offsets);
|
95
|
+
if (freeze) rb_obj_freeze(source);
|
96
|
+
|
97
|
+
return source;
|
98
|
+
}
|
99
|
+
|
100
|
+
typedef struct pm_node_stack_node {
|
101
|
+
struct pm_node_stack_node *prev;
|
102
|
+
const pm_node_t *visit;
|
103
|
+
bool visited;
|
104
|
+
} pm_node_stack_node_t;
|
105
|
+
|
106
|
+
static void
|
107
|
+
pm_node_stack_push(pm_node_stack_node_t **stack, const pm_node_t *visit) {
|
108
|
+
pm_node_stack_node_t *node = xmalloc(sizeof(pm_node_stack_node_t));
|
109
|
+
node->prev = *stack;
|
110
|
+
node->visit = visit;
|
111
|
+
node->visited = false;
|
112
|
+
*stack = node;
|
113
|
+
}
|
114
|
+
|
115
|
+
static const pm_node_t *
|
116
|
+
pm_node_stack_pop(pm_node_stack_node_t **stack) {
|
117
|
+
pm_node_stack_node_t *current = *stack;
|
118
|
+
const pm_node_t *visit = current->visit;
|
119
|
+
|
120
|
+
*stack = current->prev;
|
121
|
+
xfree(current);
|
122
|
+
|
123
|
+
return visit;
|
124
|
+
}
|
125
|
+
|
126
|
+
VALUE
|
127
|
+
pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source, bool freeze) {
|
128
|
+
VALUE constants = rb_ary_new_capa(parser->constant_pool.size);
|
129
|
+
|
130
|
+
for (uint32_t index = 0; index < parser->constant_pool.size; index++) {
|
131
|
+
pm_constant_t *constant = &parser->constant_pool.constants[index];
|
132
|
+
int state = 0;
|
133
|
+
|
134
|
+
VALUE string = rb_enc_str_new((const char *) constant->start, constant->length, encoding);
|
135
|
+
VALUE value = rb_protect(rb_str_intern, string, &state);
|
136
|
+
|
137
|
+
if (state != 0) {
|
138
|
+
value = ID2SYM(rb_intern_const("?"));
|
139
|
+
rb_set_errinfo(Qnil);
|
140
|
+
}
|
141
|
+
|
142
|
+
rb_ary_push(constants, value);
|
143
|
+
}
|
144
|
+
|
145
|
+
pm_node_stack_node_t *node_stack = NULL;
|
146
|
+
pm_node_stack_push(&node_stack, node);
|
147
|
+
VALUE value_stack = rb_ary_new();
|
148
|
+
|
149
|
+
while (node_stack != NULL) {
|
150
|
+
if (!node_stack->visited) {
|
151
|
+
if (node_stack->visit == NULL) {
|
152
|
+
pm_node_stack_pop(&node_stack);
|
153
|
+
rb_ary_push(value_stack, Qnil);
|
154
|
+
continue;
|
155
|
+
}
|
156
|
+
|
157
|
+
const pm_node_t *node = node_stack->visit;
|
158
|
+
node_stack->visited = true;
|
159
|
+
|
160
|
+
switch (PM_NODE_TYPE(node)) {
|
161
|
+
<%- nodes.each do |node| -%>
|
162
|
+
<%- if node.fields.any? { |field| [Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::NodeListField].include?(field.class) } -%>
|
163
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
164
|
+
case <%= node.type %>: {
|
165
|
+
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
|
166
|
+
<%- node.fields.each do |field| -%>
|
167
|
+
<%- case field -%>
|
168
|
+
<%- when Prism::Template::NodeField, Prism::Template::OptionalNodeField -%>
|
169
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast-><%= field.name %>);
|
170
|
+
<%- when Prism::Template::NodeListField -%>
|
171
|
+
for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
|
172
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast-><%= field.name %>.nodes[index]);
|
173
|
+
}
|
174
|
+
<%- end -%>
|
175
|
+
<%- end -%>
|
176
|
+
break;
|
177
|
+
}
|
178
|
+
<%- end -%>
|
179
|
+
<%- end -%>
|
180
|
+
default:
|
181
|
+
break;
|
182
|
+
}
|
183
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
184
|
+
} else {
|
185
|
+
const pm_node_t *node = pm_node_stack_pop(&node_stack);
|
186
|
+
|
187
|
+
switch (PM_NODE_TYPE(node)) {
|
188
|
+
<%- nodes.each do |node| -%>
|
189
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
190
|
+
case <%= node.type %>: {
|
191
|
+
<%- if node.fields.any? { |field| ![Prism::Template::NodeField, Prism::Template::OptionalNodeField].include?(field.class) } -%>
|
192
|
+
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
|
193
|
+
<%- end -%>
|
194
|
+
VALUE argv[<%= node.fields.length + 4 %>];
|
195
|
+
|
196
|
+
// source
|
197
|
+
argv[0] = source;
|
198
|
+
|
199
|
+
// node_id
|
200
|
+
argv[1] = ULONG2NUM(node->node_id);
|
201
|
+
|
202
|
+
// location
|
203
|
+
argv[2] = pm_location_new(parser, node->location.start, node->location.end, source, freeze);
|
204
|
+
|
205
|
+
// flags
|
206
|
+
argv[3] = ULONG2NUM(node->flags);
|
207
|
+
<%- node.fields.each.with_index(4) do |field, index| -%>
|
208
|
+
|
209
|
+
// <%= field.name %>
|
210
|
+
<%- case field -%>
|
211
|
+
<%- when Prism::Template::NodeField, Prism::Template::OptionalNodeField -%>
|
212
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
213
|
+
argv[<%= index %>] = rb_ary_pop(value_stack);
|
214
|
+
<%- when Prism::Template::NodeListField -%>
|
215
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
216
|
+
argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size);
|
217
|
+
for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
|
218
|
+
rb_ary_push(argv[<%= index %>], rb_ary_pop(value_stack));
|
219
|
+
}
|
220
|
+
if (freeze) rb_obj_freeze(argv[<%= index %>]);
|
221
|
+
<%- when Prism::Template::StringField -%>
|
222
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
223
|
+
argv[<%= index %>] = pm_string_new(&cast-><%= field.name %>, encoding);
|
224
|
+
<%- when Prism::Template::ConstantField -%>
|
225
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
226
|
+
assert(cast-><%= field.name %> != 0);
|
227
|
+
argv[<%= index %>] = RARRAY_AREF(constants, cast-><%= field.name %> - 1);
|
228
|
+
<%- when Prism::Template::OptionalConstantField -%>
|
229
|
+
argv[<%= index %>] = cast-><%= field.name %> == 0 ? Qnil : RARRAY_AREF(constants, cast-><%= field.name %> - 1);
|
230
|
+
<%- when Prism::Template::ConstantListField -%>
|
231
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
232
|
+
argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size);
|
233
|
+
for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
|
234
|
+
assert(cast-><%= field.name %>.ids[index] != 0);
|
235
|
+
rb_ary_push(argv[<%= index %>], RARRAY_AREF(constants, cast-><%= field.name %>.ids[index] - 1));
|
236
|
+
}
|
237
|
+
if (freeze) rb_obj_freeze(argv[<%= index %>]);
|
238
|
+
<%- when Prism::Template::LocationField -%>
|
239
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
240
|
+
argv[<%= index %>] = pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end, source, freeze);
|
241
|
+
<%- when Prism::Template::OptionalLocationField -%>
|
242
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
243
|
+
argv[<%= index %>] = cast-><%= field.name %>.start == NULL ? Qnil : pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end, source, freeze);
|
244
|
+
<%- when Prism::Template::UInt8Field -%>
|
245
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
246
|
+
argv[<%= index %>] = UINT2NUM(cast-><%= field.name %>);
|
247
|
+
<%- when Prism::Template::UInt32Field -%>
|
248
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
249
|
+
argv[<%= index %>] = ULONG2NUM(cast-><%= field.name %>);
|
250
|
+
<%- when Prism::Template::IntegerField -%>
|
251
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
252
|
+
argv[<%= index %>] = pm_integer_new(&cast-><%= field.name %>);
|
253
|
+
<%- when Prism::Template::DoubleField -%>
|
254
|
+
#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
|
255
|
+
argv[<%= index %>] = DBL2NUM(cast-><%= field.name %>);
|
256
|
+
<%- else -%>
|
257
|
+
<%- raise -%>
|
258
|
+
<%- end -%>
|
259
|
+
<%- end -%>
|
260
|
+
|
261
|
+
VALUE value = rb_class_new_instance(<%= node.fields.length + 4 %>, argv, rb_cPrism<%= node.name %>);
|
262
|
+
if (freeze) rb_obj_freeze(value);
|
263
|
+
|
264
|
+
rb_ary_push(value_stack, value);
|
265
|
+
break;
|
266
|
+
}
|
267
|
+
<%- end -%>
|
268
|
+
default:
|
269
|
+
rb_raise(rb_eRuntimeError, "unknown node type: %d", PM_NODE_TYPE(node));
|
270
|
+
}
|
271
|
+
}
|
272
|
+
}
|
273
|
+
|
274
|
+
return rb_ary_pop(value_stack);
|
275
|
+
}
|
276
|
+
|
277
|
+
void
|
278
|
+
Init_prism_api_node(void) {
|
279
|
+
<%- nodes.each do |node| -%>
|
280
|
+
rb_cPrism<%= node.name %> = rb_define_class_under(rb_cPrism, "<%= node.name %>", rb_cPrismNode);
|
281
|
+
<%- end -%>
|
282
|
+
}
|