parser 0.9.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/AST_FORMAT.md +19 -9
- data/README.md +5 -5
- data/TODO.md +3 -14
- data/bin/parse +1 -1
- data/lib/parser/base.rb +14 -5
- data/lib/parser/builders/default.rb +32 -12
- data/lib/parser/lexer.rl +9 -12
- data/lib/parser/ruby18.y +10 -10
- data/lib/parser/ruby19.y +16 -10
- data/lib/parser/ruby20.y +172 -44
- data/parser.gemspec +1 -1
- data/test/test_lexer.rb +3 -3
- data/test/test_parser.rb +234 -70
- metadata +2 -3
- data/parse.y.diff +0 -12201
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e0c9d9727b2d7da39af4c37f2fa324be928ece6
|
4
|
+
data.tar.gz: 5a9dc8e99c54aad863aeae920641064af6aa57ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4086430fbdc0d756d3d5c6b54501126793b03080a3657f64cd7889637ce73f6f38a36256c0dbee200a8204fe57743703c0407933e11993b875fa3742c01e440a
|
7
|
+
data.tar.gz: 1fc63b05dd53df335802bc7cd393685303f0eb5e73e895f391c6a6c26306832a22fd1a7b61d2abf9b6b94731e876655fd1fdde1dafac0e97a544ae128ab0a63e
|
data/AST_FORMAT.md
CHANGED
@@ -718,7 +718,7 @@ Format:
|
|
718
718
|
|
719
719
|
Format:
|
720
720
|
```
|
721
|
-
(
|
721
|
+
(restarg :foo)
|
722
722
|
"*foo"
|
723
723
|
~~~~ expression
|
724
724
|
~~~ name
|
@@ -730,7 +730,7 @@ Begin of the `expression` points to `*`.
|
|
730
730
|
|
731
731
|
Format:
|
732
732
|
```
|
733
|
-
(
|
733
|
+
(restarg)
|
734
734
|
"*"
|
735
735
|
^ expression
|
736
736
|
```
|
@@ -747,7 +747,7 @@ Format:
|
|
747
747
|
|
748
748
|
Begin of the `expression` points to `&`.
|
749
749
|
|
750
|
-
###
|
750
|
+
### Expression arguments
|
751
751
|
|
752
752
|
Ruby 1.8 allows to use arbitrary expressions as block arguments,
|
753
753
|
such as `@var` or `foo.bar`. Such expressions should be treated as
|
@@ -761,14 +761,14 @@ Format:
|
|
761
761
|
(args (arg_expr (send (send nil :foo) :a=)))
|
762
762
|
"|foo.a|"
|
763
763
|
|
764
|
-
(args (
|
764
|
+
(args (restarg_expr (ivasgn :@bar)))
|
765
765
|
"|*@bar|"
|
766
766
|
|
767
767
|
(args (blockarg_expr (ivasgn :@bar)))
|
768
768
|
"|&@bar|"
|
769
769
|
```
|
770
770
|
|
771
|
-
###
|
771
|
+
### Block shadow arguments
|
772
772
|
|
773
773
|
Format:
|
774
774
|
```
|
@@ -780,13 +780,23 @@ Format:
|
|
780
780
|
|
781
781
|
Format:
|
782
782
|
```
|
783
|
-
(def :f (args (arg :a) (mlhs (arg :foo) (
|
783
|
+
(def :f (args (arg :a) (mlhs (arg :foo) (restarg :bar))))
|
784
784
|
"def f(a, (foo, *bar)); end"
|
785
785
|
^ begin ^ end
|
786
786
|
~~~~~~~~~~~ expression
|
787
787
|
```
|
788
788
|
|
789
|
-
###
|
789
|
+
### Required keyword argument
|
790
|
+
|
791
|
+
Format:
|
792
|
+
```
|
793
|
+
(kwarg :foo (int 1))
|
794
|
+
"foo:"
|
795
|
+
~~~~ expression
|
796
|
+
~~~~ name
|
797
|
+
```
|
798
|
+
|
799
|
+
### Optional keyword argument
|
790
800
|
|
791
801
|
Format:
|
792
802
|
```
|
@@ -800,7 +810,7 @@ Format:
|
|
800
810
|
|
801
811
|
Format:
|
802
812
|
```
|
803
|
-
(
|
813
|
+
(kwrestarg :foo)
|
804
814
|
"**foo"
|
805
815
|
~~~~~ expression
|
806
816
|
~~~ name
|
@@ -810,7 +820,7 @@ Format:
|
|
810
820
|
|
811
821
|
Format:
|
812
822
|
```
|
813
|
-
(
|
823
|
+
(kwrestarg)
|
814
824
|
"**"
|
815
825
|
~~ expression
|
816
826
|
```
|
data/README.md
CHANGED
@@ -14,9 +14,9 @@ _Parser_ is a Ruby parser written in pure Ruby.
|
|
14
14
|
|
15
15
|
Parse a chunk of code:
|
16
16
|
``` ruby
|
17
|
-
require 'parser/
|
17
|
+
require 'parser/ruby20'
|
18
18
|
|
19
|
-
p Parser::
|
19
|
+
p Parser::Ruby20.parse("2 + 2")
|
20
20
|
# (send
|
21
21
|
# (int 2) :+
|
22
22
|
# (int 2))
|
@@ -24,7 +24,7 @@ p Parser::Ruby19.parse("2 + 2")
|
|
24
24
|
|
25
25
|
Parse a chunk of code and display all diagnostics:
|
26
26
|
``` ruby
|
27
|
-
parser = Parser::
|
27
|
+
parser = Parser::Ruby20.new
|
28
28
|
parser.diagnostics.consumer = lambda do |diag|
|
29
29
|
puts diag.render
|
30
30
|
end
|
@@ -43,10 +43,10 @@ p parser.parse(buffer)
|
|
43
43
|
|
44
44
|
## Features
|
45
45
|
|
46
|
-
* Precise source location reporting.
|
46
|
+
* Precise source location reporting (WIP, no, not really yet).
|
47
47
|
* [Documented](AST_FORMAT.md) AST format which is convenient to work with.
|
48
48
|
* A simple interface and a powerful, tweakable one.
|
49
|
-
* Parses 1.8, 1.9 and 2.0 syntax with backwards-compatible AST formats
|
49
|
+
* Parses 1.8, 1.9 and 2.0 syntax with backwards-compatible AST formats.
|
50
50
|
* Parsing error recovery.
|
51
51
|
* Improved [clang-like][] diagnostic messages with location information.
|
52
52
|
* Written in pure Ruby, runs on MRI 1.8.7 or >=1.9.2, JRuby and Rubinius in 1.8 and 1.9 mode.
|
data/TODO.md
CHANGED
@@ -1,19 +1,8 @@
|
|
1
|
-
# 2.0
|
2
|
-
|
3
|
-
1. test for "** interpreted as argument prefix" diagnostic
|
4
|
-
6. https://github.com/ruby/ruby/commit/c46bda
|
5
|
-
7. https://github.com/ruby/ruby/commit/1ab3974b0efea5155da005ec08a1feee90023d98
|
6
|
-
9. https://github.com/ruby/ruby/commit/d6a977f667f9d824cfe95976f3afc31e55580edb
|
7
|
-
10. https://github.com/ruby/ruby/commit/8fe3fb4c0f69535b302e124f3afc58dce4be5dbb
|
8
|
-
11. https://github.com/ruby/ruby/commit/3380974143d3fdf1721d9e28d6b2d42036f03bd2
|
9
|
-
|
10
1
|
# 2.1
|
11
2
|
|
12
|
-
1. https://github.com/ruby/ruby/commit/
|
13
|
-
2. https://github.com/ruby/ruby/commit/
|
14
|
-
3. https://github.com/ruby/ruby/commit/
|
15
|
-
4. https://github.com/ruby/ruby/commit/c07d78eb0e8e9d3a8f9e8c860b362964157ff43a
|
16
|
-
5. https://github.com/ruby/ruby/commit/34a95669dad8843e3e9a4af683682ab2f50856dd
|
3
|
+
1. https://github.com/ruby/ruby/commit/34a95669dad8843e3e9a4af683682ab2f50856dd
|
4
|
+
2. https://github.com/ruby/ruby/commit/c07d78eb0e8e9d3a8f9e8c860b362964157ff43a
|
5
|
+
3. https://github.com/ruby/ruby/commit/7ea675732ac1dac72f07756498706678d8725719
|
17
6
|
|
18
7
|
# All versions
|
19
8
|
|
data/bin/parse
CHANGED
data/lib/parser/base.rb
CHANGED
@@ -76,19 +76,28 @@ module Parser
|
|
76
76
|
|
77
77
|
protected
|
78
78
|
|
79
|
+
def next_token
|
80
|
+
@lexer.advance
|
81
|
+
end
|
82
|
+
|
79
83
|
def value_expr(v)
|
80
84
|
#p 'value_expr', v
|
81
85
|
v
|
82
86
|
end
|
83
87
|
|
84
|
-
def
|
85
|
-
|
88
|
+
def check_kwarg_name(name_t)
|
89
|
+
case name_t[0]
|
90
|
+
when /^[a-z_]/
|
91
|
+
# OK
|
92
|
+
when /^[A-Z]/
|
93
|
+
diagnostic :error, :argument_const, name_t
|
94
|
+
end
|
86
95
|
end
|
87
96
|
|
88
|
-
def diagnostic(level, kind,
|
89
|
-
_, location =
|
97
|
+
def diagnostic(level, kind, location_t, highlights_ts=[])
|
98
|
+
_, location = location_t
|
90
99
|
|
91
|
-
highlights =
|
100
|
+
highlights = highlights_ts.map do |token|
|
92
101
|
_, range = token
|
93
102
|
range
|
94
103
|
end
|
@@ -142,6 +142,10 @@ module Parser
|
|
142
142
|
s(:hash, *pairs)
|
143
143
|
end
|
144
144
|
|
145
|
+
def kwsplat(dstar_t, arg)
|
146
|
+
s(:kwsplat, arg)
|
147
|
+
end
|
148
|
+
|
145
149
|
# Ranges
|
146
150
|
|
147
151
|
def range_inclusive(lhs, token, rhs)
|
@@ -392,19 +396,35 @@ module Parser
|
|
392
396
|
s(:args, *args)
|
393
397
|
end
|
394
398
|
|
395
|
-
def arg(
|
396
|
-
t(
|
399
|
+
def arg(name_t)
|
400
|
+
t(name_t, :arg, value(name_t).to_sym)
|
401
|
+
end
|
402
|
+
|
403
|
+
def optarg(name_t, eql_t, value)
|
404
|
+
s(:optarg, value(name_t).to_sym, value)
|
405
|
+
end
|
406
|
+
|
407
|
+
def restarg(star_t, name_t=nil)
|
408
|
+
if name_t
|
409
|
+
s(:restarg, value(name_t).to_sym)
|
410
|
+
else
|
411
|
+
t(star_t, :restarg)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
def kwarg(name_t)
|
416
|
+
s(:kwarg, value(name_t).to_sym)
|
397
417
|
end
|
398
418
|
|
399
|
-
def
|
400
|
-
s(:
|
419
|
+
def kwoptarg(name_t, value)
|
420
|
+
s(:kwoptarg, value(name_t).to_sym, value)
|
401
421
|
end
|
402
422
|
|
403
|
-
def
|
404
|
-
if
|
405
|
-
s(:
|
423
|
+
def kwrestarg(dstar_t, name_t=nil)
|
424
|
+
if name_t
|
425
|
+
s(:kwrestarg, value(name_t).to_sym)
|
406
426
|
else
|
407
|
-
t(
|
427
|
+
t(dstar_t, :kwrestarg)
|
408
428
|
end
|
409
429
|
end
|
410
430
|
|
@@ -426,13 +446,13 @@ module Parser
|
|
426
446
|
end
|
427
447
|
end
|
428
448
|
|
429
|
-
def
|
449
|
+
def restarg_expr(star_t, expr=nil)
|
430
450
|
if expr.nil?
|
431
|
-
t(star_t, :
|
451
|
+
t(star_t, :restarg)
|
432
452
|
elsif expr.type == :lvasgn
|
433
|
-
expr.updated(:
|
453
|
+
expr.updated(:restarg)
|
434
454
|
else
|
435
|
-
s(:
|
455
|
+
s(:restarg_expr, expr)
|
436
456
|
end
|
437
457
|
end
|
438
458
|
|
data/lib/parser/lexer.rl
CHANGED
@@ -917,7 +917,7 @@ class Parser::Lexer
|
|
917
917
|
'::' %{ tm = p - 2 } # A::B A :: B
|
918
918
|
;
|
919
919
|
|
920
|
-
# Resolving kDO/kDO_COND/kDO_BLOCK ambiguity requires
|
920
|
+
# Resolving kDO/kDO_COND/kDO_BLOCK ambiguity requires embedding
|
921
921
|
# @cond/@cmdarg-related code to e_lbrack, e_lparen and e_lbrace.
|
922
922
|
|
923
923
|
e_lbrack = '[' % {
|
@@ -991,14 +991,10 @@ class Parser::Lexer
|
|
991
991
|
=> { emit(KEYWORDS[tok]);
|
992
992
|
fnext expr_end; fbreak; };
|
993
993
|
|
994
|
-
bareword
|
994
|
+
bareword [?=!]?
|
995
995
|
=> { emit(:tIDENTIFIER)
|
996
996
|
fnext expr_end; fbreak; };
|
997
997
|
|
998
|
-
bareword ambiguous_ident_suffix
|
999
|
-
=> { emit(:tIDENTIFIER, tok(@ts, tm), @ts, tm)
|
1000
|
-
fnext expr_end; p = tm - 1; fbreak; };
|
1001
|
-
|
1002
998
|
operator_fname |
|
1003
999
|
operator_arithmetic |
|
1004
1000
|
operator_rest
|
@@ -1114,25 +1110,26 @@ class Parser::Lexer
|
|
1114
1110
|
)
|
1115
1111
|
=> { fhold; fhold; fgoto expr_beg; };
|
1116
1112
|
|
1117
|
-
# x
|
1118
|
-
# Ambiguous
|
1119
|
-
c_space+
|
1113
|
+
# x /1
|
1114
|
+
# Ambiguous regexp literal.
|
1115
|
+
c_space+ '/'
|
1120
1116
|
=> {
|
1121
1117
|
diagnostic :warning, Parser::ERRORS[:ambiguous_literal],
|
1122
1118
|
range(@te - 1, @te)
|
1123
1119
|
|
1124
|
-
fhold;
|
1120
|
+
fhold; fgoto expr_beg;
|
1125
1121
|
};
|
1126
1122
|
|
1127
1123
|
# x *1
|
1128
1124
|
# Ambiguous splat, kwsplat or block-pass.
|
1129
|
-
c_space+ %{ tm = p } ( '*' | '&' | '**' )
|
1125
|
+
c_space+ %{ tm = p } ( '+' | '-' | '*' | '&' | '**' )
|
1130
1126
|
=> {
|
1131
1127
|
message = Parser::ERRORS[:ambiguous_prefix] % { :prefix => tok(tm, @te) }
|
1132
1128
|
diagnostic :warning, message,
|
1133
1129
|
range(tm, @te)
|
1134
1130
|
|
1135
|
-
|
1131
|
+
p = tm - 1
|
1132
|
+
fgoto expr_beg;
|
1136
1133
|
};
|
1137
1134
|
|
1138
1135
|
# x ::Foo
|
data/lib/parser/ruby18.y
CHANGED
@@ -1294,42 +1294,42 @@ rule
|
|
1294
1294
|
| block_par tCOMMA tSTAR lhs tCOMMA tAMPER lhs
|
1295
1295
|
{
|
1296
1296
|
result = val[0].
|
1297
|
-
push(@builder.
|
1297
|
+
push(@builder.restarg_expr(val[2], val[3])).
|
1298
1298
|
push(@builder.blockarg_expr(val[5], val[6]))
|
1299
1299
|
}
|
1300
1300
|
| block_par tCOMMA tSTAR tCOMMA tAMPER lhs
|
1301
1301
|
{
|
1302
1302
|
result = val[0].
|
1303
|
-
push(@builder.
|
1303
|
+
push(@builder.restarg_expr(val[2])).
|
1304
1304
|
push(@builder.blockarg_expr(val[4], val[5]))
|
1305
1305
|
}
|
1306
1306
|
| block_par tCOMMA tSTAR lhs
|
1307
1307
|
{
|
1308
1308
|
result = val[0].
|
1309
|
-
push(@builder.
|
1309
|
+
push(@builder.restarg_expr(val[2], val[3]))
|
1310
1310
|
}
|
1311
1311
|
| block_par tCOMMA tSTAR
|
1312
1312
|
{
|
1313
1313
|
result = val[0].
|
1314
|
-
push(@builder.
|
1314
|
+
push(@builder.restarg_expr(val[2]))
|
1315
1315
|
}
|
1316
1316
|
| tSTAR lhs tCOMMA tAMPER lhs
|
1317
1317
|
{
|
1318
|
-
result = [ @builder.
|
1318
|
+
result = [ @builder.restarg_expr(val[0], val[1]),
|
1319
1319
|
@builder.blockarg_expr(val[3], val[4]) ]
|
1320
1320
|
}
|
1321
1321
|
| tSTAR tCOMMA tAMPER lhs
|
1322
1322
|
{
|
1323
|
-
result = [ @builder.
|
1323
|
+
result = [ @builder.restarg_expr(val[0]),
|
1324
1324
|
@builder.blockarg_expr(val[2], val[3]) ]
|
1325
1325
|
}
|
1326
1326
|
| tSTAR lhs
|
1327
1327
|
{
|
1328
|
-
result = [ @builder.
|
1328
|
+
result = [ @builder.restarg_expr(val[0], val[1]) ]
|
1329
1329
|
}
|
1330
1330
|
| tSTAR
|
1331
1331
|
{
|
1332
|
-
result = [ @builder.
|
1332
|
+
result = [ @builder.restarg_expr(val[0]) ]
|
1333
1333
|
}
|
1334
1334
|
| tAMPER lhs
|
1335
1335
|
{
|
@@ -1850,11 +1850,11 @@ xstring_contents: # nothing
|
|
1850
1850
|
{
|
1851
1851
|
@static_env.declare val[1][0]
|
1852
1852
|
|
1853
|
-
result = [ @builder.
|
1853
|
+
result = [ @builder.restarg(val[0], val[1]) ]
|
1854
1854
|
}
|
1855
1855
|
| restarg_mark
|
1856
1856
|
{
|
1857
|
-
result = [ @builder.
|
1857
|
+
result = [ @builder.restarg(val[0]) ]
|
1858
1858
|
}
|
1859
1859
|
|
1860
1860
|
blkarg_mark: tAMPER2 | tAMPER
|
data/lib/parser/ruby19.y
CHANGED
@@ -1260,47 +1260,47 @@ rule
|
|
1260
1260
|
@static_env.declare val[3][0]
|
1261
1261
|
|
1262
1262
|
result = val[0].
|
1263
|
-
push(@builder.
|
1263
|
+
push(@builder.restarg(val[2], val[3]))
|
1264
1264
|
}
|
1265
1265
|
| f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
|
1266
1266
|
{
|
1267
1267
|
@static_env.declare val[3][0]
|
1268
1268
|
|
1269
1269
|
result = val[0].
|
1270
|
-
push(@builder.
|
1270
|
+
push(@builder.restarg(val[2], val[3])).
|
1271
1271
|
concat(val[5])
|
1272
1272
|
}
|
1273
1273
|
| f_marg_list tCOMMA tSTAR
|
1274
1274
|
{
|
1275
1275
|
result = val[0].
|
1276
|
-
push(@builder.
|
1276
|
+
push(@builder.restarg(val[2]))
|
1277
1277
|
}
|
1278
1278
|
| f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
|
1279
1279
|
{
|
1280
1280
|
result = val[0].
|
1281
|
-
push(@builder.
|
1281
|
+
push(@builder.restarg(val[2])).
|
1282
1282
|
concat(val[4])
|
1283
1283
|
}
|
1284
1284
|
| tSTAR f_norm_arg
|
1285
1285
|
{
|
1286
1286
|
@static_env.declare val[1][0]
|
1287
1287
|
|
1288
|
-
result = [ @builder.
|
1288
|
+
result = [ @builder.restarg(val[0], val[1]) ]
|
1289
1289
|
}
|
1290
1290
|
| tSTAR f_norm_arg tCOMMA f_marg_list
|
1291
1291
|
{
|
1292
1292
|
@static_env.declare val[1][0]
|
1293
1293
|
|
1294
|
-
result = [ @builder.
|
1294
|
+
result = [ @builder.restarg(val[0], val[1]),
|
1295
1295
|
*val[3] ]
|
1296
1296
|
}
|
1297
1297
|
| tSTAR
|
1298
1298
|
{
|
1299
|
-
result = [ @builder.
|
1299
|
+
result = [ @builder.restarg(val[0]) ]
|
1300
1300
|
}
|
1301
1301
|
| tSTAR tCOMMA f_marg_list
|
1302
1302
|
{
|
1303
|
-
result = [ @builder.
|
1303
|
+
result = [ @builder.restarg(val[0]),
|
1304
1304
|
*val[2] ]
|
1305
1305
|
}
|
1306
1306
|
|
@@ -2046,11 +2046,11 @@ keyword_variable: kNIL
|
|
2046
2046
|
{
|
2047
2047
|
@static_env.declare val[1][0]
|
2048
2048
|
|
2049
|
-
result = [ @builder.
|
2049
|
+
result = [ @builder.restarg(val[0], val[1]) ]
|
2050
2050
|
}
|
2051
2051
|
| restarg_mark
|
2052
2052
|
{
|
2053
|
-
result = [ @builder.
|
2053
|
+
result = [ @builder.restarg(val[0]) ]
|
2054
2054
|
}
|
2055
2055
|
|
2056
2056
|
blkarg_mark: tAMPER2 | tAMPER
|
@@ -2110,7 +2110,13 @@ keyword_variable: kNIL
|
|
2110
2110
|
opt_terms: | terms
|
2111
2111
|
opt_nl: | tNL
|
2112
2112
|
rparen: opt_nl tRPAREN
|
2113
|
+
{
|
2114
|
+
result = val[1]
|
2115
|
+
}
|
2113
2116
|
rbracket: opt_nl tRBRACK
|
2117
|
+
{
|
2118
|
+
result = val[1]
|
2119
|
+
}
|
2114
2120
|
trailer: | tNL | tCOMMA
|
2115
2121
|
|
2116
2122
|
term: tSEMI
|