parser 2.0.0.beta5 → 2.0.0.beta6
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 +20 -0
- data/README.md +3 -4
- data/doc/AST_FORMAT.md +37 -8
- data/lib/parser/ast/processor.rb +20 -68
- data/lib/parser/builders/default.rb +71 -25
- data/lib/parser/lexer.rl +4 -4
- data/lib/parser/ruby18.y +8 -5
- data/lib/parser/ruby19.y +11 -8
- data/lib/parser/ruby20.y +11 -8
- data/lib/parser/ruby21.y +11 -8
- data/lib/parser/runner/ruby_parse.rb +5 -9
- data/lib/parser/source/comment/associator.rb +2 -0
- data/lib/parser/version.rb +1 -1
- data/parser.gemspec +1 -1
- data/test/test_lexer.rb +8 -0
- data/test/test_parser.rb +204 -92
- data/test/test_source_comment_associator.rb +23 -5
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff9e3b7f7bacab0b950939c52f7df525def64ecc
|
4
|
+
data.tar.gz: 79f7bfdc451009618f190696b9d01ab9fb2a66d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20a42c7ac8a381a0eff6cdd2cca9a9dc74e1b8eea8463e8b12fa910c97e5d666402db364cd9cdd1d57c7ddb17ef148dc38d171a6be5d078f62acaa78a777ba21
|
7
|
+
data.tar.gz: 975bf3b4ebe25e4d34e2a6b5a28cd4447ec91b1b4f5b29bed0b025a29e5a5a42b15c72d73b0b54aeeaffabdcc0357d8edd8091ce4093f8b40be616a0851a317e
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,26 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
+
v2.0.0.beta6 (2013-06-17)
|
5
|
+
-------------------------
|
6
|
+
|
7
|
+
API modifications:
|
8
|
+
* Get rid of "synthesized (nil)". If it's not in source, it's not in AST (fixes #71). (Peter Zotov)
|
9
|
+
* lexer.rl, ruby{18,19,20,21}.y: source maps for interpolation (fixes #27). (Peter Zotov)
|
10
|
+
|
11
|
+
Features implemented:
|
12
|
+
* ruby{18,19,20,21}.y, builders/default: lvar-injecting match (closes #69). (Peter Zotov)
|
13
|
+
* builders/default: implicit matches (refs #69). (Peter Zotov)
|
14
|
+
* builders/default: flip-flops (refs #69). (Peter Zotov)
|
15
|
+
|
16
|
+
Bugs fixed:
|
17
|
+
* lexer.rl: fix an off-by-1 error in heredoc parsing. (Peter Zotov)
|
18
|
+
* lexer.rl: don't fail on "alias $a $b\n# comment\nalias $c $d". (Peter Zotov)
|
19
|
+
* builders/default: fix treatment of masgn in &&/|| (refs #69). (Peter Zotov)
|
20
|
+
* ruby-parse: make -L command line option work again. (Peter Zotov)
|
21
|
+
* ruby{18,19,20,21}.y: begin source map for "if foo\nthen bar end" (fixes #68). (Peter Zotov)
|
22
|
+
* Source::Comment::Associator: gracefully terminate when out of comments (fixes #67). (Peter Zotov)
|
23
|
+
|
4
24
|
v2.0.0.beta5 (2013-06-08)
|
5
25
|
-------------------------
|
6
26
|
|
data/README.md
CHANGED
@@ -31,14 +31,14 @@ p Parser::CurrentRuby.parse("2 + 2")
|
|
31
31
|
Access the AST's source map:
|
32
32
|
|
33
33
|
~~~ ruby
|
34
|
-
p Parser::CurrentRuby.parse("2 + 2").
|
34
|
+
p Parser::CurrentRuby.parse("2 + 2").loc
|
35
35
|
# #<Parser::Source::Map::Send:0x007fe0ca8a69b8
|
36
36
|
# @begin=nil,
|
37
37
|
# @end=nil,
|
38
38
|
# @expression=#<Source::Range (string) 0...5>,
|
39
39
|
# @selector=#<Source::Range (string) 2...3>>
|
40
40
|
|
41
|
-
p Parser::CurrentRuby.parse("2 + 2").
|
41
|
+
p Parser::CurrentRuby.parse("2 + 2").loc.selector.to_source
|
42
42
|
# "+"
|
43
43
|
~~~
|
44
44
|
|
@@ -104,7 +104,6 @@ $ ruby-parse -E -e "2+2"
|
|
104
104
|
* Improved [clang-like][] diagnostic messages with location information.
|
105
105
|
* Written in pure Ruby, runs on MRI 1.8.7 or >=1.9.2, JRuby and Rubinius in 1.8 and 1.9 mode.
|
106
106
|
* Only two runtime dependencies: the gems [ast][] and [slop][].
|
107
|
-
* RubyParser compatibility (WIP, no, not really yet).
|
108
107
|
* [Insane][insane-lexer] Ruby lexer rewritten from scratch in Ragel.
|
109
108
|
* 100% test coverage for Bison grammars (except error recovery).
|
110
109
|
* Readable, commented source code.
|
@@ -128,7 +127,7 @@ Documentation for parser is available online on [rdoc.info](http://rdoc.info/git
|
|
128
127
|
|
129
128
|
## Acknowledgements
|
130
129
|
|
131
|
-
The lexer testsuite
|
130
|
+
The lexer testsuite is derived from [ruby_parser](http://github.com/seattlerb/ruby_parser).
|
132
131
|
|
133
132
|
The Bison parser rules are derived from [Ruby MRI](http://github.com/ruby/ruby) parse.y.
|
134
133
|
|
data/doc/AST_FORMAT.md
CHANGED
@@ -1,14 +1,6 @@
|
|
1
1
|
AST and Source Location RFC
|
2
2
|
===========================
|
3
3
|
|
4
|
-
## Open questions:
|
5
|
-
|
6
|
-
* Should we handle these cases at all? They do not have special syntax associated.
|
7
|
-
1. How to handle lvar-injecting match (`if /(?<a>foo)/ =~ bar`)?
|
8
|
-
1. How to handle magic match (`foo if /bar/`)?
|
9
|
-
1. How to handle sed-like flip-flop?
|
10
|
-
1. How to handle awk-like flip-flop?
|
11
|
-
|
12
4
|
## Literals
|
13
5
|
|
14
6
|
### Singletons
|
@@ -1441,3 +1433,40 @@ Format:
|
|
1441
1433
|
~~~~~~~~~~~~~~~~~~ expression
|
1442
1434
|
~~~
|
1443
1435
|
|
1436
|
+
## Miscellanea
|
1437
|
+
|
1438
|
+
### Flip-flops
|
1439
|
+
|
1440
|
+
Format:
|
1441
|
+
|
1442
|
+
~~~
|
1443
|
+
(iflipflop (lvar :a) (lvar :b))
|
1444
|
+
"if a..b; end"
|
1445
|
+
~~ operator
|
1446
|
+
~~~~ expression
|
1447
|
+
|
1448
|
+
(eflipflop (lvar :a) (lvar :b))
|
1449
|
+
"if a...b; end"
|
1450
|
+
~~~ operator
|
1451
|
+
~~~~~ expression
|
1452
|
+
~~~
|
1453
|
+
|
1454
|
+
### Implicit matches
|
1455
|
+
|
1456
|
+
Format:
|
1457
|
+
|
1458
|
+
~~~
|
1459
|
+
(match-current-line (regexp (str "a") (regopt)))
|
1460
|
+
"if /a/; end"
|
1461
|
+
~~~
|
1462
|
+
|
1463
|
+
### Local variable injecting matches
|
1464
|
+
|
1465
|
+
Format:
|
1466
|
+
|
1467
|
+
~~~
|
1468
|
+
(match-with-lvasgn (regexp (str "(?<match>bar)") (regopt)) (lvar :baz))
|
1469
|
+
"/(?<match>bar)/ =~ baz"
|
1470
|
+
~~ selector
|
1471
|
+
~~~~~~~~~~~~~~~~~~~~~~ expression
|
1472
|
+
~~~
|
data/lib/parser/ast/processor.rb
CHANGED
@@ -20,7 +20,7 @@ module Parser
|
|
20
20
|
def on_var(node)
|
21
21
|
name, = *node
|
22
22
|
|
23
|
-
node
|
23
|
+
node
|
24
24
|
end
|
25
25
|
|
26
26
|
def process_variable_node(node)
|
@@ -37,8 +37,9 @@ module Parser
|
|
37
37
|
def on_vasgn(node)
|
38
38
|
name, value_node = *node
|
39
39
|
|
40
|
-
|
41
|
-
|
40
|
+
node.updated(nil, [
|
41
|
+
name, process(value_node)
|
42
|
+
])
|
42
43
|
end
|
43
44
|
|
44
45
|
def process_var_asgn_node(node)
|
@@ -67,16 +68,17 @@ module Parser
|
|
67
68
|
def on_const(node)
|
68
69
|
scope_node, name = *node
|
69
70
|
|
70
|
-
|
71
|
-
|
71
|
+
node.updated(nil, [
|
72
|
+
process(scope_node), name
|
73
|
+
])
|
72
74
|
end
|
73
75
|
|
74
76
|
def on_casgn(node)
|
75
77
|
scope_node, name, value_node = *node
|
76
78
|
|
77
|
-
|
78
|
-
|
79
|
-
|
79
|
+
node.updated(nil, [
|
80
|
+
process(scope_node), name, process(value_node)
|
81
|
+
])
|
80
82
|
end
|
81
83
|
|
82
84
|
alias on_args process_regular_node
|
@@ -84,8 +86,9 @@ module Parser
|
|
84
86
|
def on_argument(node)
|
85
87
|
arg_name, value_node = *node
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
+
node.updated(nil, [
|
90
|
+
arg_name, process(value_node)
|
91
|
+
])
|
89
92
|
end
|
90
93
|
|
91
94
|
def process_argument_node(node)
|
@@ -104,18 +107,9 @@ module Parser
|
|
104
107
|
alias on_restarg_expr process_regular_node
|
105
108
|
alias on_blockarg_expr process_regular_node
|
106
109
|
|
107
|
-
alias on_module
|
108
|
-
|
109
|
-
|
110
|
-
name_node, superclass_node, body_node = *node
|
111
|
-
|
112
|
-
superclass_node = process(superclass_node) if superclass_node
|
113
|
-
node.updated(nil, [
|
114
|
-
name_node, superclass_node, process(body_node)
|
115
|
-
])
|
116
|
-
end
|
117
|
-
|
118
|
-
alias on_sclass process_regular_node
|
110
|
+
alias on_module process_regular_node
|
111
|
+
alias on_class process_regular_node
|
112
|
+
alias on_sclass process_regular_node
|
119
113
|
|
120
114
|
def on_def(node)
|
121
115
|
name, args_node, body_node = *node
|
@@ -166,55 +160,13 @@ module Parser
|
|
166
160
|
alias on_and process_regular_node
|
167
161
|
alias on_or process_regular_node
|
168
162
|
|
169
|
-
|
170
|
-
cond_node, if_true_node, if_false_node = *node
|
171
|
-
|
172
|
-
if_true_node = process(if_true_node) if if_true_node
|
173
|
-
if_false_node = process(if_false_node) if if_false_node
|
174
|
-
|
175
|
-
node.updated(nil, [
|
176
|
-
process(cond_node),
|
177
|
-
if_true_node, if_false_node
|
178
|
-
])
|
179
|
-
end
|
163
|
+
alias on_if process_regular_node
|
180
164
|
|
181
165
|
alias on_when process_regular_node
|
166
|
+
alias on_case process_regular_node
|
182
167
|
|
183
|
-
|
184
|
-
|
185
|
-
when_nodes, else_node = bodies[0..-2], bodies[-1]
|
186
|
-
|
187
|
-
cond_node = process(cond_node) if cond_node
|
188
|
-
else_node = process(else_node) if else_node
|
189
|
-
node.updated(nil, [
|
190
|
-
cond_node,
|
191
|
-
*(process_all(when_nodes) << else_node)
|
192
|
-
])
|
193
|
-
end
|
194
|
-
|
195
|
-
def on_resbody(node)
|
196
|
-
exc_list_node, exc_var_node, body_node = *node
|
197
|
-
|
198
|
-
exc_list_node = process(exc_list_node) if exc_list_node
|
199
|
-
exc_var_node = process(exc_var_node) if exc_var_node
|
200
|
-
|
201
|
-
node.updated(nil, [
|
202
|
-
exc_list_node, exc_var_node,
|
203
|
-
process(body_node)
|
204
|
-
])
|
205
|
-
end
|
206
|
-
|
207
|
-
def on_rescue(node)
|
208
|
-
body_node, *handlers = *node
|
209
|
-
handler_nodes, else_node = handlers[0..-2], handlers[-1]
|
210
|
-
|
211
|
-
else_node = process(else_node) if else_node
|
212
|
-
node.updated(nil, [
|
213
|
-
process(body_node),
|
214
|
-
*(process_all(handler_nodes) << else_node)
|
215
|
-
])
|
216
|
-
end
|
217
|
-
|
168
|
+
alias on_resbody process_regular_node
|
169
|
+
alias on_rescue process_regular_node
|
218
170
|
alias on_ensure process_regular_node
|
219
171
|
|
220
172
|
alias on_begin process_regular_node
|
@@ -616,6 +616,28 @@ module Parser
|
|
616
616
|
source_map)
|
617
617
|
end
|
618
618
|
|
619
|
+
def match_op(receiver, match_t, arg)
|
620
|
+
source_map = send_binary_op_map(receiver, match_t, arg)
|
621
|
+
|
622
|
+
if receiver.type == :regexp &&
|
623
|
+
receiver.children.count == 2 &&
|
624
|
+
receiver.children.first.type == :str
|
625
|
+
|
626
|
+
regexp_str, _regopt = *receiver
|
627
|
+
regexp_body, = *regexp_str
|
628
|
+
|
629
|
+
Regexp.new(regexp_body).names.each do |name|
|
630
|
+
@parser.static_env.declare(name)
|
631
|
+
end
|
632
|
+
|
633
|
+
n(:match_with_lvasgn, [ receiver, arg ],
|
634
|
+
source_map)
|
635
|
+
else
|
636
|
+
n(:send, [ receiver, :=~, arg ],
|
637
|
+
source_map)
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
619
641
|
def unary_op(op_t, receiver)
|
620
642
|
case value(op_t)
|
621
643
|
when '+', '-'
|
@@ -628,14 +650,17 @@ module Parser
|
|
628
650
|
send_unary_op_map(op_t, receiver))
|
629
651
|
end
|
630
652
|
|
631
|
-
def not_op(not_t, receiver=nil)
|
653
|
+
def not_op(not_t, begin_t=nil, receiver=nil, end_t=nil)
|
632
654
|
if @parser.version == 18
|
633
655
|
n(:not, [ receiver ],
|
634
656
|
unary_op_map(not_t, receiver))
|
635
657
|
else
|
636
658
|
if receiver.nil?
|
637
|
-
|
638
|
-
|
659
|
+
nil_node = n0(:begin, collection_map(begin_t, nil, end_t))
|
660
|
+
|
661
|
+
n(:send, [
|
662
|
+
nil_node, :'!'
|
663
|
+
], send_unary_op_map(not_t, nil_node))
|
639
664
|
else
|
640
665
|
n(:send, [ receiver, :'!' ],
|
641
666
|
send_unary_op_map(not_t, receiver))
|
@@ -650,7 +675,7 @@ module Parser
|
|
650
675
|
# Logical operations: and, or
|
651
676
|
|
652
677
|
def logical_op(type, lhs, op_t, rhs)
|
653
|
-
n(type, [
|
678
|
+
n(type, [ lhs, rhs ],
|
654
679
|
binary_op_map(lhs, op_t, rhs))
|
655
680
|
end
|
656
681
|
|
@@ -765,10 +790,10 @@ module Parser
|
|
765
790
|
|
766
791
|
def compstmt(statements)
|
767
792
|
case
|
793
|
+
when statements.none?
|
794
|
+
nil
|
768
795
|
when statements.one?
|
769
796
|
statements.first
|
770
|
-
when statements.none?
|
771
|
-
n0(:nil, expr_map(nil))
|
772
797
|
else
|
773
798
|
n(:begin, statements,
|
774
799
|
collection_map(nil, statements, nil))
|
@@ -776,11 +801,10 @@ module Parser
|
|
776
801
|
end
|
777
802
|
|
778
803
|
def begin(begin_t, body, end_t)
|
779
|
-
if body.nil?
|
780
|
-
# A nil expression
|
781
|
-
|
782
|
-
|
783
|
-
expr_map(loc(begin_t).join(loc(end_t))))
|
804
|
+
if body.nil?
|
805
|
+
# A nil expression: `()' or `begin end'.
|
806
|
+
n0(:begin,
|
807
|
+
collection_map(begin_t, nil, end_t))
|
784
808
|
elsif body.type == :mlhs ||
|
785
809
|
(body.type == :begin &&
|
786
810
|
body.loc.begin.nil? && body.loc.end.nil?)
|
@@ -794,6 +818,8 @@ module Parser
|
|
794
818
|
end
|
795
819
|
end
|
796
820
|
|
821
|
+
alias :begin_keyword :begin
|
822
|
+
|
797
823
|
private
|
798
824
|
|
799
825
|
#
|
@@ -801,14 +827,37 @@ module Parser
|
|
801
827
|
#
|
802
828
|
|
803
829
|
def check_condition(cond)
|
804
|
-
|
830
|
+
case cond.type
|
831
|
+
when :masgn
|
805
832
|
diagnostic :error, ERRORS[:masgn_as_condition],
|
806
833
|
cond.loc.expression
|
807
|
-
elsif cond.type == :begin
|
808
|
-
check_condition(cond.children.last)
|
809
|
-
end
|
810
834
|
|
811
|
-
|
835
|
+
when :begin
|
836
|
+
if cond.children.count == 1
|
837
|
+
check_condition(cond.children.last)
|
838
|
+
else
|
839
|
+
cond
|
840
|
+
end
|
841
|
+
|
842
|
+
when :and, :or, :irange, :erange
|
843
|
+
lhs, rhs = *cond
|
844
|
+
|
845
|
+
type = case cond.type
|
846
|
+
when :irange; :iflipflop
|
847
|
+
when :erange; :eflipflop
|
848
|
+
end
|
849
|
+
|
850
|
+
cond.updated(type, [
|
851
|
+
check_condition(lhs),
|
852
|
+
check_condition(rhs)
|
853
|
+
])
|
854
|
+
|
855
|
+
when :regexp
|
856
|
+
n(:match_current_line, [ cond ], nil)
|
857
|
+
|
858
|
+
else
|
859
|
+
cond
|
860
|
+
end
|
812
861
|
end
|
813
862
|
|
814
863
|
def check_duplicate_args(args, map={})
|
@@ -1074,7 +1123,7 @@ module Parser
|
|
1074
1123
|
|
1075
1124
|
if end_t
|
1076
1125
|
end_l = loc(end_t)
|
1077
|
-
elsif args.any? && !
|
1126
|
+
elsif args.any? && !args.last.nil?
|
1078
1127
|
end_l = args.last.loc.expression
|
1079
1128
|
elsif args.any? && args.count > 1
|
1080
1129
|
end_l = args[-2].loc.expression
|
@@ -1098,7 +1147,7 @@ module Parser
|
|
1098
1147
|
end_l = else_e.loc.expression
|
1099
1148
|
elsif loc(else_t)
|
1100
1149
|
end_l = loc(else_t)
|
1101
|
-
elsif body_e.loc.expression
|
1150
|
+
elsif body_e && body_e.loc.expression
|
1102
1151
|
end_l = body_e.loc.expression
|
1103
1152
|
elsif loc(begin_t)
|
1104
1153
|
end_l = loc(begin_t)
|
@@ -1125,7 +1174,8 @@ module Parser
|
|
1125
1174
|
def rescue_body_map(keyword_t, exc_list_e, assoc_t,
|
1126
1175
|
exc_var_e, then_t,
|
1127
1176
|
compstmt_e)
|
1128
|
-
end_l = compstmt_e.loc.expression
|
1177
|
+
end_l = compstmt_e.loc.expression if compstmt_e
|
1178
|
+
end_l = loc(then_t) if end_l.nil? && then_t
|
1129
1179
|
end_l = exc_var_e.loc.expression if end_l.nil? && exc_var_e
|
1130
1180
|
end_l = exc_list_e.loc.expression if end_l.nil? && exc_list_e
|
1131
1181
|
end_l = loc(keyword_t) if end_l.nil?
|
@@ -1136,7 +1186,7 @@ module Parser
|
|
1136
1186
|
|
1137
1187
|
def eh_keyword_map(compstmt_e, keyword_t, body_es,
|
1138
1188
|
else_t, else_e)
|
1139
|
-
if
|
1189
|
+
if compstmt_e.nil?
|
1140
1190
|
if keyword_t.nil?
|
1141
1191
|
begin_l = body_es.first.loc.expression
|
1142
1192
|
else
|
@@ -1148,7 +1198,7 @@ module Parser
|
|
1148
1198
|
|
1149
1199
|
if else_t
|
1150
1200
|
end_l = else_e.loc.expression
|
1151
|
-
elsif !
|
1201
|
+
elsif !body_es.last.nil?
|
1152
1202
|
end_l = body_es.last.loc.expression
|
1153
1203
|
else
|
1154
1204
|
end_l = loc(keyword_t)
|
@@ -1167,10 +1217,6 @@ module Parser
|
|
1167
1217
|
[:str, :dstr].include?(parts.first.type)
|
1168
1218
|
end
|
1169
1219
|
|
1170
|
-
def synthesized_nil?(node)
|
1171
|
-
node.type == :nil && node.loc.expression.nil?
|
1172
|
-
end
|
1173
|
-
|
1174
1220
|
def value(token)
|
1175
1221
|
token[0]
|
1176
1222
|
end
|