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.
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 = {});