parser 0.9.2 → 1.0.0
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/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
|