line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# $Revision: #3 $$Date: 2005/08/31 $$Author: jd150722 $ |
2
|
|
|
|
|
|
|
###################################################################### |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# This program is Copyright 2003-2005 by Jeff Dutton. |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify |
7
|
|
|
|
|
|
|
# it under the terms of either the GNU General Public License or the |
8
|
|
|
|
|
|
|
# Perl Artistic License. |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
11
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
12
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13
|
|
|
|
|
|
|
# GNU General Public License for more details. |
14
|
|
|
|
|
|
|
# |
15
|
|
|
|
|
|
|
# If you do not have a copy of the GNU General Public License write to |
16
|
|
|
|
|
|
|
# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, |
17
|
|
|
|
|
|
|
# MA 02139, USA. |
18
|
|
|
|
|
|
|
###################################################################### |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
package Parse::RandGen::Production; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
require 5.006_001; |
23
|
4
|
|
|
4
|
|
24
|
use Carp; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
339
|
|
24
|
4
|
|
|
4
|
|
25
|
use Parse::RandGen qw($Debug); |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
491
|
|
25
|
4
|
|
|
4
|
|
22
|
use strict; |
|
4
|
|
|
|
|
15
|
|
|
4
|
|
|
|
|
135
|
|
26
|
4
|
|
|
4
|
|
21
|
use vars qw($Debug); |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
10453
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
###################################################################### |
29
|
|
|
|
|
|
|
#### Creators |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
sub new { |
32
|
11
|
|
|
11
|
1
|
20
|
my $class = shift; |
33
|
11
|
|
|
|
|
68
|
my $self = { |
34
|
|
|
|
|
|
|
_conditions => [ ], # Ordered list of Conditions that must be satisfied for the production to be true |
35
|
|
|
|
|
|
|
_action => undef, # Action to take if the production is satisfied |
36
|
|
|
|
|
|
|
_rule => undef, # The Rule that this Production belongs to |
37
|
|
|
|
|
|
|
_name => undef, # The name of the Production (most are anonymous, but Productions can be named if they need to be accessed later) |
38
|
|
|
|
|
|
|
_number => undef, # The number of the Production in the Rule (which production is this 0...X) |
39
|
|
|
|
|
|
|
#@_, |
40
|
|
|
|
|
|
|
}; |
41
|
11
|
|
33
|
|
|
80
|
bless $self, ref($class)||$class; |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# Optional named arguments can be passed. Any unknown named arguments are turned into object data members. |
44
|
11
|
|
|
|
|
157
|
my @args = @_; # Arguments can override defaults or create new attributes in the object |
45
|
11
|
|
|
|
|
24
|
my $numArgs = $#args + 1; |
46
|
11
|
50
|
|
|
|
57
|
if ($numArgs == 1) { |
|
|
100
|
|
|
|
|
|
47
|
0
|
|
|
|
|
0
|
$self->addCond(shift(@args)); |
48
|
|
|
|
|
|
|
} elsif ($numArgs) { |
49
|
1
|
50
|
|
|
|
4
|
($numArgs % 2) and confess("%Error: new Production called with an odd number of arguments ($numArgs); arguments must be in named pairs (or a single Condition argument)!"); |
50
|
1
|
|
|
|
|
11
|
$self->set(@args); |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
10
|
|
|
|
|
29
|
my $rule = $self->{_rule}; |
54
|
10
|
50
|
33
|
|
|
52
|
(!defined($self->{_rule}) || UNIVERSAL::isa($rule, "Parse::RandGen::Rule")) |
55
|
|
|
|
|
|
|
or confess("%Error: new Production was passed an unknown \"rule\" argument \"$rule\"!\n"); |
56
|
|
|
|
|
|
|
|
57
|
10
|
|
|
|
|
36
|
return($self); |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
###################################################################### |
61
|
|
|
|
|
|
|
#### Methods |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub set { |
64
|
1
|
50
|
|
1
|
0
|
7
|
my $self = shift or confess("%Error: Cannot call without a valid object!"); |
65
|
1
|
|
|
|
|
3
|
my @args = @_; |
66
|
|
|
|
|
|
|
|
67
|
1
|
|
|
|
|
1
|
my $numArgs = $#args + 1; |
68
|
1
|
50
|
|
|
|
4
|
($numArgs) or confess("%Error: Production::set() called with no arguments!"); |
69
|
1
|
50
|
|
|
|
4
|
($numArgs % 2) and confess("%Error: Production::set() called with an odd number of arguments ($numArgs); arguments must be in named pairs!"); |
70
|
1
|
|
|
|
|
3
|
while ($#args >= 0) { |
71
|
1
|
|
|
|
|
3
|
my ($arg, $val) = (shift(@args), shift(@args)); |
72
|
1
|
50
|
|
|
|
3
|
if ($arg eq "cond") { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
73
|
1
|
|
|
|
|
4
|
$self->addCond($val); |
74
|
|
|
|
|
|
|
} elsif ($arg eq "action") { |
75
|
0
|
|
|
|
|
0
|
$self->{_action} = $val; |
76
|
|
|
|
|
|
|
} elsif ($arg eq "rule") { |
77
|
0
|
0
|
|
|
|
0
|
UNIVERSAL::isa($val, "Parse::RandGen::Rule") or confess("%Error: Production::set() called with a bad \"rule\" argument ($val)!"); |
78
|
0
|
|
|
|
|
0
|
$self->{_rule} = $val; |
79
|
|
|
|
|
|
|
} else { |
80
|
|
|
|
|
|
|
# Unknown arguments become data members |
81
|
0
|
|
|
|
|
0
|
$self->{$arg} = $val; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub addCond { |
87
|
11
|
50
|
|
11
|
0
|
34
|
my $self = shift or confess("%Error: Cannot call without a valid object!"); |
88
|
11
|
|
|
|
|
57
|
my @args = @_; |
89
|
|
|
|
|
|
|
|
90
|
11
|
|
|
|
|
32
|
while ($#args >= 0) { |
91
|
11
|
|
|
|
|
19
|
my $val = shift(@args); |
92
|
11
|
50
|
|
|
|
29
|
defined($val) or confess("%Error: Production::addCond(): condition is undefined!"); |
93
|
11
|
|
|
|
|
14
|
my $element = $val; |
94
|
11
|
|
|
|
|
15
|
my $cond = undef; |
95
|
11
|
|
|
|
|
17
|
my $valRef = ref($val); |
96
|
11
|
50
|
|
|
|
22
|
if ($valRef) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
97
|
11
|
100
|
|
|
|
43
|
if ($valRef eq "Regexp") { |
98
|
|
|
|
|
|
|
# Regular expression |
99
|
1
|
|
|
|
|
22
|
$cond = Parse::RandGen::Regexp->new($element); |
100
|
|
|
|
|
|
|
} else { |
101
|
10
|
50
|
|
|
|
46
|
(UNIVERSAL::isa($val, "Parse::RandGen::Condition")) |
102
|
|
|
|
|
|
|
or confess("%Error: The Production condition is a reference (ref=\"$valRef\"), but not a supported type!"); |
103
|
10
|
|
|
|
|
21
|
$cond = $val; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
} elsif ($val =~ m/^\s* (\w+) (?: \( (.*?) \) )? \s*$/x) { # subrule(subargs) |
106
|
0
|
|
|
|
|
0
|
my ($min, $max) = (1, 1); |
107
|
0
|
|
|
|
|
0
|
$element = $1; |
108
|
0
|
|
|
|
|
0
|
my $subargs = $2; |
109
|
0
|
0
|
0
|
|
|
0
|
if (defined($subargs) && $subargs) { |
110
|
0
|
0
|
|
|
|
0
|
if ($subargs eq "?" ) { $min = 0; $max = 1; } # ? |
|
0
|
0
|
|
|
|
0
|
|
|
0
|
0
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
|
111
|
0
|
|
|
|
|
0
|
elsif ($subargs =~ m/^(s|\+)$/ ) { $min = 1; $max = undef; } # s or + |
|
0
|
|
|
|
|
0
|
|
112
|
0
|
|
|
|
|
0
|
elsif ($subargs =~ m/^((s\?)|\*)$/ ) { $min = 0; $max = undef; } # s? or * |
|
0
|
|
|
|
|
0
|
|
113
|
0
|
|
0
|
|
|
0
|
elsif ($subargs =~ /(\d+)(?:\.\.(\d+))?/ ) { $min = $1; $max = ($2 || $min); } # 2..3 or ..4 or 5.. |
|
0
|
|
|
|
|
0
|
|
114
|
|
|
|
|
|
|
else { |
115
|
0
|
|
|
|
|
0
|
confess("%Error: The Production condition \"${val}\" has decoded to be a subrule, but the subargs are not understood (${subargs})!"); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
} |
118
|
0
|
|
|
|
|
0
|
$cond = Parse::RandGen::Subrule->new($element, min=>$min, max=>$max); |
119
|
|
|
|
|
|
|
} elsif ($element =~ $Parse::RandGen::Literal::ValidLiteralRE) { |
120
|
|
|
|
|
|
|
# Must be a literal surrounded by single or double quotes |
121
|
0
|
|
|
|
|
0
|
$element = Parse::RandGen::Literal::stripLiteral($element); |
122
|
0
|
|
|
|
|
0
|
$cond = Parse::RandGen::Literal->new($element); |
123
|
|
|
|
|
|
|
} else { |
124
|
0
|
|
|
|
|
0
|
confess("%Error: The Production condition \"${val}\" has decoded to be a literal, but it doesn't look good!"); |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
10
|
|
|
|
|
19
|
$cond->{_production} = $self; |
128
|
10
|
|
|
|
|
13
|
push @{$self->{_conditions}}, $cond; |
|
10
|
|
|
|
|
521
|
|
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub check { |
133
|
0
|
0
|
|
0
|
1
|
0
|
my $self = shift or confess("%Error: Cannot call without a valid object!"); |
134
|
0
|
0
|
|
|
|
0
|
return "%Error: Production has no RandGen object!\n" unless $self->grammar(); |
135
|
0
|
|
|
|
|
0
|
my $grammarName = $self->grammar()->name(); |
136
|
|
|
|
|
|
|
|
137
|
0
|
|
|
|
|
0
|
my $err = ""; |
138
|
0
|
|
|
|
|
0
|
foreach my $cond (@{$self->{_conditions}}) { |
|
0
|
|
|
|
|
0
|
|
139
|
0
|
0
|
|
|
|
0
|
next unless $cond->isSubrule(); |
140
|
0
|
|
|
|
|
0
|
my $subrule = $cond->subrule(); # Will be undef if there is a problem |
141
|
0
|
|
|
|
|
0
|
my $subruleName = $cond->element(); |
142
|
0
|
0
|
|
|
|
0
|
next unless defined($subruleName); # Anonymous subrule |
143
|
0
|
|
|
|
|
0
|
my $rule = $self->grammar()->rule($subruleName); |
144
|
0
|
0
|
0
|
|
|
0
|
next if (defined($rule) && ($rule == $subrule)); # Everything is OK! |
145
|
0
|
|
|
|
|
0
|
my $ruleName = $self->rule()->name(); # The name of the rule that this production belongs to... |
146
|
0
|
0
|
|
|
|
0
|
$err .= "%Error: The \"${ruleName}\" rule references the subrule \"${subruleName}\", which is not defined in the \"${grammarName}\" grammar!\n" unless (defined($subrule)); |
147
|
|
|
|
|
|
|
} |
148
|
0
|
|
|
|
|
0
|
return $err; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub dump { |
152
|
0
|
0
|
|
0
|
0
|
0
|
my $self = shift or confess("%Error: Cannot call without a valid object!"); |
153
|
0
|
|
|
|
|
0
|
my $output = ""; |
154
|
0
|
|
|
|
|
0
|
foreach my $cond (@{$self->{_conditions}}) { |
|
0
|
|
|
|
|
0
|
|
155
|
0
|
0
|
|
|
|
0
|
$output .= " " if $output; |
156
|
0
|
|
|
|
|
0
|
$output .= $cond->dump(); |
157
|
|
|
|
|
|
|
} |
158
|
0
|
|
|
|
|
0
|
$output .= $self->_dumpParseFunction(); |
159
|
0
|
|
|
|
|
0
|
return $output; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub dumpHeir { |
163
|
400
|
50
|
|
400
|
0
|
1677
|
my $self = shift or confess("%Error: Cannot call without a valid object!"); |
164
|
400
|
|
|
|
|
660
|
my $output = ""; |
165
|
400
|
|
|
|
|
395
|
foreach my $cond (@{$self->{_conditions}}) { |
|
400
|
|
|
|
|
1409
|
|
166
|
400
|
50
|
|
|
|
1401
|
$output .= " " if $output; |
167
|
400
|
|
|
|
|
1289
|
$output .= $cond->dump(); |
168
|
|
|
|
|
|
|
} |
169
|
400
|
|
|
|
|
1904
|
return $output; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub pick { |
173
|
805
|
50
|
|
805
|
0
|
1873
|
my $self = shift or confess("%Error: Cannot call without a valid object!"); |
174
|
805
|
|
|
|
|
3368
|
my %args = ( match=>1, # Default is to pick matching data |
175
|
|
|
|
|
|
|
vals => { }, # Hash of values of various hard-coded sub-rules (by name) |
176
|
|
|
|
|
|
|
@_ ); |
177
|
805
|
|
|
|
|
2419
|
my @conds = $self->conditions(); |
178
|
805
|
|
|
|
|
1267
|
my $badCond; |
179
|
805
|
|
|
|
|
1093
|
my $val = ""; |
180
|
|
|
|
|
|
|
|
181
|
805
|
100
|
|
|
|
1815
|
if (!$args{match}) { |
182
|
132
|
|
|
|
|
449
|
my @badConds; |
183
|
132
|
|
|
|
|
228
|
foreach my $cond (@conds) { |
184
|
233
|
50
|
66
|
|
|
966
|
next if ($cond->isQuantSupported() && $cond->zeroOrMore()); # Cannot corrupt |
185
|
233
|
|
|
|
|
680
|
push(@badConds, $cond); |
186
|
|
|
|
|
|
|
} |
187
|
132
|
|
|
|
|
6890
|
my $i = int(rand($#badConds+1)); |
188
|
132
|
|
|
|
|
274
|
$badCond = $badConds[$i]; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
805
|
|
|
|
|
2114
|
for (my $i=0; $i <= $#conds; $i++) { |
192
|
1007
|
|
66
|
|
|
7001
|
$val .= $conds[$i]->pick(%args, match=>($args{match} || ((defined($badCond) && ($badCond==$conds[$i]))?0:1)) ); |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
805
|
|
|
|
|
31794
|
return( $val ); |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# Returns true (1) if this production contains any of the rules specified by the "vals" argument |
199
|
|
|
|
|
|
|
sub containsVals { |
200
|
1812
|
50
|
|
1812
|
0
|
4586
|
my $self = shift or confess("%Error: Cannot call without a valid object!"); |
201
|
1812
|
|
|
|
|
9261
|
my %args = ( vals => { }, # Hash of values of various hard-coded sub-rules (by name) |
202
|
|
|
|
|
|
|
@_ ); |
203
|
1812
|
|
|
|
|
7597
|
foreach my $cond ($self->conditions()) { |
204
|
2014
|
50
|
|
|
|
7671
|
return 1 if $cond->containsVals(%args); |
205
|
|
|
|
|
|
|
} |
206
|
1812
|
|
|
|
|
15574
|
return 0; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
###################################################################### |
210
|
|
|
|
|
|
|
#### Accessors |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub action { |
213
|
0
|
0
|
|
0
|
0
|
0
|
my $self = shift or confess("%Error: Cannot call name() without a valid object!"); |
214
|
0
|
|
|
|
|
0
|
return $self->{_action}; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub rule { # Rule that this Production belongs to |
218
|
0
|
0
|
|
0
|
1
|
0
|
my $self = shift or confess("%Error: Cannot call rule() without a valid object!"); |
219
|
0
|
|
|
|
|
0
|
return $self->{_rule}; |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
sub name { # Name of the Production (optional) |
223
|
0
|
0
|
|
0
|
0
|
0
|
my $self = shift or confess("%Error: Cannot call rule() without a valid object!"); |
224
|
0
|
|
|
|
|
0
|
return $self->{_name}; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub number { # Production number on its Rule (required if defined(rule())) |
228
|
0
|
0
|
|
0
|
0
|
0
|
my $self = shift or confess("%Error: Cannot call rule() without a valid object!"); |
229
|
0
|
|
|
|
|
0
|
return $self->{_number}; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub grammar { |
233
|
0
|
0
|
|
0
|
1
|
0
|
my $self = shift or confess("%Error: Cannot call grammar() without a valid object!"); |
234
|
0
|
0
|
|
|
|
0
|
my $grammar = $self->rule()->grammar() if defined($self->rule()); |
235
|
0
|
|
|
|
|
0
|
return $grammar; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
sub conditions { |
239
|
2617
|
50
|
|
2617
|
1
|
8318
|
my $self = shift or confess("%Error: Cannot call conditions() without a valid object!"); |
240
|
2617
|
|
|
|
|
3322
|
return (@{$self->{_conditions}}); |
|
2617
|
|
|
|
|
7979
|
|
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
###################################################################### |
244
|
|
|
|
|
|
|
#### Private Functions |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub _dumpParseFunction { |
247
|
0
|
0
|
|
0
|
|
|
my $self = shift or confess("%Error: Cannot call without a valid object!"); |
248
|
0
|
|
|
|
|
|
my $output = "\n\t\t\t {\t"; |
249
|
0
|
|
|
|
|
|
my $indent = "\n\t\t\t\t"; |
250
|
|
|
|
|
|
|
|
251
|
0
|
0
|
|
|
|
|
if (defined($self->{_action})) { |
252
|
0
|
|
|
|
|
|
$output .= $self->{_action} . " }"; |
253
|
0
|
|
|
|
|
|
return $output; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
# Determine whether this is a single terminal production or not |
256
|
0
|
|
|
|
|
|
my @conds = @{$self->{_conditions}}; |
|
0
|
|
|
|
|
|
|
257
|
0
|
|
|
|
|
|
my $ind = 1; # Index 0 is the rule name |
258
|
0
|
|
|
|
|
|
$output .= 'my $val=""; my $obj={val=>undef,offset=>$itempos[1]{offset}{from},len=>0,rules=>{}};'; |
259
|
0
|
|
|
|
|
|
foreach my $cond (@conds) { |
260
|
0
|
|
|
|
|
|
$output .= $indent; |
261
|
0
|
0
|
|
|
|
|
my $sName = $cond->isSubrule() ? $cond->subrule()->name() : ""; # Name of subrule, if subrule... |
262
|
0
|
0
|
0
|
|
|
|
my $sKeep = $sName ? $cond->subrule()->{keep}||"" : ""; # Keep this subrule? |
263
|
0
|
0
|
0
|
|
|
|
my $sParse = $sName ? $cond->subrule()->{parse}||"" : ""; # Parse this subrule (preserve heirarchy beneath it) |
264
|
0
|
0
|
|
|
|
|
if ($cond->once()) { |
265
|
|
|
|
|
|
|
#$output .= "if (ref(\$item[$ind])) { \$val.=\$item[$ind]->{val}; } else { \$val.=\$item[$ind]; }"; |
266
|
0
|
0
|
|
|
|
|
if ($sName) { |
267
|
0
|
|
|
|
|
|
$output .= "\$val.=\$item[$ind]->{val};"; |
268
|
0
|
0
|
|
|
|
|
if ($sKeep eq "once") { |
|
|
0
|
|
|
|
|
|
269
|
0
|
|
|
|
|
|
$output .= " \$obj->{rules}{$sName}=\$item[$ind];"; |
270
|
|
|
|
|
|
|
} elsif ($sKeep eq "all") { |
271
|
0
|
|
|
|
|
|
$output .= " \$obj->{rules}{$sName}||=[]; push(\@{\$obj->{rules}{$sName}}, \$item[$ind]);"; |
272
|
|
|
|
|
|
|
} |
273
|
0
|
0
|
|
|
|
|
if (!$sParse) { # Not adding a new level of parse, so flatten rules |
274
|
0
|
|
|
|
|
|
$output .= "${indent}foreach my \$j (keys \%{\$item[$ind]->{rules}}) {" |
275
|
|
|
|
|
|
|
."${indent}\tmy \$o=\$item[$ind]->{rules}{\$j};" |
276
|
|
|
|
|
|
|
."${indent}\tif (ref(\$o) eq \"ARRAY\") { \$obj->{rules}{\$j}||=[]; push(\@{\$obj->{rules}{\$j}}, \$o); }" |
277
|
|
|
|
|
|
|
."${indent}\telse { \$obj->{rules}{\$j}=\$o; } }"; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
} else { |
280
|
0
|
|
|
|
|
|
$output .= "\$val.=\$item[$ind];"; |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
} else { |
283
|
|
|
|
|
|
|
#$output .= "foreach my \$i (\@{\$item[$ind]}) { if(ref(\$i)){ \$val.=\$i->{val}; } else { \$val.=\$i; }"; |
284
|
0
|
0
|
|
|
|
|
if ($sName) { |
285
|
0
|
|
|
|
|
|
$output .= "foreach my \$i (\@{\$item[$ind]}) { \$val.=\$i->{val};"; |
286
|
0
|
0
|
|
|
|
|
if ($sKeep eq "once") { |
|
|
0
|
|
|
|
|
|
287
|
0
|
|
|
|
|
|
$output .= " \$obj->{rules}{$sName}=\$i;"; |
288
|
|
|
|
|
|
|
} elsif ($sKeep eq "all") { |
289
|
0
|
|
|
|
|
|
$output .= " \$obj->{rules}{$sName} ||= []; push(\@{\$obj->{rules}{$sName}}, \$i);"; |
290
|
|
|
|
|
|
|
} |
291
|
0
|
0
|
|
|
|
|
if (!$sParse) { # Not adding a new level of parse, so flatten rules |
292
|
0
|
|
|
|
|
|
$output .= "${indent}\tforeach my \$j (keys \%{\$i->{rules}}) {" |
293
|
|
|
|
|
|
|
."${indent}\t\tmy \$o=\$i->{rules}{\$j};" |
294
|
|
|
|
|
|
|
."${indent}\t\tif (ref(\$o) eq \"ARRAY\") { \$obj->{rules}{\$j}||=[]; push(\@{\$obj->{rules}{\$j}}, \$o); }" |
295
|
|
|
|
|
|
|
."${indent}\t\telse { \$obj->{rules}{\$j}=\$o; } }"; |
296
|
|
|
|
|
|
|
} |
297
|
0
|
|
|
|
|
|
$output .= " }"; |
298
|
|
|
|
|
|
|
} else { |
299
|
0
|
|
|
|
|
|
$output .= "foreach my \$i (\@{\$item[$ind]}) { \$val.=\$i; }"; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
} |
302
|
0
|
|
|
|
|
|
$ind++; |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
#$output .= " print(\$item[0],\" [\",\$itempos[1]{offset}{from},\"..\${thisoffset}]\\n\");"; |
305
|
0
|
0
|
0
|
|
|
|
(defined($self->rule()) and $self->rule()->name()) or confess("%Error: _dumpParseFunction(): Rule is not defined or the Rule is anonymous (no name)!"); |
306
|
0
|
|
|
|
|
|
my $ruleName = $self->rule()->name(); |
307
|
0
|
|
|
|
|
|
my $prodNum = $self->number(); |
308
|
0
|
0
|
|
|
|
|
($self->grammar()->rule($ruleName) == $self->rule()) or confess("%Error: Internal error! Cannot find our Rule \"$ruleName\" on our RandGen!"); |
309
|
|
|
|
|
|
|
#$output .= " \$thisparser->{local}{grammar}->rule(\"$ruleName\")->production($prodNum);"; |
310
|
0
|
|
|
|
|
|
$output .= $indent.'$obj->{val}=$val; $obj->{len}=length($val);'; |
311
|
0
|
|
|
|
|
|
$output .= ' $return=$obj; }'; |
312
|
0
|
|
|
|
|
|
return $output; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
###################################################################### |
316
|
|
|
|
|
|
|
#### Package return |
317
|
|
|
|
|
|
|
1; |
318
|
|
|
|
|
|
|
__END__ |