line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Pugs::Emitter::Rule::Perl5; |
2
|
|
|
|
|
|
|
|
3
|
17
|
|
|
17
|
|
179703
|
use Pugs::Emitter::Rule::Perl5::Ratchet; |
|
17
|
|
|
|
|
69
|
|
|
17
|
|
|
|
|
1268
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# p6-rule perl5 emitter |
6
|
|
|
|
|
|
|
|
7
|
17
|
|
|
17
|
|
216
|
use strict; |
|
17
|
|
|
|
|
40
|
|
|
17
|
|
|
|
|
952
|
|
8
|
17
|
|
|
17
|
|
126
|
use warnings; |
|
17
|
|
|
|
|
1187
|
|
|
17
|
|
|
|
|
833
|
|
9
|
17
|
|
|
17
|
|
195
|
use Data::Dumper; |
|
17
|
|
|
|
|
39
|
|
|
17
|
|
|
|
|
13523
|
|
10
|
|
|
|
|
|
|
$Data::Dumper::Indent = 1; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
our $capture_count; |
13
|
|
|
|
|
|
|
our $capture_to_array; |
14
|
|
|
|
|
|
|
our %capture_seen; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub call_subrule { |
17
|
0
|
|
|
0
|
0
|
|
my ( $subrule, $tab, $positionals, @param ) = @_; |
18
|
0
|
0
|
|
|
|
|
$subrule = "\$_[4]->" . $subrule unless $subrule =~ / :: | \. | -> /x; |
19
|
0
|
|
|
|
|
|
$subrule =~ s/\./->/; # XXX - source filter |
20
|
|
|
|
|
|
|
|
21
|
0
|
0
|
0
|
|
|
|
$positionals = shift @param if $positionals eq '' && @param == 1; # odd number of elements in hash |
22
|
|
|
|
|
|
|
#print "PARAM: ",Dumper(@param); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
return |
25
|
0
|
|
|
|
|
|
"$tab sub{ |
26
|
|
|
|
|
|
|
$tab my \$prior = \$::_V6_PRIOR_; |
27
|
|
|
|
|
|
|
$tab my \$param = { \%{ \$_[7] || {} }, positionals => [ $positionals ], args => {" . |
28
|
|
|
|
|
|
|
join(", ",@param) . "} }; |
29
|
|
|
|
|
|
|
$tab \$_[3] = $subrule( \$_[0], \$param, \$_[3], ); |
30
|
|
|
|
|
|
|
$tab \$::_V6_PRIOR_ = \$prior; |
31
|
|
|
|
|
|
|
$tab } |
32
|
|
|
|
|
|
|
"; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub call_subrule_no_capture { |
36
|
0
|
|
|
0
|
0
|
|
my ( $subrule, $tab, $positionals, @param ) = @_; |
37
|
0
|
0
|
|
|
|
|
$subrule = "\$_[4]->" . $subrule unless $subrule =~ / :: | \. | -> /x; |
38
|
0
|
|
|
|
|
|
$subrule =~ s/\./->/; # XXX - source filter |
39
|
|
|
|
|
|
|
|
40
|
0
|
0
|
0
|
|
|
|
$positionals = shift @param if $positionals eq '' && @param == 1; # odd number of elements in hash |
41
|
|
|
|
|
|
|
#print "PARAM: ",Dumper(@param); |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
return |
44
|
0
|
|
|
|
|
|
"$tab sub{ |
45
|
|
|
|
|
|
|
$tab my \$prior = \$::_V6_PRIOR_; |
46
|
|
|
|
|
|
|
$tab my \$param = { \%{ \$_[7] || {} }, positionals => [ $positionals ], args => {" . |
47
|
|
|
|
|
|
|
join(", ",@param) . "} }; |
48
|
|
|
|
|
|
|
$tab \$_[3] = $subrule( \$_[0], \$param, \$_[3], ); |
49
|
|
|
|
|
|
|
$tab \$_[3]->data->{match} = []; |
50
|
|
|
|
|
|
|
$tab \$_[3]->data->{named} = {}; |
51
|
|
|
|
|
|
|
$tab \$::_V6_PRIOR_ = \$prior; |
52
|
|
|
|
|
|
|
$tab } |
53
|
|
|
|
|
|
|
"; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub emit { |
57
|
0
|
|
|
0
|
0
|
|
my ($grammar, $ast) = @_; |
58
|
|
|
|
|
|
|
# runtime parameters: $grammar, $string, $state, $arg_list |
59
|
|
|
|
|
|
|
# rule parameters: see Runtime::Rule.pm |
60
|
0
|
|
|
|
|
|
local $capture_count = -1; |
61
|
0
|
|
|
|
|
|
local $capture_to_array = 0; |
62
|
0
|
|
|
|
|
|
local %capture_seen = (); |
63
|
|
|
|
|
|
|
#print "emit capture_to_array $capture_to_array\n"; |
64
|
|
|
|
|
|
|
# print "emit: ", Dumper($ast); |
65
|
|
|
|
|
|
|
#die emit_rule( $ast, ' ' ); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
return |
68
|
0
|
|
|
|
|
|
"do { |
69
|
|
|
|
|
|
|
package Pugs::Runtime::Regex; |
70
|
|
|
|
|
|
|
my \$matcher = \n" . emit_rule( $ast, ' ' ) . "; |
71
|
|
|
|
|
|
|
my \$rule; |
72
|
|
|
|
|
|
|
\$rule = sub {" . |
73
|
|
|
|
|
|
|
# grammar, string, state, args |
74
|
|
|
|
|
|
|
#" print \"match args: \",Dumper(\@_);\n" . |
75
|
|
|
|
|
|
|
" |
76
|
|
|
|
|
|
|
my \$tree; |
77
|
|
|
|
|
|
|
if ( defined \$_[3]{p} |
78
|
|
|
|
|
|
|
&& ! \$_[3]{continue} |
79
|
|
|
|
|
|
|
) { |
80
|
|
|
|
|
|
|
\$matcher->( \$_[1], \$_[2], \$tree, \$tree, \$_[0], \$_[3]{p}, \$_[1], \$_[3] ); |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
else { |
83
|
|
|
|
|
|
|
\$_[3]{p} ||= 0; |
84
|
|
|
|
|
|
|
for my \$pos ( \$_[3]{p} .. length( \$_[1] ) ) { |
85
|
|
|
|
|
|
|
my \$param = { \%{\$_[3]}, p => \$pos }; |
86
|
|
|
|
|
|
|
\$matcher->( \$_[1], \$_[2], \$tree, \$tree, \$_[0], \$pos, \$_[1], \$param ); |
87
|
|
|
|
|
|
|
last if \$tree; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
\$tree = Pugs::Grammar::Base->no_match(\@_) |
90
|
|
|
|
|
|
|
unless defined \$tree; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
my \$cap = \$tree->data->{capture}; |
93
|
|
|
|
|
|
|
if ( ref \$cap eq 'CODE' ) { |
94
|
|
|
|
|
|
|
\$::_V6_MATCH_ = \$tree; |
95
|
|
|
|
|
|
|
\$tree->data->{capture} = \\(\$cap->( \$tree )); |
96
|
|
|
|
|
|
|
}; |
97
|
|
|
|
|
|
|
if ( \$tree ) { |
98
|
|
|
|
|
|
|
# \$::_V6_PRIOR_ = \$rule |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
my \$prior = \$::_V6_PRIOR_; |
101
|
|
|
|
|
|
|
\$::_V6_PRIOR_ = sub { |
102
|
|
|
|
|
|
|
local \$main::_V6_PRIOR_ = \$prior; |
103
|
|
|
|
|
|
|
\$rule->(\@_); |
104
|
|
|
|
|
|
|
}; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
return \$tree; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
"; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub emit_rule { |
114
|
0
|
|
|
0
|
0
|
|
my $n = $_[0]; |
115
|
0
|
|
|
|
|
|
my $tab = $_[1] . ' '; |
116
|
0
|
0
|
|
|
|
|
die "unknown node: ", Dumper( $n ) |
117
|
|
|
|
|
|
|
unless ref( $n ) eq 'HASH'; |
118
|
|
|
|
|
|
|
#print "NODE ", Dumper($n); |
119
|
0
|
|
|
|
|
|
my @keys = grep { substr($_, 0, 1) ne '_' } keys %$n; |
|
0
|
|
|
|
|
|
|
120
|
0
|
|
|
|
|
|
my ($k) = @keys; |
121
|
0
|
|
|
|
|
|
my $v = $$n{$k}; |
122
|
|
|
|
|
|
|
# XXX - use real references |
123
|
17
|
|
|
17
|
|
123
|
no strict 'refs'; |
|
17
|
|
|
|
|
37
|
|
|
17
|
|
|
|
|
82229
|
|
124
|
0
|
|
|
|
|
|
my $code = &$k( $v, $tab ); |
125
|
0
|
|
|
|
|
|
return $code; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
#rule nodes |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub capturing_group { |
131
|
0
|
|
|
0
|
0
|
|
my $program = $_[0]; |
132
|
|
|
|
|
|
|
|
133
|
0
|
|
|
|
|
|
$capture_count++; |
134
|
|
|
|
|
|
|
{ |
135
|
0
|
|
|
|
|
|
$capture_seen{$capture_count}++; |
|
0
|
|
|
|
|
|
|
136
|
0
|
|
|
|
|
|
local $capture_count = -1; |
137
|
0
|
|
|
|
|
|
local $capture_to_array = 0; |
138
|
0
|
|
|
|
|
|
local %capture_seen = (); |
139
|
0
|
0
|
|
|
|
|
$program = emit_rule( $program, $_[1].' ' ) |
140
|
|
|
|
|
|
|
if ref( $program ); |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
return |
144
|
0
|
|
0
|
|
|
|
"$_[1] positional( $capture_count, " . |
145
|
|
|
|
|
|
|
( $capture_to_array || ( $capture_seen{$capture_count} > 1 ? 1 : 0 ) ) . |
146
|
|
|
|
|
|
|
", \n" . |
147
|
|
|
|
|
|
|
$program . |
148
|
|
|
|
|
|
|
"$_[1] )\n"; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
sub capture_as_result { |
151
|
0
|
|
|
0
|
0
|
|
my $program = $_[0]; |
152
|
|
|
|
|
|
|
|
153
|
0
|
|
|
|
|
|
$capture_count++; |
154
|
|
|
|
|
|
|
{ |
155
|
0
|
|
|
|
|
|
$capture_seen{$capture_count}++; |
|
0
|
|
|
|
|
|
|
156
|
0
|
|
|
|
|
|
local $capture_count = -1; |
157
|
0
|
|
|
|
|
|
local $capture_to_array = 0; |
158
|
0
|
|
|
|
|
|
local %capture_seen = (); |
159
|
0
|
0
|
|
|
|
|
$program = emit_rule( $program, $_[1].' ' ) |
160
|
|
|
|
|
|
|
if ref( $program ); |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
return |
164
|
0
|
|
|
|
|
|
"$_[1] capture_as_result( \n" . |
165
|
|
|
|
|
|
|
$program . |
166
|
|
|
|
|
|
|
"$_[1] )\n"; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
sub non_capturing_group { |
169
|
0
|
|
|
0
|
0
|
|
return emit_rule( $_[0], $_[1] ); |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
sub quant { |
172
|
0
|
|
|
0
|
0
|
|
my $term = $_[0]->{'term'}; |
173
|
0
|
|
0
|
|
|
|
my $quantifier = $_[0]->{quant} || ''; |
174
|
0
|
|
0
|
|
|
|
my $greedy = $_[0]->{greedy} || ''; # + ? |
175
|
|
|
|
|
|
|
|
176
|
0
|
0
|
|
|
|
|
if ( ref( $quantifier ) eq 'HASH' ) |
177
|
|
|
|
|
|
|
{ |
178
|
0
|
|
|
|
|
|
die "quantifier not implemented: " . Dumper( $quantifier ); |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
#return |
181
|
|
|
|
|
|
|
# "$_[1] concat(\n" . |
182
|
|
|
|
|
|
|
# join( ',', ($rul) x $count ) . |
183
|
|
|
|
|
|
|
# "$_[1] )\n"; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
0
|
|
|
|
|
|
my $quant = $quantifier . $greedy; |
187
|
0
|
|
|
|
|
|
my $sub = { |
188
|
|
|
|
|
|
|
'*' =>'greedy_star', |
189
|
|
|
|
|
|
|
'+' =>'greedy_plus', |
190
|
|
|
|
|
|
|
'*?'=>'non_greedy_star', |
191
|
|
|
|
|
|
|
'+?'=>'non_greedy_plus', |
192
|
|
|
|
|
|
|
'?' =>'optional', |
193
|
|
|
|
|
|
|
'??'=>'null_or_optional', |
194
|
|
|
|
|
|
|
'' => '', |
195
|
|
|
|
|
|
|
}->{$quant}; |
196
|
0
|
0
|
|
|
|
|
die "quantifier not implemented: $quant" |
197
|
|
|
|
|
|
|
unless defined $sub; |
198
|
|
|
|
|
|
|
|
199
|
0
|
|
|
|
|
|
my $rul; |
200
|
|
|
|
|
|
|
{ |
201
|
0
|
|
|
|
|
|
my $cap = $capture_to_array; |
|
0
|
|
|
|
|
|
|
202
|
0
|
|
0
|
|
|
|
local $capture_to_array = $cap || ( $quant ne '' ? 1 : 0 ); |
203
|
0
|
|
|
|
|
|
$rul = emit_rule( $term, $_[1] . ' ' ); |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
0
|
0
|
|
|
|
|
return $rul |
207
|
|
|
|
|
|
|
if $sub eq ''; |
208
|
|
|
|
|
|
|
return |
209
|
0
|
|
|
|
|
|
"$_[1] $sub(\n" . |
210
|
|
|
|
|
|
|
$rul . |
211
|
|
|
|
|
|
|
"$_[1] )\n"; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
sub alt { |
214
|
0
|
|
|
0
|
0
|
|
my @s; |
215
|
|
|
|
|
|
|
# print "Alt: ", Dumper($_[0]); |
216
|
0
|
|
|
|
|
|
my $count = $capture_count; |
217
|
0
|
|
|
|
|
|
my $max = -1; |
218
|
0
|
|
|
|
|
|
for ( @{$_[0]} ) { |
|
0
|
|
|
|
|
|
|
219
|
0
|
|
|
|
|
|
$capture_count = $count; |
220
|
|
|
|
|
|
|
|
221
|
0
|
|
|
|
|
|
my $_capture_count = $capture_count; |
222
|
0
|
|
|
|
|
|
my $_capture_to_array = $capture_to_array; |
223
|
0
|
|
|
|
|
|
my %_capture_seen = ( %capture_seen ); |
224
|
0
|
|
|
|
|
|
local $capture_count = $_capture_count; |
225
|
0
|
|
|
|
|
|
local $capture_to_array = $_capture_to_array; |
226
|
0
|
|
|
|
|
|
local %capture_seen = ( %_capture_seen ); |
227
|
|
|
|
|
|
|
|
228
|
0
|
|
|
|
|
|
my $tmp = emit_rule( $_, $_[1].' ' ); |
229
|
|
|
|
|
|
|
# print ' ',$capture_count; |
230
|
0
|
0
|
|
|
|
|
$max = $capture_count |
231
|
|
|
|
|
|
|
if $capture_count > $max; |
232
|
0
|
0
|
|
|
|
|
push @s, $tmp if $tmp; |
233
|
|
|
|
|
|
|
} |
234
|
0
|
|
|
|
|
|
$capture_count = $max; |
235
|
|
|
|
|
|
|
|
236
|
0
|
|
|
|
|
|
return "$_[1] alternation( [\n" . |
237
|
|
|
|
|
|
|
join( ',', @s ) . |
238
|
|
|
|
|
|
|
"$_[1] ] )\n"; |
239
|
|
|
|
|
|
|
} |
240
|
0
|
|
|
0
|
0
|
|
sub alt1 { &alt } |
241
|
|
|
|
|
|
|
sub concat { |
242
|
0
|
|
|
0
|
0
|
|
my @s; |
243
|
0
|
|
|
|
|
|
for ( @{$_[0]} ) { |
|
0
|
|
|
|
|
|
|
244
|
0
|
|
|
|
|
|
my $tmp = emit_rule( $_, $_[1] ); |
245
|
0
|
0
|
|
|
|
|
push @s, $tmp if $tmp; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
return |
248
|
0
|
|
|
|
|
|
"$_[1] concat( \n" . |
249
|
|
|
|
|
|
|
join( ',', @s ) . |
250
|
|
|
|
|
|
|
"$_[1] )\n"; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
sub code { |
253
|
0
|
|
|
0
|
0
|
|
return "$_[1] $_[0]\n"; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
sub dot { |
256
|
0
|
|
|
0
|
0
|
|
return call_subrule( 'any', $_[1], '' ); |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
sub variable { |
259
|
0
|
|
|
0
|
0
|
|
my $name = "$_[0]"; |
260
|
0
|
|
|
|
|
|
my $value = undef; |
261
|
|
|
|
|
|
|
# XXX - eval $name doesn't look up in user lexical pad |
262
|
|
|
|
|
|
|
# XXX - what &xxx interpolate to? |
263
|
|
|
|
|
|
|
|
264
|
0
|
0
|
|
|
|
|
if ( $name =~ /^\$/ ) { |
265
|
|
|
|
|
|
|
# $^a, $^b |
266
|
0
|
0
|
|
|
|
|
if ( $name =~ /^ \$ \^ ([^\s]*) /x ) { |
267
|
0
|
|
|
|
|
|
my $index = ord($1)-ord('a'); |
268
|
|
|
|
|
|
|
#print "Variable #$index\n"; |
269
|
|
|
|
|
|
|
#return "$_[1] constant( \$_[7][$index] )\n"; |
270
|
|
|
|
|
|
|
|
271
|
0
|
|
|
|
|
|
my $code = |
272
|
|
|
|
|
|
|
" sub { |
273
|
|
|
|
|
|
|
#print \"Runtime Variable args[\", join(\",\",\@_) ,\"] \$_[7][$index]\\n\"; |
274
|
|
|
|
|
|
|
return constant( \$_[7][$index] )->(\@_); |
275
|
|
|
|
|
|
|
}"; |
276
|
0
|
|
|
|
|
|
$code =~ s/^/$_[1]/mg; |
277
|
0
|
|
|
|
|
|
return "$code\n"; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
else { |
280
|
0
|
|
|
|
|
|
$value = eval $name; |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
# ??? $value = join('', eval $name) if $name =~ /^\@/; |
285
|
|
|
|
|
|
|
|
286
|
0
|
0
|
|
|
|
|
if ( $name =~ /^%/ ) { |
287
|
|
|
|
|
|
|
# XXX - runtime or compile-time interpolation? |
288
|
0
|
0
|
|
|
|
|
return "$_[1] hash( \\$name )\n" if $name =~ /::/; |
289
|
0
|
|
|
|
|
|
return "$_[1] hash( get_variable( '$name' ) )\n"; |
290
|
|
|
|
|
|
|
} |
291
|
0
|
0
|
|
|
|
|
die "interpolation of $name not implemented" |
292
|
|
|
|
|
|
|
unless defined $value; |
293
|
|
|
|
|
|
|
|
294
|
0
|
|
|
|
|
|
return "$_[1] constant( '" . $value . "' )\n"; |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
sub special_char { |
297
|
0
|
|
|
0
|
0
|
|
my ($char, $data) = $_[0] =~ /^.(.)(.*)/; |
298
|
0
|
0
|
|
|
|
|
$_[1] = '' unless defined $_[1]; |
299
|
|
|
|
|
|
|
|
300
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '\\N{" . join( "}\\N{", split( /\s*;\s*/, $data ) ) . "}' )\n" |
301
|
|
|
|
|
|
|
if $char eq 'c'; |
302
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '(?!\\N{" . join( "}\\N{", split( /\s*;\s*/, $data ) ) . "})\\X' )\n" |
303
|
|
|
|
|
|
|
if $char eq 'C'; |
304
|
|
|
|
|
|
|
|
305
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '\\x{$data}' )\n" |
306
|
|
|
|
|
|
|
if $char eq 'x'; |
307
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '(?!\\x{$data})\\X' )\n" |
308
|
|
|
|
|
|
|
if $char eq 'X'; |
309
|
|
|
|
|
|
|
|
310
|
0
|
0
|
|
|
|
|
return special_char( sprintf("\\x%X", oct($data) ) ) |
311
|
|
|
|
|
|
|
if $char eq 'o'; |
312
|
0
|
0
|
|
|
|
|
return special_char( sprintf("\\X%X", oct($data) ) ) |
313
|
|
|
|
|
|
|
if $char eq 'O'; |
314
|
|
|
|
|
|
|
|
315
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '(?:\\n\\r?|\\r\\n?|\\x85|\\x{2028})' )\n" |
316
|
|
|
|
|
|
|
if $char eq 'n'; |
317
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '(?!\\n\\r?|\\r\\n?|\\x85|\\x{2028})\\X' )\n" |
318
|
|
|
|
|
|
|
if $char eq 'N'; |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# XXX - Infinite loop in pugs stdrules.t |
321
|
|
|
|
|
|
|
#return metasyntax( '?_horizontal_ws', $_[1] ) |
322
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '[\\x20\\x09]' )\n" |
323
|
|
|
|
|
|
|
if $char eq 'h'; |
324
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '[^\\x20\\x09]' )\n" |
325
|
|
|
|
|
|
|
if $char eq 'H'; |
326
|
|
|
|
|
|
|
#return metasyntax( '?_vertical_ws', $_[1] ) |
327
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '[\\x0A\\x0D]' )\n" |
328
|
|
|
|
|
|
|
if $char eq 'v'; |
329
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '[^\\x0A\\x0D]' )\n" |
330
|
|
|
|
|
|
|
if $char eq 'V'; |
331
|
|
|
|
|
|
|
|
332
|
0
|
|
|
|
|
|
for ( qw( r n t e f w d s ) ) { |
333
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '\\$_' )\n" if $char eq $_; |
334
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( '[^\\$_]' )\n" if $char eq uc($_); |
335
|
|
|
|
|
|
|
} |
336
|
0
|
0
|
|
|
|
|
$char = '\\\\' if $char eq '\\'; |
337
|
0
|
0
|
|
|
|
|
return "$_[1] constant( q!$char! )\n" unless $char eq '!'; |
338
|
0
|
|
|
|
|
|
return "$_[1] constant( q($char) )\n"; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
sub match_variable { |
341
|
0
|
|
|
0
|
0
|
|
my $name = $_[0]; |
342
|
0
|
|
|
|
|
|
my $num = substr($name,1); |
343
|
|
|
|
|
|
|
#print "var name: ", $num, "\n"; |
344
|
0
|
|
|
|
|
|
my $code = |
345
|
|
|
|
|
|
|
" sub { |
346
|
|
|
|
|
|
|
my \$m = \$_[2]; |
347
|
|
|
|
|
|
|
#print 'var: ',\$m->perl; |
348
|
|
|
|
|
|
|
#print 'var: ',\$m->[$num]; |
349
|
|
|
|
|
|
|
return constant( \"\$m->[$num]\" )->(\@_); |
350
|
|
|
|
|
|
|
}"; |
351
|
0
|
|
|
|
|
|
$code =~ s/^/$_[1]/mg; |
352
|
0
|
|
|
|
|
|
return "$code\n"; |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
sub closure { |
355
|
0
|
|
|
0
|
0
|
|
my $code = $_[0]{closure}; |
356
|
0
|
|
|
|
|
|
my $modifier = $_[0]{modifier}; # 'plain', '', '?', '!' |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
#die "closure modifier not implemented '$modifier'" |
359
|
|
|
|
|
|
|
# unless $modifier eq 'plain'; |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
#warn "CODE $code"; |
362
|
0
|
0
|
|
|
|
|
$code = '' if $code eq '{*}'; # "whatever" |
363
|
|
|
|
|
|
|
|
364
|
0
|
0
|
0
|
|
|
|
if ( ref( $code ) |
365
|
|
|
|
|
|
|
&& defined $Pugs::Compiler::Perl6::VERSION |
366
|
|
|
|
|
|
|
) { |
367
|
|
|
|
|
|
|
# perl6 compiler is loaded |
368
|
0
|
|
|
|
|
|
$code = Pugs::Emitter::Perl6::Perl5::emit( 'grammar', $code, 'self' ); |
369
|
0
|
|
|
|
|
|
$code = '{ my $_V6_SELF = shift; ' . $code . '}'; # make it a "method" |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
else { |
372
|
|
|
|
|
|
|
# XXX XXX XXX - source-filter - temporary hacks to translate p6 to p5 |
373
|
|
|
|
|
|
|
# $() |
374
|
0
|
|
|
|
|
|
$code =~ s/ ([^']) \$ \( \) < (.*?) > /$1 \$_[0]->[$2]/sgx; |
375
|
|
|
|
|
|
|
# $ |
376
|
0
|
|
|
|
|
|
$code =~ s/ ([^']) \$ < (.*?) > /$1 \$_[0]->{$2}/sgx; |
377
|
|
|
|
|
|
|
# $() |
378
|
0
|
|
|
|
|
|
$code =~ s/ ([^']) \$ \( \) /$1 \$_[0]->()/sgx; |
379
|
|
|
|
|
|
|
# $/ |
380
|
0
|
|
|
|
|
|
$code =~ s/ ([^']) \$ \/ /$1 \$_[0]/sgx; |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
#print "Code: $code\n"; |
383
|
|
|
|
|
|
|
|
384
|
0
|
0
|
|
|
|
|
return " |
385
|
|
|
|
|
|
|
sub { |
386
|
|
|
|
|
|
|
\$_[3] = Pugs::Runtime::Match->new( { |
387
|
|
|
|
|
|
|
bool => \\1, |
388
|
|
|
|
|
|
|
str => \\(\$_[0]), |
389
|
|
|
|
|
|
|
from => \\(\$_[7]{p} || 0), |
390
|
|
|
|
|
|
|
to => \\(\$_[7]{p} || 0), |
391
|
|
|
|
|
|
|
match => [], |
392
|
|
|
|
|
|
|
named => {}, |
393
|
|
|
|
|
|
|
capture => sub { $code }, |
394
|
|
|
|
|
|
|
abort => 1, |
395
|
|
|
|
|
|
|
} ) |
396
|
|
|
|
|
|
|
}\n" |
397
|
|
|
|
|
|
|
if $code =~ /return/; |
398
|
|
|
|
|
|
|
|
399
|
0
|
|
|
|
|
|
my $bool = "\\\$::_V6_SUCCEED"; |
400
|
0
|
0
|
|
|
|
|
$bool = "\\( \$capture ? 1 : 0 )" if $modifier eq '?'; |
401
|
0
|
0
|
|
|
|
|
$bool = "\\( \$capture ? 0 : 1 )" if $modifier eq '!'; |
402
|
|
|
|
|
|
|
|
403
|
0
|
|
|
|
|
|
my $cap = "\\\$capture"; |
404
|
0
|
0
|
0
|
|
|
|
$cap = "undef" if $modifier eq '?' || $modifier eq '!'; |
405
|
|
|
|
|
|
|
|
406
|
0
|
|
|
|
|
|
return " |
407
|
|
|
|
|
|
|
sub { |
408
|
|
|
|
|
|
|
\$::_V6_MATCH_ = \$_[0]; |
409
|
|
|
|
|
|
|
local \$::_V6_SUCCEED = 1; |
410
|
|
|
|
|
|
|
my \$capture = sub { $code }->( \$_[3] ); |
411
|
|
|
|
|
|
|
\$_[3] = Pugs::Runtime::Match->new( { |
412
|
|
|
|
|
|
|
bool => $bool, |
413
|
|
|
|
|
|
|
str => \\(\$_[0]), |
414
|
|
|
|
|
|
|
from => \\(\$_[7]{p} || 0), |
415
|
|
|
|
|
|
|
to => \\(\$_[7]{p} || 0), |
416
|
|
|
|
|
|
|
match => [], |
417
|
|
|
|
|
|
|
named => {}, |
418
|
|
|
|
|
|
|
capture => undef, |
419
|
|
|
|
|
|
|
} ) |
420
|
|
|
|
|
|
|
}\n"; |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
sub named_capture { |
424
|
0
|
|
|
0
|
0
|
|
my $name = $_[0]{ident}; |
425
|
0
|
0
|
|
|
|
|
$name = $name->{match_variable} if ref($name) eq 'HASH'; |
426
|
0
|
|
|
|
|
|
$name =~ s/^[\$\@\%]//; # TODO - change semantics as needed |
427
|
0
|
|
|
|
|
|
my $program = $_[0]{rule}; |
428
|
0
|
|
|
|
|
|
$capture_seen{$name}++; |
429
|
|
|
|
|
|
|
return |
430
|
0
|
|
0
|
|
|
|
"$_[1] named( '$name', " . |
431
|
|
|
|
|
|
|
( $capture_to_array || ( $capture_seen{$name} > 1 ? 1 : 0 ) ) . |
432
|
|
|
|
|
|
|
", \n" . |
433
|
|
|
|
|
|
|
emit_rule($program, $_[1]) . |
434
|
|
|
|
|
|
|
"$_[1] )\n"; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
sub negate { |
437
|
0
|
|
|
0
|
0
|
|
my $program = $_[0]; |
438
|
|
|
|
|
|
|
#print "Negate: ", Dumper($_[0]); |
439
|
|
|
|
|
|
|
return |
440
|
0
|
|
|
|
|
|
"$_[1] negate( \n" . |
441
|
|
|
|
|
|
|
emit_rule($program, $_[1]) . |
442
|
|
|
|
|
|
|
"$_[1] )\n"; |
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
sub before { |
445
|
0
|
|
|
0
|
0
|
|
my $program = $_[0]{rule}; |
446
|
|
|
|
|
|
|
return |
447
|
0
|
|
|
|
|
|
"$_[1] before( \n" . |
448
|
|
|
|
|
|
|
emit_rule($program, $_[1]) . |
449
|
|
|
|
|
|
|
"$_[1] )\n"; |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
sub colon { |
452
|
0
|
|
|
0
|
0
|
|
my $str = $_[0]; |
453
|
0
|
0
|
|
|
|
|
return "$_[1] at_start() \n" |
454
|
|
|
|
|
|
|
if $str eq '^'; |
455
|
0
|
0
|
|
|
|
|
return "$_[1] alternation( [ null(), failed_abort() ] ) \n" |
456
|
|
|
|
|
|
|
if $str eq ':'; |
457
|
0
|
0
|
|
|
|
|
return "$_[1] at_end_of_string() \n" |
458
|
|
|
|
|
|
|
if $str eq '$'; |
459
|
0
|
0
|
|
|
|
|
return "$_[1] at_line_start() \n" |
460
|
|
|
|
|
|
|
if $str eq '^^'; |
461
|
0
|
0
|
|
|
|
|
return "$_[1] at_line_end() \n" |
462
|
|
|
|
|
|
|
if $str eq '$$'; |
463
|
0
|
0
|
|
|
|
|
return metasyntax( '?_wb_left', $_[1] ) |
464
|
|
|
|
|
|
|
if $str eq '<<'; |
465
|
0
|
0
|
|
|
|
|
return metasyntax( '?_wb_right', $_[1] ) |
466
|
|
|
|
|
|
|
if $str eq '>>'; |
467
|
0
|
|
|
|
|
|
die "'$str' not implemented"; |
468
|
|
|
|
|
|
|
} |
469
|
|
|
|
|
|
|
sub modifier { |
470
|
0
|
|
|
0
|
0
|
|
my $str = $_[0]{modifier}; |
471
|
0
|
|
|
|
|
|
my $rule = $_[0]{rule}; |
472
|
|
|
|
|
|
|
|
473
|
0
|
0
|
|
|
|
|
return "$_[1] ignorecase( \n" |
474
|
|
|
|
|
|
|
. emit_rule( $rule, $_[1] . ' ' ) |
475
|
|
|
|
|
|
|
. " )\n" |
476
|
|
|
|
|
|
|
if $str eq 'ignorecase'; |
477
|
|
|
|
|
|
|
|
478
|
0
|
|
|
|
|
|
die "modifier '$str' not implemented"; |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
sub constant { |
481
|
0
|
0
|
|
0
|
0
|
|
my $char = $_[0] eq '\\' ? '\\\\' : $_[0]; |
482
|
0
|
0
|
|
|
|
|
return "$_[1] constant( q!$char! )\n" unless $char =~ /!/; |
483
|
0
|
|
|
|
|
|
return "$_[1] constant( q($char) )\n"; |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
sub char_class { |
486
|
0
|
|
|
0
|
0
|
|
my $cmd = Pugs::Emitter::Rule::Perl5::CharClass::emit( $_[0] ); |
487
|
0
|
0
|
|
|
|
|
return "$_[1] perl5( q!$cmd! )\n" unless $cmd =~ /!/; |
488
|
0
|
|
|
|
|
|
return "$_[1] perl5( q($cmd) )\n"; # XXX if $cmd eq '!)' |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
sub call { |
491
|
|
|
|
|
|
|
#die "not implemented: ", Dumper(\@_); |
492
|
0
|
|
|
0
|
0
|
|
my $param = $_[0]{params}; |
493
|
0
|
|
|
|
|
|
my $name = $_[0]{method}; |
494
|
|
|
|
|
|
|
# capturing subrule |
495
|
|
|
|
|
|
|
# |
496
|
0
|
|
|
|
|
|
my ($param_list) = $param =~ /\{(.*)\}/; |
497
|
0
|
0
|
|
|
|
|
$param_list = '' unless defined $param_list; |
498
|
0
|
|
|
|
|
|
my @param = split( ',', $param_list ); |
499
|
0
|
|
|
|
|
|
$capture_seen{$name}++; |
500
|
|
|
|
|
|
|
#print "subrule ", $capture_seen{$name}, "\n"; |
501
|
|
|
|
|
|
|
#print "param: ", Dumper(\@param); |
502
|
|
|
|
|
|
|
return |
503
|
0
|
|
0
|
|
|
|
"$_[1] named( '$name', " . |
504
|
|
|
|
|
|
|
( $capture_to_array || ( $capture_seen{$name} > 1 ? 1 : 0 ) ) . |
505
|
|
|
|
|
|
|
", \n" . |
506
|
|
|
|
|
|
|
call_subrule( $name, $_[1]." ", "", @param ) . |
507
|
|
|
|
|
|
|
"$_[1] )\n"; |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
sub metasyntax { |
510
|
0
|
|
|
0
|
0
|
|
my $cmd = $_[0]{metasyntax}; |
511
|
0
|
|
0
|
|
|
|
my $modifier = delete $_[0]{modifier} || ''; # ? ! |
512
|
0
|
0
|
|
|
|
|
return negate( { metasyntax => $_[0] }, $_[1] ) if $modifier eq '!'; |
513
|
|
|
|
|
|
|
|
514
|
0
|
|
|
|
|
|
my $prefix = substr( $cmd, 0, 1 ); |
515
|
0
|
0
|
|
|
|
|
if ( $prefix eq '@' ) { |
516
|
|
|
|
|
|
|
# XXX - wrap @array items - see end of Pugs::Grammar::Rule |
517
|
|
|
|
|
|
|
return |
518
|
0
|
|
|
|
|
|
"$_[1] alternation( \\$cmd )\n"; |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
0
|
0
|
|
|
|
|
if ( $prefix eq '%' ) { |
522
|
|
|
|
|
|
|
# XXX - runtime or compile-time interpolation? |
523
|
0
|
|
|
|
|
|
my $name = substr( $cmd, 1 ); |
524
|
0
|
|
|
|
|
|
$capture_seen{$name}++; |
525
|
0
|
0
|
0
|
|
|
|
return "$_[1] named( '$name', " . |
526
|
|
|
|
|
|
|
( $capture_to_array || ( $capture_seen{$name} > 1 ? 1 : 0 ) ) . |
527
|
|
|
|
|
|
|
", hash( \\$cmd ) )\n" |
528
|
|
|
|
|
|
|
if $cmd =~ /::/; |
529
|
0
|
|
0
|
|
|
|
return "$_[1] named( '$name', " . |
530
|
|
|
|
|
|
|
( $capture_to_array || ( $capture_seen{$name} > 1 ? 1 : 0 ) ) . |
531
|
|
|
|
|
|
|
", hash( get_variable( '$cmd' ) ) )\n"; |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
|
534
|
0
|
0
|
|
|
|
|
if ( $prefix eq '$' ) { |
535
|
0
|
0
|
|
|
|
|
if ( $cmd =~ /::/ ) { |
536
|
|
|
|
|
|
|
# call method in fully qualified $package::var |
537
|
|
|
|
|
|
|
return |
538
|
0
|
|
|
|
|
|
"$_[1] sub { \n" . |
539
|
|
|
|
|
|
|
# "$_[1] print 'params: ',Dumper(\@_);\n" . |
540
|
|
|
|
|
|
|
"$_[1] \$_[3] = $cmd->match( \$_[0], \$_[4], \$_[7], \$_[1] );\n" . |
541
|
|
|
|
|
|
|
"$_[1] }\n"; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
# call method in lexical $var |
544
|
|
|
|
|
|
|
return |
545
|
0
|
|
|
|
|
|
"$_[1] sub { \n" . |
546
|
|
|
|
|
|
|
#"$_[1] print 'params: ',Dumper(\@_);\n" . |
547
|
|
|
|
|
|
|
"$_[1] my \$r = get_variable( '$cmd' );\n" . |
548
|
|
|
|
|
|
|
"$_[1] \$_[3] = \$r->match( \$_[0], \$_[4], \$_[7], \$_[1] );\n" . |
549
|
|
|
|
|
|
|
"$_[1] }\n"; |
550
|
|
|
|
|
|
|
} |
551
|
0
|
0
|
|
|
|
|
if ( $prefix eq q(') ) { # single quoted literal ' |
552
|
0
|
|
|
|
|
|
$cmd = substr( $cmd, 1, -1 ); |
553
|
0
|
0
|
|
|
|
|
return "$_[1] constant( q!$cmd! )\n" unless $cmd =~ /!/; |
554
|
0
|
|
|
|
|
|
return "$_[1] constant( q($cmd) )\n"; |
555
|
|
|
|
|
|
|
} |
556
|
0
|
0
|
|
|
|
|
if ( $prefix eq q(") ) { # interpolated literal " |
557
|
0
|
|
|
|
|
|
$cmd = substr( $cmd, 1, -1 ); |
558
|
0
|
|
|
|
|
|
warn "<\"...\"> not implemented"; |
559
|
0
|
|
|
|
|
|
return; |
560
|
|
|
|
|
|
|
} |
561
|
0
|
0
|
|
|
|
|
if ( $prefix eq '.' ) { # non_capturing_subrule / code assertion |
562
|
0
|
|
|
|
|
|
$cmd = substr( $cmd, 1 ); |
563
|
0
|
0
|
|
|
|
|
if ( $cmd =~ /^{/ ) { |
564
|
0
|
|
|
|
|
|
warn "code assertion not implemented"; |
565
|
0
|
|
|
|
|
|
return; |
566
|
|
|
|
|
|
|
} |
567
|
0
|
|
|
|
|
|
return call_subrule_no_capture( $cmd, $_[1], '' ); |
568
|
|
|
|
|
|
|
} |
569
|
0
|
0
|
|
|
|
|
if ( $prefix eq '?' ) { # non_capturing_subrule / code assertion |
570
|
|
|
|
|
|
|
# XXX FIXME |
571
|
0
|
|
|
|
|
|
$cmd = substr( $cmd, 1 ); |
572
|
0
|
0
|
|
|
|
|
if ( $cmd =~ /^{/ ) { |
573
|
0
|
|
|
|
|
|
warn "code assertion not implemented"; |
574
|
0
|
|
|
|
|
|
return; |
575
|
|
|
|
|
|
|
} |
576
|
0
|
|
|
|
|
|
return call_subrule_no_capture( $cmd, $_[1], '' ); |
577
|
|
|
|
|
|
|
} |
578
|
0
|
0
|
|
|
|
|
if ( $prefix =~ /[_[:alnum:]]/ ) { |
579
|
0
|
0
|
|
|
|
|
if ( $cmd eq 'cut' ) { |
580
|
0
|
|
|
|
|
|
warn "<$cmd> not implemented"; |
581
|
0
|
|
|
|
|
|
return; |
582
|
|
|
|
|
|
|
} |
583
|
0
|
0
|
|
|
|
|
if ( $cmd eq 'commit' ) { |
584
|
0
|
|
|
|
|
|
warn "<$cmd> not implemented"; |
585
|
0
|
|
|
|
|
|
return; |
586
|
|
|
|
|
|
|
} |
587
|
|
|
|
|
|
|
# capturing subrule |
588
|
|
|
|
|
|
|
# |
589
|
0
|
|
|
|
|
|
my ( $name, $param_list ) = split( /[\(\)]/, $cmd ); |
590
|
0
|
0
|
|
|
|
|
$param_list = '' unless defined $param_list; |
591
|
0
|
|
|
|
|
|
my @param = split( ',', $param_list ); |
592
|
0
|
|
|
|
|
|
$capture_seen{$name}++; |
593
|
|
|
|
|
|
|
#print "subrule ", $capture_seen{$name}, "\n"; |
594
|
|
|
|
|
|
|
#print "param: ", Dumper(\@param); |
595
|
|
|
|
|
|
|
return |
596
|
0
|
|
0
|
|
|
|
"$_[1] named( '$name', " . |
597
|
|
|
|
|
|
|
( $capture_to_array || ( $capture_seen{$name} > 1 ? 1 : 0 ) ) . |
598
|
|
|
|
|
|
|
", \n" . |
599
|
|
|
|
|
|
|
call_subrule( $name, $_[1]." ", "", @param ) . |
600
|
|
|
|
|
|
|
"$_[1] )\n"; |
601
|
|
|
|
|
|
|
} |
602
|
|
|
|
|
|
|
#if ( $prefix eq '.' ) { |
603
|
|
|
|
|
|
|
# my ( $method, $param_list ) = split( /[\(\)]/, $cmd ); |
604
|
|
|
|
|
|
|
# $method =~ s/^\.//; |
605
|
|
|
|
|
|
|
# $param_list ||= ''; |
606
|
|
|
|
|
|
|
# return "$_[1] try_method( '$method', '$param_list' ) "; |
607
|
|
|
|
|
|
|
#} |
608
|
0
|
|
|
|
|
|
die "<$cmd> not implemented"; |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
1; |