natalie_parser 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 = {});
|