regexp_parser 0.4.6 → 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +13 -0
- data/README.md +4 -3
- data/lib/regexp_parser/expression.rb +8 -8
- data/lib/regexp_parser/expression/classes/backref.rb +7 -7
- data/lib/regexp_parser/expression/classes/conditional.rb +2 -2
- data/lib/regexp_parser/expression/classes/group.rb +2 -2
- data/lib/regexp_parser/expression/classes/root.rb +4 -18
- data/lib/regexp_parser/expression/classes/set.rb +1 -1
- data/lib/regexp_parser/expression/subexpression.rb +2 -2
- data/lib/regexp_parser/lexer.rb +10 -6
- data/lib/regexp_parser/parser.rb +202 -172
- data/lib/regexp_parser/scanner.rb +151 -148
- data/lib/regexp_parser/scanner/scanner.rl +44 -41
- data/lib/regexp_parser/syntax/tokens/backref.rb +1 -1
- data/lib/regexp_parser/version.rb +2 -2
- data/test/expression/test_to_h.rb +2 -2
- data/test/lexer/test_refcalls.rb +3 -0
- data/test/parser/test_errors.rb +13 -9
- data/test/parser/test_groups.rb +140 -14
- data/test/parser/test_refcalls.rb +13 -0
- data/test/scanner/test_free_space.rb +43 -0
- data/test/scanner/test_refcalls.rb +3 -0
- data/test/syntax/ruby/test_1.8.rb +1 -1
- metadata +3 -3
@@ -2,15 +2,101 @@
|
|
2
2
|
|
3
3
|
# line 1 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
4
4
|
|
5
|
-
# line
|
5
|
+
# line 771 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
6
6
|
|
7
7
|
|
8
8
|
# THIS IS A GENERATED FILE, DO NOT EDIT DIRECTLY
|
9
9
|
# This file was generated from lib/regexp_parser/scanner/scanner.rl
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
class Regexp::Scanner
|
12
|
+
# General scanner error (catch all)
|
13
|
+
class ScannerError < StandardError; end
|
14
|
+
|
15
|
+
# Base for all scanner validation errors
|
16
|
+
class ValidationError < StandardError
|
17
|
+
def initialize(reason)
|
18
|
+
super reason
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Unexpected end of pattern
|
23
|
+
class PrematureEndError < ScannerError
|
24
|
+
def initialize(where = '')
|
25
|
+
super "Premature end of pattern at #{where}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Invalid sequence format. Used for escape sequences, mainly.
|
30
|
+
class InvalidSequenceError < ValidationError
|
31
|
+
def initialize(what = 'sequence', where = '')
|
32
|
+
super "Invalid #{what} at #{where}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Invalid group. Used for named groups.
|
37
|
+
class InvalidGroupError < ValidationError
|
38
|
+
def initialize(what, reason)
|
39
|
+
super "Invalid #{what}, #{reason}."
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Invalid groupOption. Used for inline options.
|
44
|
+
class InvalidGroupOption < ValidationError
|
45
|
+
def initialize(option, text)
|
46
|
+
super "Invalid group option #{option} in #{text}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Invalid back reference. Used for name a number refs/calls.
|
51
|
+
class InvalidBackrefError < ValidationError
|
52
|
+
def initialize(what, reason)
|
53
|
+
super "Invalid back reference #{what}, #{reason}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# The property name was not recognized by the scanner.
|
58
|
+
class UnknownUnicodePropertyError < ValidationError
|
59
|
+
def initialize(name)
|
60
|
+
super "Unknown unicode character property name #{name}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Scans the given regular expression text, or Regexp object and collects the
|
65
|
+
# emitted token into an array that gets returned at the end. If a block is
|
66
|
+
# given, it gets called for each emitted token.
|
67
|
+
#
|
68
|
+
# This method may raise errors if a syntax error is encountered.
|
69
|
+
# --------------------------------------------------------------------------
|
70
|
+
def self.scan(input_object, &block)
|
71
|
+
new.scan(input_object, &block)
|
72
|
+
end
|
73
|
+
|
74
|
+
def scan(input_object, &block)
|
75
|
+
@literal, top, stack = nil, 0, []
|
76
|
+
|
77
|
+
if input_object.is_a?(Regexp)
|
78
|
+
input = input_object.source
|
79
|
+
@free_spacing = (input_object.options & Regexp::EXTENDED != 0)
|
80
|
+
else
|
81
|
+
input = input_object
|
82
|
+
@free_spacing = false
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
data = input.unpack("c*") if input.is_a?(String)
|
87
|
+
eof = data.length
|
88
|
+
|
89
|
+
@tokens = []
|
90
|
+
@block = block_given? ? block : nil
|
91
|
+
|
92
|
+
@in_group, @group_depth = false, 0
|
93
|
+
@spacing_stack = [{:free_spacing => @free_spacing, :depth => 0}]
|
94
|
+
|
95
|
+
in_set, set_depth, set_type = false, 0, :set
|
96
|
+
in_conditional, conditional_depth, conditional_stack = false, 0, []
|
97
|
+
|
98
|
+
|
99
|
+
# line 99 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner.rb"
|
14
100
|
class << self
|
15
101
|
attr_accessor :_re_scanner_trans_keys
|
16
102
|
private :_re_scanner_trans_keys, :_re_scanner_trans_keys=
|
@@ -1586,92 +1672,9 @@ end
|
|
1586
1672
|
self.re_scanner_en_main = 142;
|
1587
1673
|
|
1588
1674
|
|
1589
|
-
# line
|
1590
|
-
|
1591
|
-
# General scanner error (catch all)
|
1592
|
-
class ScannerError < StandardError; end
|
1593
|
-
|
1594
|
-
# Base for all scanner validation errors
|
1595
|
-
class ValidationError < StandardError
|
1596
|
-
def initialize(reason)
|
1597
|
-
super reason
|
1598
|
-
end
|
1599
|
-
end
|
1600
|
-
|
1601
|
-
# Unexpected end of pattern
|
1602
|
-
class PrematureEndError < ScannerError
|
1603
|
-
def initialize(where = '')
|
1604
|
-
super "Premature end of pattern at #{where}"
|
1605
|
-
end
|
1606
|
-
end
|
1607
|
-
|
1608
|
-
# Invalid sequence format. Used for escape sequences, mainly.
|
1609
|
-
class InvalidSequenceError < ValidationError
|
1610
|
-
def initialize(what = 'sequence', where = '')
|
1611
|
-
super "Invalid #{what} at #{where}"
|
1612
|
-
end
|
1613
|
-
end
|
1614
|
-
|
1615
|
-
# Invalid group. Used for named groups.
|
1616
|
-
class InvalidGroupError < ValidationError
|
1617
|
-
def initialize(what, reason)
|
1618
|
-
super "Invalid #{what}, #{reason}."
|
1619
|
-
end
|
1620
|
-
end
|
1621
|
-
|
1622
|
-
# Invalid groupOption. Used for inline options.
|
1623
|
-
class InvalidGroupOption < ValidationError
|
1624
|
-
def initialize(option, text)
|
1625
|
-
super "Invalid group option #{option} in #{text}"
|
1626
|
-
end
|
1627
|
-
end
|
1628
|
-
|
1629
|
-
# Invalid back reference. Used for name a number refs/calls.
|
1630
|
-
class InvalidBackrefError < ValidationError
|
1631
|
-
def initialize(what, reason)
|
1632
|
-
super "Invalid back reference #{what}, #{reason}"
|
1633
|
-
end
|
1634
|
-
end
|
1635
|
-
|
1636
|
-
# The property name was not recognized by the scanner.
|
1637
|
-
class UnknownUnicodePropertyError < ValidationError
|
1638
|
-
def initialize(name)
|
1639
|
-
super "Unknown unicode character property name #{name}"
|
1640
|
-
end
|
1641
|
-
end
|
1642
|
-
|
1643
|
-
# Scans the given regular expression text, or Regexp object and collects the
|
1644
|
-
# emitted token into an array that gets returned at the end. If a block is
|
1645
|
-
# given, it gets called for each emitted token.
|
1646
|
-
#
|
1647
|
-
# This method may raise errors if a syntax error is encountered.
|
1648
|
-
# --------------------------------------------------------------------------
|
1649
|
-
def self.scan(input_object, &block)
|
1650
|
-
@literal, top, stack = nil, 0, []
|
1651
|
-
|
1652
|
-
if input_object.is_a?(Regexp)
|
1653
|
-
input = input_object.source
|
1654
|
-
@free_spacing = (input_object.options & Regexp::EXTENDED != 0)
|
1655
|
-
else
|
1656
|
-
input = input_object
|
1657
|
-
@free_spacing = false
|
1658
|
-
end
|
1659
|
-
|
1660
|
-
|
1661
|
-
data = input.unpack("c*") if input.is_a?(String)
|
1662
|
-
eof = data.length
|
1663
|
-
|
1664
|
-
@tokens = []
|
1665
|
-
@block = block_given? ? block : nil
|
1666
|
-
|
1667
|
-
@in_group, @group_depth = false, 0
|
1668
|
-
@in_options, @spacing_stack = false, [[@free_spacing, 0]]
|
1669
|
-
|
1670
|
-
in_set, set_depth, set_type = false, 0, :set
|
1671
|
-
in_conditional, conditional_depth, conditional_stack = false, 0, []
|
1672
|
-
|
1675
|
+
# line 864 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
1673
1676
|
|
1674
|
-
# line
|
1677
|
+
# line 1677 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner.rb"
|
1675
1678
|
begin
|
1676
1679
|
p ||= 0
|
1677
1680
|
pe ||= data.length
|
@@ -1682,9 +1685,9 @@ begin
|
|
1682
1685
|
act = 0
|
1683
1686
|
end
|
1684
1687
|
|
1685
|
-
# line
|
1688
|
+
# line 865 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
1686
1689
|
|
1687
|
-
# line
|
1690
|
+
# line 1690 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner.rb"
|
1688
1691
|
begin
|
1689
1692
|
testEof = false
|
1690
1693
|
_slen, _trans, _keys, _inds, _acts, _nacts = nil
|
@@ -1712,7 +1715,7 @@ begin
|
|
1712
1715
|
begin
|
1713
1716
|
ts = p
|
1714
1717
|
end
|
1715
|
-
# line
|
1718
|
+
# line 1718 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner.rb"
|
1716
1719
|
end
|
1717
1720
|
_keys = cs << 1
|
1718
1721
|
_inds = _re_scanner_index_offsets[cs]
|
@@ -3385,7 +3388,7 @@ te = p+1
|
|
3385
3388
|
begin
|
3386
3389
|
te = p+1
|
3387
3390
|
begin
|
3388
|
-
if in_conditional and conditional_stack.length > 0 and
|
3391
|
+
if in_conditional and conditional_stack.length > 0 and
|
3389
3392
|
conditional_stack.last[1] == @group_depth
|
3390
3393
|
emit(:conditional, :separator, *text(data, ts, te))
|
3391
3394
|
else
|
@@ -3547,7 +3550,7 @@ te = p+1
|
|
3547
3550
|
end
|
3548
3551
|
end
|
3549
3552
|
when 13 then
|
3550
|
-
# line
|
3553
|
+
# line 638 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3551
3554
|
begin
|
3552
3555
|
te = p+1
|
3553
3556
|
begin
|
@@ -3619,7 +3622,7 @@ te = p+1
|
|
3619
3622
|
end
|
3620
3623
|
end
|
3621
3624
|
when 58 then
|
3622
|
-
# line
|
3625
|
+
# line 709 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3623
3626
|
begin
|
3624
3627
|
te = p+1
|
3625
3628
|
begin
|
@@ -3631,7 +3634,7 @@ te = p+1
|
|
3631
3634
|
end
|
3632
3635
|
end
|
3633
3636
|
when 54 then
|
3634
|
-
# line
|
3637
|
+
# line 717 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3635
3638
|
begin
|
3636
3639
|
te = p+1
|
3637
3640
|
begin
|
@@ -3643,7 +3646,7 @@ te = p+1
|
|
3643
3646
|
end
|
3644
3647
|
end
|
3645
3648
|
when 56 then
|
3646
|
-
# line
|
3649
|
+
# line 725 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3647
3650
|
begin
|
3648
3651
|
te = p+1
|
3649
3652
|
begin
|
@@ -3655,7 +3658,7 @@ te = p+1
|
|
3655
3658
|
end
|
3656
3659
|
end
|
3657
3660
|
when 64 then
|
3658
|
-
# line
|
3661
|
+
# line 733 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3659
3662
|
begin
|
3660
3663
|
te = p+1
|
3661
3664
|
begin
|
@@ -3663,7 +3666,7 @@ te = p+1
|
|
3663
3666
|
end
|
3664
3667
|
end
|
3665
3668
|
when 4 then
|
3666
|
-
# line
|
3669
|
+
# line 743 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3667
3670
|
begin
|
3668
3671
|
te = p+1
|
3669
3672
|
begin
|
@@ -3684,7 +3687,7 @@ p = p - 1; begin
|
|
3684
3687
|
end
|
3685
3688
|
end
|
3686
3689
|
when 57 then
|
3687
|
-
# line
|
3690
|
+
# line 709 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3688
3691
|
begin
|
3689
3692
|
te = p
|
3690
3693
|
p = p - 1; begin
|
@@ -3696,7 +3699,7 @@ p = p - 1; begin
|
|
3696
3699
|
end
|
3697
3700
|
end
|
3698
3701
|
when 53 then
|
3699
|
-
# line
|
3702
|
+
# line 717 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3700
3703
|
begin
|
3701
3704
|
te = p
|
3702
3705
|
p = p - 1; begin
|
@@ -3708,7 +3711,7 @@ p = p - 1; begin
|
|
3708
3711
|
end
|
3709
3712
|
end
|
3710
3713
|
when 55 then
|
3711
|
-
# line
|
3714
|
+
# line 725 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3712
3715
|
begin
|
3713
3716
|
te = p
|
3714
3717
|
p = p - 1; begin
|
@@ -3720,7 +3723,7 @@ p = p - 1; begin
|
|
3720
3723
|
end
|
3721
3724
|
end
|
3722
3725
|
when 63 then
|
3723
|
-
# line
|
3726
|
+
# line 733 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3724
3727
|
begin
|
3725
3728
|
te = p
|
3726
3729
|
p = p - 1; begin
|
@@ -3728,7 +3731,7 @@ p = p - 1; begin
|
|
3728
3731
|
end
|
3729
3732
|
end
|
3730
3733
|
when 59 then
|
3731
|
-
# line
|
3734
|
+
# line 739 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3732
3735
|
begin
|
3733
3736
|
te = p
|
3734
3737
|
p = p - 1; begin
|
@@ -3743,7 +3746,7 @@ p = p - 1; begin
|
|
3743
3746
|
end
|
3744
3747
|
end
|
3745
3748
|
when 50 then
|
3746
|
-
# line
|
3749
|
+
# line 751 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3747
3750
|
begin
|
3748
3751
|
te = p
|
3749
3752
|
p = p - 1; begin
|
@@ -3755,7 +3758,7 @@ p = p - 1; begin
|
|
3755
3758
|
end
|
3756
3759
|
end
|
3757
3760
|
when 49 then
|
3758
|
-
# line
|
3761
|
+
# line 766 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3759
3762
|
begin
|
3760
3763
|
te = p
|
3761
3764
|
p = p - 1; begin
|
@@ -3772,7 +3775,7 @@ p = p - 1; begin
|
|
3772
3775
|
end
|
3773
3776
|
end
|
3774
3777
|
when 12 then
|
3775
|
-
# line
|
3778
|
+
# line 739 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3776
3779
|
begin
|
3777
3780
|
begin p = ((te))-1; end
|
3778
3781
|
begin
|
@@ -3787,7 +3790,7 @@ p = p - 1; begin
|
|
3787
3790
|
end
|
3788
3791
|
end
|
3789
3792
|
when 3 then
|
3790
|
-
# line
|
3793
|
+
# line 766 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
3791
3794
|
begin
|
3792
3795
|
begin p = ((te))-1; end
|
3793
3796
|
begin
|
@@ -4085,14 +4088,10 @@ te = p+1
|
|
4085
4088
|
end
|
4086
4089
|
else
|
4087
4090
|
if @spacing_stack.length > 1 and
|
4088
|
-
@spacing_stack.last[
|
4091
|
+
@spacing_stack.last[:depth] == (@group_depth + 1)
|
4089
4092
|
@spacing_stack.pop
|
4090
4093
|
|
4091
|
-
@free_spacing = @spacing_stack.last[
|
4092
|
-
|
4093
|
-
if @spacing_stack.length == 1
|
4094
|
-
@in_options = false
|
4095
|
-
end
|
4094
|
+
@free_spacing = @spacing_stack.last[:free_spacing]
|
4096
4095
|
end
|
4097
4096
|
|
4098
4097
|
emit(:group, :close, *text(data, ts, te))
|
@@ -4144,10 +4143,10 @@ act = 22; end
|
|
4144
4143
|
begin
|
4145
4144
|
te = p+1
|
4146
4145
|
end
|
4147
|
-
# line
|
4146
|
+
# line 766 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
4148
4147
|
begin
|
4149
4148
|
act = 59; end
|
4150
|
-
# line
|
4149
|
+
# line 4149 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner.rb"
|
4151
4150
|
end
|
4152
4151
|
end
|
4153
4152
|
end
|
@@ -4165,7 +4164,7 @@ ts = nil; end
|
|
4165
4164
|
begin
|
4166
4165
|
act = 0
|
4167
4166
|
end
|
4168
|
-
# line
|
4167
|
+
# line 4167 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner.rb"
|
4169
4168
|
end
|
4170
4169
|
|
4171
4170
|
if cs == 0
|
@@ -4199,7 +4198,7 @@ act = 0
|
|
4199
4198
|
text = ts ? copy(data, ts-1..-1) : data.pack('c*')
|
4200
4199
|
raise PrematureEndError.new( text )
|
4201
4200
|
end
|
4202
|
-
# line
|
4201
|
+
# line 4201 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner.rb"
|
4203
4202
|
end
|
4204
4203
|
end
|
4205
4204
|
|
@@ -4210,7 +4209,7 @@ act = 0
|
|
4210
4209
|
end
|
4211
4210
|
end
|
4212
4211
|
|
4213
|
-
# line
|
4212
|
+
# line 866 "/Users/jannoschmuller/code/regexp_parser/lib/regexp_parser/scanner/scanner.rl"
|
4214
4213
|
|
4215
4214
|
if cs == re_scanner_error
|
4216
4215
|
text = ts ? copy(data, ts-1..-1) : data.pack('c*')
|
@@ -4228,12 +4227,25 @@ end
|
|
4228
4227
|
@tokens
|
4229
4228
|
end
|
4230
4229
|
|
4230
|
+
# Emits an array with the details of the scanned pattern
|
4231
|
+
def emit(type, token, text, ts, te)
|
4232
|
+
#puts "EMIT: type: #{type}, token: #{token}, text: #{text}, ts: #{ts}, te: #{te}"
|
4233
|
+
|
4234
|
+
emit_literal if @literal
|
4235
|
+
|
4236
|
+
if @block
|
4237
|
+
@block.call type, token, text, ts, te
|
4238
|
+
end
|
4239
|
+
|
4240
|
+
@tokens << [type, token, text, ts, te]
|
4241
|
+
end
|
4242
|
+
|
4231
4243
|
private
|
4232
4244
|
|
4233
4245
|
# Ragel's regex-based scan of the group options introduced a lot of
|
4234
4246
|
# ambiguity, so we just ask it to find the beginning of what looks
|
4235
4247
|
# like an options run and handle the rest in here.
|
4236
|
-
def
|
4248
|
+
def scan_options(p, data, ts, te)
|
4237
4249
|
text = text(data, ts, te).first
|
4238
4250
|
|
4239
4251
|
options_char, options_length = true, 0
|
@@ -4285,26 +4297,26 @@ end
|
|
4285
4297
|
end
|
4286
4298
|
|
4287
4299
|
# Copy from ts to te from data as text
|
4288
|
-
def
|
4300
|
+
def copy(data, range)
|
4289
4301
|
data[range].pack('c*')
|
4290
4302
|
end
|
4291
4303
|
|
4292
4304
|
# Copy from ts to te from data as text, returning an array with the text
|
4293
4305
|
# and the offsets used to copy it.
|
4294
|
-
def
|
4306
|
+
def text(data, ts, te, soff = 0)
|
4295
4307
|
[copy(data, ts-soff..te-1), ts-soff, te]
|
4296
4308
|
end
|
4297
4309
|
|
4298
4310
|
# Appends one or more characters to the literal buffer, to be emitted later
|
4299
4311
|
# by a call to emit_literal. Contents can be a mix of ASCII and UTF-8.
|
4300
|
-
def
|
4312
|
+
def append_literal(data, ts, te)
|
4301
4313
|
@literal ||= []
|
4302
4314
|
@literal << text(data, ts, te)
|
4303
4315
|
end
|
4304
4316
|
|
4305
4317
|
# Emits the literal run collected by calls to the append_literal method,
|
4306
4318
|
# using the total start (ts) and end (te) offsets of the run.
|
4307
|
-
def
|
4319
|
+
def emit_literal
|
4308
4320
|
ts, te = @literal.first[1], @literal.last[2]
|
4309
4321
|
text = @literal.map {|t| t[0]}.join
|
4310
4322
|
|
@@ -4314,43 +4326,34 @@ end
|
|
4314
4326
|
emit(:literal, :literal, text, ts, te)
|
4315
4327
|
end
|
4316
4328
|
|
4317
|
-
def
|
4318
|
-
if text =~ /\(\?([mixdau]
|
4319
|
-
positive, negative = $1, $2
|
4329
|
+
def emit_options(text, ts, te)
|
4330
|
+
if text =~ /\(\?([mixdau]*)-?([mix]*)(:)?/
|
4331
|
+
positive, negative, group_local = $1, $2, $3
|
4320
4332
|
|
4321
|
-
if positive
|
4333
|
+
if positive.include?('x')
|
4322
4334
|
@free_spacing = true
|
4323
4335
|
end
|
4324
4336
|
|
4325
4337
|
# If the x appears in both, treat it like ruby does, the second cancels
|
4326
4338
|
# the first.
|
4327
|
-
if negative
|
4339
|
+
if negative.include?('x')
|
4328
4340
|
@free_spacing = false
|
4329
4341
|
end
|
4330
|
-
end
|
4331
4342
|
|
4332
|
-
|
4333
|
-
|
4334
|
-
|
4335
|
-
|
4336
|
-
|
4337
|
-
|
4338
|
-
# Emits an array with the details of the scanned pattern
|
4339
|
-
def self.emit(type, token, text, ts, te)
|
4340
|
-
#puts "EMIT: type: #{type}, token: #{token}, text: #{text}, ts: #{ts}, te: #{te}"
|
4341
|
-
|
4342
|
-
emit_literal if @literal
|
4343
|
-
|
4344
|
-
if @block
|
4345
|
-
@block.call type, token, text, ts, te
|
4343
|
+
if group_local
|
4344
|
+
@spacing_stack << {:free_spacing => @free_spacing, :depth => @group_depth}
|
4345
|
+
else
|
4346
|
+
# switch for parent group level
|
4347
|
+
@spacing_stack.last[:free_spacing] = @free_spacing
|
4348
|
+
end
|
4346
4349
|
end
|
4347
4350
|
|
4348
|
-
|
4351
|
+
emit(:group, :options, text, ts, te)
|
4349
4352
|
end
|
4350
4353
|
|
4351
4354
|
# Centralizes and unifies the handling of validation related
|
4352
4355
|
# errors.
|
4353
|
-
def
|
4356
|
+
def validation_error(type, what, reason)
|
4354
4357
|
case type
|
4355
4358
|
when :group
|
4356
4359
|
error = InvalidGroupError.new(what, reason)
|
@@ -4366,12 +4369,12 @@ end
|
|
4366
4369
|
end
|
4367
4370
|
|
4368
4371
|
# Used for references with an empty name or number
|
4369
|
-
def
|
4372
|
+
def empty_backref_error(type, what)
|
4370
4373
|
validation_error(:backref, what, 'ref ID is empty')
|
4371
4374
|
end
|
4372
4375
|
|
4373
4376
|
# Used for named expressions with an empty name
|
4374
|
-
def
|
4377
|
+
def empty_name_error(type, what)
|
4375
4378
|
validation_error(type, what, 'name is empty')
|
4376
4379
|
end
|
4377
4380
|
|