parser 2.0.0.beta5 → 2.0.0.beta6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef56ab825b77544fdfbc486ccb592cede5bd7da3
4
- data.tar.gz: 30dcf6e9bd3566babf73ba48b026cd7521f32f07
3
+ metadata.gz: ff9e3b7f7bacab0b950939c52f7df525def64ecc
4
+ data.tar.gz: 79f7bfdc451009618f190696b9d01ab9fb2a66d4
5
5
  SHA512:
6
- metadata.gz: 4274e893bce829d8736cb57659eae865c76b520903c3175d2b24475e90a2219596572972c179591677d37801b978fd855189df7e4405a30020e6cfa1d74e6193
7
- data.tar.gz: c79fdcbe3ab0b0927773111ee0b5699bf337eb53fd4aad3911bcd1ca2801cd6f8d7d2cbdcc846031dd115bd24c910b383a92ca21c5395d85f8354f6d4c8109a6
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").src
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").src.selector.to_source
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 and ruby_parser compatibility testsuite are derived from [ruby_parser](http://github.com/seattlerb/ruby_parser).
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
+ ~~~
@@ -20,7 +20,7 @@ module Parser
20
20
  def on_var(node)
21
21
  name, = *node
22
22
 
23
- node.updated
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
- value_node = process(value_node) if value_node
41
- node.updated(nil, [ name, value_node ])
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
- scope_node = process(scope_node) if scope_node
71
- node.updated(nil, [ scope_node, name ])
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
- scope_node = process(scope_node) if scope_node
78
- value_node = process(value_node) if value_node
79
- node.updated(nil, [ scope_node, name, value_node ])
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
- value_node = process(value_node) if value_node
88
- node.updated(nil, [ arg_name, value_node ])
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 process_regular_node
108
-
109
- def on_class(node)
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
- def on_if(node)
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
- def on_case(node)
184
- cond_node, *bodies = *node
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
- n(:send, [ n0(:nil, nil), :'!' ],
638
- send_unary_op_map(not_t, nil))
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, [ check_condition(lhs), check_condition(rhs) ],
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? || synthesized_nil?(body)
780
- # A nil expression, or a synthesized (nil) from compstmt
781
- # without any inner statements.
782
- n0(:nil,
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
- if cond.type == :masgn
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
- cond
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? && !synthesized_nil?(args.last)
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 || loc(then_t)
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 synthesized_nil?(compstmt_e)
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 !synthesized_nil?(body_es.last)
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