natalie_parser 1.1.1 → 2.0.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 +25 -1
- data/Rakefile +3 -1
- data/include/natalie_parser/node/array_pattern_node.hpp +20 -2
- data/include/natalie_parser/node/bignum_node.hpp +4 -0
- data/include/natalie_parser/node/case_in_node.hpp +5 -2
- data/include/natalie_parser/node/colon2_node.hpp +1 -0
- data/include/natalie_parser/node/fixnum_node.hpp +4 -0
- data/include/natalie_parser/node/float_node.hpp +4 -0
- data/include/natalie_parser/node/hash_node.hpp +8 -3
- data/include/natalie_parser/node/hash_pattern_node.hpp +2 -1
- data/include/natalie_parser/node/infix_op_node.hpp +1 -1
- data/include/natalie_parser/node/keyword_rest_pattern_node.hpp +43 -0
- data/include/natalie_parser/node/node.hpp +3 -0
- data/include/natalie_parser/node/unary_op_node.hpp +1 -1
- data/include/natalie_parser/node.hpp +1 -0
- data/include/natalie_parser/parser.hpp +4 -1
- data/include/natalie_parser/token.hpp +43 -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 +164 -169
- data/src/node/begin_rescue_node.cpp +1 -1
- data/src/node/node.cpp +7 -0
- data/src/parser.cpp +185 -70
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b35f9b98f6bbe4ec3bf8d5d9bce2c7e082504db23f442964f2a58e1ac9e11dc7
|
4
|
+
data.tar.gz: 1fbf06aa6fae8400855ea0d363d77a1b27d78869266bfb17b0f45cf9b8a30d41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 936ec0ef70541afd5839dbe4450401d7e8713499c3536d9ac7e53eb5617671dd308eee8e4f458188a9b0890f5a7ed5d855b3011c5539b64eb31639b4140e07fc
|
7
|
+
data.tar.gz: f6deb35c75e17e5c9fb49c6092e48453e904e7c7d4b515e2c7b5fe7fe69dc656da2faa6096b665b6021557ae8c47844ec65a9e8aca1933712f35d72f4db47c50
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,29 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 2.0.0 (2022-06-24)
|
4
|
+
|
5
|
+
- FEAT: Differentiate between bare/implicit hash and explicit one
|
6
|
+
- FIX: Fix calling colon2
|
7
|
+
- FIX: Parse implicit method calls with nth ref argument
|
8
|
+
|
9
|
+
## 1.2.1 (2022-06-16)
|
10
|
+
|
11
|
+
- FIX: Fix regression with unary/infix operators (+/-)
|
12
|
+
|
13
|
+
## 1.2.0 (2022-06-16)
|
14
|
+
|
15
|
+
- CHORE: Enable true random fuzzing
|
16
|
+
- FEAT: Add Node::debug() function to help with debugging
|
17
|
+
- FEAT: Parse more pattern matching cases
|
18
|
+
- FIX: Don't error if ext/natalie_parser/build.log isn't written yet
|
19
|
+
- FIX: Fix block association inside call with parentheses
|
20
|
+
- FIX: Fix bug negating an already-negative number
|
21
|
+
- FIX: Fix bug parsing unary operator as an infix operation
|
22
|
+
- FIX: Fix method definition with lonely ensure
|
23
|
+
- FIX: Fix parsing endless ranges inside case/when and other odd places
|
24
|
+
- FIX: Make sure every token knows if it has preceding whitespace
|
25
|
+
- FIX: Parse method calls with constant receiver
|
26
|
+
|
3
27
|
## 1.1.1 (2022-06-04)
|
4
28
|
|
5
29
|
- FIX: Workaround for clang declspec bug
|
@@ -8,7 +32,7 @@
|
|
8
32
|
|
9
33
|
- CHORE: Add ccache and compiledb for the ext/natalie_parser directory
|
10
34
|
- CHORE: Add tests for numbered block arg shorthand
|
11
|
-
- FEAT Parse arg forwarding (...) shorthand
|
35
|
+
- FEAT: Parse arg forwarding (...) shorthand
|
12
36
|
- FEAT: Parse complex and rational numbers
|
13
37
|
- FIX: Fix panic when closing word array delimiter is not found
|
14
38
|
- FIX: Fix precedence bug with op assign operators (+= et al)
|
data/Rakefile
CHANGED
@@ -127,7 +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
|
-
|
130
|
+
if File.exist?('ext/natalie_parser/build.log')
|
131
|
+
sh 'cd ext/natalie_parser && compiledb < build.log'
|
132
|
+
end
|
131
133
|
end
|
132
134
|
end
|
133
135
|
else
|
@@ -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
|
}
|
@@ -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:
|
@@ -23,6 +23,7 @@ public:
|
|
23
23
|
virtual Type type() const override { return Type::Colon2; }
|
24
24
|
|
25
25
|
virtual bool is_assignable() const override { return true; }
|
26
|
+
virtual bool is_callable() const override { return true; }
|
26
27
|
|
27
28
|
const SharedPtr<Node> left() const { return m_left; }
|
28
29
|
SharedPtr<String> name() const { return m_name; }
|
@@ -11,8 +11,9 @@ using namespace TM;
|
|
11
11
|
|
12
12
|
class HashNode : public Node {
|
13
13
|
public:
|
14
|
-
HashNode(const Token &token)
|
15
|
-
: Node { token }
|
14
|
+
HashNode(const Token &token, bool bare)
|
15
|
+
: Node { token }
|
16
|
+
, m_bare { bare } { }
|
16
17
|
|
17
18
|
virtual Type type() const override { return Type::Hash; }
|
18
19
|
|
@@ -23,12 +24,16 @@ public:
|
|
23
24
|
const Vector<SharedPtr<Node>> &nodes() const { return m_nodes; }
|
24
25
|
|
25
26
|
virtual void transform(Creator *creator) const override {
|
26
|
-
|
27
|
+
if (m_bare)
|
28
|
+
creator->set_type("bare_hash");
|
29
|
+
else
|
30
|
+
creator->set_type("hash");
|
27
31
|
for (auto node : m_nodes)
|
28
32
|
creator->append(node);
|
29
33
|
}
|
30
34
|
|
31
35
|
protected:
|
32
36
|
Vector<SharedPtr<Node>> m_nodes {};
|
37
|
+
bool m_bare { false };
|
33
38
|
};
|
34
39
|
}
|
@@ -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
|
|
@@ -13,7 +14,7 @@ using namespace TM;
|
|
13
14
|
class HashPatternNode : public HashNode {
|
14
15
|
public:
|
15
16
|
HashPatternNode(const Token &token)
|
16
|
-
: HashNode { token } { }
|
17
|
+
: HashNode { token, true } { }
|
17
18
|
|
18
19
|
virtual Type type() const override { return Type::HashPattern; }
|
19
20
|
|
@@ -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
|
+
}
|
@@ -56,6 +56,7 @@ public:
|
|
56
56
|
InterpolatedSymbol,
|
57
57
|
InterpolatedSymbolKey,
|
58
58
|
KeywordArg,
|
59
|
+
KeywordRestPattern,
|
59
60
|
KeywordSplat,
|
60
61
|
LogicalAnd,
|
61
62
|
LogicalOr,
|
@@ -150,6 +151,8 @@ public:
|
|
150
151
|
return type() != Type::Invalid;
|
151
152
|
}
|
152
153
|
|
154
|
+
void debug();
|
155
|
+
|
153
156
|
protected:
|
154
157
|
static inline SharedPtr<Node> s_invalid {};
|
155
158
|
Token m_token {};
|
@@ -20,7 +20,7 @@ public:
|
|
20
20
|
|
21
21
|
virtual Type type() const override { return Type::UnaryOp; }
|
22
22
|
|
23
|
-
virtual bool is_callable() const override { return
|
23
|
+
virtual bool is_callable() const override { return false; }
|
24
24
|
virtual bool can_accept_a_block() const override { return false; }
|
25
25
|
|
26
26
|
const SharedPtr<String> op() const { return m_op; }
|
@@ -45,6 +45,7 @@
|
|
45
45
|
#include "natalie_parser/node/interpolated_symbol_node.hpp"
|
46
46
|
#include "natalie_parser/node/iter_node.hpp"
|
47
47
|
#include "natalie_parser/node/keyword_arg_node.hpp"
|
48
|
+
#include "natalie_parser/node/keyword_rest_pattern_node.hpp"
|
48
49
|
#include "natalie_parser/node/keyword_splat_node.hpp"
|
49
50
|
#include "natalie_parser/node/logical_and_node.hpp"
|
50
51
|
#include "natalie_parser/node/logical_or_node.hpp"
|
@@ -82,6 +82,8 @@ 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 &);
|
@@ -102,7 +104,7 @@ private:
|
|
102
104
|
SharedPtr<Node> parse_forward_args(LocalsHashmap &);
|
103
105
|
SharedPtr<Node> parse_group(LocalsHashmap &);
|
104
106
|
SharedPtr<Node> parse_hash(LocalsHashmap &);
|
105
|
-
SharedPtr<Node> parse_hash_inner(LocalsHashmap &, Precedence, Token::Type, SharedPtr<Node> = {});
|
107
|
+
SharedPtr<Node> parse_hash_inner(LocalsHashmap &, Precedence, Token::Type, bool, SharedPtr<Node> = {});
|
106
108
|
SharedPtr<Node> parse_identifier(LocalsHashmap &);
|
107
109
|
SharedPtr<Node> parse_if(LocalsHashmap &);
|
108
110
|
void parse_interpolated_body(LocalsHashmap &, InterpolatedNode &, Token::Type);
|
@@ -197,6 +199,7 @@ private:
|
|
197
199
|
|
198
200
|
SharedPtr<NodeWithArgs> to_node_with_args(SharedPtr<Node> node);
|
199
201
|
|
202
|
+
Token &previous_token() const;
|
200
203
|
Token ¤t_token() const;
|
201
204
|
Token &peek_token() const;
|
202
205
|
|
@@ -158,58 +158,64 @@ public:
|
|
158
158
|
|
159
159
|
Token() { }
|
160
160
|
|
161
|
-
Token(Type type, SharedPtr<String> file, size_t line, size_t column)
|
161
|
+
Token(Type type, SharedPtr<String> file, size_t line, size_t column, bool whitespace_precedes)
|
162
162
|
: m_type { type }
|
163
163
|
, m_file { file }
|
164
164
|
, m_line { line }
|
165
|
-
, m_column { column }
|
165
|
+
, m_column { column }
|
166
|
+
, m_whitespace_precedes { whitespace_precedes } {
|
166
167
|
assert(file);
|
167
168
|
}
|
168
169
|
|
169
|
-
Token(Type type, const char *literal, SharedPtr<String> file, size_t line, size_t column)
|
170
|
+
Token(Type type, const char *literal, SharedPtr<String> file, size_t line, size_t column, bool whitespace_precedes)
|
170
171
|
: m_type { type }
|
171
172
|
, m_literal { new String(literal) }
|
172
173
|
, m_file { file }
|
173
174
|
, m_line { line }
|
174
|
-
, m_column { column }
|
175
|
+
, m_column { column }
|
176
|
+
, m_whitespace_precedes { whitespace_precedes } {
|
175
177
|
assert(literal);
|
176
178
|
assert(file);
|
177
179
|
}
|
178
180
|
|
179
|
-
Token(Type type, SharedPtr<String> literal, SharedPtr<String> file, size_t line, size_t column)
|
181
|
+
Token(Type type, SharedPtr<String> literal, SharedPtr<String> file, size_t line, size_t column, bool whitespace_precedes)
|
180
182
|
: m_type { type }
|
181
183
|
, m_literal { literal }
|
182
184
|
, m_file { file }
|
183
185
|
, m_line { line }
|
184
|
-
, m_column { column }
|
186
|
+
, m_column { column }
|
187
|
+
, m_whitespace_precedes { whitespace_precedes } {
|
185
188
|
assert(literal);
|
186
189
|
assert(file);
|
187
190
|
}
|
188
191
|
|
189
|
-
Token(Type type, char literal, SharedPtr<String> file, size_t line, size_t column)
|
192
|
+
Token(Type type, char literal, SharedPtr<String> file, size_t line, size_t column, bool whitespace_precedes)
|
190
193
|
: m_type { type }
|
191
194
|
, m_literal { new String(literal) }
|
192
195
|
, m_file { file }
|
193
196
|
, m_line { line }
|
194
|
-
, m_column { column }
|
197
|
+
, m_column { column }
|
198
|
+
, m_whitespace_precedes { whitespace_precedes } {
|
195
199
|
assert(file);
|
196
200
|
}
|
197
201
|
|
198
|
-
Token(Type type, long long fixnum, SharedPtr<String> file, size_t line, size_t column)
|
202
|
+
Token(Type type, long long fixnum, SharedPtr<String> file, size_t line, size_t column, bool whitespace_precedes)
|
199
203
|
: m_type { type }
|
200
204
|
, m_fixnum { fixnum }
|
201
205
|
, m_file { file }
|
202
206
|
, m_line { line }
|
203
|
-
, m_column { column }
|
207
|
+
, m_column { column }
|
208
|
+
, m_whitespace_precedes { whitespace_precedes } {
|
204
209
|
assert(file);
|
205
210
|
}
|
206
211
|
|
207
|
-
Token(Type type, double dbl, SharedPtr<String> file, size_t line, size_t column)
|
212
|
+
Token(Type type, double dbl, SharedPtr<String> file, size_t line, size_t column, bool whitespace_precedes)
|
208
213
|
: m_type { type }
|
209
214
|
, m_double { dbl }
|
210
215
|
, m_file { file }
|
211
216
|
, m_line { line }
|
212
|
-
, m_column { column }
|
217
|
+
, m_column { column }
|
218
|
+
, m_whitespace_precedes { whitespace_precedes } {
|
213
219
|
assert(file);
|
214
220
|
}
|
215
221
|
|
@@ -636,6 +642,7 @@ public:
|
|
636
642
|
bool is_elsif_keyword() const { return m_type == Type::ElsifKeyword; }
|
637
643
|
bool is_end_keyword() const { return m_type == Type::EndKeyword; }
|
638
644
|
bool is_end_of_expression() const { return m_type == Type::EndKeyword || m_type == Type::RCurlyBrace || m_type == Type::Newline || m_type == Type::Semicolon || m_type == Type::Eof || is_expression_modifier(); }
|
645
|
+
bool is_ensure() const { return m_type == Type::EnsureKeyword; }
|
639
646
|
bool is_eof() const { return m_type == Type::Eof; }
|
640
647
|
bool is_end_of_line() const { return m_type == Type::Newline || m_type == Type::Semicolon; }
|
641
648
|
bool is_equal() const { return m_type == Type::Equal; }
|
@@ -644,6 +651,7 @@ public:
|
|
644
651
|
bool is_lparen() const { return m_type == Type::LParen; }
|
645
652
|
bool is_newline() const { return m_type == Type::Newline; }
|
646
653
|
bool is_rbracket() const { return m_type == Type::RBracket; }
|
654
|
+
bool is_rescue() const { return m_type == Type::RescueKeyword; }
|
647
655
|
bool is_rparen() const { return m_type == Type::RParen; }
|
648
656
|
bool is_semicolon() const { return m_type == Type::Semicolon; }
|
649
657
|
bool is_splat() const { return m_type == Type::Star || m_type == Type::StarStar; }
|
@@ -662,6 +670,7 @@ public:
|
|
662
670
|
case Token::Type::RParen:
|
663
671
|
case Token::Type::SafeNavigation:
|
664
672
|
case Token::Type::TernaryColon:
|
673
|
+
case Token::Type::ThenKeyword:
|
665
674
|
return true;
|
666
675
|
default:
|
667
676
|
return false;
|
@@ -680,7 +689,6 @@ public:
|
|
680
689
|
case Token::Type::Comparison:
|
681
690
|
case Token::Type::ConstantResolution:
|
682
691
|
case Token::Type::Dot:
|
683
|
-
case Token::Type::DotDot:
|
684
692
|
case Token::Type::Equal:
|
685
693
|
case Token::Type::EqualEqual:
|
686
694
|
case Token::Type::EqualEqualEqual:
|
@@ -763,13 +771,16 @@ public:
|
|
763
771
|
case Token::Type::LBracketRBracket:
|
764
772
|
case Token::Type::LINEKeyword:
|
765
773
|
case Token::Type::LParen:
|
774
|
+
case Token::Type::Minus:
|
766
775
|
case Token::Type::NilKeyword:
|
767
776
|
case Token::Type::Not:
|
768
777
|
case Token::Type::NotKeyword:
|
778
|
+
case Token::Type::NthRef:
|
769
779
|
case Token::Type::PercentLowerI:
|
770
780
|
case Token::Type::PercentLowerW:
|
771
781
|
case Token::Type::PercentUpperI:
|
772
782
|
case Token::Type::PercentUpperW:
|
783
|
+
case Token::Type::Plus:
|
773
784
|
case Token::Type::SelfKeyword:
|
774
785
|
case Token::Type::Star:
|
775
786
|
case Token::Type::String:
|
@@ -824,6 +835,25 @@ public:
|
|
824
835
|
}
|
825
836
|
}
|
826
837
|
|
838
|
+
bool can_be_range_arg_token() const {
|
839
|
+
if (is_closing_token())
|
840
|
+
return false;
|
841
|
+
if (is_semicolon() || is_eof())
|
842
|
+
return false;
|
843
|
+
switch (m_type) {
|
844
|
+
case Type::ElseKeyword:
|
845
|
+
case Type::ElsifKeyword:
|
846
|
+
case Type::EndKeyword:
|
847
|
+
case Type::InKeyword:
|
848
|
+
case Type::ThenKeyword:
|
849
|
+
case Type::WhenKeyword:
|
850
|
+
// TODO: likely many more cases!
|
851
|
+
return false;
|
852
|
+
default:
|
853
|
+
return true;
|
854
|
+
}
|
855
|
+
}
|
856
|
+
|
827
857
|
void set_literal(const char *literal) { m_literal = new String(literal); }
|
828
858
|
void set_literal(SharedPtr<String> literal) { m_literal = literal; }
|
829
859
|
void set_literal(String literal) { m_literal = new String(literal); }
|
@@ -14,7 +14,7 @@ Token InterpolatedStringLexer::build_next_token() {
|
|
14
14
|
case State::EndToken:
|
15
15
|
return finish();
|
16
16
|
case State::Done:
|
17
|
-
return Token { Token::Type::Eof, m_file, m_cursor_line, m_cursor_column };
|
17
|
+
return Token { Token::Type::Eof, m_file, m_cursor_line, m_cursor_column, m_whitespace_precedes };
|
18
18
|
}
|
19
19
|
TM_UNREACHABLE();
|
20
20
|
}
|
@@ -26,13 +26,13 @@ Token InterpolatedStringLexer::consume_string() {
|
|
26
26
|
advance(); // backslash
|
27
27
|
auto result = consume_escaped_byte(*buf);
|
28
28
|
if (!result.first)
|
29
|
-
return Token { result.second, current_char(), m_file, m_cursor_line, m_cursor_column };
|
29
|
+
return Token { result.second, current_char(), m_file, m_cursor_line, m_cursor_column, m_whitespace_precedes };
|
30
30
|
} else if (c == '#' && peek() == '{') {
|
31
31
|
if (buf->is_empty()) {
|
32
32
|
advance(2);
|
33
33
|
return start_evaluation();
|
34
34
|
}
|
35
|
-
auto token = Token { Token::Type::String, buf, m_file, m_token_line, m_token_column };
|
35
|
+
auto token = Token { Token::Type::String, buf, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
36
36
|
advance(2);
|
37
37
|
m_state = State::EvaluateBegin;
|
38
38
|
return token;
|
@@ -49,7 +49,7 @@ Token InterpolatedStringLexer::consume_string() {
|
|
49
49
|
return finish();
|
50
50
|
} else {
|
51
51
|
m_state = State::EndToken;
|
52
|
-
return Token { Token::Type::String, buf, m_file, m_token_line, m_token_column };
|
52
|
+
return Token { Token::Type::String, buf, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
53
53
|
}
|
54
54
|
} else {
|
55
55
|
buf->append_char(c);
|
@@ -62,27 +62,27 @@ Token InterpolatedStringLexer::consume_string() {
|
|
62
62
|
if (m_stop_char == 0) {
|
63
63
|
advance();
|
64
64
|
m_state = State::EndToken;
|
65
|
-
return Token { Token::Type::String, buf, m_file, m_token_line, m_token_column };
|
65
|
+
return Token { Token::Type::String, buf, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
66
66
|
}
|
67
67
|
|
68
|
-
return Token { Token::Type::UnterminatedString, buf, m_file, m_token_line, m_token_column };
|
68
|
+
return Token { Token::Type::UnterminatedString, buf, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
69
69
|
}
|
70
70
|
|
71
71
|
Token InterpolatedStringLexer::start_evaluation() {
|
72
72
|
m_nested_lexer = new Lexer { *this, '{', '}' };
|
73
73
|
m_state = State::EvaluateEnd;
|
74
|
-
return Token { Token::Type::EvaluateToStringBegin, m_file, m_token_line, m_token_column };
|
74
|
+
return Token { Token::Type::EvaluateToStringBegin, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
75
75
|
}
|
76
76
|
|
77
77
|
Token InterpolatedStringLexer::stop_evaluation() {
|
78
78
|
advance(); // }
|
79
79
|
m_state = State::InProgress;
|
80
|
-
return Token { Token::Type::EvaluateToStringEnd, m_file, m_token_line, m_token_column };
|
80
|
+
return Token { Token::Type::EvaluateToStringEnd, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
81
81
|
}
|
82
82
|
|
83
83
|
Token InterpolatedStringLexer::finish() {
|
84
84
|
m_state = State::Done;
|
85
|
-
return Token { m_end_type, m_file, m_cursor_line, m_cursor_column };
|
85
|
+
return Token { m_end_type, m_file, m_cursor_line, m_cursor_column, m_whitespace_precedes };
|
86
86
|
}
|
87
87
|
|
88
88
|
};
|
data/src/lexer/regexp_lexer.cpp
CHANGED
@@ -11,7 +11,7 @@ Token RegexpLexer::build_next_token() {
|
|
11
11
|
m_nested_lexer = new Lexer { *this };
|
12
12
|
m_nested_lexer->set_stop_char('}');
|
13
13
|
m_state = State::EvaluateEnd;
|
14
|
-
return Token { Token::Type::EvaluateToStringBegin, m_file, m_token_line, m_token_column };
|
14
|
+
return Token { Token::Type::EvaluateToStringBegin, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
15
15
|
case State::EvaluateEnd:
|
16
16
|
advance(); // }
|
17
17
|
if (current_char() == m_stop_char) {
|
@@ -21,16 +21,16 @@ Token RegexpLexer::build_next_token() {
|
|
21
21
|
} else {
|
22
22
|
m_state = State::InProgress;
|
23
23
|
}
|
24
|
-
return Token { Token::Type::EvaluateToStringEnd, m_file, m_token_line, m_token_column };
|
24
|
+
return Token { Token::Type::EvaluateToStringEnd, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
25
25
|
case State::EndToken: {
|
26
26
|
m_state = State::Done;
|
27
|
-
auto token = Token { Token::Type::InterpolatedRegexpEnd, m_file, m_cursor_line, m_cursor_column };
|
27
|
+
auto token = Token { Token::Type::InterpolatedRegexpEnd, m_file, m_cursor_line, m_cursor_column, m_whitespace_precedes };
|
28
28
|
if (m_options && !m_options->is_empty())
|
29
29
|
token.set_literal(m_options);
|
30
30
|
return token;
|
31
31
|
}
|
32
32
|
case State::Done:
|
33
|
-
return Token { Token::Type::Eof, m_file, m_cursor_line, m_cursor_column };
|
33
|
+
return Token { Token::Type::Eof, m_file, m_cursor_line, m_cursor_column, m_whitespace_precedes };
|
34
34
|
}
|
35
35
|
TM_UNREACHABLE();
|
36
36
|
}
|
@@ -55,7 +55,7 @@ Token RegexpLexer::consume_regexp() {
|
|
55
55
|
}
|
56
56
|
advance();
|
57
57
|
} else if (c == '#' && peek() == '{') {
|
58
|
-
auto token = Token { Token::Type::String, buf, m_file, m_token_line, m_token_column };
|
58
|
+
auto token = Token { Token::Type::String, buf, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
59
59
|
buf = new String;
|
60
60
|
advance(2);
|
61
61
|
m_state = State::EvaluateBegin;
|
@@ -72,14 +72,14 @@ Token RegexpLexer::consume_regexp() {
|
|
72
72
|
} else {
|
73
73
|
m_options = consume_options();
|
74
74
|
m_state = State::EndToken;
|
75
|
-
return Token { Token::Type::String, buf, m_file, m_token_line, m_token_column };
|
75
|
+
return Token { Token::Type::String, buf, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
76
76
|
}
|
77
77
|
} else {
|
78
78
|
buf->append_char(c);
|
79
79
|
advance();
|
80
80
|
}
|
81
81
|
}
|
82
|
-
return Token { Token::Type::UnterminatedRegexp, buf, m_file, m_token_line, m_token_column };
|
82
|
+
return Token { Token::Type::UnterminatedRegexp, buf, m_file, m_token_line, m_token_column, m_whitespace_precedes };
|
83
83
|
}
|
84
84
|
|
85
85
|
String *RegexpLexer::consume_options() {
|