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 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