regexp_parser 0.4.6 → 0.4.7
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/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
|
|