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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/README.md +11 -4
  4. data/Rakefile +12 -5
  5. data/ext/natalie_parser/mri_creator.hpp +25 -7
  6. data/include/natalie_parser/creator/debug_creator.hpp +13 -3
  7. data/include/natalie_parser/creator.hpp +4 -2
  8. data/include/natalie_parser/node/array_pattern_node.hpp +20 -2
  9. data/include/natalie_parser/node/bignum_node.hpp +5 -1
  10. data/include/natalie_parser/node/case_in_node.hpp +5 -2
  11. data/include/natalie_parser/node/complex_node.hpp +49 -0
  12. data/include/natalie_parser/node/fixnum_node.hpp +5 -1
  13. data/include/natalie_parser/node/float_node.hpp +4 -0
  14. data/include/natalie_parser/node/forward_args_node.hpp +26 -0
  15. data/include/natalie_parser/node/hash_pattern_node.hpp +1 -0
  16. data/include/natalie_parser/node/infix_op_node.hpp +1 -1
  17. data/include/natalie_parser/node/iter_node.hpp +1 -1
  18. data/include/natalie_parser/node/keyword_rest_pattern_node.hpp +43 -0
  19. data/include/natalie_parser/node/node.hpp +7 -1
  20. data/include/natalie_parser/node/nth_ref_node.hpp +1 -1
  21. data/include/natalie_parser/node/rational_node.hpp +45 -0
  22. data/include/natalie_parser/node.hpp +4 -0
  23. data/include/natalie_parser/parser.hpp +14 -1
  24. data/include/natalie_parser/token.hpp +62 -13
  25. data/lib/natalie_parser/version.rb +1 -1
  26. data/src/lexer/interpolated_string_lexer.cpp +9 -9
  27. data/src/lexer/regexp_lexer.cpp +7 -7
  28. data/src/lexer/word_array_lexer.cpp +13 -13
  29. data/src/lexer.cpp +210 -181
  30. data/src/node/begin_rescue_node.cpp +1 -1
  31. data/src/node/interpolated_regexp_node.cpp +1 -1
  32. data/src/node/node.cpp +7 -0
  33. data/src/node/node_with_args.cpp +1 -0
  34. data/src/parser.cpp +261 -91
  35. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '048e048ede42652f8a81298a3310313f8bf9929ba5cd952a89d3269d8333b363'
4
- data.tar.gz: 5c2388c8125b1444c454c0ee3a0d4a07f305cc3fd668d8e03dbc4404201a50f7
3
+ metadata.gz: db5a804188bcf10ccfbadada61b82e266f227650c5a0b53929f719975d967999
4
+ data.tar.gz: b14cc0efffacc5219f7bcd5174116d0f302f7d56c4c69bfc13214b7b653adbb7
5
5
  SHA512:
6
- metadata.gz: 55932c3dc24ceeeab109a4a980ddf96babf276ced15dffb68d7c013ca5cc246d2551b59acc94f82c1ec5c0073859267ace3a264a3d8b9470465672ea5aebb59d
7
- data.tar.gz: bcbaaad396877bcbf6453e8d55ad3f46dcb68ba09bcfe2f6cf0f1fa6d96966c646f530e3872d77736ef40b5818feed888d69fe33e62beeb95dcfd1c6f5115203
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
- - [ ] Argument forwarding (`...`)
29
- - [ ] Pattern matching
30
- - [ ] Numbered block parameters (`_1`, `_2`, etc.)
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
- - [ ] Rational and Complex literals (`1r` and `2i`)
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 <<-SH
178
- cd #{build_dir} && \
179
- ruby extconf.rb && \
180
- make -j
181
- SH
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 append_float(double number) override {
65
- rb_ary_push(m_sexp, rb_float_new(number));
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 append_integer(long long number) override {
69
- rb_ary_push(m_sexp, rb_int_new(number));
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 append_integer(TM::String &number) override {
73
- auto string_obj = rb_utf8_str_new(number.c_str(), number.length());
74
- rb_ary_push(m_sexp, rb_Integer(string_obj));
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 append_float(double number) override {
45
+ virtual void append_bignum(TM::String &number) override {
46
46
  m_nodes.push(String(number));
47
47
  }
48
48
 
49
- virtual void append_integer(long long number) override {
49
+ virtual void append_fixnum(long long number) override {
50
50
  m_nodes.push(String(number));
51
51
  }
52
52
 
53
- virtual void append_integer(TM::String &number) override {
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
- creator->append(node);
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->append_integer(*m_number);
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
- for (auto node : m_body->nodes())
33
- creator->append(node);
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->append_integer(m_number);
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
  };
@@ -30,6 +30,10 @@ public:
30
30
  m_number *= -1;
31
31
  }
32
32
 
33
+ bool negative() const {
34
+ return m_number < 0.0;
35
+ }
36
+
33
37
  protected:
34
38
  double 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
+ }
@@ -3,6 +3,7 @@
3
3
  #include "natalie_parser/node/hash_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/symbol_key_node.hpp"
6
7
  #include "tm/hashmap.hpp"
7
8
  #include "tm/string.hpp"
8
9
 
@@ -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 true; }
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; }
@@ -32,7 +32,7 @@ public:
32
32
  if (m_has_args)
33
33
  append_method_or_block_args(creator);
34
34
  else
35
- creator->append_integer(0);
35
+ creator->append_fixnum(0);
36
36
  if (!m_body->is_empty())
37
37
  creator->append(m_body->without_unnecessary_nesting());
38
38
  }
@@ -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->append_integer((int)type());
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 {};
@@ -18,7 +18,7 @@ public:
18
18
 
19
19
  virtual void transform(Creator *creator) const override {
20
20
  creator->set_type("nth_ref");
21
- creator->append_integer(m_num);
21
+ creator->append_fixnum(m_num);
22
22
  }
23
23
 
24
24
  protected:
@@ -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
- void parse_def_single_arg(Vector<SharedPtr<Node>> &, LocalsHashmap &);
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 &current_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 = {});