natalie_parser 1.0.0 → 1.2.0
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/CHANGELOG.md +27 -0
- data/README.md +11 -4
- data/Rakefile +12 -5
- data/ext/natalie_parser/mri_creator.hpp +25 -7
- data/include/natalie_parser/creator/debug_creator.hpp +13 -3
- data/include/natalie_parser/creator.hpp +4 -2
- data/include/natalie_parser/node/array_pattern_node.hpp +20 -2
- data/include/natalie_parser/node/bignum_node.hpp +5 -1
- data/include/natalie_parser/node/case_in_node.hpp +5 -2
- data/include/natalie_parser/node/complex_node.hpp +49 -0
- data/include/natalie_parser/node/fixnum_node.hpp +5 -1
- data/include/natalie_parser/node/float_node.hpp +4 -0
- data/include/natalie_parser/node/forward_args_node.hpp +26 -0
- data/include/natalie_parser/node/hash_pattern_node.hpp +1 -0
- data/include/natalie_parser/node/infix_op_node.hpp +1 -1
- data/include/natalie_parser/node/iter_node.hpp +1 -1
- data/include/natalie_parser/node/keyword_rest_pattern_node.hpp +43 -0
- data/include/natalie_parser/node/node.hpp +7 -1
- data/include/natalie_parser/node/nth_ref_node.hpp +1 -1
- data/include/natalie_parser/node/rational_node.hpp +45 -0
- data/include/natalie_parser/node.hpp +4 -0
- data/include/natalie_parser/parser.hpp +14 -1
- data/include/natalie_parser/token.hpp +62 -13
- data/lib/natalie_parser/version.rb +1 -1
- data/src/lexer/interpolated_string_lexer.cpp +9 -9
- data/src/lexer/regexp_lexer.cpp +7 -7
- data/src/lexer/word_array_lexer.cpp +13 -13
- data/src/lexer.cpp +210 -181
- data/src/node/begin_rescue_node.cpp +1 -1
- data/src/node/interpolated_regexp_node.cpp +1 -1
- data/src/node/node.cpp +7 -0
- data/src/node/node_with_args.cpp +1 -0
- data/src/parser.cpp +261 -91
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db5a804188bcf10ccfbadada61b82e266f227650c5a0b53929f719975d967999
|
4
|
+
data.tar.gz: b14cc0efffacc5219f7bcd5174116d0f302f7d56c4c69bfc13214b7b653adbb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb144d0f89276c280a3e7500f765cf98df9cffd4cfa8f0d0ed8d4a6d3a0d98f21b6b27d9d32b6b053a89edc0c092921e7d1215a546b7322162bd5bab7c37cf25
|
7
|
+
data.tar.gz: b467baf8f5619ea58d6ce8fb2802d63509b51b020459de8b2c8a53ed7af8927b45f3191ddda1429456d875f892be0ffc79f426915395f968210b90a030aab8f6
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.2.0 (2022-06-16)
|
4
|
+
|
5
|
+
- CHORE: Enable true random fuzzing
|
6
|
+
- FEAT: Add Node::debug() function to help with debugging
|
7
|
+
- FEAT: Parse more pattern matching cases
|
8
|
+
- FIX: Don't error if ext/natalie_parser/build.log isn't written yet
|
9
|
+
- FIX: Fix block association inside call with parentheses
|
10
|
+
- FIX: Fix bug negating an already-negative number
|
11
|
+
- FIX: Fix bug parsing unary operator as an infix operation
|
12
|
+
- FIX: Fix method definition with lonely ensure
|
13
|
+
- FIX: Fix parsing endless ranges inside case/when and other odd places
|
14
|
+
- FIX: Make sure every token knows if it has preceding whitespace
|
15
|
+
- FIX: Parse method calls with constant receiver
|
16
|
+
|
17
|
+
## 1.1.1 (2022-06-04)
|
18
|
+
|
19
|
+
- FIX: Workaround for clang declspec bug
|
20
|
+
|
21
|
+
## 1.1.0 (2022-06-04)
|
22
|
+
|
23
|
+
- CHORE: Add ccache and compiledb for the ext/natalie_parser directory
|
24
|
+
- CHORE: Add tests for numbered block arg shorthand
|
25
|
+
- FEAT: Parse arg forwarding (...) shorthand
|
26
|
+
- FEAT: Parse complex and rational numbers
|
27
|
+
- FIX: Fix panic when closing word array delimiter is not found
|
28
|
+
- FIX: Fix precedence bug with op assign operators (+= et al)
|
29
|
+
|
3
30
|
## 1.0.0 (2022-06-03)
|
4
31
|
|
5
32
|
### Summary
|
data/README.md
CHANGED
@@ -25,14 +25,21 @@ production applications.**
|
|
25
25
|
- [ ] Support different source encodings
|
26
26
|
- [ ] Support more of the Ruby 3.0 syntax
|
27
27
|
- [x] "Endless" method definition (`def foo = bar`)
|
28
|
-
- [
|
29
|
-
- [
|
30
|
-
- [
|
28
|
+
- [x] Argument forwarding (`...`)
|
29
|
+
- [x] Numbered block parameters (`_1`, `_2`, etc.)
|
30
|
+
- [x] Rational and Complex literals (`1r` and `2i`)
|
31
31
|
- [ ] Non-ASCII identifiers
|
32
|
-
- [ ]
|
32
|
+
- [ ] Pattern matching
|
33
33
|
|
34
34
|
## Development
|
35
35
|
|
36
|
+
You'll need:
|
37
|
+
|
38
|
+
- gcc or clang
|
39
|
+
- ruby-dev (dev headers)
|
40
|
+
- ccache (optional)
|
41
|
+
- compiledb (optional)
|
42
|
+
|
36
43
|
```sh
|
37
44
|
rake
|
38
45
|
ruby -I lib:ext -r natalie_parser -e "p NatalieParser.parse('1 + 2')"
|
data/Rakefile
CHANGED
@@ -127,6 +127,9 @@ if system('which compiledb 2>&1 >/dev/null')
|
|
127
127
|
if $compiledb_out.any?
|
128
128
|
File.write('build/build.log', $compiledb_out.join("\n"))
|
129
129
|
sh 'compiledb < build/build.log'
|
130
|
+
if File.exist?('ext/natalie_parser/build.log')
|
131
|
+
sh 'cd ext/natalie_parser && compiledb < build.log'
|
132
|
+
end
|
130
133
|
end
|
131
134
|
end
|
132
135
|
else
|
@@ -172,13 +175,17 @@ file "ext/natalie_parser/natalie_parser.#{so_ext}" => [
|
|
172
175
|
'ext/natalie_parser/mri_creator.hpp',
|
173
176
|
] + SOURCES + HEADERS do |t|
|
174
177
|
build_dir = File.expand_path('ext/natalie_parser', __dir__)
|
178
|
+
log_file = File.join(build_dir, 'build.log')
|
175
179
|
Rake::FileList['ext/natalie_parser/*.o'].each { |path| rm path }
|
176
180
|
rm_rf 'ext/natalie_parser/natalie_parser.so'
|
177
|
-
sh
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
181
|
+
sh "cd #{build_dir} && ruby extconf.rb"
|
182
|
+
if `#{cxx} -v 2>&1` =~ /clang/
|
183
|
+
# workaround for clang bug: https://bugs.ruby-lang.org/issues/18616
|
184
|
+
cxx_hacky = "#{cxx} -fdeclspec"
|
185
|
+
else
|
186
|
+
cxx_hacky = cxx
|
187
|
+
end
|
188
|
+
sh "CC=#{cc.inspect} CXX=#{cxx_hacky.inspect} make -C #{build_dir} -j -e V=1 2>&1 | tee #{log_file}"
|
182
189
|
end
|
183
190
|
|
184
191
|
file 'build/fragments.hpp' => ['test/parser_test.rb', 'test/support/extract_parser_test_fragments.rb'] do
|
@@ -61,17 +61,20 @@ public:
|
|
61
61
|
rb_ary_push(m_sexp, Qfalse);
|
62
62
|
}
|
63
63
|
|
64
|
-
virtual void
|
65
|
-
|
64
|
+
virtual void append_bignum(TM::String &number) override {
|
65
|
+
auto string_obj = rb_utf8_str_new(number.c_str(), number.length());
|
66
|
+
auto num = rb_Integer(string_obj);
|
67
|
+
rb_ary_push(m_sexp, num);
|
66
68
|
}
|
67
69
|
|
68
|
-
virtual void
|
69
|
-
|
70
|
+
virtual void append_fixnum(long long number) override {
|
71
|
+
auto num = rb_int_new(number);
|
72
|
+
rb_ary_push(m_sexp, num);
|
70
73
|
}
|
71
74
|
|
72
|
-
virtual void
|
73
|
-
auto
|
74
|
-
rb_ary_push(m_sexp,
|
75
|
+
virtual void append_float(double number) override {
|
76
|
+
auto num = rb_float_new(number);
|
77
|
+
rb_ary_push(m_sexp, num);
|
75
78
|
}
|
76
79
|
|
77
80
|
virtual void append_nil() override {
|
@@ -109,6 +112,21 @@ public:
|
|
109
112
|
rb_ary_push(m_sexp, Qtrue);
|
110
113
|
}
|
111
114
|
|
115
|
+
virtual void make_complex_number() override {
|
116
|
+
auto num = rb_ary_pop(m_sexp);
|
117
|
+
num = rb_Complex(INT2FIX(0), num);
|
118
|
+
rb_ary_push(m_sexp, num);
|
119
|
+
}
|
120
|
+
|
121
|
+
virtual void make_rational_number() override {
|
122
|
+
auto num = rb_ary_pop(m_sexp);
|
123
|
+
if (TYPE(num) == T_FLOAT)
|
124
|
+
num = rb_flt_rationalize(num);
|
125
|
+
else
|
126
|
+
num = rb_Rational(num, INT2FIX(1));
|
127
|
+
rb_ary_push(m_sexp, num);
|
128
|
+
}
|
129
|
+
|
112
130
|
virtual void wrap(const char *type) override {
|
113
131
|
auto inner = m_sexp;
|
114
132
|
reset_sexp();
|
@@ -42,15 +42,15 @@ public:
|
|
42
42
|
m_nodes.push("false");
|
43
43
|
}
|
44
44
|
|
45
|
-
virtual void
|
45
|
+
virtual void append_bignum(TM::String &number) override {
|
46
46
|
m_nodes.push(String(number));
|
47
47
|
}
|
48
48
|
|
49
|
-
virtual void
|
49
|
+
virtual void append_fixnum(long long number) override {
|
50
50
|
m_nodes.push(String(number));
|
51
51
|
}
|
52
52
|
|
53
|
-
virtual void
|
53
|
+
virtual void append_float(double number) override {
|
54
54
|
m_nodes.push(String(number));
|
55
55
|
}
|
56
56
|
|
@@ -89,6 +89,16 @@ public:
|
|
89
89
|
m_nodes.push("true");
|
90
90
|
}
|
91
91
|
|
92
|
+
virtual void make_complex_number() override {
|
93
|
+
auto num = m_nodes.pop();
|
94
|
+
m_nodes.push(String::format("Complex(0, {})", num));
|
95
|
+
}
|
96
|
+
|
97
|
+
virtual void make_rational_number() override {
|
98
|
+
auto num = m_nodes.pop();
|
99
|
+
m_nodes.push(String::format("Rational({}, 1)", num));
|
100
|
+
}
|
101
|
+
|
92
102
|
virtual void wrap(const char *type) override {
|
93
103
|
auto inner = to_string();
|
94
104
|
m_nodes.clear();
|
@@ -27,9 +27,9 @@ public:
|
|
27
27
|
virtual void append_array(const TM::SharedPtr<ArrayNode> array) { append_array(*array); }
|
28
28
|
virtual void append_array(const ArrayNode &array) = 0;
|
29
29
|
virtual void append_false() = 0;
|
30
|
+
virtual void append_bignum(TM::String &number) = 0;
|
31
|
+
virtual void append_fixnum(long long number) = 0;
|
30
32
|
virtual void append_float(double number) = 0;
|
31
|
-
virtual void append_integer(long long number) = 0;
|
32
|
-
virtual void append_integer(TM::String &number) = 0;
|
33
33
|
virtual void append_nil() = 0;
|
34
34
|
virtual void append_range(long long first, long long last, bool exclude_end) = 0;
|
35
35
|
virtual void append_regexp(TM::String &pattern, int options) = 0;
|
@@ -37,6 +37,8 @@ public:
|
|
37
37
|
virtual void append_string(TM::String &string) = 0;
|
38
38
|
virtual void append_symbol(TM::String &symbol) = 0;
|
39
39
|
virtual void append_true() = 0;
|
40
|
+
virtual void make_complex_number() = 0;
|
41
|
+
virtual void make_rational_number() = 0;
|
40
42
|
virtual void wrap(const char *type) = 0;
|
41
43
|
|
42
44
|
virtual ~Creator() { }
|
@@ -3,6 +3,8 @@
|
|
3
3
|
#include "natalie_parser/node/array_node.hpp"
|
4
4
|
#include "natalie_parser/node/node.hpp"
|
5
5
|
#include "natalie_parser/node/node_with_args.hpp"
|
6
|
+
#include "natalie_parser/node/splat_node.hpp"
|
7
|
+
#include "natalie_parser/node/symbol_node.hpp"
|
6
8
|
#include "tm/hashmap.hpp"
|
7
9
|
#include "tm/string.hpp"
|
8
10
|
|
@@ -15,14 +17,30 @@ public:
|
|
15
17
|
ArrayPatternNode(const Token &token)
|
16
18
|
: ArrayNode { token } { }
|
17
19
|
|
20
|
+
ArrayPatternNode(const Token &token, SharedPtr<Node> node)
|
21
|
+
: ArrayNode { token } {
|
22
|
+
m_nodes.push(node);
|
23
|
+
}
|
24
|
+
|
18
25
|
virtual Type type() const override { return Type::ArrayPattern; }
|
19
26
|
|
20
27
|
virtual void transform(Creator *creator) const override {
|
21
28
|
creator->set_type("array_pat");
|
22
29
|
if (!m_nodes.is_empty())
|
23
30
|
creator->append_nil(); // NOTE: I don't know what this nil is for
|
24
|
-
for (auto node : m_nodes)
|
25
|
-
|
31
|
+
for (auto node : m_nodes) {
|
32
|
+
if (node->type() == Node::Type::Splat) {
|
33
|
+
auto splat_node = node.static_cast_as<SplatNode>();
|
34
|
+
auto name = String("*");
|
35
|
+
if (splat_node->node()) {
|
36
|
+
assert(splat_node->node()->type() == Node::Type::Symbol);
|
37
|
+
name.append(splat_node->node().static_cast_as<SymbolNode>()->name().ref());
|
38
|
+
}
|
39
|
+
creator->append_symbol(name);
|
40
|
+
} else {
|
41
|
+
creator->append(node);
|
42
|
+
}
|
43
|
+
}
|
26
44
|
}
|
27
45
|
};
|
28
46
|
}
|
@@ -23,7 +23,7 @@ public:
|
|
23
23
|
|
24
24
|
virtual void transform(Creator *creator) const override {
|
25
25
|
creator->set_type("lit");
|
26
|
-
creator->
|
26
|
+
creator->append_bignum(*m_number);
|
27
27
|
}
|
28
28
|
|
29
29
|
void negate() {
|
@@ -31,6 +31,10 @@ public:
|
|
31
31
|
m_number->prepend_char('-');
|
32
32
|
}
|
33
33
|
|
34
|
+
bool negative() const {
|
35
|
+
return m_number->at(0) == '-';
|
36
|
+
}
|
37
|
+
|
34
38
|
protected:
|
35
39
|
SharedPtr<String> m_number;
|
36
40
|
};
|
@@ -29,8 +29,11 @@ public:
|
|
29
29
|
virtual void transform(Creator *creator) const override {
|
30
30
|
creator->set_type("in");
|
31
31
|
creator->append(m_pattern.ref());
|
32
|
-
|
33
|
-
|
32
|
+
if (!m_body->is_empty())
|
33
|
+
for (auto node : m_body->nodes())
|
34
|
+
creator->append(node);
|
35
|
+
else
|
36
|
+
creator->append_nil();
|
34
37
|
}
|
35
38
|
|
36
39
|
protected:
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "natalie_parser/node/bignum_node.hpp"
|
4
|
+
#include "natalie_parser/node/fixnum_node.hpp"
|
5
|
+
#include "natalie_parser/node/float_node.hpp"
|
6
|
+
#include "natalie_parser/node/node.hpp"
|
7
|
+
#include "natalie_parser/node/rational_node.hpp"
|
8
|
+
|
9
|
+
namespace NatalieParser {
|
10
|
+
|
11
|
+
using namespace TM;
|
12
|
+
|
13
|
+
class ComplexNode : public Node {
|
14
|
+
public:
|
15
|
+
ComplexNode(const Token &token, SharedPtr<Node> value)
|
16
|
+
: Node { token }
|
17
|
+
, m_value { value } { }
|
18
|
+
|
19
|
+
virtual Type type() const override { return Type::Complex; }
|
20
|
+
|
21
|
+
virtual void transform(Creator *creator) const override {
|
22
|
+
creator->set_type("lit");
|
23
|
+
transform_number(creator);
|
24
|
+
creator->make_complex_number();
|
25
|
+
}
|
26
|
+
|
27
|
+
void transform_number(Creator *creator) const {
|
28
|
+
switch (m_value->type()) {
|
29
|
+
case Node::Type::Bignum:
|
30
|
+
creator->append_bignum(m_value.static_cast_as<BignumNode>()->number().ref());
|
31
|
+
break;
|
32
|
+
case Node::Type::Fixnum:
|
33
|
+
creator->append_fixnum(m_value.static_cast_as<FixnumNode>()->number());
|
34
|
+
break;
|
35
|
+
case Node::Type::Float:
|
36
|
+
creator->append_float(m_value.static_cast_as<FloatNode>()->number());
|
37
|
+
break;
|
38
|
+
case Node::Type::Rational:
|
39
|
+
m_value.static_cast_as<RationalNode>()->transform_number(creator);
|
40
|
+
break;
|
41
|
+
default:
|
42
|
+
TM_UNREACHABLE();
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
protected:
|
47
|
+
SharedPtr<Node> m_value;
|
48
|
+
};
|
49
|
+
}
|
@@ -23,13 +23,17 @@ public:
|
|
23
23
|
|
24
24
|
virtual void transform(Creator *creator) const override {
|
25
25
|
creator->set_type("lit");
|
26
|
-
creator->
|
26
|
+
creator->append_fixnum(m_number);
|
27
27
|
}
|
28
28
|
|
29
29
|
void negate() {
|
30
30
|
m_number *= -1;
|
31
31
|
}
|
32
32
|
|
33
|
+
bool negative() const {
|
34
|
+
return m_number < 0;
|
35
|
+
}
|
36
|
+
|
33
37
|
protected:
|
34
38
|
long long m_number;
|
35
39
|
};
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "natalie_parser/node/node.hpp"
|
4
|
+
#include "tm/hashmap.hpp"
|
5
|
+
|
6
|
+
namespace NatalieParser {
|
7
|
+
|
8
|
+
using namespace TM;
|
9
|
+
|
10
|
+
class ForwardArgsNode : public Node {
|
11
|
+
public:
|
12
|
+
ForwardArgsNode(const Token &token)
|
13
|
+
: Node { token } { }
|
14
|
+
|
15
|
+
virtual Type type() const override { return Type::ForwardArgs; }
|
16
|
+
|
17
|
+
void add_to_locals(TM::Hashmap<TM::String> &locals) {
|
18
|
+
locals.set("...");
|
19
|
+
}
|
20
|
+
|
21
|
+
virtual void transform(Creator *creator) const override {
|
22
|
+
creator->set_type("forward_args");
|
23
|
+
}
|
24
|
+
};
|
25
|
+
|
26
|
+
}
|
@@ -22,7 +22,7 @@ public:
|
|
22
22
|
|
23
23
|
virtual Type type() const override { return Type::InfixOp; }
|
24
24
|
|
25
|
-
virtual bool is_callable() const override { return
|
25
|
+
virtual bool is_callable() const override { return false; }
|
26
26
|
virtual bool can_accept_a_block() const override { return false; }
|
27
27
|
|
28
28
|
const SharedPtr<Node> left() const { return m_left; }
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "natalie_parser/node/array_node.hpp"
|
4
|
+
#include "natalie_parser/node/node.hpp"
|
5
|
+
#include "natalie_parser/node/node_with_args.hpp"
|
6
|
+
#include "natalie_parser/node/splat_node.hpp"
|
7
|
+
#include "natalie_parser/node/symbol_node.hpp"
|
8
|
+
#include "tm/hashmap.hpp"
|
9
|
+
#include "tm/string.hpp"
|
10
|
+
|
11
|
+
namespace NatalieParser {
|
12
|
+
|
13
|
+
using namespace TM;
|
14
|
+
|
15
|
+
class KeywordRestPatternNode : public Node {
|
16
|
+
public:
|
17
|
+
KeywordRestPatternNode(const Token &token)
|
18
|
+
: Node { token } { }
|
19
|
+
|
20
|
+
KeywordRestPatternNode(const Token &token, String name)
|
21
|
+
: Node { token }
|
22
|
+
, m_name { new String(name) } { }
|
23
|
+
|
24
|
+
KeywordRestPatternNode(const Token &token, SharedPtr<String> name)
|
25
|
+
: Node { token }
|
26
|
+
, m_name { name } { }
|
27
|
+
|
28
|
+
virtual Type type() const override { return Type::KeywordRestPattern; }
|
29
|
+
|
30
|
+
const SharedPtr<String> name() const { return m_name; }
|
31
|
+
|
32
|
+
virtual void transform(Creator *creator) const override {
|
33
|
+
creator->set_type("kwrest");
|
34
|
+
auto name = String("**");
|
35
|
+
if (m_name)
|
36
|
+
name.append(m_name.ref());
|
37
|
+
creator->append_symbol(name);
|
38
|
+
}
|
39
|
+
|
40
|
+
private:
|
41
|
+
SharedPtr<String> m_name;
|
42
|
+
};
|
43
|
+
}
|
@@ -33,6 +33,7 @@ public:
|
|
33
33
|
Class,
|
34
34
|
Colon2,
|
35
35
|
Colon3,
|
36
|
+
Complex,
|
36
37
|
Constant,
|
37
38
|
Def,
|
38
39
|
Defined,
|
@@ -42,6 +43,7 @@ public:
|
|
42
43
|
False,
|
43
44
|
Fixnum,
|
44
45
|
Float,
|
46
|
+
ForwardArgs,
|
45
47
|
Hash,
|
46
48
|
HashPattern,
|
47
49
|
Identifier,
|
@@ -54,6 +56,7 @@ public:
|
|
54
56
|
InterpolatedSymbol,
|
55
57
|
InterpolatedSymbolKey,
|
56
58
|
KeywordArg,
|
59
|
+
KeywordRestPattern,
|
57
60
|
KeywordSplat,
|
58
61
|
LogicalAnd,
|
59
62
|
LogicalOr,
|
@@ -73,6 +76,7 @@ public:
|
|
73
76
|
OpAssignOr,
|
74
77
|
Pin,
|
75
78
|
Range,
|
79
|
+
Rational,
|
76
80
|
Redo,
|
77
81
|
Regexp,
|
78
82
|
Retry,
|
@@ -122,7 +126,7 @@ public:
|
|
122
126
|
|
123
127
|
virtual void transform(Creator *creator) const {
|
124
128
|
creator->set_type("NOT_YET_IMPLEMENTED");
|
125
|
-
creator->
|
129
|
+
creator->append_fixnum((int)type());
|
126
130
|
}
|
127
131
|
|
128
132
|
SharedPtr<String> file() const { return m_token.file(); }
|
@@ -147,6 +151,8 @@ public:
|
|
147
151
|
return type() != Type::Invalid;
|
148
152
|
}
|
149
153
|
|
154
|
+
void debug();
|
155
|
+
|
150
156
|
protected:
|
151
157
|
static inline SharedPtr<Node> s_invalid {};
|
152
158
|
Token m_token {};
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "natalie_parser/node/bignum_node.hpp"
|
4
|
+
#include "natalie_parser/node/fixnum_node.hpp"
|
5
|
+
#include "natalie_parser/node/float_node.hpp"
|
6
|
+
#include "natalie_parser/node/node.hpp"
|
7
|
+
|
8
|
+
namespace NatalieParser {
|
9
|
+
|
10
|
+
using namespace TM;
|
11
|
+
|
12
|
+
class RationalNode : public Node {
|
13
|
+
public:
|
14
|
+
RationalNode(const Token &token, SharedPtr<Node> value)
|
15
|
+
: Node { token }
|
16
|
+
, m_value { value } { }
|
17
|
+
|
18
|
+
virtual Type type() const override { return Type::Rational; }
|
19
|
+
|
20
|
+
virtual void transform(Creator *creator) const override {
|
21
|
+
creator->set_type("lit");
|
22
|
+
transform_number(creator);
|
23
|
+
creator->make_rational_number();
|
24
|
+
}
|
25
|
+
|
26
|
+
void transform_number(Creator *creator) const {
|
27
|
+
switch (m_value->type()) {
|
28
|
+
case Node::Type::Bignum:
|
29
|
+
creator->append_bignum(m_value.static_cast_as<BignumNode>()->number().ref());
|
30
|
+
break;
|
31
|
+
case Node::Type::Fixnum:
|
32
|
+
creator->append_fixnum(m_value.static_cast_as<FixnumNode>()->number());
|
33
|
+
break;
|
34
|
+
case Node::Type::Float:
|
35
|
+
creator->append_float(m_value.static_cast_as<FloatNode>()->number());
|
36
|
+
break;
|
37
|
+
default:
|
38
|
+
TM_UNREACHABLE();
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
protected:
|
43
|
+
SharedPtr<Node> m_value;
|
44
|
+
};
|
45
|
+
}
|
@@ -21,6 +21,7 @@
|
|
21
21
|
#include "natalie_parser/node/class_node.hpp"
|
22
22
|
#include "natalie_parser/node/colon2_node.hpp"
|
23
23
|
#include "natalie_parser/node/colon3_node.hpp"
|
24
|
+
#include "natalie_parser/node/complex_node.hpp"
|
24
25
|
#include "natalie_parser/node/constant_node.hpp"
|
25
26
|
#include "natalie_parser/node/def_node.hpp"
|
26
27
|
#include "natalie_parser/node/defined_node.hpp"
|
@@ -30,6 +31,7 @@
|
|
30
31
|
#include "natalie_parser/node/false_node.hpp"
|
31
32
|
#include "natalie_parser/node/fixnum_node.hpp"
|
32
33
|
#include "natalie_parser/node/float_node.hpp"
|
34
|
+
#include "natalie_parser/node/forward_args_node.hpp"
|
33
35
|
#include "natalie_parser/node/hash_node.hpp"
|
34
36
|
#include "natalie_parser/node/hash_pattern_node.hpp"
|
35
37
|
#include "natalie_parser/node/identifier_node.hpp"
|
@@ -43,6 +45,7 @@
|
|
43
45
|
#include "natalie_parser/node/interpolated_symbol_node.hpp"
|
44
46
|
#include "natalie_parser/node/iter_node.hpp"
|
45
47
|
#include "natalie_parser/node/keyword_arg_node.hpp"
|
48
|
+
#include "natalie_parser/node/keyword_rest_pattern_node.hpp"
|
46
49
|
#include "natalie_parser/node/keyword_splat_node.hpp"
|
47
50
|
#include "natalie_parser/node/logical_and_node.hpp"
|
48
51
|
#include "natalie_parser/node/logical_or_node.hpp"
|
@@ -63,6 +66,7 @@
|
|
63
66
|
#include "natalie_parser/node/op_assign_or_node.hpp"
|
64
67
|
#include "natalie_parser/node/pin_node.hpp"
|
65
68
|
#include "natalie_parser/node/range_node.hpp"
|
69
|
+
#include "natalie_parser/node/rational_node.hpp"
|
66
70
|
#include "natalie_parser/node/redo_node.hpp"
|
67
71
|
#include "natalie_parser/node/regexp_node.hpp"
|
68
72
|
#include "natalie_parser/node/retry_node.hpp"
|
@@ -82,16 +82,26 @@ private:
|
|
82
82
|
SharedPtr<Node> parse_class_or_module_name(LocalsHashmap &);
|
83
83
|
SharedPtr<Node> parse_case(LocalsHashmap &);
|
84
84
|
SharedPtr<Node> parse_case_in_pattern(LocalsHashmap &);
|
85
|
+
SharedPtr<Node> parse_case_in_pattern_alternation(LocalsHashmap &);
|
86
|
+
SharedPtr<Node> parse_case_in_pattern_hash_symbol_key(LocalsHashmap &);
|
85
87
|
SharedPtr<Node> parse_case_in_patterns(LocalsHashmap &);
|
86
88
|
void parse_comma_separated_expressions(ArrayNode &, LocalsHashmap &);
|
87
89
|
SharedPtr<Node> parse_constant(LocalsHashmap &);
|
88
90
|
SharedPtr<Node> parse_def(LocalsHashmap &);
|
89
91
|
SharedPtr<Node> parse_defined(LocalsHashmap &);
|
92
|
+
|
90
93
|
void parse_def_args(Vector<SharedPtr<Node>> &, LocalsHashmap &);
|
91
|
-
|
94
|
+
enum class ArgsContext {
|
95
|
+
Block,
|
96
|
+
Method,
|
97
|
+
Proc,
|
98
|
+
};
|
99
|
+
void parse_def_single_arg(Vector<SharedPtr<Node>> &, LocalsHashmap &, ArgsContext);
|
100
|
+
|
92
101
|
SharedPtr<Node> parse_encoding(LocalsHashmap &);
|
93
102
|
SharedPtr<Node> parse_end_block(LocalsHashmap &);
|
94
103
|
SharedPtr<Node> parse_file_constant(LocalsHashmap &);
|
104
|
+
SharedPtr<Node> parse_forward_args(LocalsHashmap &);
|
95
105
|
SharedPtr<Node> parse_group(LocalsHashmap &);
|
96
106
|
SharedPtr<Node> parse_hash(LocalsHashmap &);
|
97
107
|
SharedPtr<Node> parse_hash_inner(LocalsHashmap &, Precedence, Token::Type, SharedPtr<Node> = {});
|
@@ -128,6 +138,7 @@ private:
|
|
128
138
|
SharedPtr<Node> parse_symbol_key(LocalsHashmap &);
|
129
139
|
SharedPtr<Node> parse_statement_keyword(LocalsHashmap &);
|
130
140
|
SharedPtr<Node> parse_top_level_constant(LocalsHashmap &);
|
141
|
+
SharedPtr<Node> parse_triple_dot(LocalsHashmap &);
|
131
142
|
SharedPtr<Node> parse_unary_operator(LocalsHashmap &);
|
132
143
|
SharedPtr<Node> parse_undef(LocalsHashmap &);
|
133
144
|
SharedPtr<Node> parse_unless(LocalsHashmap &);
|
@@ -188,6 +199,7 @@ private:
|
|
188
199
|
|
189
200
|
SharedPtr<NodeWithArgs> to_node_with_args(SharedPtr<Node> node);
|
190
201
|
|
202
|
+
Token &previous_token() const;
|
191
203
|
Token ¤t_token() const;
|
192
204
|
Token &peek_token() const;
|
193
205
|
|
@@ -195,6 +207,7 @@ private:
|
|
195
207
|
void skip_newlines();
|
196
208
|
|
197
209
|
void expect(Token::Type, const char *);
|
210
|
+
[[noreturn]] void throw_error(const Token &, const char *);
|
198
211
|
[[noreturn]] void throw_unexpected(const Token &, const char *, const char * = nullptr);
|
199
212
|
[[noreturn]] void throw_unexpected(const char *);
|
200
213
|
[[noreturn]] void throw_unterminated_thing(Token, Token = {});
|