parser 2.6.3.0 → 2.6.4.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/.travis.yml +10 -10
- data/CHANGELOG.md +24 -2
- data/doc/AST_FORMAT.md +45 -3
- data/lib/parser.rb +1 -0
- data/lib/parser/ast/processor.rb +24 -1
- data/lib/parser/builders/default.rb +64 -12
- data/lib/parser/context.rb +8 -0
- data/lib/parser/current.rb +3 -3
- data/lib/parser/lexer.rl +84 -3
- data/lib/parser/lexer/max_numparam_stack.rb +42 -0
- data/lib/parser/messages.rb +26 -20
- data/lib/parser/meta.rb +1 -0
- data/lib/parser/ruby25.y +1 -1
- data/lib/parser/ruby27.y +65 -31
- data/lib/parser/runner/ruby_parse.rb +2 -2
- data/lib/parser/version.rb +1 -1
- data/parser.gemspec +1 -1
- data/test/test_lexer.rb +75 -0
- data/test/test_parser.rb +382 -3
- data/test/test_runner_parse.rb +35 -0
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e113f6f42c44591674f288ebda60f8c4f17f5b6aee601d1cc5c2e20c50ef2e6
|
4
|
+
data.tar.gz: '08cf94385ef5cd8f211de395e1c272e5b7950e155463160e327cda2eb047dfad'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25fd7715c94cf32eb097e8c0049d48f7b8185bef6ea4dafe21f0f7013c13892ff6d929e2e45f18480903f081ed9738aa8f0059287dd528cdb63feb94a47fd42e
|
7
|
+
data.tar.gz: 8dfe6966704a8b5b662f99a2ee15d525f6d4cd3d74b62b0c3946f01933c86f50075572cf32a81de3bfe2fe96a07d8197a55a11906f870b80daa2d81e50987944
|
data/.travis.yml
CHANGED
@@ -11,14 +11,14 @@ matrix:
|
|
11
11
|
- name: 2.3.8 / Parser tests
|
12
12
|
rvm: 2.3.8
|
13
13
|
script: bundle exec rake test_cov
|
14
|
-
- name: 2.4.
|
15
|
-
rvm: 2.4.
|
14
|
+
- name: 2.4.7 / Parser tests
|
15
|
+
rvm: 2.4.7
|
16
16
|
script: bundle exec rake test_cov
|
17
|
-
- name: 2.5.
|
18
|
-
rvm: 2.5.
|
17
|
+
- name: 2.5.6 / Parser tests
|
18
|
+
rvm: 2.5.6
|
19
19
|
script: bundle exec rake test_cov
|
20
|
-
- name: 2.6.
|
21
|
-
rvm: 2.6.
|
20
|
+
- name: 2.6.4 / Parser tests
|
21
|
+
rvm: 2.6.4
|
22
22
|
script: bundle exec rake test_cov
|
23
23
|
- name: ruby-head / Parser tests
|
24
24
|
rvm: ruby-head
|
@@ -29,11 +29,11 @@ matrix:
|
|
29
29
|
- name: rbx-2 / Parser tests
|
30
30
|
rvm: rbx-2
|
31
31
|
script: bundle exec rake test_cov
|
32
|
-
- name: 2.5.
|
33
|
-
rvm: 2.5.
|
32
|
+
- name: 2.5.6 / Rubocop tests
|
33
|
+
rvm: 2.5.6
|
34
34
|
script: ./ci/run_rubocop_specs
|
35
|
-
- name: 2.6.
|
36
|
-
rvm: 2.6.
|
35
|
+
- name: 2.6.4 / Rubocop tests
|
36
|
+
rvm: 2.6.4
|
37
37
|
script: ./ci/run_rubocop_specs
|
38
38
|
allow_failures:
|
39
39
|
- rvm: ruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,30 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
v2.6.4.0 (2019-08-30)
|
5
|
+
---------------------
|
6
|
+
|
7
|
+
API modifications:
|
8
|
+
* Added specs for heredocs with mixed encoding. (#581) (Ilya Bylich)
|
9
|
+
|
10
|
+
Features implemented:
|
11
|
+
* ruby27.y: Revert "pipeline operator" (#601) (Koichi ITO)
|
12
|
+
* ruby27.y: Fix parsing of mutiple assignment with rescue modifier (#600) (Koichi ITO)
|
13
|
+
* ruby27.y: hoisted out f_rest_marg. (#594) (Ilya Bylich)
|
14
|
+
* ruby27.y: added pipeline operator. (#592) (Ilya Bylich)
|
15
|
+
* ruby27.y: reject safe navigator in LHS of mass-assignment. (#586) (Ilya Bylich)
|
16
|
+
* lexer.rl: reject whitespaces in meta and control chars. (#585) (Ilya Bylich)
|
17
|
+
* lexer.rl: Reject numparams as symbol literals. (#582) (Ilya Bylich)
|
18
|
+
* ruby27.y: Added numbered parameters support. (#565) (Ilya Bylich)
|
19
|
+
* lexer.rl: Reject \n and \r in heredoc identifiers starting from 2.7. (#575) (Ilya Bylich)
|
20
|
+
|
21
|
+
Bugs fixed:
|
22
|
+
* ruby-parse: print empty string when --emit-json and empty input are given. (#590) (Ilya Bylich)
|
23
|
+
* AST_FORMAT: fixed documentation of the string with interpolation. (#589) (Ilya Bylich)
|
24
|
+
* builder.rb, processor.rb: Changed format of the procarg0 node. (#587) (Ilya Bylich)
|
25
|
+
|
26
|
+
v2.6.3.0 (2019-04-28)
|
27
|
+
---------------------
|
6
28
|
|
7
29
|
Features implemented:
|
8
30
|
* ruby27.y: Added beginless ranges support. (#570) (Ilya Bylich)
|
data/doc/AST_FORMAT.md
CHANGED
@@ -102,10 +102,13 @@ Format:
|
|
102
102
|
Format:
|
103
103
|
|
104
104
|
~~~
|
105
|
-
(dstr (str "foo") (lvar bar) (str "baz"))
|
105
|
+
(dstr (str "foo") (begin (lvar bar)) (str "baz"))
|
106
106
|
'"foo#{bar}baz"'
|
107
107
|
^ begin ^ end
|
108
108
|
~~~~~~~~~~~~~~ expression
|
109
|
+
^^ begin (begin)
|
110
|
+
^ end (begin)
|
111
|
+
^^^^^^ expression (begin)
|
109
112
|
~~~
|
110
113
|
|
111
114
|
#### Here document
|
@@ -933,10 +936,15 @@ the sole argument (e.g. `|foo,|`).
|
|
933
936
|
Format:
|
934
937
|
|
935
938
|
~~~
|
936
|
-
(procarg0 :foo)
|
939
|
+
(procarg0 (arg :foo))
|
937
940
|
"|foo|"
|
938
941
|
~~~ expression
|
939
|
-
|
942
|
+
|
943
|
+
(procarg0 (arg :foo) (arg :bar))
|
944
|
+
"|(foo, bar)|"
|
945
|
+
~ begin
|
946
|
+
~ end
|
947
|
+
~~~~~~~~~~ expression
|
940
948
|
~~~
|
941
949
|
|
942
950
|
### Expression arguments
|
@@ -1083,6 +1091,40 @@ However, the following code results in a parse error:
|
|
1083
1091
|
def f(*a: b); end
|
1084
1092
|
~~~
|
1085
1093
|
|
1094
|
+
## Numbered parameters
|
1095
|
+
|
1096
|
+
### Block with numbered parameters
|
1097
|
+
|
1098
|
+
Ruby 2.7 introduced a feature called "numbered parameters".
|
1099
|
+
Numbered and ordinal parameters are mutually exclusive, so if the block
|
1100
|
+
has only numbered parameters it also has a different AST node.
|
1101
|
+
|
1102
|
+
Note that the second child represents a total number of numbered parameters.
|
1103
|
+
|
1104
|
+
Format:
|
1105
|
+
|
1106
|
+
~~~
|
1107
|
+
s(:numblock,
|
1108
|
+
s(:send, nil, :proc), 3,
|
1109
|
+
s(:send,
|
1110
|
+
s(:numparam, 1), :+,
|
1111
|
+
s(:numparam, 3)))
|
1112
|
+
"proc { @1 + @3 }"
|
1113
|
+
~ begin ~ end
|
1114
|
+
~~~~~~~~~~~~~~~~ expression
|
1115
|
+
~~~
|
1116
|
+
|
1117
|
+
### Numbered parameter
|
1118
|
+
|
1119
|
+
Format:
|
1120
|
+
|
1121
|
+
~~~
|
1122
|
+
(numparam 10)
|
1123
|
+
"@10"
|
1124
|
+
~~~ name
|
1125
|
+
~~~ expression
|
1126
|
+
~~~
|
1127
|
+
|
1086
1128
|
## Send
|
1087
1129
|
|
1088
1130
|
### To self
|
data/lib/parser.rb
CHANGED
data/lib/parser/ast/processor.rb
CHANGED
@@ -124,7 +124,22 @@ module Parser
|
|
124
124
|
alias on_kwarg process_argument_node
|
125
125
|
alias on_kwoptarg process_argument_node
|
126
126
|
alias on_kwrestarg process_argument_node
|
127
|
-
|
127
|
+
|
128
|
+
def on_procarg0(node)
|
129
|
+
if node.children[0].is_a?(Symbol)
|
130
|
+
# This branch gets executed when the builder
|
131
|
+
# is not configured to emit and 'arg' inside 'procarg0', i.e. when
|
132
|
+
# Parser::Builders::Default.emit_arg_inside_procarg0
|
133
|
+
# is set to false.
|
134
|
+
#
|
135
|
+
# If this flag is set to true this branch is unreachable.
|
136
|
+
# s(:procarg0, :a)
|
137
|
+
on_argument(node)
|
138
|
+
else
|
139
|
+
# s(:procarg0, s(:arg, :a), s(:arg, :b))
|
140
|
+
process_regular_node(node)
|
141
|
+
end
|
142
|
+
end
|
128
143
|
|
129
144
|
alias on_arg_expr process_regular_node
|
130
145
|
alias on_restarg_expr process_regular_node
|
@@ -173,6 +188,14 @@ module Parser
|
|
173
188
|
alias on_block process_regular_node
|
174
189
|
alias on_lambda process_regular_node
|
175
190
|
|
191
|
+
def on_numblock(node)
|
192
|
+
method_call, max_numparam, body = *node
|
193
|
+
|
194
|
+
node.updated(nil, [
|
195
|
+
process(method_call), max_numparam, process(body)
|
196
|
+
])
|
197
|
+
end
|
198
|
+
|
176
199
|
alias on_while process_regular_node
|
177
200
|
alias on_while_post process_regular_node
|
178
201
|
alias on_until process_regular_node
|
@@ -80,6 +80,21 @@ module Parser
|
|
80
80
|
attr_accessor :emit_index
|
81
81
|
end
|
82
82
|
|
83
|
+
class << self
|
84
|
+
##
|
85
|
+
# AST compatibility attribute; causes a single non-mlhs
|
86
|
+
# block argument to be wrapped in s(:procarg0).
|
87
|
+
#
|
88
|
+
# If set to false (the default), block arguments `|a|` are emitted as
|
89
|
+
# `s(:args, s(:procarg0, :a))`
|
90
|
+
#
|
91
|
+
# If set to true, block arguments `|a|` are emitted as
|
92
|
+
# `s(:args, s(:procarg0, s(:arg, :a))`
|
93
|
+
#
|
94
|
+
# @return [Boolean]
|
95
|
+
attr_accessor :emit_arg_inside_procarg0
|
96
|
+
end
|
97
|
+
|
83
98
|
@emit_index = false
|
84
99
|
|
85
100
|
class << self
|
@@ -90,6 +105,7 @@ module Parser
|
|
90
105
|
@emit_procarg0 = true
|
91
106
|
@emit_encoding = true
|
92
107
|
@emit_index = true
|
108
|
+
@emit_arg_inside_procarg0 = true
|
93
109
|
end
|
94
110
|
end
|
95
111
|
|
@@ -437,6 +453,11 @@ module Parser
|
|
437
453
|
variable_map(token))
|
438
454
|
end
|
439
455
|
|
456
|
+
def numparam(token)
|
457
|
+
n(:numparam, [ value(token).to_i ],
|
458
|
+
variable_map(token))
|
459
|
+
end
|
460
|
+
|
440
461
|
def back_ref(token)
|
441
462
|
n(:back_ref, [ value(token).to_sym ],
|
442
463
|
token_map(token))
|
@@ -663,6 +684,10 @@ module Parser
|
|
663
684
|
collection_map(begin_t, args, end_t))
|
664
685
|
end
|
665
686
|
|
687
|
+
def numargs(max_numparam)
|
688
|
+
n(:numargs, [ max_numparam ], nil)
|
689
|
+
end
|
690
|
+
|
666
691
|
def arg(name_t)
|
667
692
|
n(:arg, [ value(name_t).to_sym ],
|
668
693
|
variable_map(name_t))
|
@@ -717,7 +742,12 @@ module Parser
|
|
717
742
|
|
718
743
|
def procarg0(arg)
|
719
744
|
if self.class.emit_procarg0
|
720
|
-
arg.
|
745
|
+
if arg.type == :arg && self.class.emit_arg_inside_procarg0
|
746
|
+
n(:procarg0, [ arg ],
|
747
|
+
Source::Map::Collection.new(nil, nil, arg.location.expression))
|
748
|
+
else
|
749
|
+
arg.updated(:procarg0)
|
750
|
+
end
|
721
751
|
else
|
722
752
|
arg
|
723
753
|
end
|
@@ -835,15 +865,23 @@ module Parser
|
|
835
865
|
diagnostic :error, :block_and_blockarg, nil, last_arg.loc.expression, [loc(begin_t)]
|
836
866
|
end
|
837
867
|
|
868
|
+
|
869
|
+
if args.type == :numargs
|
870
|
+
block_type = :numblock
|
871
|
+
args = args.children[0]
|
872
|
+
else
|
873
|
+
block_type = :block
|
874
|
+
end
|
875
|
+
|
838
876
|
if [:send, :csend, :index, :super, :zsuper, :lambda].include?(method_call.type)
|
839
|
-
n(
|
877
|
+
n(block_type, [ method_call, args, body ],
|
840
878
|
block_map(method_call.loc.expression, begin_t, end_t))
|
841
879
|
else
|
842
880
|
# Code like "return foo 1 do end" is reduced in a weird sequence.
|
843
881
|
# Here, method_call is actually (return).
|
844
882
|
actual_send, = *method_call
|
845
883
|
block =
|
846
|
-
n(
|
884
|
+
n(block_type, [ actual_send, args, body ],
|
847
885
|
block_map(actual_send.loc.expression, begin_t, end_t))
|
848
886
|
|
849
887
|
n(method_call.type, [ block ],
|
@@ -1215,18 +1253,18 @@ module Parser
|
|
1215
1253
|
case this_arg.type
|
1216
1254
|
when :arg, :optarg, :restarg, :blockarg,
|
1217
1255
|
:kwarg, :kwoptarg, :kwrestarg,
|
1218
|
-
:shadowarg
|
1256
|
+
:shadowarg
|
1219
1257
|
|
1220
|
-
|
1258
|
+
check_duplicate_arg(this_arg, map)
|
1221
1259
|
|
1222
|
-
|
1223
|
-
that_name, = *that_arg
|
1260
|
+
when :procarg0
|
1224
1261
|
|
1225
|
-
if
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1262
|
+
if this_arg.children[0].is_a?(Symbol)
|
1263
|
+
# s(:procarg0, :a)
|
1264
|
+
check_duplicate_arg(this_arg, map)
|
1265
|
+
else
|
1266
|
+
# s(:procarg0, s(:arg, :a), ...)
|
1267
|
+
check_duplicate_args(this_arg.children, map)
|
1230
1268
|
end
|
1231
1269
|
|
1232
1270
|
when :mlhs
|
@@ -1235,6 +1273,20 @@ module Parser
|
|
1235
1273
|
end
|
1236
1274
|
end
|
1237
1275
|
|
1276
|
+
def check_duplicate_arg(this_arg, map={})
|
1277
|
+
this_name, = *this_arg
|
1278
|
+
|
1279
|
+
that_arg = map[this_name]
|
1280
|
+
that_name, = *that_arg
|
1281
|
+
|
1282
|
+
if that_arg.nil?
|
1283
|
+
map[this_name] = this_arg
|
1284
|
+
elsif arg_name_collides?(this_name, that_name)
|
1285
|
+
diagnostic :error, :duplicate_argument, nil,
|
1286
|
+
this_arg.loc.name, [ that_arg.loc.name ]
|
1287
|
+
end
|
1288
|
+
end
|
1289
|
+
|
1238
1290
|
def arg_name_collides?(this_name, that_name)
|
1239
1291
|
case @parser.version
|
1240
1292
|
when 18
|
data/lib/parser/context.rb
CHANGED
@@ -47,5 +47,13 @@ module Parser
|
|
47
47
|
end
|
48
48
|
alias module_definition_allowed? class_definition_allowed?
|
49
49
|
alias dynamic_const_definition_allowed? class_definition_allowed?
|
50
|
+
|
51
|
+
def in_block?
|
52
|
+
@stack.last == :block
|
53
|
+
end
|
54
|
+
|
55
|
+
def in_lambda?
|
56
|
+
@stack.last == :lambda
|
57
|
+
end
|
50
58
|
end
|
51
59
|
end
|
data/lib/parser/current.rb
CHANGED
@@ -48,7 +48,7 @@ module Parser
|
|
48
48
|
CurrentRuby = Ruby23
|
49
49
|
|
50
50
|
when /^2\.4\./
|
51
|
-
current_version = '2.4.
|
51
|
+
current_version = '2.4.7'
|
52
52
|
if RUBY_VERSION != current_version
|
53
53
|
warn_syntax_deviation 'parser/ruby24', current_version
|
54
54
|
end
|
@@ -57,7 +57,7 @@ module Parser
|
|
57
57
|
CurrentRuby = Ruby24
|
58
58
|
|
59
59
|
when /^2\.5\./
|
60
|
-
current_version = '2.5.
|
60
|
+
current_version = '2.5.6'
|
61
61
|
if RUBY_VERSION != current_version
|
62
62
|
warn_syntax_deviation 'parser/ruby25', current_version
|
63
63
|
end
|
@@ -66,7 +66,7 @@ module Parser
|
|
66
66
|
CurrentRuby = Ruby25
|
67
67
|
|
68
68
|
when /^2\.6\./
|
69
|
-
current_version = '2.6.
|
69
|
+
current_version = '2.6.4'
|
70
70
|
if RUBY_VERSION != current_version
|
71
71
|
warn_syntax_deviation 'parser/ruby26', current_version
|
72
72
|
end
|
data/lib/parser/lexer.rl
CHANGED
@@ -89,7 +89,10 @@ class Parser::Lexer
|
|
89
89
|
|
90
90
|
REGEXP_META_CHARACTERS = Regexp.union(*"\\$()*+.<>?[]^{|}".chars).freeze
|
91
91
|
|
92
|
+
NUMPARAM_MAX = 100
|
93
|
+
|
92
94
|
attr_reader :source_buffer
|
95
|
+
attr_reader :max_numparam_stack
|
93
96
|
|
94
97
|
attr_accessor :diagnostics
|
95
98
|
attr_accessor :static_env
|
@@ -176,6 +179,9 @@ class Parser::Lexer
|
|
176
179
|
|
177
180
|
# State before =begin / =end block comment
|
178
181
|
@cs_before_block_comment = self.class.lex_en_line_begin
|
182
|
+
|
183
|
+
# Maximum numbered parameters stack
|
184
|
+
@max_numparam_stack = MaxNumparamStack.new
|
179
185
|
end
|
180
186
|
|
181
187
|
def source_buffer=(source_buffer)
|
@@ -249,6 +255,10 @@ class Parser::Lexer
|
|
249
255
|
@cond = @cond_stack.pop
|
250
256
|
end
|
251
257
|
|
258
|
+
def max_numparam
|
259
|
+
@max_numparam_stack.top
|
260
|
+
end
|
261
|
+
|
252
262
|
def dedent_level
|
253
263
|
# We erase @dedent_level as a precaution to avoid accidentally
|
254
264
|
# using a stale value.
|
@@ -705,6 +715,14 @@ class Parser::Lexer
|
|
705
715
|
diagnostic :fatal, :invalid_escape
|
706
716
|
}
|
707
717
|
|
718
|
+
action read_post_meta_or_ctrl_char {
|
719
|
+
@escape = @source_buffer.slice(p - 1).chr
|
720
|
+
|
721
|
+
if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord))
|
722
|
+
diagnostic :fatal, :invalid_escape
|
723
|
+
end
|
724
|
+
}
|
725
|
+
|
708
726
|
action slash_c_char {
|
709
727
|
@escape = encode_escape(@escape[0].ord & 0x9f)
|
710
728
|
}
|
@@ -715,13 +733,13 @@ class Parser::Lexer
|
|
715
733
|
|
716
734
|
maybe_escaped_char = (
|
717
735
|
'\\' c_any %unescape_char
|
718
|
-
| ( c_any - [\\] ) %
|
736
|
+
| ( c_any - [\\] ) %read_post_meta_or_ctrl_char
|
719
737
|
);
|
720
738
|
|
721
739
|
maybe_escaped_ctrl_char = ( # why?!
|
722
740
|
'\\' c_any %unescape_char %slash_c_char
|
723
741
|
| '?' % { @escape = "\x7f" }
|
724
|
-
| ( c_any - [\\?] ) %
|
742
|
+
| ( c_any - [\\?] ) %read_post_meta_or_ctrl_char %slash_c_char
|
725
743
|
);
|
726
744
|
|
727
745
|
escape = (
|
@@ -1301,6 +1319,36 @@ class Parser::Lexer
|
|
1301
1319
|
fnext *stack_pop; fbreak;
|
1302
1320
|
};
|
1303
1321
|
|
1322
|
+
'@' [0-9]+
|
1323
|
+
=> {
|
1324
|
+
if @version < 27
|
1325
|
+
diagnostic :error, :ivar_name, { :name => tok }
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
value = tok[1..-1]
|
1329
|
+
|
1330
|
+
if value[0] == '0'
|
1331
|
+
diagnostic :error, :leading_zero_in_numparam, nil, range(@ts, @te)
|
1332
|
+
end
|
1333
|
+
|
1334
|
+
if value.to_i > NUMPARAM_MAX
|
1335
|
+
diagnostic :error, :too_large_numparam, nil, range(@ts, @te)
|
1336
|
+
end
|
1337
|
+
|
1338
|
+
if !@context.in_block? && !@context.in_lambda?
|
1339
|
+
diagnostic :error, :numparam_outside_block, nil, range(@ts, @te)
|
1340
|
+
end
|
1341
|
+
|
1342
|
+
if !@max_numparam_stack.can_have_numparams?
|
1343
|
+
diagnostic :error, :ordinary_param_defined, nil, range(@ts, @te)
|
1344
|
+
end
|
1345
|
+
|
1346
|
+
@max_numparam_stack.register(value.to_i)
|
1347
|
+
|
1348
|
+
emit(:tNUMPARAM, tok[1..-1])
|
1349
|
+
fnext *stack_pop; fbreak;
|
1350
|
+
};
|
1351
|
+
|
1304
1352
|
instance_var_v
|
1305
1353
|
=> {
|
1306
1354
|
if tok =~ /^@[0-9]/
|
@@ -1733,7 +1781,11 @@ class Parser::Lexer
|
|
1733
1781
|
type = $3.empty? ? '<<"'.freeze : ('<<'.freeze + $3)
|
1734
1782
|
delimiter = $4
|
1735
1783
|
|
1736
|
-
if @version >=
|
1784
|
+
if @version >= 27
|
1785
|
+
if delimiter.count("\n") > 0 || delimiter.count("\r") > 0
|
1786
|
+
diagnostic :error, :unterminated_heredoc_id, nil, range(@ts, @ts + 1)
|
1787
|
+
end
|
1788
|
+
elsif @version >= 24
|
1737
1789
|
if delimiter.count("\n") > 0
|
1738
1790
|
if delimiter.end_with?("\n")
|
1739
1791
|
diagnostic :warning, :heredoc_id_ends_with_nl, nil, range(@ts, @ts + 1)
|
@@ -1756,6 +1808,21 @@ class Parser::Lexer
|
|
1756
1808
|
end
|
1757
1809
|
};
|
1758
1810
|
|
1811
|
+
# Escaped unterminated heredoc start
|
1812
|
+
# <<'END | <<"END | <<`END |
|
1813
|
+
# <<-'END | <<-"END | <<-`END |
|
1814
|
+
# <<~'END | <<~"END | <<~`END
|
1815
|
+
#
|
1816
|
+
# If the heredoc is terminated the rule above should handle it
|
1817
|
+
'<<' [~\-]?
|
1818
|
+
('"' (any - c_nl - '"')*
|
1819
|
+
|"'" (any - c_nl - "'")*
|
1820
|
+
|"`" (any - c_nl - "`")
|
1821
|
+
)
|
1822
|
+
=> {
|
1823
|
+
diagnostic :error, :unterminated_heredoc_id, nil, range(@ts, @ts + 1)
|
1824
|
+
};
|
1825
|
+
|
1759
1826
|
#
|
1760
1827
|
# SYMBOL LITERALS
|
1761
1828
|
#
|
@@ -1796,6 +1863,20 @@ class Parser::Lexer
|
|
1796
1863
|
fnext expr_end; fbreak;
|
1797
1864
|
};
|
1798
1865
|
|
1866
|
+
':' ( '@' %{ tm = p - 1; diag_msg = :ivar_name }
|
1867
|
+
| '@@' %{ tm = p - 2; diag_msg = :cvar_name }
|
1868
|
+
) [0-9]*
|
1869
|
+
=> {
|
1870
|
+
if @version >= 27
|
1871
|
+
diagnostic :error, diag_msg, { name: tok(tm, @te) }, range(tm, @te)
|
1872
|
+
else
|
1873
|
+
emit(:tCOLON, tok(@ts, @ts + 1), @ts, @ts + 1)
|
1874
|
+
p = @ts
|
1875
|
+
end
|
1876
|
+
|
1877
|
+
fnext expr_end; fbreak;
|
1878
|
+
};
|
1879
|
+
|
1799
1880
|
#
|
1800
1881
|
# AMBIGUOUS TERNARY OPERATOR
|
1801
1882
|
#
|