parser 2.1.0.pre1 → 2.1.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/parser.rb +1 -52
- data/lib/parser/base.rb +5 -7
- data/lib/parser/builders/default.rb +12 -20
- data/lib/parser/diagnostic.rb +23 -5
- data/lib/parser/diagnostic/engine.rb +3 -2
- data/lib/parser/lexer.rl +27 -37
- data/lib/parser/lexer/literal.rb +3 -7
- data/lib/parser/messages.rb +64 -0
- data/lib/parser/ruby18.y +12 -12
- data/lib/parser/ruby19.y +11 -11
- data/lib/parser/ruby20.y +10 -10
- data/lib/parser/ruby21.y +10 -10
- data/lib/parser/source/rewriter.rb +4 -2
- data/lib/parser/version.rb +1 -1
- data/test/parse_helper.rb +5 -2
- data/test/test_diagnostic.rb +5 -5
- data/test/test_diagnostic_engine.rb +6 -6
- data/test/test_lexer.rb +8 -0
- metadata +45 -44
data/lib/parser/lexer/literal.rb
CHANGED
@@ -44,8 +44,8 @@ module Parser
|
|
44
44
|
delimiter = coerce_encoding(delimiter)
|
45
45
|
|
46
46
|
unless TYPES.include?(str_type)
|
47
|
-
|
48
|
-
|
47
|
+
lexer.send(:diagnostic, :error, :unexpected_percent_str,
|
48
|
+
{ :type => str_type }, @lexer.send(:range, str_s, str_s + 2))
|
49
49
|
end
|
50
50
|
|
51
51
|
# String type. For :'foo', it is :'
|
@@ -157,11 +157,7 @@ module Parser
|
|
157
157
|
|
158
158
|
@buffer_e = te
|
159
159
|
|
160
|
-
|
161
|
-
@buffer << string.encode(@lexer.encoding)
|
162
|
-
else
|
163
|
-
@buffer << string
|
164
|
-
end
|
160
|
+
@buffer << string
|
165
161
|
end
|
166
162
|
|
167
163
|
def flush_string
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Parser
|
2
|
+
##
|
3
|
+
# Diagnostic messages (errors, warnings and notices) that can be generated.
|
4
|
+
#
|
5
|
+
# @see Diagnostic
|
6
|
+
#
|
7
|
+
# @api public
|
8
|
+
#
|
9
|
+
MESSAGES = {
|
10
|
+
# Lexer errors
|
11
|
+
:unicode_point_too_large => 'invalid Unicode codepoint (too large)',
|
12
|
+
:invalid_escape => 'invalid escape character syntax',
|
13
|
+
:incomplete_escape => 'incomplete character syntax',
|
14
|
+
:invalid_hex_escape => 'invalid hex escape',
|
15
|
+
:invalid_unicode_escape => 'invalid Unicode escape',
|
16
|
+
:unterminated_unicode => 'unterminated Unicode escape',
|
17
|
+
:escape_eof => 'escape sequence meets end of file',
|
18
|
+
:string_eof => 'unterminated string meets end of file',
|
19
|
+
:regexp_options => 'unknown regexp options: %{options}',
|
20
|
+
:cvar_name => "`%{name}' is not allowed as a class variable name",
|
21
|
+
:ivar_name => "`%{name}' is not allowed as an instance variable name",
|
22
|
+
:trailing_in_number => "trailing `%{character}' in number",
|
23
|
+
:empty_numeric => 'numeric literal without digits',
|
24
|
+
:invalid_octal => 'invalid octal digit',
|
25
|
+
:no_dot_digit_literal => 'no .<digit> floating literal anymore; put 0 before dot',
|
26
|
+
:bare_backslash => 'bare backslash only allowed before newline',
|
27
|
+
:unexpected => "unexpected `%{character}'",
|
28
|
+
:embedded_document => 'embedded document meets end of file (and they embark on a romantic journey)',
|
29
|
+
|
30
|
+
# Lexer warnings
|
31
|
+
:invalid_escape_use => 'invalid character syntax; use ?%{escape}',
|
32
|
+
:ambiguous_literal => 'ambiguous first argument; parenthesize arguments or add whitespace to the right',
|
33
|
+
:ambiguous_prefix => "`%{prefix}' interpreted as argument prefix",
|
34
|
+
|
35
|
+
# Parser errors
|
36
|
+
:nth_ref_alias => 'cannot define an alias for a back-reference variable',
|
37
|
+
:begin_in_method => 'BEGIN in method',
|
38
|
+
:backref_assignment => 'cannot assign to a back-reference variable',
|
39
|
+
:invalid_assignment => 'cannot assign to a keyword',
|
40
|
+
:module_name_const => 'class or module name must be a constant literal',
|
41
|
+
:unexpected_token => 'unexpected token %{token}',
|
42
|
+
:argument_const => 'formal argument cannot be a constant',
|
43
|
+
:argument_ivar => 'formal argument cannot be an instance variable',
|
44
|
+
:argument_gvar => 'formal argument cannot be a global variable',
|
45
|
+
:argument_cvar => 'formal argument cannot be a class variable',
|
46
|
+
:duplicate_argument => 'duplicate argument name',
|
47
|
+
:empty_symbol => 'empty symbol literal',
|
48
|
+
:odd_hash => 'odd number of entries for a hash',
|
49
|
+
:singleton_literal => 'cannot define a singleton method for a literal',
|
50
|
+
:dynamic_const => 'dynamic constant assignment',
|
51
|
+
:module_in_def => 'module definition in method body',
|
52
|
+
:class_in_def => 'class definition in method body',
|
53
|
+
:unexpected_percent_str => '%{type}: unknown type of percent-literal',
|
54
|
+
:block_and_blockarg => 'both block argument and literal block are passed',
|
55
|
+
:masgn_as_condition => 'multiple assignment in conditional context',
|
56
|
+
|
57
|
+
# Parser warnings
|
58
|
+
:useless_else => 'else without rescue is useless',
|
59
|
+
|
60
|
+
# Rewriter diagnostics
|
61
|
+
:invalid_action => 'cannot %{action}',
|
62
|
+
:clobbered => 'clobbered by: %{action}',
|
63
|
+
}.freeze
|
64
|
+
end
|
data/lib/parser/ruby18.y
CHANGED
@@ -55,7 +55,7 @@ rule
|
|
55
55
|
ensure_t, ensure_ = val[3]
|
56
56
|
|
57
57
|
if rescue_bodies.empty? && !else_.nil?
|
58
|
-
diagnostic :warning, :useless_else, else_t
|
58
|
+
diagnostic :warning, :useless_else, nil, else_t
|
59
59
|
end
|
60
60
|
|
61
61
|
result = @builder.begin_body(val[0],
|
@@ -108,7 +108,7 @@ rule
|
|
108
108
|
}
|
109
109
|
| kALIAS tGVAR tNTH_REF
|
110
110
|
{
|
111
|
-
diagnostic
|
111
|
+
diagnostic :error, :nth_ref_alias, nil, val[2]
|
112
112
|
}
|
113
113
|
| kUNDEF undef_list
|
114
114
|
{
|
@@ -143,7 +143,7 @@ rule
|
|
143
143
|
| klBEGIN tLCURLY compstmt tRCURLY
|
144
144
|
{
|
145
145
|
if in_def?
|
146
|
-
diagnostic
|
146
|
+
diagnostic :error, :begin_in_method, nil, val[0]
|
147
147
|
end
|
148
148
|
|
149
149
|
result = @builder.preexe(val[0], val[1], val[2], val[3])
|
@@ -468,7 +468,7 @@ rule
|
|
468
468
|
|
469
469
|
cname: tIDENTIFIER
|
470
470
|
{
|
471
|
-
diagnostic
|
471
|
+
diagnostic :error, :module_name_const, nil, val[0]
|
472
472
|
}
|
473
473
|
| tCONSTANT
|
474
474
|
|
@@ -573,11 +573,11 @@ rule
|
|
573
573
|
}
|
574
574
|
| primary_value tCOLON2 tCONSTANT tOP_ASGN arg
|
575
575
|
{
|
576
|
-
diagnostic
|
576
|
+
diagnostic :error, :dynamic_const, nil, val[2], [ val[3] ]
|
577
577
|
}
|
578
578
|
| tCOLON3 tCONSTANT tOP_ASGN arg
|
579
579
|
{
|
580
|
-
diagnostic
|
580
|
+
diagnostic :error, :dynamic_const, nil, val[1], [ val[2] ]
|
581
581
|
}
|
582
582
|
| backref tOP_ASGN arg
|
583
583
|
{
|
@@ -1126,7 +1126,7 @@ rule
|
|
1126
1126
|
bodystmt kEND
|
1127
1127
|
{
|
1128
1128
|
if in_def?
|
1129
|
-
diagnostic
|
1129
|
+
diagnostic :error, :class_in_def, nil, val[0]
|
1130
1130
|
end
|
1131
1131
|
|
1132
1132
|
lt_t, superclass = val[2]
|
@@ -1159,7 +1159,7 @@ rule
|
|
1159
1159
|
bodystmt kEND
|
1160
1160
|
{
|
1161
1161
|
if in_def?
|
1162
|
-
diagnostic
|
1162
|
+
diagnostic :error, :module_in_def, nil, val[0]
|
1163
1163
|
end
|
1164
1164
|
|
1165
1165
|
result = @builder.def_module(val[0], val[1],
|
@@ -1768,19 +1768,19 @@ xstring_contents: # nothing
|
|
1768
1768
|
|
1769
1769
|
f_norm_arg: tCONSTANT
|
1770
1770
|
{
|
1771
|
-
diagnostic
|
1771
|
+
diagnostic :error, :argument_const, nil, val[0]
|
1772
1772
|
}
|
1773
1773
|
| tIVAR
|
1774
1774
|
{
|
1775
|
-
diagnostic
|
1775
|
+
diagnostic :error, :argument_ivar, nil, val[0]
|
1776
1776
|
}
|
1777
1777
|
| tGVAR
|
1778
1778
|
{
|
1779
|
-
diagnostic
|
1779
|
+
diagnostic :error, :argument_gvar, nil, val[0]
|
1780
1780
|
}
|
1781
1781
|
| tCVAR
|
1782
1782
|
{
|
1783
|
-
diagnostic
|
1783
|
+
diagnostic :error, :argument_cvar, nil, val[0]
|
1784
1784
|
}
|
1785
1785
|
| tIDENTIFIER
|
1786
1786
|
{
|
data/lib/parser/ruby19.y
CHANGED
@@ -82,7 +82,7 @@ rule
|
|
82
82
|
ensure_t, ensure_ = val[3]
|
83
83
|
|
84
84
|
if rescue_bodies.empty? && !else_.nil?
|
85
|
-
diagnostic :warning, :useless_else, else_t
|
85
|
+
diagnostic :warning, :useless_else, nil, else_t
|
86
86
|
end
|
87
87
|
|
88
88
|
result = @builder.begin_body(val[0],
|
@@ -135,7 +135,7 @@ rule
|
|
135
135
|
}
|
136
136
|
| kALIAS tGVAR tNTH_REF
|
137
137
|
{
|
138
|
-
diagnostic
|
138
|
+
diagnostic :error, :nth_ref_alias, nil, val[2]
|
139
139
|
}
|
140
140
|
| kUNDEF undef_list
|
141
141
|
{
|
@@ -528,7 +528,7 @@ rule
|
|
528
528
|
|
529
529
|
cname: tIDENTIFIER
|
530
530
|
{
|
531
|
-
diagnostic
|
531
|
+
diagnostic :error, :module_name_const, nil, val[0]
|
532
532
|
}
|
533
533
|
| tCONSTANT
|
534
534
|
|
@@ -645,11 +645,11 @@ rule
|
|
645
645
|
}
|
646
646
|
| primary_value tCOLON2 tCONSTANT tOP_ASGN arg
|
647
647
|
{
|
648
|
-
diagnostic
|
648
|
+
diagnostic :error, :dynamic_const, nil, val[2], [ val[3] ]
|
649
649
|
}
|
650
650
|
| tCOLON3 tCONSTANT tOP_ASGN arg
|
651
651
|
{
|
652
|
-
diagnostic
|
652
|
+
diagnostic :error, :dynamic_const, nil, val[1], [ val[2] ]
|
653
653
|
}
|
654
654
|
| backref tOP_ASGN arg
|
655
655
|
{
|
@@ -1088,7 +1088,7 @@ rule
|
|
1088
1088
|
bodystmt kEND
|
1089
1089
|
{
|
1090
1090
|
if in_def?
|
1091
|
-
diagnostic
|
1091
|
+
diagnostic :error, :class_in_def, nil, val[0]
|
1092
1092
|
end
|
1093
1093
|
|
1094
1094
|
lt_t, superclass = val[2]
|
@@ -1121,7 +1121,7 @@ rule
|
|
1121
1121
|
bodystmt kEND
|
1122
1122
|
{
|
1123
1123
|
if in_def?
|
1124
|
-
diagnostic
|
1124
|
+
diagnostic :error, :module_in_def, nil, val[0]
|
1125
1125
|
end
|
1126
1126
|
|
1127
1127
|
result = @builder.def_module(val[0], val[1],
|
@@ -1952,19 +1952,19 @@ keyword_variable: kNIL
|
|
1952
1952
|
|
1953
1953
|
f_bad_arg: tCONSTANT
|
1954
1954
|
{
|
1955
|
-
diagnostic
|
1955
|
+
diagnostic :error, :argument_const, nil, val[0]
|
1956
1956
|
}
|
1957
1957
|
| tIVAR
|
1958
1958
|
{
|
1959
|
-
diagnostic
|
1959
|
+
diagnostic :error, :argument_ivar, nil, val[0]
|
1960
1960
|
}
|
1961
1961
|
| tGVAR
|
1962
1962
|
{
|
1963
|
-
diagnostic
|
1963
|
+
diagnostic :error, :argument_gvar, nil, val[0]
|
1964
1964
|
}
|
1965
1965
|
| tCVAR
|
1966
1966
|
{
|
1967
|
-
diagnostic
|
1967
|
+
diagnostic :error, :argument_cvar, nil, val[0]
|
1968
1968
|
}
|
1969
1969
|
|
1970
1970
|
f_norm_arg: f_bad_arg
|
data/lib/parser/ruby20.y
CHANGED
@@ -82,7 +82,7 @@ rule
|
|
82
82
|
ensure_t, ensure_ = val[3]
|
83
83
|
|
84
84
|
if rescue_bodies.empty? && !else_.nil?
|
85
|
-
diagnostic :warning, :useless_else, else_t
|
85
|
+
diagnostic :warning, :useless_else, nil, else_t
|
86
86
|
end
|
87
87
|
|
88
88
|
result = @builder.begin_body(val[0],
|
@@ -117,7 +117,7 @@ rule
|
|
117
117
|
| klBEGIN tLCURLY top_compstmt tRCURLY
|
118
118
|
{
|
119
119
|
if in_def?
|
120
|
-
diagnostic
|
120
|
+
diagnostic :error, :begin_in_method, nil, val[0]
|
121
121
|
end
|
122
122
|
|
123
123
|
result = @builder.preexe(val[0], val[1], val[2], val[3])
|
@@ -145,7 +145,7 @@ rule
|
|
145
145
|
}
|
146
146
|
| kALIAS tGVAR tNTH_REF
|
147
147
|
{
|
148
|
-
diagnostic
|
148
|
+
diagnostic :error, :nth_ref_alias, nil, val[2]
|
149
149
|
}
|
150
150
|
| kUNDEF undef_list
|
151
151
|
{
|
@@ -535,7 +535,7 @@ rule
|
|
535
535
|
|
536
536
|
cname: tIDENTIFIER
|
537
537
|
{
|
538
|
-
diagnostic
|
538
|
+
diagnostic :error, :module_name_const, nil, val[0]
|
539
539
|
}
|
540
540
|
| tCONSTANT
|
541
541
|
|
@@ -1116,7 +1116,7 @@ rule
|
|
1116
1116
|
bodystmt kEND
|
1117
1117
|
{
|
1118
1118
|
if in_def?
|
1119
|
-
diagnostic
|
1119
|
+
diagnostic :error, :class_in_def, nil, val[0]
|
1120
1120
|
end
|
1121
1121
|
|
1122
1122
|
lt_t, superclass = val[2]
|
@@ -1149,7 +1149,7 @@ rule
|
|
1149
1149
|
bodystmt kEND
|
1150
1150
|
{
|
1151
1151
|
if in_def?
|
1152
|
-
diagnostic
|
1152
|
+
diagnostic :error, :module_in_def, nil, val[0]
|
1153
1153
|
end
|
1154
1154
|
|
1155
1155
|
result = @builder.def_module(val[0], val[1],
|
@@ -2075,19 +2075,19 @@ keyword_variable: kNIL
|
|
2075
2075
|
|
2076
2076
|
f_bad_arg: tCONSTANT
|
2077
2077
|
{
|
2078
|
-
diagnostic
|
2078
|
+
diagnostic :error, :argument_const, nil, val[0]
|
2079
2079
|
}
|
2080
2080
|
| tIVAR
|
2081
2081
|
{
|
2082
|
-
diagnostic
|
2082
|
+
diagnostic :error, :argument_ivar, nil, val[0]
|
2083
2083
|
}
|
2084
2084
|
| tGVAR
|
2085
2085
|
{
|
2086
|
-
diagnostic
|
2086
|
+
diagnostic :error, :argument_gvar, nil, val[0]
|
2087
2087
|
}
|
2088
2088
|
| tCVAR
|
2089
2089
|
{
|
2090
|
-
diagnostic
|
2090
|
+
diagnostic :error, :argument_cvar, nil, val[0]
|
2091
2091
|
}
|
2092
2092
|
|
2093
2093
|
f_norm_arg: f_bad_arg
|
data/lib/parser/ruby21.y
CHANGED
@@ -83,7 +83,7 @@ rule
|
|
83
83
|
ensure_t, ensure_ = val[3]
|
84
84
|
|
85
85
|
if rescue_bodies.empty? && !else_.nil?
|
86
|
-
diagnostic :warning, :useless_else, else_t
|
86
|
+
diagnostic :warning, :useless_else, nil, else_t
|
87
87
|
end
|
88
88
|
|
89
89
|
result = @builder.begin_body(val[0],
|
@@ -117,7 +117,7 @@ rule
|
|
117
117
|
stmt_or_begin: stmt
|
118
118
|
| klBEGIN tLCURLY top_compstmt tRCURLY
|
119
119
|
{
|
120
|
-
diagnostic
|
120
|
+
diagnostic :error, :begin_in_method, nil, val[0]
|
121
121
|
}
|
122
122
|
|
123
123
|
stmt: kALIAS fitem
|
@@ -142,7 +142,7 @@ rule
|
|
142
142
|
}
|
143
143
|
| kALIAS tGVAR tNTH_REF
|
144
144
|
{
|
145
|
-
diagnostic
|
145
|
+
diagnostic :error, :nth_ref_alias, nil, val[2]
|
146
146
|
}
|
147
147
|
| kUNDEF undef_list
|
148
148
|
{
|
@@ -527,7 +527,7 @@ rule
|
|
527
527
|
|
528
528
|
cname: tIDENTIFIER
|
529
529
|
{
|
530
|
-
diagnostic
|
530
|
+
diagnostic :error, :module_name_const, nil, val[0]
|
531
531
|
}
|
532
532
|
| tCONSTANT
|
533
533
|
|
@@ -1106,7 +1106,7 @@ rule
|
|
1106
1106
|
bodystmt kEND
|
1107
1107
|
{
|
1108
1108
|
if in_def?
|
1109
|
-
diagnostic
|
1109
|
+
diagnostic :error, :class_in_def, nil, val[0]
|
1110
1110
|
end
|
1111
1111
|
|
1112
1112
|
lt_t, superclass = val[2]
|
@@ -1139,7 +1139,7 @@ rule
|
|
1139
1139
|
bodystmt kEND
|
1140
1140
|
{
|
1141
1141
|
if in_def?
|
1142
|
-
diagnostic
|
1142
|
+
diagnostic :error, :module_in_def, nil, val[0]
|
1143
1143
|
end
|
1144
1144
|
|
1145
1145
|
result = @builder.def_module(val[0], val[1],
|
@@ -2062,19 +2062,19 @@ keyword_variable: kNIL
|
|
2062
2062
|
|
2063
2063
|
f_bad_arg: tCONSTANT
|
2064
2064
|
{
|
2065
|
-
diagnostic
|
2065
|
+
diagnostic :error, :argument_const, nil, val[0]
|
2066
2066
|
}
|
2067
2067
|
| tIVAR
|
2068
2068
|
{
|
2069
|
-
diagnostic
|
2069
|
+
diagnostic :error, :argument_ivar, nil, val[0]
|
2070
2070
|
}
|
2071
2071
|
| tGVAR
|
2072
2072
|
{
|
2073
|
-
diagnostic
|
2073
|
+
diagnostic :error, :argument_gvar, nil, val[0]
|
2074
2074
|
}
|
2075
2075
|
| tCVAR
|
2076
2076
|
{
|
2077
|
-
diagnostic
|
2077
|
+
diagnostic :error, :argument_cvar, nil, val[0]
|
2078
2078
|
}
|
2079
2079
|
|
2080
2080
|
f_norm_arg: f_bad_arg
|
@@ -118,13 +118,15 @@ module Parser
|
|
118
118
|
if (clobber_action = clobbered?(action.range))
|
119
119
|
# cannot replace 3 characters with "foobar"
|
120
120
|
diagnostic = Diagnostic.new(:error,
|
121
|
-
|
121
|
+
:invalid_action,
|
122
|
+
{ :action => action },
|
122
123
|
action.range)
|
123
124
|
@diagnostics.process(diagnostic)
|
124
125
|
|
125
126
|
# clobbered by: remove 3 characters
|
126
127
|
diagnostic = Diagnostic.new(:note,
|
127
|
-
|
128
|
+
:clobbered,
|
129
|
+
{ :action => clobber_action },
|
128
130
|
clobber_action.range)
|
129
131
|
@diagnostics.process(diagnostic)
|
130
132
|
|
data/lib/parser/version.rb
CHANGED
data/test/parse_helper.rb
CHANGED
@@ -129,10 +129,13 @@ module ParseHelper
|
|
129
129
|
|
130
130
|
emitted_diagnostic = @diagnostics.first
|
131
131
|
|
132
|
-
level,
|
133
|
-
|
132
|
+
level, reason, arguments = diagnostic
|
133
|
+
arguments ||= {}
|
134
|
+
message = Parser::MESSAGES[reason] % arguments
|
134
135
|
|
135
136
|
assert_equal level, emitted_diagnostic.level
|
137
|
+
assert_equal reason, emitted_diagnostic.reason
|
138
|
+
assert_equal arguments, emitted_diagnostic.arguments
|
136
139
|
assert_equal message, emitted_diagnostic.message
|
137
140
|
|
138
141
|
parse_source_map_descriptions(source_maps) \
|