natalie_parser 1.1.1 → 2.0.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 +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() {
|