line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# ----------------------------------------------------------------------------------------------------- # |
2
|
|
|
|
|
|
|
# MarpaX::Symboltable # |
3
|
|
|
|
|
|
|
# # |
4
|
|
|
|
|
|
|
# manage a symbol table with rules parsed from an antlr4 grammar. # |
5
|
|
|
|
|
|
|
# # |
6
|
|
|
|
|
|
|
# ----------------------------------------------------------------------------------------------------- # |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
package MarpaX::G4::Symboltable; |
9
|
|
|
|
|
|
|
|
10
|
2
|
|
|
2
|
|
11
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
56
|
|
11
|
2
|
|
|
2
|
|
24
|
use warnings FATAL => 'all'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
65
|
|
12
|
2
|
|
|
2
|
|
10
|
use Data::Dumper; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
84
|
|
13
|
2
|
|
|
2
|
|
11
|
use MarpaX::G4::Parser; |
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
3864
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub new |
16
|
|
|
|
|
|
|
{ |
17
|
1
|
|
|
1
|
0
|
2
|
my $invocant = shift; |
18
|
1
|
|
33
|
|
|
6
|
my $class = ref($invocant) || $invocant; # Object or class name |
19
|
1
|
|
|
|
|
3
|
my $self = {}; # initiate our handy hashref |
20
|
1
|
|
|
|
|
2
|
bless($self,$class); # make it usable |
21
|
|
|
|
|
|
|
|
22
|
1
|
|
|
|
|
7
|
$self->{symboltable} = {}; |
23
|
1
|
|
|
|
|
2
|
$self->{startrule} = undef; |
24
|
1
|
|
|
|
|
2
|
$self->{currentidx} = -1; |
25
|
1
|
|
|
|
|
3
|
$self->{ruletable} = []; |
26
|
|
|
|
|
|
|
|
27
|
1
|
|
|
|
|
2
|
return $self; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
2
|
|
|
2
|
0
|
4
|
sub symbols { my ($self) = @_; return keys %{$self->{symboltable}}; } |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
11
|
|
31
|
3
|
|
|
3
|
0
|
6
|
sub startrule { my ($self) = @_; return $self->{startrule}; } |
|
3
|
|
|
|
|
7
|
|
32
|
2
|
|
|
2
|
0
|
3
|
sub ruletable { my ($self) = @_; return $self->{ruletable}; } |
|
2
|
|
|
|
|
4
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub setStartRule |
35
|
|
|
|
|
|
|
{ |
36
|
0
|
|
|
0
|
0
|
0
|
my ($self, $rulename) = @_; |
37
|
0
|
0
|
|
|
|
0
|
die "can't set non-existent rule $rulename as start rule" if !exists $self->{symboltable}{$rulename}; |
38
|
0
|
|
|
|
|
0
|
my $symbol = $self->{symboltable}{$rulename}; |
39
|
0
|
|
|
|
|
0
|
$self->{startrule} = { name => $rulename, index => $symbol->{index} }; |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub rule |
43
|
|
|
|
|
|
|
{ |
44
|
85
|
|
|
85
|
0
|
99
|
my ($self, $rulename) = @_; |
45
|
85
|
50
|
33
|
|
|
123
|
$self->addEOF() if $rulename eq "EOF" && !exists $self->{symboltable}{$rulename}; |
46
|
85
|
100
|
66
|
|
|
191
|
return undef if !defined $rulename || !exists $self->{symboltable}{$rulename}; |
47
|
67
|
|
|
|
|
108
|
return $self->{symboltable}{$rulename}; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub tagrule |
51
|
|
|
|
|
|
|
{ |
52
|
28
|
|
|
28
|
0
|
36
|
my ($self, $rulename, $status) = @_; |
53
|
28
|
50
|
|
|
|
44
|
die "trying to tag nonexistent rule '$rulename'" if !exists $self->{symboltable}{$rulename}; |
54
|
28
|
|
|
|
|
34
|
my $symbol = $self->{symboltable}{$rulename}; |
55
|
28
|
50
|
|
|
|
54
|
$symbol->{generationstatus} = defined($status) ? $status : 'todo'; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
## |
59
|
|
|
|
|
|
|
# create a synthetic 'EOF' token, so that the grammar won't fail. |
60
|
|
|
|
|
|
|
## |
61
|
|
|
|
|
|
|
sub addEOF |
62
|
|
|
|
|
|
|
{ |
63
|
0
|
|
|
0
|
0
|
0
|
my ($self) = @_; |
64
|
|
|
|
|
|
|
|
65
|
0
|
|
|
|
|
0
|
$self->addRule( -1, |
66
|
|
|
|
|
|
|
{ |
67
|
|
|
|
|
|
|
name => 'EOF', |
68
|
|
|
|
|
|
|
type => 'fragment', |
69
|
|
|
|
|
|
|
generationstatus => 'synthetic', |
70
|
|
|
|
|
|
|
'rightsides' => [ |
71
|
|
|
|
|
|
|
{ |
72
|
|
|
|
|
|
|
'rhs' => { |
73
|
|
|
|
|
|
|
'token' => { |
74
|
|
|
|
|
|
|
'value' => '\z', |
75
|
|
|
|
|
|
|
'type' => 'literal' |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
], |
80
|
|
|
|
|
|
|
}); |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub rulestatus |
84
|
|
|
|
|
|
|
{ |
85
|
23
|
|
|
23
|
0
|
31
|
my ($self, $rulename, $status) = @_; |
86
|
|
|
|
|
|
|
|
87
|
23
|
50
|
33
|
|
|
38
|
$self->addEOF() if $rulename eq "EOF" && !exists $self->{symboltable}{$rulename}; |
88
|
|
|
|
|
|
|
|
89
|
23
|
50
|
|
|
|
36
|
die "trying to query nonexistent rule '$rulename'" if !exists $self->{symboltable}{$rulename}; |
90
|
23
|
|
|
|
|
27
|
my $symbol = $self->{symboltable}{$rulename}; |
91
|
23
|
100
|
|
|
|
42
|
return exists $symbol->{generationstatus} ? $symbol->{generationstatus} : undef; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
## ----------- |
95
|
|
|
|
|
|
|
# import the parse tree into the symbol table |
96
|
|
|
|
|
|
|
## ----------- |
97
|
|
|
|
|
|
|
sub importParseTree |
98
|
|
|
|
|
|
|
{ |
99
|
1
|
|
|
1
|
0
|
5
|
my ($self, $tree) = @_; |
100
|
|
|
|
|
|
|
|
101
|
1
|
50
|
|
|
|
4
|
die "parse tree must be an array of rules" if ref($tree) ne "ARRAY"; |
102
|
1
|
|
|
|
|
3
|
my $ruleindex = $self->{currentidx}; |
103
|
|
|
|
|
|
|
|
104
|
1
|
|
|
|
|
3
|
for my $rule (@$tree) |
105
|
|
|
|
|
|
|
{ |
106
|
16
|
|
|
|
|
16
|
++$ruleindex; |
107
|
16
|
50
|
|
|
|
22
|
die "rule[$ruleindex] is not a hash" if ref($rule) ne "HASH"; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
SWITCH: { |
110
|
16
|
100
|
|
|
|
15
|
(exists $rule->{name}) && do { |
|
16
|
|
|
|
|
22
|
|
111
|
14
|
|
|
|
|
16
|
my $name = $rule->{name}; |
112
|
|
|
|
|
|
|
# printf "rule[$ruleindex] : %s\n", $name; |
113
|
14
|
|
|
|
|
21
|
$self->addRule($ruleindex, $rule); |
114
|
14
|
100
|
|
|
|
20
|
$self->{startrule} = { name => $name, index => $ruleindex } if !defined $self->{startrule}; |
115
|
14
|
|
|
|
|
17
|
last SWITCH; |
116
|
|
|
|
|
|
|
}; |
117
|
2
|
50
|
|
|
|
4
|
(exists $rule->{grammarspec}) && do { |
118
|
|
|
|
|
|
|
# printf "rule[$ruleindex] : grammar %s\n", $rule->{grammarspec}; |
119
|
2
|
|
|
|
|
3
|
last SWITCH; |
120
|
|
|
|
|
|
|
}; |
121
|
0
|
0
|
|
|
|
0
|
(exists $rule->{comment}) && do { |
122
|
|
|
|
|
|
|
# printf "rule[$ruleindex] : comment\n"; |
123
|
0
|
|
|
|
|
0
|
$self->addComment($ruleindex, $rule); |
124
|
0
|
|
|
|
|
0
|
last SWITCH; |
125
|
|
|
|
|
|
|
}; |
126
|
0
|
|
|
|
|
0
|
do { |
127
|
0
|
|
|
|
|
0
|
die "rule[$ruleindex] : can't process"; |
128
|
0
|
|
|
|
|
0
|
last SWITCH; |
129
|
|
|
|
|
|
|
}; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
1
|
|
|
|
|
3
|
$self->{currentidx} = $ruleindex; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub addRule |
137
|
|
|
|
|
|
|
{ |
138
|
14
|
|
|
14
|
0
|
17
|
my ($self, $ruleindex, $rule) = @_; |
139
|
|
|
|
|
|
|
|
140
|
14
|
|
|
|
|
15
|
my $name = $rule->{name}; |
141
|
14
|
|
|
|
|
12
|
my $symboltable = \%{$self->{symboltable}}; |
|
14
|
|
|
|
|
17
|
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
SWITCH: { |
144
|
14
|
50
|
|
|
|
14
|
(exists $rule->{rightsides}) && do { |
|
14
|
|
|
|
|
18
|
|
145
|
14
|
50
|
|
|
|
19
|
die "$name is a duplicate rule" if exists $symboltable->{$name}; |
146
|
14
|
|
|
|
|
16
|
$rule->{index} = $ruleindex; |
147
|
14
|
|
|
|
|
22
|
$symboltable->{$name} = $rule; |
148
|
14
|
|
|
|
|
14
|
last SWITCH; |
149
|
|
|
|
|
|
|
}; |
150
|
0
|
|
|
|
|
0
|
do { |
151
|
0
|
|
|
|
|
0
|
die "can't import rule[$ruleindex] : $name"; |
152
|
0
|
|
|
|
|
0
|
last SWITCH; |
153
|
|
|
|
|
|
|
}; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# add the rule to the index-based lookup table if it is not a synthetic rule. |
157
|
14
|
50
|
|
|
|
27
|
$self->{ruletable}->[$ruleindex] = $rule if $ruleindex != -1; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub addComment |
161
|
|
|
|
|
|
|
{ |
162
|
0
|
|
|
0
|
0
|
|
my ($self, $ruleindex, $rule) = @_; |
163
|
0
|
|
|
|
|
|
$self->{ruletable}->[$ruleindex] = $rule; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
## ----------- |
167
|
|
|
|
|
|
|
# recursively walk the symbol table to verify consistency |
168
|
|
|
|
|
|
|
## ----------- |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
sub walkgroup |
171
|
|
|
|
|
|
|
{ |
172
|
0
|
|
|
0
|
0
|
|
my ($rulename, $tokengroup) = @_; |
173
|
|
|
|
|
|
|
|
174
|
0
|
|
|
|
|
|
my $namelist = []; |
175
|
|
|
|
|
|
|
|
176
|
0
|
|
|
|
|
|
my $definition = $tokengroup->{definition}; |
177
|
0
|
|
|
|
|
|
for my $e (@$definition) |
178
|
|
|
|
|
|
|
{ |
179
|
0
|
0
|
|
|
|
|
if (ref $e->{token} eq "") |
180
|
|
|
|
|
|
|
{ |
181
|
0
|
|
|
|
|
|
push @$namelist, $e->{token}; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
else |
184
|
|
|
|
|
|
|
{ |
185
|
0
|
0
|
0
|
|
|
|
if (ref $e eq "HASH" && exists $e->{token}) |
186
|
|
|
|
|
|
|
{ |
187
|
0
|
|
|
|
|
|
my $sr = walktoken($rulename, $e->{token}); |
188
|
0
|
|
|
|
|
|
push (@$namelist, @$sr); |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
else |
191
|
|
|
|
|
|
|
{ |
192
|
0
|
|
|
|
|
|
$Data::Dumper::Indent = 1; |
193
|
0
|
|
|
|
|
|
print Dumper($tokengroup); |
194
|
0
|
|
|
|
|
|
die "can't process group for rule $rulename"; |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
0
|
|
|
|
|
|
return $namelist; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub walktoken |
203
|
|
|
|
|
|
|
{ |
204
|
0
|
|
|
0
|
0
|
|
my ($rulename, $token) = @_; |
205
|
|
|
|
|
|
|
|
206
|
0
|
|
|
|
|
|
my $namelist = []; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
SWITCH: |
209
|
|
|
|
|
|
|
{ |
210
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{type} && $token->{type} eq "rulegroup") && do { |
|
0
|
|
0
|
|
|
|
|
211
|
0
|
|
|
|
|
|
my $sr = walkgroup($rulename, $token->{token}); |
212
|
0
|
|
|
|
|
|
push (@$namelist, @$sr); |
213
|
0
|
|
|
|
|
|
last SWITCH; |
214
|
|
|
|
|
|
|
}; |
215
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{type} && $token->{type} eq "tokengroup") && do { |
|
|
|
0
|
|
|
|
|
216
|
0
|
|
|
|
|
|
my $sr = walkgroup($rulename, $token->{token}); |
217
|
0
|
|
|
|
|
|
push (@$namelist, @$sr); |
218
|
0
|
|
|
|
|
|
last SWITCH; |
219
|
|
|
|
|
|
|
}; |
220
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{token}) && do { |
221
|
0
|
|
|
|
|
|
my $nestedtoken = $token->{token}; |
222
|
0
|
|
|
|
|
|
my $sr = walktoken($rulename, $nestedtoken); |
223
|
0
|
|
|
|
|
|
push (@$namelist, @$sr); |
224
|
0
|
|
|
|
|
|
last SWITCH; |
225
|
|
|
|
|
|
|
}; |
226
|
0
|
0
|
|
|
|
|
(ref $token eq "") && do { |
227
|
0
|
|
|
|
|
|
push @$namelist, $token; |
228
|
0
|
|
|
|
|
|
last SWITCH; |
229
|
|
|
|
|
|
|
}; |
230
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{type} && $token->{type} eq "literal") && do { |
|
|
|
0
|
|
|
|
|
231
|
0
|
|
|
|
|
|
last SWITCH; |
232
|
|
|
|
|
|
|
}; |
233
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{type} && $token->{type} eq "class") && do { |
|
|
|
0
|
|
|
|
|
234
|
0
|
|
|
|
|
|
last SWITCH; |
235
|
|
|
|
|
|
|
}; |
236
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{type} && $token->{type} eq "regex") && do { |
|
|
|
0
|
|
|
|
|
237
|
0
|
|
|
|
|
|
last SWITCH; |
238
|
|
|
|
|
|
|
}; |
239
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{type} && $token->{type} eq "range") && do { |
|
|
|
0
|
|
|
|
|
240
|
0
|
|
|
|
|
|
last SWITCH; |
241
|
|
|
|
|
|
|
}; |
242
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{type} && $token->{type} eq "value") && do { |
|
|
|
0
|
|
|
|
|
243
|
0
|
|
|
|
|
|
last SWITCH; |
244
|
|
|
|
|
|
|
}; |
245
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{comment}) && do { |
246
|
0
|
|
|
|
|
|
last SWITCH; |
247
|
|
|
|
|
|
|
}; |
248
|
0
|
0
|
0
|
|
|
|
(ref $token eq "HASH" && exists $token->{action}) && do { |
249
|
0
|
|
|
|
|
|
last SWITCH; |
250
|
|
|
|
|
|
|
}; |
251
|
0
|
|
|
|
|
|
do { |
252
|
0
|
|
|
|
|
|
$Data::Dumper::Indent = 1; |
253
|
0
|
|
|
|
|
|
print Dumper($token); |
254
|
0
|
|
|
|
|
|
die "can't process token for rule $rulename"; |
255
|
0
|
|
|
|
|
|
last SWITCH; |
256
|
|
|
|
|
|
|
}; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
0
|
|
|
|
|
|
return $namelist; |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
sub walknonterminal |
263
|
|
|
|
|
|
|
{ |
264
|
0
|
|
|
0
|
0
|
|
my ( $rulename, $nonterminal ) = @_; |
265
|
|
|
|
|
|
|
|
266
|
0
|
|
|
|
|
|
my $namelist = []; |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
SWITCH: |
269
|
|
|
|
|
|
|
{ |
270
|
0
|
0
|
|
|
|
|
(exists $nonterminal->{rhs}) && do { |
|
0
|
|
|
|
|
|
|
271
|
0
|
|
|
|
|
|
my $rhs = $nonterminal->{rhs}; |
272
|
0
|
|
|
|
|
|
my $sr = walktoken($rulename, $rhs); |
273
|
0
|
|
|
|
|
|
push (@$namelist, @$sr); |
274
|
0
|
|
|
|
|
|
last SWITCH; |
275
|
|
|
|
|
|
|
}; |
276
|
0
|
|
|
|
|
|
do { |
277
|
0
|
|
|
|
|
|
$Data::Dumper::Indent = 1; |
278
|
0
|
|
|
|
|
|
print Dumper($nonterminal); |
279
|
0
|
|
|
|
|
|
die "can't process nonterminal for rule $rulename"; |
280
|
0
|
|
|
|
|
|
last SWITCH; |
281
|
|
|
|
|
|
|
}; |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
0
|
|
|
|
|
|
return $namelist; |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
sub walksubrule |
288
|
|
|
|
|
|
|
{ |
289
|
0
|
|
|
0
|
0
|
|
my ($rulename, $rule) = @_; |
290
|
|
|
|
|
|
|
|
291
|
0
|
0
|
0
|
|
|
|
if (ref $rule ne "HASH" || !exists $rule->{rightsides}) |
292
|
|
|
|
|
|
|
{ |
293
|
0
|
|
|
|
|
|
$Data::Dumper::Indent = 1; |
294
|
0
|
|
|
|
|
|
print Dumper($rule); |
295
|
0
|
|
|
|
|
|
die "'rule' is not a hash"; |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
|
298
|
0
|
|
|
|
|
|
my $rhs = $rule->{rightsides}; |
299
|
|
|
|
|
|
|
|
300
|
0
|
0
|
|
|
|
|
return [] if !defined $rhs; |
301
|
|
|
|
|
|
|
|
302
|
0
|
0
|
|
|
|
|
if (ref $rhs ne "ARRAY") |
303
|
|
|
|
|
|
|
{ |
304
|
0
|
|
|
|
|
|
$Data::Dumper::Indent = 1; |
305
|
0
|
|
|
|
|
|
print Dumper($rhs); |
306
|
0
|
|
|
|
|
|
die "'rhs' is not an array ref"; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
0
|
|
|
|
|
|
my $namelist = []; |
310
|
|
|
|
|
|
|
|
311
|
0
|
|
|
|
|
|
for my $r (@$rhs) |
312
|
|
|
|
|
|
|
{ |
313
|
0
|
|
|
|
|
|
my $sr = walknonterminal($rulename, $r); |
314
|
0
|
|
|
|
|
|
push (@$namelist, @$sr); |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
0
|
|
|
|
|
|
return $namelist; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
sub joinReferences |
321
|
|
|
|
|
|
|
{ |
322
|
0
|
|
|
0
|
0
|
|
my ($sr) = @_; |
323
|
|
|
|
|
|
|
|
324
|
0
|
|
|
|
|
|
my $temp = {}; |
325
|
0
|
|
|
|
|
|
my $result = ""; |
326
|
0
|
|
|
|
|
|
my $delim = ""; |
327
|
|
|
|
|
|
|
|
328
|
0
|
|
|
|
|
|
for my $s (@$sr) |
329
|
|
|
|
|
|
|
{ |
330
|
0
|
0
|
|
|
|
|
if (!exists $temp->{$s}) |
331
|
|
|
|
|
|
|
{ |
332
|
0
|
|
|
|
|
|
$temp->{$s} = 1; |
333
|
0
|
|
|
|
|
|
my $len = 16 - length($s); |
334
|
0
|
|
|
|
|
|
my $ts = $s; |
335
|
0
|
0
|
|
|
|
|
if ($len < 0) |
336
|
|
|
|
|
|
|
{ |
337
|
0
|
|
|
|
|
|
$len = 0; |
338
|
0
|
|
|
|
|
|
$ts = substr($ts, 0, 16); |
339
|
|
|
|
|
|
|
} |
340
|
0
|
|
|
|
|
|
my $pad = ""; |
341
|
0
|
0
|
|
|
|
|
$pad = ' ' x $len if $len > 0; |
342
|
0
|
|
|
|
|
|
$result .= $delim . $ts . $pad; |
343
|
0
|
|
|
|
|
|
$delim = " "; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
0
|
|
|
|
|
|
return $result; |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
sub verifySymbolNames |
351
|
|
|
|
|
|
|
{ |
352
|
0
|
|
|
0
|
0
|
|
my ($self, $rulename, $symbolnames ) = @_; |
353
|
|
|
|
|
|
|
|
354
|
0
|
|
|
|
|
|
my $symboltable = \%{$self->{symboltable}}; |
|
0
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
|
356
|
0
|
|
|
|
|
|
for my $sn (@$symbolnames) |
357
|
|
|
|
|
|
|
{ |
358
|
0
|
0
|
|
|
|
|
if (!exists $symboltable->{$sn}) |
359
|
|
|
|
|
|
|
{ |
360
|
0
|
|
|
|
|
|
printf "[%-1s][%-45s][%-2s] missing from symbol table : %s\n", "", $rulename, "", $sn; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub validateSymbolTable |
366
|
|
|
|
|
|
|
{ |
367
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
368
|
|
|
|
|
|
|
|
369
|
0
|
|
|
|
|
|
my $symboltable = \%{$self->{symboltable}}; |
|
0
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
|
printf "===\n=== Composite Rules\n===\n\n"; |
372
|
0
|
|
|
|
|
|
printf <<'END_OF_SOURCE'; |
373
|
|
|
|
|
|
|
+-------------------------------------------------------- rule name |
374
|
|
|
|
|
|
|
+--!-------------------------------------------------------- Fragment (F), Lexeme (L) or regular rule |
375
|
|
|
|
|
|
|
! ! +--------- redirected (->) or contributing rule |
376
|
|
|
|
|
|
|
! ! ! +----- number of rule references |
377
|
|
|
|
|
|
|
! ! ! ! +- list of rule references |
378
|
|
|
|
|
|
|
! ! ! ! ! |
379
|
|
|
|
|
|
|
V V V V V |
380
|
|
|
|
|
|
|
END_OF_SOURCE |
381
|
|
|
|
|
|
|
|
382
|
0
|
|
|
|
|
|
for my $name (sort keys %$symboltable) |
383
|
|
|
|
|
|
|
{ |
384
|
0
|
|
|
|
|
|
my $rule = $symboltable->{$name}; |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
SWITCH: |
387
|
|
|
|
|
|
|
{ |
388
|
0
|
|
|
|
|
|
(exists $rule->{name}) && do |
389
|
0
|
0
|
|
|
|
|
{ |
390
|
0
|
|
|
|
|
|
my $name = $rule->{name}; |
391
|
|
|
|
|
|
|
# if ($name eq "alter_table_properties") |
392
|
|
|
|
|
|
|
# { |
393
|
|
|
|
|
|
|
# printf "found!\n"; |
394
|
|
|
|
|
|
|
# } |
395
|
0
|
|
|
|
|
|
my $symbolreferences = walksubrule($name, $rule); |
396
|
|
|
|
|
|
|
|
397
|
0
|
0
|
|
|
|
|
if (scalar @$symbolreferences > 0) |
398
|
|
|
|
|
|
|
{ |
399
|
0
|
|
|
|
|
|
my $strReferences = joinReferences($symbolreferences); |
400
|
0
|
|
|
|
|
|
my $type = ""; |
401
|
0
|
0
|
0
|
|
|
|
$type = "L" if exists $rule->{isLexeme} || (exists $rule->{grammarstate} && $rule->{grammarstate} eq "lexer"); |
|
|
|
0
|
|
|
|
|
402
|
0
|
0
|
0
|
|
|
|
$type = "F" if exists $rule->{type} && $rule->{type} eq "fragment"; |
403
|
0
|
0
|
|
|
|
|
printf "[%-1s][%-45s][%-2s][%2d] %s\n", $type, $name, (exists $rule->{redirect}) ? "->" : "", scalar @$symbolreferences, $strReferences; |
404
|
0
|
|
|
|
|
|
$self->verifySymbolNames( $name, $symbolreferences ); |
405
|
|
|
|
|
|
|
} |
406
|
0
|
|
|
|
|
|
last SWITCH; |
407
|
|
|
|
|
|
|
}; |
408
|
|
|
|
|
|
|
do |
409
|
0
|
|
|
|
|
|
{ |
410
|
0
|
|
|
|
|
|
die "can't process rule"; |
411
|
0
|
|
|
|
|
|
last SWITCH; |
412
|
|
|
|
|
|
|
}; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
|
416
|
0
|
|
|
|
|
|
printf "\n===\n=== Basic Rules\n===\n\n"; |
417
|
0
|
|
|
|
|
|
printf <<'END_OF_SOURCE'; |
418
|
|
|
|
|
|
|
+-------------------------------------------------------- rule name |
419
|
|
|
|
|
|
|
+--!-------------------------------------------------------- Fragment (F), Lexeme (L) or regular rule |
420
|
|
|
|
|
|
|
! ! +--------- redirected (->) or contributing rule |
421
|
|
|
|
|
|
|
! ! ! +----- n/a |
422
|
|
|
|
|
|
|
! ! ! ! |
423
|
|
|
|
|
|
|
V V V V |
424
|
|
|
|
|
|
|
END_OF_SOURCE |
425
|
|
|
|
|
|
|
|
426
|
0
|
|
|
|
|
|
for my $name (sort keys %$symboltable) |
427
|
|
|
|
|
|
|
{ |
428
|
0
|
|
|
|
|
|
my $rule = $symboltable->{$name}; |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
SWITCH: |
431
|
|
|
|
|
|
|
{ |
432
|
0
|
|
|
|
|
|
(exists $rule->{name}) && do |
433
|
0
|
0
|
|
|
|
|
{ |
434
|
0
|
|
|
|
|
|
my $name = $rule->{name}; |
435
|
0
|
|
|
|
|
|
my $symbolreferences = walksubrule($name, $rule); |
436
|
|
|
|
|
|
|
|
437
|
0
|
0
|
|
|
|
|
if ($name eq "TILDE_OPERATOR_PART") |
438
|
|
|
|
|
|
|
{ |
439
|
0
|
|
|
|
|
|
printf "found!\n"; |
440
|
|
|
|
|
|
|
} |
441
|
0
|
0
|
|
|
|
|
if (scalar @$symbolreferences == 0) |
442
|
|
|
|
|
|
|
{ |
443
|
0
|
|
|
|
|
|
my $type = ""; |
444
|
0
|
0
|
0
|
|
|
|
$type = "L" if exists $rule->{isLexeme} || (exists $rule->{grammarstate} && $rule->{grammarstate} eq "lexer"); |
|
|
|
0
|
|
|
|
|
445
|
0
|
0
|
0
|
|
|
|
$type = "F" if exists $rule->{type} && $rule->{type} eq "fragment"; |
446
|
0
|
0
|
|
|
|
|
printf "[%-1s][%-45s][%-2s][%2s] %s\n", $type, $name, (exists $rule->{redirect}) ? "->" : "", "", ""; |
447
|
|
|
|
|
|
|
} |
448
|
0
|
|
|
|
|
|
last SWITCH; |
449
|
|
|
|
|
|
|
}; |
450
|
|
|
|
|
|
|
do |
451
|
0
|
|
|
|
|
|
{ |
452
|
0
|
|
|
|
|
|
die "can't process rule"; |
453
|
0
|
|
|
|
|
|
last SWITCH; |
454
|
|
|
|
|
|
|
}; |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
|
458
|
0
|
|
|
|
|
|
printf "\n"; |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
1; |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
# ABSTRACT: manage symbol table of rules parsed from antlr grammar |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=head1 SYNOPSIS |
466
|
|
|
|
|
|
|
use MarpaX::G4::Symboltable; |
467
|
|
|
|
|
|
|
my $symboltable = new MarpaX::G4::Symboltable; |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
my $grammartext = readFile($infile); |
470
|
|
|
|
|
|
|
my $data = MarpaX::G4::Parser::parse_rules($grammartext); |
471
|
|
|
|
|
|
|
$symboltable->importParseTree($data); |
472
|
|
|
|
|
|
|
$symboltable->validateSymbolTable(); |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=head1 DESCRIPTION |
475
|
|
|
|
|
|
|
Import the rules from the ANTLR4 parse tree into a symbol table. |
476
|
|
|
|
|
|
|
'validateSymbolTable' does a depth-first tree traversal of the symbol table to produce a report of productions and terminal symbols. |
477
|
|
|
|
|
|
|
=cut |
478
|
|
|
|
|
|
|
|