line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyright 2022 Jeffrey Kegler |
2
|
|
|
|
|
|
|
# This file is part of Marpa::R2. Marpa::R2 is free software: you can |
3
|
|
|
|
|
|
|
# redistribute it and/or modify it under the terms of the GNU Lesser |
4
|
|
|
|
|
|
|
# General Public License as published by the Free Software Foundation, |
5
|
|
|
|
|
|
|
# either version 3 of the License, or (at your option) any later version. |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# Marpa::R2 is distributed in the hope that it will be useful, |
8
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
9
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
10
|
|
|
|
|
|
|
# Lesser General Public License for more details. |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# You should have received a copy of the GNU Lesser |
13
|
|
|
|
|
|
|
# General Public License along with Marpa::R2. If not, see |
14
|
|
|
|
|
|
|
# http://www.gnu.org/licenses/. |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
package Marpa::R2::Scanless::G; |
17
|
|
|
|
|
|
|
|
18
|
132
|
|
|
132
|
|
2687
|
use 5.010001; |
|
132
|
|
|
|
|
556
|
|
19
|
132
|
|
|
132
|
|
852
|
use strict; |
|
132
|
|
|
|
|
356
|
|
|
132
|
|
|
|
|
3019
|
|
20
|
132
|
|
|
132
|
|
1124
|
use warnings; |
|
132
|
|
|
|
|
339
|
|
|
132
|
|
|
|
|
4517
|
|
21
|
|
|
|
|
|
|
|
22
|
132
|
|
|
132
|
|
817
|
use vars qw($VERSION $STRING_VERSION); |
|
132
|
|
|
|
|
416
|
|
|
132
|
|
|
|
|
13574
|
|
23
|
|
|
|
|
|
|
$VERSION = '12.000000'; |
24
|
|
|
|
|
|
|
$STRING_VERSION = $VERSION; |
25
|
|
|
|
|
|
|
## no critic(BuiltinFunctions::ProhibitStringyEval) |
26
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
27
|
|
|
|
|
|
|
## use critic |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
package Marpa::R2::Internal::Scanless::G; |
30
|
|
|
|
|
|
|
|
31
|
132
|
|
|
132
|
|
1083
|
use Scalar::Util 'blessed'; |
|
132
|
|
|
|
|
346
|
|
|
132
|
|
|
|
|
9800
|
|
32
|
132
|
|
|
132
|
|
2313
|
use English qw( -no_match_vars ); |
|
132
|
|
|
|
|
341
|
|
|
132
|
|
|
|
|
1045
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# names of packages for strings |
35
|
|
|
|
|
|
|
our $PACKAGE = 'Marpa::R2::Scanless::G'; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub Marpa::R2::Internal::Scanless::meta_grammar { |
38
|
|
|
|
|
|
|
|
39
|
72
|
|
|
72
|
|
283
|
my $meta_slg = bless [], 'Marpa::R2::Scanless::G'; |
40
|
72
|
|
|
|
|
390
|
state $hashed_metag = Marpa::R2::Internal::MetaG::hashed_grammar(); |
41
|
72
|
|
|
|
|
387
|
$meta_slg->[Marpa::R2::Internal::Scanless::G::TRACE_TERMINALS] = 0; |
42
|
72
|
|
|
|
|
684
|
Marpa::R2::Internal::Scanless::G::hash_to_runtime( $meta_slg, |
43
|
|
|
|
|
|
|
$hashed_metag, |
44
|
|
|
|
|
|
|
{ bless_package => 'Marpa::R2::Internal::MetaAST_Nodes' } ); |
45
|
|
|
|
|
|
|
|
46
|
72
|
|
|
|
|
482
|
my $thick_g1_grammar = |
47
|
|
|
|
|
|
|
$meta_slg->[Marpa::R2::Internal::Scanless::G::THICK_G1_GRAMMAR]; |
48
|
72
|
|
|
|
|
231
|
my @mask_by_rule_id; |
49
|
|
|
|
|
|
|
$mask_by_rule_id[$_] = $thick_g1_grammar->_rule_mask($_) |
50
|
72
|
|
|
|
|
545
|
for $thick_g1_grammar->rule_ids(); |
51
|
72
|
|
|
|
|
474
|
$meta_slg->[Marpa::R2::Internal::Scanless::G::MASK_BY_RULE_ID] = |
52
|
|
|
|
|
|
|
\@mask_by_rule_id; |
53
|
72
|
|
|
|
|
243
|
$meta_slg->[Marpa::R2::Internal::Scanless::G::TRACE_TERMINALS] = 0; |
54
|
|
|
|
|
|
|
|
55
|
72
|
|
|
|
|
441
|
return $meta_slg; |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
} ## end sub Marpa::R2::Internal::Scanless::meta_grammar |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::new { |
60
|
199
|
|
|
199
|
|
74236
|
my ( $class, @hash_ref_args ) = @_; |
61
|
|
|
|
|
|
|
|
62
|
199
|
|
|
|
|
601
|
my $slg = []; |
63
|
199
|
|
|
|
|
595
|
bless $slg, $class; |
64
|
|
|
|
|
|
|
|
65
|
199
|
|
|
|
|
898
|
my ($dsl, $g1_args) = Marpa::R2::Internal::Scanless::G::set ( $slg, 'new', @hash_ref_args ); |
66
|
199
|
|
|
|
|
1385
|
my $ast = Marpa::R2::Internal::MetaAST->new( $dsl ); |
67
|
196
|
|
|
|
|
1102
|
my $hashed_ast = $ast->ast_to_hash(); |
68
|
196
|
|
|
|
|
1193
|
Marpa::R2::Internal::Scanless::G::hash_to_runtime($slg, $hashed_ast, $g1_args); |
69
|
180
|
|
|
|
|
36276
|
return $slg; |
70
|
|
|
|
|
|
|
} ## end sub Marpa::R2::Scanless::G::new |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::set { |
73
|
1
|
|
|
1
|
|
1367
|
my ( $slg, @hash_ref_args ) = @_; |
74
|
1
|
|
|
|
|
6
|
Marpa::R2::Internal::Scanless::G::set ( $slg, 'set', @hash_ref_args ); |
75
|
1
|
|
|
|
|
3
|
return $slg; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# The context flag indicates whether this ::set() is called directly by the user; |
79
|
|
|
|
|
|
|
# is for the external constructor; or is for the internal ("meta") constructor. |
80
|
|
|
|
|
|
|
# "Context" flags of this kind |
81
|
|
|
|
|
|
|
# are much decried practice, and for good reason, but in this case |
82
|
|
|
|
|
|
|
# I think it is justified. |
83
|
|
|
|
|
|
|
# This logic really needs to be all in one place, and so a flag |
84
|
|
|
|
|
|
|
# to trigger the minor differences needed by the various calling |
85
|
|
|
|
|
|
|
# contexts is a small price to pay. |
86
|
|
|
|
|
|
|
sub Marpa::R2::Internal::Scanless::G::set { |
87
|
200
|
|
|
200
|
|
747
|
my ( $slg, $method, @hash_ref_args ) = @_; |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# Other possible grammar options: |
90
|
|
|
|
|
|
|
# default_rank |
91
|
|
|
|
|
|
|
# inaccessible_ok |
92
|
|
|
|
|
|
|
# unproductive_ok |
93
|
|
|
|
|
|
|
# warnings |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
state $copy_to_g1_args = |
96
|
200
|
|
|
|
|
574
|
{ map { ( $_, 1 ); } |
|
272
|
|
|
|
|
840
|
|
97
|
|
|
|
|
|
|
qw(trace_file_handle action_object default_action bless_package) }; |
98
|
|
|
|
|
|
|
state $set_method_args = |
99
|
200
|
|
|
|
|
540
|
{ map { ( $_, 1 ); } qw(trace_file_handle trace_terminals) }; |
|
136
|
|
|
|
|
481
|
|
100
|
|
|
|
|
|
|
state $new_method_args = { |
101
|
200
|
|
|
|
|
530
|
map { ( $_, 1 ); } qw(source trace_terminals), keys %{$copy_to_g1_args} |
|
408
|
|
|
|
|
821
|
|
|
68
|
|
|
|
|
313
|
|
102
|
|
|
|
|
|
|
}; |
103
|
200
|
|
|
|
|
825
|
for my $args (@hash_ref_args) { |
104
|
200
|
|
|
|
|
644
|
my $ref_type = ref $args; |
105
|
200
|
50
|
|
|
|
703
|
if ( not $ref_type ) { |
106
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( q{$slg->} |
107
|
|
|
|
|
|
|
. $method |
108
|
|
|
|
|
|
|
. qq{() expects args as ref to HASH; got non-reference instead} |
109
|
|
|
|
|
|
|
); |
110
|
|
|
|
|
|
|
} ## end if ( not $ref_type ) |
111
|
200
|
50
|
|
|
|
971
|
if ( $ref_type ne 'HASH' ) { |
112
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( q{$slg->} |
113
|
|
|
|
|
|
|
. $method |
114
|
|
|
|
|
|
|
. qq{() expects args as ref to HASH, got ref to $ref_type instead} |
115
|
|
|
|
|
|
|
); |
116
|
|
|
|
|
|
|
} ## end if ( $ref_type ne 'HASH' ) |
117
|
|
|
|
|
|
|
} ## end for my $args (@hash_ref_args) |
118
|
|
|
|
|
|
|
|
119
|
200
|
|
|
|
|
529
|
my %flat_args = (); |
120
|
200
|
|
|
|
|
569
|
for my $hash_ref (@hash_ref_args) { |
121
|
200
|
|
|
|
|
393
|
ARG: for my $arg_name ( keys %{$hash_ref} ) { |
|
200
|
|
|
|
|
778
|
|
122
|
239
|
|
|
|
|
910
|
$flat_args{$arg_name} = $hash_ref->{$arg_name}; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
200
|
|
|
|
|
481
|
my $ok_args = $set_method_args; |
127
|
200
|
100
|
|
|
|
858
|
$ok_args = $new_method_args if $method eq 'new'; |
128
|
200
|
|
|
|
|
711
|
my @bad_args = grep { not $ok_args->{$_} } keys %flat_args; |
|
239
|
|
|
|
|
1028
|
|
129
|
200
|
50
|
|
|
|
992
|
if ( scalar @bad_args ) { |
130
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( |
131
|
|
|
|
|
|
|
q{Bad named argument(s) to $slg->} |
132
|
|
|
|
|
|
|
. $method |
133
|
|
|
|
|
|
|
. q{() method: } |
134
|
|
|
|
|
|
|
. join q{ }, |
135
|
|
|
|
|
|
|
@bad_args |
136
|
|
|
|
|
|
|
); |
137
|
|
|
|
|
|
|
} ## end if ( scalar @bad_args ) |
138
|
|
|
|
|
|
|
|
139
|
200
|
|
|
|
|
518
|
my $dsl; |
140
|
200
|
100
|
|
|
|
728
|
if ( $method eq 'new' ) { |
141
|
199
|
|
|
|
|
414
|
state $arg_name = 'source'; |
142
|
199
|
|
|
|
|
513
|
$dsl = $flat_args{$arg_name}; |
143
|
199
|
50
|
|
|
|
631
|
Marpa::R2::exception( |
144
|
|
|
|
|
|
|
qq{Marpa::R2::Scanless::G::new() called without a "$arg_name" argument} |
145
|
|
|
|
|
|
|
) if not defined $dsl; |
146
|
199
|
|
|
|
|
658
|
my $ref_type = ref $dsl; |
147
|
199
|
50
|
|
|
|
625
|
if ( $ref_type ne 'SCALAR' ) { |
148
|
0
|
0
|
|
|
|
0
|
my $desc = $ref_type ? "a ref to $ref_type" : 'not a ref'; |
149
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( |
150
|
|
|
|
|
|
|
qq{'$arg_name' name argument to Marpa::R2::Scanless::G->new() is $desc\n}, |
151
|
|
|
|
|
|
|
" It should be a ref to a string\n" |
152
|
|
|
|
|
|
|
); |
153
|
|
|
|
|
|
|
} ## end if ( $ref_type ne 'SCALAR' ) |
154
|
199
|
50
|
|
|
|
381
|
if ( not defined ${$dsl} ) { |
|
199
|
|
|
|
|
720
|
|
155
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( |
156
|
|
|
|
|
|
|
qq{'$arg_name' name argument to Marpa::R2::Scanless::G->new() is a ref to a an undef\n}, |
157
|
|
|
|
|
|
|
" It should be a ref to a string\n" |
158
|
|
|
|
|
|
|
); |
159
|
|
|
|
|
|
|
} ## end if ( $ref_type ne 'SCALAR' ) |
160
|
|
|
|
|
|
|
} ## end if ( $method eq 'new' ) |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# A bit hack-ish, but some named args will be copies straight to a member of |
163
|
|
|
|
|
|
|
# the Scanless::G class, so this maps named args to the index of the array |
164
|
|
|
|
|
|
|
# that holds the members. |
165
|
200
|
|
|
|
|
553
|
state $copy_arg_to_index = { |
166
|
|
|
|
|
|
|
trace_file_handle => Marpa::R2::Internal::Scanless::G::TRACE_FILE_HANDLE, |
167
|
|
|
|
|
|
|
trace_terminals => Marpa::R2::Internal::Scanless::G::TRACE_TERMINALS |
168
|
|
|
|
|
|
|
}; |
169
|
|
|
|
|
|
|
|
170
|
200
|
|
|
|
|
641
|
ARG: for my $arg_name ( keys %flat_args ) { |
171
|
239
|
|
|
|
|
565
|
my $index = $copy_arg_to_index->{$arg_name}; |
172
|
239
|
100
|
|
|
|
903
|
next ARG if not defined $index; |
173
|
1
|
|
|
|
|
3
|
my $value = $flat_args{$arg_name}; |
174
|
1
|
|
|
|
|
3
|
$slg->[$index] = $value; |
175
|
|
|
|
|
|
|
} ## end ARG: for my $arg_name ( keys %flat_args ) |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# Normalize trace_terminals |
178
|
200
|
100
|
|
|
|
2053
|
$slg->[Marpa::R2::Internal::Scanless::G::TRACE_TERMINALS] = 0 |
179
|
|
|
|
|
|
|
if not Scalar::Util::looks_like_number( |
180
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::TRACE_TERMINALS] ); |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# Trace file handle needs to be populated downwards |
183
|
200
|
100
|
|
|
|
1002
|
if ( defined( my $trace_file_handle = $flat_args{trace_file_handle} ) ) { |
184
|
|
|
|
|
|
|
GRAMMAR: |
185
|
1
|
|
|
|
|
3
|
for my $naif_grammar ( |
186
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::THICK_G1_GRAMMAR], |
187
|
1
|
|
|
|
|
5
|
@{ $slg->[Marpa::R2::Internal::Scanless::G::THICK_LEX_GRAMMARS] } |
188
|
|
|
|
|
|
|
) |
189
|
|
|
|
|
|
|
{ |
190
|
2
|
50
|
|
|
|
7
|
next GRAMMAR if not defined $naif_grammar; |
191
|
2
|
|
|
|
|
9
|
$naif_grammar->set( { trace_file_handle => $trace_file_handle } ); |
192
|
|
|
|
|
|
|
} ## end GRAMMAR: for my $naif_grammar ( $slg->[...]) |
193
|
|
|
|
|
|
|
} ## end if ( defined( my $trace_file_handle = $flat_args{...})) |
194
|
|
|
|
|
|
|
|
195
|
200
|
100
|
|
|
|
742
|
if ( $method eq 'new' ) { |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
# Prune flat args of all those named args which are NOT to be copied |
198
|
|
|
|
|
|
|
# into the NAIF recce args |
199
|
199
|
|
|
|
|
560
|
for my $arg_name ( keys %flat_args ) { |
200
|
|
|
|
|
|
|
delete $flat_args{$arg_name} |
201
|
238
|
100
|
|
|
|
1010
|
if not $copy_to_g1_args->{$arg_name}; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# trace file handle must always be defined |
205
|
199
|
|
50
|
|
|
1443
|
$slg->[Marpa::R2::Internal::Scanless::G::TRACE_FILE_HANDLE] //= \*STDERR; |
206
|
|
|
|
|
|
|
|
207
|
199
|
|
|
|
|
888
|
return ($dsl, \%flat_args); |
208
|
|
|
|
|
|
|
} ## end if ( $method eq 'new' ) |
209
|
|
|
|
|
|
|
|
210
|
1
|
|
|
|
|
3
|
return; |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
} ## end sub Marpa::R2::Internal::Scanless::G::set |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub Marpa::R2::Internal::Scanless::G::hash_to_runtime { |
215
|
268
|
|
|
268
|
|
1029
|
my ( $slg, $hashed_source, $g1_args ) = @_; |
216
|
|
|
|
|
|
|
|
217
|
268
|
|
|
|
|
767
|
my $trace_terminals = |
218
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::TRACE_TERMINALS]; |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# Pre-lexer G1 processing |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
my $start_lhs = $hashed_source->{'start_lhs'} |
223
|
268
|
|
66
|
|
|
1434
|
// $hashed_source->{'first_lhs'}; |
224
|
268
|
50
|
|
|
|
994
|
Marpa::R2::exception('No rules in SLIF grammar') |
225
|
|
|
|
|
|
|
if not defined $start_lhs; |
226
|
268
|
|
|
|
|
1506
|
Marpa::R2::Internal::MetaAST::start_rule_create( $hashed_source, |
227
|
|
|
|
|
|
|
$start_lhs ); |
228
|
|
|
|
|
|
|
|
229
|
268
|
|
|
|
|
908
|
$slg->[Marpa::R2::Internal::Scanless::G::CACHE_RULEIDS_BY_LHS_NAME] = {}; |
230
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::DEFAULT_G1_START_ACTION] = |
231
|
268
|
|
|
|
|
788
|
$hashed_source->{'default_g1_start_action'}; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
my $trace_fh = |
234
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::TRACE_FILE_HANDLE] = |
235
|
268
|
|
50
|
|
|
1863
|
$g1_args->{trace_file_handle} // \*STDERR; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
my $if_inaccessible_default = |
238
|
268
|
|
100
|
|
|
1650
|
$hashed_source->{defaults}->{if_inaccessible} // 'warn'; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
# Prepare the arguments for the G1 grammar |
241
|
268
|
|
|
|
|
804
|
$g1_args->{rules} = $hashed_source->{rules}->{G1}; |
242
|
268
|
|
|
|
|
706
|
$g1_args->{symbols} = $hashed_source->{symbols}->{G1}; |
243
|
268
|
|
|
|
|
620
|
state $g1_target_symbol = '[:start]'; |
244
|
268
|
|
|
|
|
784
|
$g1_args->{start} = $g1_target_symbol; |
245
|
268
|
|
|
|
|
1144
|
$g1_args->{'_internal_'} = |
246
|
|
|
|
|
|
|
{ 'if_inaccessible' => $if_inaccessible_default }; |
247
|
|
|
|
|
|
|
|
248
|
268
|
|
|
|
|
1863
|
my $thick_g1_grammar = Marpa::R2::Grammar->new($g1_args); |
249
|
264
|
|
|
|
|
1278
|
my $g1_tracer = $thick_g1_grammar->tracer(); |
250
|
264
|
|
|
|
|
1018
|
my $g1_thin = $g1_tracer->grammar(); |
251
|
|
|
|
|
|
|
|
252
|
264
|
|
|
|
|
722
|
my $symbol_ids_by_event_name_and_type = {}; |
253
|
264
|
|
|
|
|
735
|
$slg->[ |
254
|
|
|
|
|
|
|
Marpa::R2::Internal::Scanless::G::SYMBOL_IDS_BY_EVENT_NAME_AND_TYPE] |
255
|
|
|
|
|
|
|
= $symbol_ids_by_event_name_and_type; |
256
|
|
|
|
|
|
|
|
257
|
264
|
|
|
|
|
614
|
my $completion_events_by_name = $hashed_source->{completion_events}; |
258
|
264
|
|
|
|
|
771
|
my $completion_events_by_id = |
259
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::COMPLETION_EVENT_BY_ID] = []; |
260
|
264
|
|
|
|
|
586
|
for my $symbol_name ( keys %{$completion_events_by_name} ) { |
|
264
|
|
|
|
|
1155
|
|
261
|
|
|
|
|
|
|
my ( $event_name, $is_active ) = |
262
|
54
|
|
|
|
|
92
|
@{ $completion_events_by_name->{$symbol_name} }; |
|
54
|
|
|
|
|
127
|
|
263
|
54
|
|
|
|
|
148
|
my $symbol_id = $g1_tracer->symbol_by_name($symbol_name); |
264
|
54
|
50
|
|
|
|
142
|
if ( not defined $symbol_id ) { |
265
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( |
266
|
|
|
|
|
|
|
"Completion event defined for non-existent symbol: $symbol_name\n" |
267
|
|
|
|
|
|
|
); |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
# Must be done before precomputation |
271
|
54
|
|
|
|
|
195
|
$g1_thin->symbol_is_completion_event_set( $symbol_id, 1 ); |
272
|
54
|
100
|
|
|
|
153
|
$g1_thin->completion_symbol_activate( $symbol_id, 0 ) |
273
|
|
|
|
|
|
|
if not $is_active; |
274
|
54
|
|
|
|
|
118
|
$slg->[Marpa::R2::Internal::Scanless::G::COMPLETION_EVENT_BY_ID] |
275
|
|
|
|
|
|
|
->[$symbol_id] = $event_name; |
276
|
|
|
|
|
|
|
push |
277
|
54
|
|
|
|
|
94
|
@{ $symbol_ids_by_event_name_and_type->{$event_name}->{completion} |
278
|
54
|
|
|
|
|
288
|
}, $symbol_id; |
279
|
|
|
|
|
|
|
} ## end for my $symbol_name ( keys %{$completion_events_by_name...}) |
280
|
|
|
|
|
|
|
|
281
|
264
|
|
|
|
|
725
|
my $nulled_events_by_name = $hashed_source->{nulled_events}; |
282
|
264
|
|
|
|
|
891
|
my $nulled_events_by_id = |
283
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::NULLED_EVENT_BY_ID] = []; |
284
|
264
|
|
|
|
|
545
|
for my $symbol_name ( keys %{$nulled_events_by_name} ) { |
|
264
|
|
|
|
|
935
|
|
285
|
|
|
|
|
|
|
my ( $event_name, $is_active ) = |
286
|
46
|
|
|
|
|
67
|
@{ $nulled_events_by_name->{$symbol_name} }; |
|
46
|
|
|
|
|
95
|
|
287
|
46
|
|
|
|
|
103
|
my $symbol_id = $g1_tracer->symbol_by_name($symbol_name); |
288
|
46
|
50
|
|
|
|
94
|
if ( not defined $symbol_id ) { |
289
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( |
290
|
|
|
|
|
|
|
"nulled event defined for non-existent symbol: $symbol_name\n" |
291
|
|
|
|
|
|
|
); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# Must be done before precomputation |
295
|
46
|
|
|
|
|
124
|
$g1_thin->symbol_is_nulled_event_set( $symbol_id, 1 ); |
296
|
46
|
100
|
|
|
|
98
|
$g1_thin->nulled_symbol_activate( $symbol_id, 0 ) if not $is_active; |
297
|
46
|
|
|
|
|
84
|
$slg->[Marpa::R2::Internal::Scanless::G::NULLED_EVENT_BY_ID] |
298
|
|
|
|
|
|
|
->[$symbol_id] = $event_name; |
299
|
46
|
|
|
|
|
68
|
push @{ $symbol_ids_by_event_name_and_type->{$event_name}->{nulled} }, |
|
46
|
|
|
|
|
199
|
|
300
|
|
|
|
|
|
|
$symbol_id; |
301
|
|
|
|
|
|
|
} ## end for my $symbol_name ( keys %{$nulled_events_by_name} ) |
302
|
|
|
|
|
|
|
|
303
|
264
|
|
|
|
|
677
|
my $prediction_events_by_name = $hashed_source->{prediction_events}; |
304
|
264
|
|
|
|
|
807
|
my $prediction_events_by_id = |
305
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::PREDICTION_EVENT_BY_ID] = []; |
306
|
264
|
|
|
|
|
562
|
for my $symbol_name ( keys %{$prediction_events_by_name} ) { |
|
264
|
|
|
|
|
881
|
|
307
|
|
|
|
|
|
|
my ( $event_name, $is_active ) = |
308
|
52
|
|
|
|
|
86
|
@{ $prediction_events_by_name->{$symbol_name} }; |
|
52
|
|
|
|
|
110
|
|
309
|
52
|
|
|
|
|
146
|
my $symbol_id = $g1_tracer->symbol_by_name($symbol_name); |
310
|
52
|
50
|
|
|
|
111
|
if ( not defined $symbol_id ) { |
311
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( |
312
|
|
|
|
|
|
|
"prediction event defined for non-existent symbol: $symbol_name\n" |
313
|
|
|
|
|
|
|
); |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# Must be done before precomputation |
317
|
52
|
|
|
|
|
158
|
$g1_thin->symbol_is_prediction_event_set( $symbol_id, 1 ); |
318
|
52
|
100
|
|
|
|
102
|
$g1_thin->prediction_symbol_activate( $symbol_id, 0 ) |
319
|
|
|
|
|
|
|
if not $is_active; |
320
|
52
|
|
|
|
|
129
|
$slg->[Marpa::R2::Internal::Scanless::G::PREDICTION_EVENT_BY_ID] |
321
|
|
|
|
|
|
|
->[$symbol_id] = $event_name; |
322
|
|
|
|
|
|
|
push |
323
|
52
|
|
|
|
|
68
|
@{ $symbol_ids_by_event_name_and_type->{$event_name}->{prediction} |
324
|
52
|
|
|
|
|
240
|
}, $symbol_id; |
325
|
|
|
|
|
|
|
} ## end for my $symbol_name ( keys %{$prediction_events_by_name...}) |
326
|
|
|
|
|
|
|
|
327
|
264
|
|
|
|
|
834
|
my $lexeme_events_by_id = |
328
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::LEXEME_EVENT_BY_ID] = []; |
329
|
|
|
|
|
|
|
|
330
|
264
|
100
|
|
|
|
1211
|
if (defined( |
331
|
|
|
|
|
|
|
my $precompute_error = |
332
|
|
|
|
|
|
|
Marpa::R2::Internal::Grammar::slif_precompute( |
333
|
|
|
|
|
|
|
$thick_g1_grammar) |
334
|
|
|
|
|
|
|
) |
335
|
|
|
|
|
|
|
) |
336
|
|
|
|
|
|
|
{ |
337
|
1
|
50
|
|
|
|
3
|
if ( $precompute_error == $Marpa::R2::Error::UNPRODUCTIVE_START ) { |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# Maybe someday improve this by finding the start rule and showing |
340
|
|
|
|
|
|
|
# its RHS -- for now it is clear enough |
341
|
1
|
|
|
|
|
6
|
Marpa::R2::exception(qq{Unproductive start symbol}); |
342
|
|
|
|
|
|
|
} ## end if ( $precompute_error == ...) |
343
|
|
|
|
|
|
|
Marpa::R2::exception( |
344
|
0
|
|
|
|
|
0
|
'Internal errror: unnkown precompute error code ', |
345
|
|
|
|
|
|
|
$precompute_error ); |
346
|
|
|
|
|
|
|
} ## end if ( defined( my $precompute_error = ...)) |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# Find out the list of lexemes according to G1 |
349
|
260
|
|
|
|
|
768
|
my %g1_id_by_lexeme_name = (); |
350
|
260
|
|
|
|
|
1656
|
SYMBOL: for my $symbol_id ( 0 .. $g1_thin->highest_symbol_id() ) { |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# Not a lexeme, according to G1 |
353
|
12758
|
100
|
|
|
|
26560
|
next SYMBOL if not $g1_thin->symbol_is_terminal($symbol_id); |
354
|
|
|
|
|
|
|
|
355
|
7686
|
|
|
|
|
14180
|
my $symbol_name = $g1_tracer->symbol_name($symbol_id); |
356
|
7686
|
|
|
|
|
14028
|
$g1_id_by_lexeme_name{$symbol_name} = $symbol_id; |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
} ## end SYMBOL: for my $symbol_id ( 0 .. $g1_thin->highest_symbol_id(...)) |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
# A first phase of applying defaults |
361
|
260
|
|
|
|
|
1087
|
my $discard_default_adverbs = $hashed_source->{discard_default_adverbs}; |
362
|
260
|
|
|
|
|
749
|
my $lexeme_declarations = $hashed_source->{lexeme_declarations}; |
363
|
260
|
|
|
|
|
657
|
my $lexeme_default_adverbs = $hashed_source->{lexeme_default_adverbs}; |
364
|
260
|
|
100
|
|
|
1179
|
my $latm_default_value = $lexeme_default_adverbs->{latm} // 0; |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# Current lexeme data is spread out in many places. |
367
|
|
|
|
|
|
|
# Change so that it all resides in this hash, indexed by |
368
|
|
|
|
|
|
|
# name |
369
|
260
|
|
|
|
|
694
|
my %lexeme_data = (); |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
# Determine "latm" status |
372
|
260
|
|
|
|
|
1847
|
LEXEME: for my $lexeme_name ( keys %g1_id_by_lexeme_name ) { |
373
|
7686
|
|
|
|
|
10182
|
my $declarations = $lexeme_declarations->{$lexeme_name}; |
374
|
7686
|
|
100
|
|
|
17395
|
my $latm_value = $declarations->{latm} // $latm_default_value; |
375
|
7686
|
|
|
|
|
18581
|
$lexeme_data{$lexeme_name}{latm} = $latm_value; |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
# Lexers |
379
|
|
|
|
|
|
|
|
380
|
260
|
|
|
|
|
1108
|
my $lexer_id = 0; |
381
|
260
|
|
|
|
|
666
|
my $lexer_name = 'L0'; |
382
|
|
|
|
|
|
|
|
383
|
260
|
|
|
|
|
587
|
my %lexer_id_by_name = (); |
384
|
260
|
|
|
|
|
551
|
my %thick_grammar_by_lexer_name = (); |
385
|
260
|
|
|
|
|
523
|
my @discard_event_by_lexer_rule_id = (); |
386
|
260
|
|
|
|
|
517
|
my %lexer_and_rule_to_g1_lexeme = (); |
387
|
260
|
|
|
|
|
509
|
my %character_class_table_by_lexer_name = (); |
388
|
260
|
|
|
|
|
522
|
state $lex_start_symbol_name = '[:start_lex]'; |
389
|
260
|
|
|
|
|
506
|
state $discard_symbol_name = '[:discard]'; |
390
|
|
|
|
|
|
|
|
391
|
260
|
|
|
|
|
666
|
my $lexer_rules = $hashed_source->{rules}->{$lexer_name}; |
392
|
260
|
|
|
|
|
571
|
my $character_class_hash = $hashed_source->{character_classes}; |
393
|
260
|
|
|
|
|
615
|
my $lexer_symbols = $hashed_source->{symbols}->{'L'}; |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
# If no lexer rules, fake a lexer |
396
|
|
|
|
|
|
|
# Fake a lexer -- it discards symbols in character classes which |
397
|
|
|
|
|
|
|
# never matches |
398
|
260
|
100
|
|
|
|
931
|
if ( not $lexer_rules ) { |
399
|
2
|
|
|
|
|
11
|
$character_class_hash = { '[[^\\d\\D]]' => [ '[^\\d\\D]', '' ] }; |
400
|
2
|
|
|
|
|
40
|
$lexer_rules = [ |
401
|
|
|
|
|
|
|
{ 'rhs' => [ '[[^\\d\\D]]' ], |
402
|
|
|
|
|
|
|
'lhs' => '[:discard]', |
403
|
|
|
|
|
|
|
'symbol_as_event' => '[^\\d\\D]', |
404
|
|
|
|
|
|
|
'description' => 'Discard rule for <[[^\\d\\D]]>' |
405
|
|
|
|
|
|
|
}, |
406
|
|
|
|
|
|
|
]; |
407
|
2
|
|
|
|
|
19
|
$lexer_symbols = { |
408
|
|
|
|
|
|
|
'[:discard]' => { |
409
|
|
|
|
|
|
|
'display_form' => ':discard', |
410
|
|
|
|
|
|
|
'description' => 'Internal LHS for lexer "L0" discard' |
411
|
|
|
|
|
|
|
}, |
412
|
|
|
|
|
|
|
'[[^\\d\\D]]' => { |
413
|
|
|
|
|
|
|
'dsl_form' => '[^\\d\\D]', |
414
|
|
|
|
|
|
|
'display_form' => '[^\\d\\D]', |
415
|
|
|
|
|
|
|
'description' => 'Character class: [^\\d\\D]' |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
}; |
418
|
|
|
|
|
|
|
} ## end if ( not $lexer_rules ) |
419
|
|
|
|
|
|
|
|
420
|
260
|
|
|
|
|
609
|
my %lex_lhs = (); |
421
|
260
|
|
|
|
|
571
|
my %lex_rhs = (); |
422
|
260
|
|
|
|
|
502
|
my %lex_separator = (); |
423
|
260
|
|
|
|
|
516
|
my %lexer_rule_by_tag = (); |
424
|
|
|
|
|
|
|
|
425
|
260
|
|
|
|
|
638
|
my $rule_tag = 'rule0'; |
426
|
260
|
|
|
|
|
470
|
for my $lex_rule ( @{$lexer_rules} ) { |
|
260
|
|
|
|
|
685
|
|
427
|
12004
|
|
|
|
|
23031
|
$lex_rule->{tag} = ++$rule_tag; |
428
|
12004
|
|
|
|
|
14632
|
my %lex_rule_copy = %{$lex_rule}; |
|
12004
|
|
|
|
|
54591
|
|
429
|
12004
|
|
|
|
|
33559
|
$lexer_rule_by_tag{$rule_tag} = \%lex_rule_copy; |
430
|
12004
|
|
|
|
|
16259
|
delete $lex_rule->{event}; |
431
|
12004
|
|
|
|
|
14599
|
delete $lex_rule->{symbol_as_event}; |
432
|
12004
|
|
|
|
|
21324
|
$lex_lhs{ $lex_rule->{lhs} } = 1; |
433
|
12004
|
|
|
|
|
14638
|
$lex_rhs{$_} = 1 for @{ $lex_rule->{rhs} }; |
|
12004
|
|
|
|
|
39078
|
|
434
|
12004
|
100
|
|
|
|
28151
|
if ( defined( my $separator = $lex_rule->{separator} ) ) { |
435
|
144
|
|
|
|
|
716
|
$lex_separator{$separator} = 1; |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
} ## end for my $lex_rule ( @{$lexer_rules} ) |
438
|
|
|
|
|
|
|
|
439
|
260
|
|
|
|
|
900
|
my %this_lexer_symbols = (); |
440
|
|
|
|
|
|
|
SYMBOL: |
441
|
260
|
|
|
|
|
4285
|
for my $symbol_name ( ( keys %lex_lhs ), ( keys %lex_rhs ), |
442
|
|
|
|
|
|
|
( keys %lex_separator ) ) |
443
|
|
|
|
|
|
|
{ |
444
|
17910
|
|
|
|
|
23994
|
my $symbol_data = $lexer_symbols->{$symbol_name}; |
445
|
17910
|
100
|
|
|
|
34436
|
$this_lexer_symbols{$symbol_name} = $symbol_data |
446
|
|
|
|
|
|
|
if defined $symbol_data; |
447
|
|
|
|
|
|
|
} ## end SYMBOL: for my $symbol_name ( ( keys %lex_lhs ), ( keys %lex_rhs...)) |
448
|
|
|
|
|
|
|
|
449
|
7870
|
|
|
|
|
13915
|
my %is_lexeme_in_this_lexer = map { $_ => 1 } |
450
|
260
|
|
100
|
|
|
2762
|
grep { not $lex_rhs{$_} and not $lex_separator{$_} } |
|
10336
|
|
|
|
|
25223
|
|
451
|
|
|
|
|
|
|
keys %lex_lhs; |
452
|
|
|
|
|
|
|
|
453
|
260
|
|
|
|
|
2738
|
my @lex_lexeme_names = keys %is_lexeme_in_this_lexer; |
454
|
|
|
|
|
|
|
|
455
|
260
|
50
|
|
|
|
1052
|
Marpa::R2::exception( "No lexemes in lexer: $lexer_name\n", |
456
|
|
|
|
|
|
|
" An SLIF grammar must have at least one lexeme\n" ) |
457
|
|
|
|
|
|
|
if not scalar @lex_lexeme_names; |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
# Do I need this? |
460
|
|
|
|
|
|
|
my @unproductive = |
461
|
0
|
|
|
|
|
0
|
map {"<$_>"} |
462
|
260
|
|
66
|
|
|
1693
|
grep { not $lex_lhs{$_} and not $_ =~ /\A \[\[ /xms } |
|
7574
|
|
|
|
|
23668
|
|
463
|
|
|
|
|
|
|
( keys %lex_rhs, keys %lex_separator ); |
464
|
260
|
50
|
|
|
|
1390
|
if (@unproductive) { |
465
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( 'Unproductive lexical symbols: ', |
466
|
|
|
|
|
|
|
join q{ }, @unproductive ); |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
$this_lexer_symbols{$lex_start_symbol_name}->{display_form} = |
470
|
260
|
|
|
|
|
1127
|
':start_lex'; |
471
|
|
|
|
|
|
|
$this_lexer_symbols{$lex_start_symbol_name}->{description} = |
472
|
260
|
|
|
|
|
771
|
'Internal L0 (lexical) start symbol'; |
473
|
260
|
|
|
|
|
4134
|
push @{$lexer_rules}, map { |
474
|
260
|
|
|
|
|
553
|
; |
475
|
7870
|
|
|
|
|
32377
|
{ description => "Internal lexical start rule for <$_>", |
476
|
|
|
|
|
|
|
lhs => $lex_start_symbol_name, |
477
|
|
|
|
|
|
|
rhs => [$_] |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
} sort keys %is_lexeme_in_this_lexer; |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
# Prepare the arguments for the lex grammar |
482
|
260
|
|
|
|
|
1476
|
my %lex_args = (); |
483
|
260
|
|
|
|
|
855
|
$lex_args{trace_file_handle} = $trace_fh; |
484
|
260
|
|
|
|
|
759
|
$lex_args{start} = $lex_start_symbol_name; |
485
|
260
|
|
|
|
|
976
|
$lex_args{'_internal_'} = |
486
|
|
|
|
|
|
|
{ 'if_inaccessible' => $if_inaccessible_default }; |
487
|
260
|
|
|
|
|
717
|
$lex_args{rules} = $lexer_rules; |
488
|
260
|
|
|
|
|
701
|
$lex_args{symbols} = \%this_lexer_symbols; |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
# Create the thick lex grammar |
491
|
260
|
|
|
|
|
1371
|
my $lex_grammar = Marpa::R2::Grammar->new( \%lex_args ); |
492
|
260
|
|
|
|
|
1018
|
$thick_grammar_by_lexer_name{$lexer_name} = $lex_grammar; |
493
|
260
|
|
|
|
|
1057
|
my $lex_tracer = $lex_grammar->tracer(); |
494
|
260
|
|
|
|
|
942
|
my $lex_thin = $lex_tracer->grammar(); |
495
|
|
|
|
|
|
|
|
496
|
260
|
|
100
|
|
|
984
|
my $lex_discard_symbol_id = |
497
|
|
|
|
|
|
|
$lex_tracer->symbol_by_name($discard_symbol_name) // -1; |
498
|
260
|
|
|
|
|
649
|
my @lex_lexeme_to_g1_symbol; |
499
|
260
|
|
|
|
|
4757
|
$lex_lexeme_to_g1_symbol[$_] = -1 for 0 .. $g1_thin->highest_symbol_id(); |
500
|
|
|
|
|
|
|
|
501
|
260
|
|
|
|
|
1284
|
LEXEME_NAME: for my $lexeme_name (@lex_lexeme_names) { |
502
|
7868
|
100
|
|
|
|
14379
|
next LEXEME_NAME if $lexeme_name eq $discard_symbol_name; |
503
|
7684
|
50
|
|
|
|
12402
|
next LEXEME_NAME if $lexeme_name eq $lex_start_symbol_name; |
504
|
7684
|
|
|
|
|
11466
|
my $g1_symbol_id = $g1_id_by_lexeme_name{$lexeme_name}; |
505
|
7684
|
100
|
|
|
|
12577
|
if ( not defined $g1_symbol_id ) { |
506
|
4
|
|
|
|
|
22
|
Marpa::R2::exception( |
507
|
|
|
|
|
|
|
qq{<$lexeme_name> is a lexeme but it is not a legal lexeme in G1:\n}, |
508
|
|
|
|
|
|
|
qq{ Lexemes must be G1 symbols that do not appear on a G1 LHS.\n} |
509
|
|
|
|
|
|
|
); |
510
|
|
|
|
|
|
|
} |
511
|
7680
|
100
|
|
|
|
19104
|
if ( not $g1_thin->symbol_is_accessible($g1_symbol_id) ) { |
512
|
2
|
|
|
|
|
11
|
my $message = |
513
|
|
|
|
|
|
|
"A lexeme in lexer $lexer_name is not accessible from the G1 start symbol: $lexeme_name"; |
514
|
2
|
50
|
|
|
|
7
|
say {$trace_fh} $message |
|
0
|
|
|
|
|
0
|
|
515
|
|
|
|
|
|
|
if $if_inaccessible_default eq 'warn'; |
516
|
2
|
50
|
|
|
|
6
|
Marpa::R2::exception($message) |
517
|
|
|
|
|
|
|
if $if_inaccessible_default eq 'fatal'; |
518
|
|
|
|
|
|
|
} ## end if ( not $g1_thin->symbol_is_accessible($g1_symbol_id...)) |
519
|
7680
|
|
|
|
|
15100
|
my $lex_symbol_id = $lex_tracer->symbol_by_name($lexeme_name); |
520
|
7680
|
|
|
|
|
26992
|
$lexeme_data{$lexeme_name}{lexers}{$lexer_name}{'id'} = |
521
|
|
|
|
|
|
|
$lex_symbol_id; |
522
|
7680
|
|
|
|
|
13441
|
$lex_lexeme_to_g1_symbol[$lex_symbol_id] = $g1_symbol_id; |
523
|
|
|
|
|
|
|
} ## end LEXEME_NAME: for my $lexeme_name (@lex_lexeme_names) |
524
|
|
|
|
|
|
|
|
525
|
256
|
|
|
|
|
750
|
my @lex_rule_to_g1_lexeme; |
526
|
256
|
|
|
|
|
1018
|
my $lex_start_symbol_id = |
527
|
|
|
|
|
|
|
$lex_tracer->symbol_by_name($lex_start_symbol_name); |
528
|
256
|
|
|
|
|
1482
|
RULE_ID: for my $rule_id ( 0 .. $lex_thin->highest_rule_id() ) { |
529
|
19862
|
|
|
|
|
33089
|
my $lhs_id = $lex_thin->rule_lhs($rule_id); |
530
|
19862
|
100
|
|
|
|
32568
|
if ( $lhs_id == $lex_discard_symbol_id ) { |
531
|
295
|
|
|
|
|
773
|
$lex_rule_to_g1_lexeme[$rule_id] = -2; |
532
|
295
|
|
|
|
|
670
|
next RULE_ID; |
533
|
|
|
|
|
|
|
} |
534
|
19567
|
100
|
|
|
|
31740
|
if ( $lhs_id != $lex_start_symbol_id ) { |
535
|
11703
|
|
|
|
|
15441
|
$lex_rule_to_g1_lexeme[$rule_id] = -1; |
536
|
11703
|
|
|
|
|
16474
|
next RULE_ID; |
537
|
|
|
|
|
|
|
} |
538
|
7864
|
|
|
|
|
13848
|
my $lexer_lexeme_id = $lex_thin->rule_rhs( $rule_id, 0 ); |
539
|
7864
|
100
|
|
|
|
13489
|
if ( $lexer_lexeme_id == $lex_discard_symbol_id ) { |
540
|
184
|
|
|
|
|
583
|
$lex_rule_to_g1_lexeme[$rule_id] = -1; |
541
|
184
|
|
|
|
|
428
|
next RULE_ID; |
542
|
|
|
|
|
|
|
} |
543
|
7680
|
|
50
|
|
|
13570
|
my $lexeme_id = $lex_lexeme_to_g1_symbol[$lexer_lexeme_id] // -1; |
544
|
7680
|
|
|
|
|
10669
|
$lex_rule_to_g1_lexeme[$rule_id] = $lexeme_id; |
545
|
7680
|
50
|
|
|
|
12405
|
next RULE_ID if $lexeme_id < 0; |
546
|
7680
|
|
|
|
|
14908
|
my $lexeme_name = $g1_tracer->symbol_name($lexeme_id); |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
# If 1 is the default, we don't need an assertion |
549
|
7680
|
100
|
|
|
|
16065
|
next RULE_ID if not $lexeme_data{$lexeme_name}{latm}; |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
my $assertion_id = |
552
|
7253
|
|
|
|
|
11278
|
$lexeme_data{$lexeme_name}{lexers}{$lexer_name}{'assertion'}; |
553
|
7253
|
50
|
|
|
|
11783
|
if ( not defined $assertion_id ) { |
554
|
7253
|
|
|
|
|
13055
|
$assertion_id = $lex_thin->zwa_new(0); |
555
|
|
|
|
|
|
|
|
556
|
7253
|
50
|
|
|
|
12599
|
if ( $trace_terminals >= 2 ) { |
557
|
0
|
|
|
|
|
0
|
say {$trace_fh} "Assertion $assertion_id defaults to 0"; |
|
0
|
|
|
|
|
0
|
|
558
|
|
|
|
|
|
|
} |
559
|
|
|
|
|
|
|
|
560
|
7253
|
|
|
|
|
12265
|
$lexeme_data{$lexeme_name}{lexers}{$lexer_name}{'assertion'} = |
561
|
|
|
|
|
|
|
$assertion_id; |
562
|
|
|
|
|
|
|
} ## end if ( not defined $assertion_id ) |
563
|
7253
|
|
|
|
|
18067
|
$lex_thin->zwa_place( $assertion_id, $rule_id, 0 ); |
564
|
7253
|
50
|
|
|
|
14502
|
if ( $trace_terminals >= 2 ) { |
565
|
0
|
|
|
|
|
0
|
say {$trace_fh} |
|
0
|
|
|
|
|
0
|
|
566
|
|
|
|
|
|
|
"Assertion $assertion_id applied to $lexer_name rule ", |
567
|
|
|
|
|
|
|
slg_rule_show( $slg, $rule_id, $lex_grammar ); |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
} ## end RULE_ID: for my $rule_id ( 0 .. $lex_thin->highest_rule_id() ) |
570
|
|
|
|
|
|
|
|
571
|
256
|
|
|
|
|
1529
|
Marpa::R2::Internal::Grammar::slif_precompute($lex_grammar); |
572
|
|
|
|
|
|
|
|
573
|
256
|
|
|
|
|
903
|
my @class_table = (); |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
CLASS_SYMBOL: |
576
|
256
|
|
|
|
|
701
|
for my $class_symbol ( sort keys %{$character_class_hash} ) { |
|
256
|
|
|
|
|
4107
|
|
577
|
5104
|
|
|
|
|
11370
|
my $symbol_id = $lex_tracer->symbol_by_name($class_symbol); |
578
|
5104
|
50
|
|
|
|
9759
|
next CLASS_SYMBOL if not defined $symbol_id; |
579
|
5104
|
|
|
|
|
8281
|
my $cc_components = $character_class_hash->{$class_symbol}; |
580
|
5104
|
|
|
|
|
9700
|
my ( $compiled_re, $error ) = |
581
|
|
|
|
|
|
|
Marpa::R2::Internal::MetaAST::char_class_to_re($cc_components); |
582
|
5104
|
50
|
|
|
|
9638
|
if ( not $compiled_re ) { |
583
|
0
|
|
|
|
|
0
|
$error =~ s/^/ /gxms; #indent all lines |
584
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( |
585
|
|
|
|
|
|
|
"Failed belatedly to evaluate character class\n", $error ); |
586
|
|
|
|
|
|
|
} |
587
|
5104
|
|
|
|
|
12159
|
push @class_table, [ $symbol_id, $compiled_re ]; |
588
|
|
|
|
|
|
|
} ## end CLASS_SYMBOL: for my $class_symbol ( sort keys %{...}) |
589
|
256
|
|
|
|
|
1479
|
$character_class_table_by_lexer_name{$lexer_name} = \@class_table; |
590
|
|
|
|
|
|
|
|
591
|
256
|
|
|
|
|
776
|
$lexer_and_rule_to_g1_lexeme{$lexer_name} = \@lex_rule_to_g1_lexeme; |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
# Apply defaults to determine the discard event for every |
594
|
|
|
|
|
|
|
# rule id of the lexer. |
595
|
|
|
|
|
|
|
|
596
|
256
|
|
|
|
|
768
|
my $default_discard_event = $discard_default_adverbs->{event}; |
597
|
256
|
|
|
|
|
1518
|
RULE_ID: for my $rule_id ( 0 .. $lex_thin->highest_rule_id() ) { |
598
|
19862
|
|
|
|
|
35133
|
my $tag = $lex_grammar->tag($rule_id); |
599
|
19862
|
100
|
|
|
|
36205
|
next RULE_ID if not defined $tag; |
600
|
11998
|
|
|
|
|
14469
|
my $event; |
601
|
|
|
|
|
|
|
FIND_EVENT: { |
602
|
11998
|
|
|
|
|
14190
|
$event = $lexer_rule_by_tag{$tag}->{event}; |
|
11998
|
|
|
|
|
21529
|
|
603
|
11998
|
100
|
|
|
|
19465
|
last FIND_EVENT if defined $event; |
604
|
11947
|
|
|
|
|
20717
|
my $lhs_id = $lex_thin->rule_lhs($rule_id); |
605
|
11947
|
100
|
|
|
|
22815
|
last FIND_EVENT if $lhs_id != $lex_discard_symbol_id; |
606
|
244
|
|
|
|
|
592
|
$event = $default_discard_event; |
607
|
|
|
|
|
|
|
} ## end FIND_EVENT: |
608
|
11998
|
100
|
|
|
|
22348
|
next RULE_ID if not defined $event; |
609
|
|
|
|
|
|
|
|
610
|
60
|
|
|
|
|
120
|
my ( $event_name, $event_starts_active ) = @{$event}; |
|
60
|
|
|
|
|
169
|
|
611
|
60
|
100
|
|
|
|
160
|
if ( $event_name eq q{'symbol} ) { |
612
|
|
|
|
|
|
|
my @event = ( |
613
|
|
|
|
|
|
|
$lexer_rule_by_tag{$tag}->{symbol_as_event}, |
614
|
15
|
|
|
|
|
36
|
$event_starts_active |
615
|
|
|
|
|
|
|
); |
616
|
15
|
|
|
|
|
26
|
$discard_event_by_lexer_rule_id[$rule_id] = \@event; |
617
|
15
|
|
|
|
|
28
|
next RULE_ID; |
618
|
|
|
|
|
|
|
} ## end if ( $event_name eq q{'symbol} ) |
619
|
45
|
50
|
|
|
|
150
|
if ( ( substr $event_name, 0, 1 ) ne q{'} ) { |
620
|
45
|
|
|
|
|
86
|
$discard_event_by_lexer_rule_id[$rule_id] = $event; |
621
|
45
|
|
|
|
|
93
|
next RULE_ID; |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
Marpa::R2::exception( |
624
|
0
|
|
|
|
|
0
|
qq{Discard event has unknown name: "$event_name"} |
625
|
|
|
|
|
|
|
); |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
} ## end RULE_ID: for my $rule_id ( 0 .. $lex_thin->highest_rule_id() ) |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
# Post-lexer G1 processing |
630
|
|
|
|
|
|
|
|
631
|
256
|
|
|
|
|
1090
|
my $thick_L0 = $thick_grammar_by_lexer_name{'L0'}; |
632
|
256
|
|
|
|
|
944
|
my $thin_L0 = $thick_L0->[Marpa::R2::Internal::Grammar::C]; |
633
|
256
|
|
|
|
|
1280
|
my $thin_slg = $slg->[Marpa::R2::Internal::Scanless::G::C] = |
634
|
|
|
|
|
|
|
Marpa::R2::Thin::SLG->new( $thin_L0, $g1_tracer->grammar() ); |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
# Relies on default lexer being given number zero |
637
|
256
|
|
|
|
|
947
|
$lexer_id_by_name{'L0'} = 0; |
638
|
|
|
|
|
|
|
|
639
|
256
|
|
|
|
|
2107
|
LEXEME: for my $lexeme_name ( keys %g1_id_by_lexeme_name ) { |
640
|
|
|
|
|
|
|
Marpa::R2::exception( |
641
|
|
|
|
|
|
|
"A lexeme in G1 is not a lexeme in any of the lexers: $lexeme_name" |
642
|
7681
|
100
|
|
|
|
14021
|
) if not defined $lexeme_data{$lexeme_name}{'lexers'}; |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
# At this point we know which symbols are lexemes. |
646
|
|
|
|
|
|
|
# So now let's check for inconsistencies |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
# Check for lexeme declarations for things which are not lexemes |
649
|
252
|
|
|
|
|
1047
|
for my $lexeme_name ( keys %{$lexeme_declarations} ) { |
|
252
|
|
|
|
|
1106
|
|
650
|
|
|
|
|
|
|
Marpa::R2::exception( |
651
|
|
|
|
|
|
|
"Symbol <$lexeme_name> is declared as a lexeme, but it is not used as one.\n" |
652
|
59
|
50
|
|
|
|
203
|
) if not defined $g1_id_by_lexeme_name{$lexeme_name}; |
653
|
|
|
|
|
|
|
} |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
# Now that we know the lexemes, check attempts to defined a |
656
|
|
|
|
|
|
|
# completion or a nulled event for one |
657
|
252
|
|
|
|
|
566
|
for my $symbol_name ( keys %{$completion_events_by_name} ) { |
|
252
|
|
|
|
|
824
|
|
658
|
|
|
|
|
|
|
Marpa::R2::exception( |
659
|
|
|
|
|
|
|
"A completion event is declared for <$symbol_name>, but it is a lexeme.\n", |
660
|
|
|
|
|
|
|
" Completion events are only valid for symbols on the LHS of G1 rules.\n" |
661
|
54
|
50
|
|
|
|
163
|
) if defined $g1_id_by_lexeme_name{$symbol_name}; |
662
|
|
|
|
|
|
|
} ## end for my $symbol_name ( keys %{$completion_events_by_name...}) |
663
|
|
|
|
|
|
|
|
664
|
252
|
|
|
|
|
548
|
for my $symbol_name ( keys %{$nulled_events_by_name} ) { |
|
252
|
|
|
|
|
759
|
|
665
|
|
|
|
|
|
|
Marpa::R2::exception( |
666
|
|
|
|
|
|
|
"A nulled event is declared for <$symbol_name>, but it is a G1 lexeme.\n", |
667
|
|
|
|
|
|
|
" nulled events are only valid for symbols on the LHS of G1 rules.\n" |
668
|
46
|
50
|
|
|
|
105
|
) if defined $g1_id_by_lexeme_name{$symbol_name}; |
669
|
|
|
|
|
|
|
} ## end for my $symbol_name ( keys %{$nulled_events_by_name} ) |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
# Mark the lexemes, and set their data |
672
|
|
|
|
|
|
|
# Now that we have created the SLG, we can set the latm value, |
673
|
|
|
|
|
|
|
# already determined above. |
674
|
252
|
|
|
|
|
1496
|
LEXEME: for my $lexeme_name ( keys %g1_id_by_lexeme_name ) { |
675
|
7676
|
|
|
|
|
10724
|
my $g1_lexeme_id = $g1_id_by_lexeme_name{$lexeme_name}; |
676
|
7676
|
|
|
|
|
9567
|
my $declarations = $lexeme_declarations->{$lexeme_name}; |
677
|
7676
|
|
100
|
|
|
17824
|
my $priority = $declarations->{priority} // 0; |
678
|
7676
|
|
|
|
|
16133
|
$thin_slg->g1_lexeme_set( $g1_lexeme_id, $priority ); |
679
|
7676
|
|
50
|
|
|
13694
|
my $latm_value = $lexeme_data{$lexeme_name}{latm} // 0; |
680
|
7676
|
|
|
|
|
16189
|
$thin_slg->g1_lexeme_latm_set( $g1_lexeme_id, $latm_value ); |
681
|
7676
|
|
|
|
|
9817
|
my $pause_value = $declarations->{pause}; |
682
|
7676
|
100
|
|
|
|
15392
|
if ( defined $pause_value ) { |
683
|
54
|
|
|
|
|
258
|
$thin_slg->g1_lexeme_pause_set( $g1_lexeme_id, $pause_value ); |
684
|
54
|
|
|
|
|
97
|
my $is_active = 1; |
685
|
|
|
|
|
|
|
|
686
|
54
|
100
|
|
|
|
169
|
if ( defined( my $event_data = $declarations->{'event'} ) ) { |
687
|
49
|
|
|
|
|
77
|
my $event_name; |
688
|
49
|
|
|
|
|
88
|
( $event_name, $is_active ) = @{$event_data}; |
|
49
|
|
|
|
|
113
|
|
689
|
49
|
|
|
|
|
125
|
$lexeme_events_by_id->[$g1_lexeme_id] = $event_name; |
690
|
49
|
|
|
|
|
117
|
push @{ $symbol_ids_by_event_name_and_type->{$event_name} |
691
|
49
|
|
|
|
|
240
|
->{lexeme} }, $g1_lexeme_id; |
692
|
|
|
|
|
|
|
} ## end if ( defined( my $event_data = $declarations->{'event'...})) |
693
|
|
|
|
|
|
|
|
694
|
54
|
|
|
|
|
211
|
$thin_slg->g1_lexeme_pause_activate( $g1_lexeme_id, $is_active ); |
695
|
|
|
|
|
|
|
} ## end if ( defined $pause_value ) |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
} ## end LEXEME: for my $lexeme_name ( keys %g1_id_by_lexeme_name ) |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
# Second phase of lexer processing |
700
|
252
|
|
|
|
|
1277
|
my $lexer_rule_to_g1_lexeme = $lexer_and_rule_to_g1_lexeme{$lexer_name}; |
701
|
|
|
|
|
|
|
|
702
|
252
|
|
|
|
|
616
|
RULE_ID: for my $lexer_rule_id ( 0 .. $#{$lexer_rule_to_g1_lexeme} ) { |
|
252
|
|
|
|
|
889
|
|
703
|
19852
|
|
|
|
|
25268
|
my $g1_lexeme_id = $lexer_rule_to_g1_lexeme->[$lexer_rule_id]; |
704
|
19852
|
|
|
|
|
34231
|
my $lexeme_name = $g1_tracer->symbol_name($g1_lexeme_id); |
705
|
|
|
|
|
|
|
my $assertion_id = |
706
|
19852
|
|
100
|
|
|
41766
|
$lexeme_data{$lexeme_name}{lexers}{$lexer_name}{'assertion'} |
707
|
|
|
|
|
|
|
// -1; |
708
|
19852
|
|
|
|
|
39995
|
$thin_slg->lexer_rule_to_g1_lexeme_set( $lexer_rule_id, |
709
|
|
|
|
|
|
|
$g1_lexeme_id, $assertion_id ); |
710
|
19852
|
|
|
|
|
25020
|
my $discard_event = $discard_event_by_lexer_rule_id[$lexer_rule_id]; |
711
|
19852
|
100
|
|
|
|
36623
|
if ( defined $discard_event ) { |
712
|
60
|
|
|
|
|
110
|
my ( $event_name, $is_active ) = @{$discard_event}; |
|
60
|
|
|
|
|
123
|
|
713
|
60
|
|
|
|
|
167
|
$slg->[ |
714
|
|
|
|
|
|
|
Marpa::R2::Internal::Scanless::G::DISCARD_EVENT_BY_LEXER_RULE |
715
|
|
|
|
|
|
|
]->[$lexer_rule_id] = $event_name; |
716
|
60
|
|
|
|
|
94
|
push @{ $symbol_ids_by_event_name_and_type->{$event_name} |
717
|
60
|
|
|
|
|
246
|
->{discard} }, $lexer_rule_id; |
718
|
60
|
|
|
|
|
195
|
$thin_slg->discard_event_set( $lexer_rule_id, 1 ); |
719
|
60
|
100
|
|
|
|
240
|
$thin_slg->discard_event_activate( $lexer_rule_id, 1 ) |
720
|
|
|
|
|
|
|
if $is_active; |
721
|
|
|
|
|
|
|
} ## end if ( defined $discard_event ) |
722
|
|
|
|
|
|
|
} ## end RULE_ID: for my $lexer_rule_id ( 0 .. $#{$lexer_rule_to_g1_lexeme...}) |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
# Second phase of G1 processing |
725
|
|
|
|
|
|
|
|
726
|
252
|
|
|
|
|
1681
|
$thin_slg->precompute(); |
727
|
252
|
|
|
|
|
661
|
$slg->[Marpa::R2::Internal::Scanless::G::THICK_G1_GRAMMAR] = |
728
|
|
|
|
|
|
|
$thick_g1_grammar; |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
# More lexer processing |
731
|
|
|
|
|
|
|
# Determine events by lexer rule, applying the defaults |
732
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
{ |
734
|
252
|
|
|
|
|
442
|
my $character_class_table = |
735
|
252
|
|
|
|
|
599
|
$character_class_table_by_lexer_name{$lexer_name}; |
736
|
252
|
|
|
|
|
686
|
$slg->[Marpa::R2::Internal::Scanless::G::CHARACTER_CLASS_TABLES] |
737
|
|
|
|
|
|
|
->[$lexer_id] = $character_class_table; |
738
|
|
|
|
|
|
|
$slg->[Marpa::R2::Internal::Scanless::G::THICK_LEX_GRAMMARS] |
739
|
252
|
|
|
|
|
766
|
->[$lexer_id] = $thick_grammar_by_lexer_name{$lexer_name}; |
740
|
|
|
|
|
|
|
} |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
# This section violates the NAIF interface, directly changing some |
743
|
|
|
|
|
|
|
# of its internal structures. |
744
|
|
|
|
|
|
|
# |
745
|
|
|
|
|
|
|
# Some lexeme default adverbs are applied in earlier phases. |
746
|
|
|
|
|
|
|
# |
747
|
|
|
|
|
|
|
APPLY_DEFAULT_LEXEME_ADVERBS: { |
748
|
252
|
50
|
|
|
|
542
|
last APPLY_DEFAULT_LEXEME_ADVERBS if not $lexeme_default_adverbs; |
|
252
|
|
|
|
|
849
|
|
749
|
|
|
|
|
|
|
|
750
|
252
|
|
|
|
|
704
|
my $action = $lexeme_default_adverbs->{action}; |
751
|
252
|
|
|
|
|
572
|
my $g1_symbols = |
752
|
|
|
|
|
|
|
$thick_g1_grammar->[Marpa::R2::Internal::Grammar::SYMBOLS]; |
753
|
|
|
|
|
|
|
LEXEME: |
754
|
252
|
|
|
|
|
2188
|
for my $lexeme_name ( keys %g1_id_by_lexeme_name ) { |
755
|
7676
|
|
|
|
|
11102
|
my $g1_lexeme_id = $g1_id_by_lexeme_name{$lexeme_name}; |
756
|
7676
|
|
|
|
|
11368
|
my $g1_symbol = $g1_symbols->[$g1_lexeme_id]; |
757
|
7676
|
100
|
|
|
|
18230
|
next LEXEME if $lexeme_name =~ m/ \] \z/xms; |
758
|
1575
|
|
66
|
|
|
5481
|
$g1_symbol->[Marpa::R2::Internal::Symbol::LEXEME_SEMANTICS] //= |
759
|
|
|
|
|
|
|
$action; |
760
|
|
|
|
|
|
|
} ## end LEXEME: for my $lexeme_name ( keys %g1_id_by_lexeme_name ) |
761
|
|
|
|
|
|
|
|
762
|
252
|
|
|
|
|
1339
|
my $blessing = $lexeme_default_adverbs->{bless}; |
763
|
252
|
100
|
|
|
|
1118
|
last APPLY_DEFAULT_LEXEME_ADVERBS if not $blessing; |
764
|
76
|
50
|
|
|
|
412
|
last APPLY_DEFAULT_LEXEME_ADVERBS if $blessing eq '::undef'; |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
LEXEME: |
767
|
76
|
|
|
|
|
1037
|
for my $lexeme_name ( keys %g1_id_by_lexeme_name ) { |
768
|
7158
|
|
|
|
|
9896
|
my $g1_lexeme_id = $g1_id_by_lexeme_name{$lexeme_name}; |
769
|
7158
|
|
|
|
|
8905
|
my $g1_symbol = $g1_symbols->[$g1_lexeme_id]; |
770
|
7158
|
100
|
|
|
|
16199
|
next LEXEME if $lexeme_name =~ m/ \] \z/xms; |
771
|
1312
|
50
|
|
|
|
2665
|
if ( $blessing eq '::name' ) { |
772
|
1312
|
50
|
|
|
|
3012
|
if ( $lexeme_name =~ / [^ [:alnum:]] /xms ) { |
773
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( |
774
|
|
|
|
|
|
|
qq{Lexeme blessing by '::name' only allowed if lexeme name is whitespace and alphanumerics\n}, |
775
|
|
|
|
|
|
|
qq{ Problematic lexeme was <$lexeme_name>\n} |
776
|
|
|
|
|
|
|
); |
777
|
|
|
|
|
|
|
} ## end if ( $lexeme_name =~ / [^ [:alnum:]] /xms ) |
778
|
1312
|
|
|
|
|
1769
|
my $blessing_by_name = $lexeme_name; |
779
|
1312
|
|
|
|
|
3824
|
$blessing_by_name =~ s/[ ]/_/gxms; |
780
|
1312
|
|
33
|
|
|
4971
|
$g1_symbol->[Marpa::R2::Internal::Symbol::BLESSING] //= |
781
|
|
|
|
|
|
|
$blessing_by_name; |
782
|
1312
|
|
|
|
|
2267
|
next LEXEME; |
783
|
|
|
|
|
|
|
} ## end if ( $blessing eq '::name' ) |
784
|
0
|
0
|
|
|
|
0
|
if ( $blessing =~ / [\W] /xms ) { |
785
|
0
|
|
|
|
|
0
|
Marpa::R2::exception( |
786
|
|
|
|
|
|
|
qq{Blessing lexeme as '$blessing' is not allowed\n}, |
787
|
|
|
|
|
|
|
qq{ Problematic lexeme was <$lexeme_name>\n} |
788
|
|
|
|
|
|
|
); |
789
|
|
|
|
|
|
|
} ## end if ( $blessing =~ / [\W] /xms ) |
790
|
0
|
|
0
|
|
|
0
|
$g1_symbol->[Marpa::R2::Internal::Symbol::BLESSING] //= $blessing; |
791
|
|
|
|
|
|
|
} ## end LEXEME: for my $lexeme_name ( keys %g1_id_by_lexeme_name ) |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
} ## end APPLY_DEFAULT_LEXEME_ADVERBS: |
794
|
|
|
|
|
|
|
|
795
|
252
|
|
|
|
|
20042
|
return $slg; |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
} ## end sub Marpa::R2::Internal::Scanless::G::hash_to_runtime |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
sub thick_subgrammar_by_name { |
800
|
665
|
|
|
665
|
|
998
|
my ( $slg, $subgrammar ) = @_; |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
# Allow G0 as legacy synonym for L0 |
803
|
665
|
|
|
|
|
943
|
state $grammar_names = { 'G0' => 1, 'G1' => 1, 'L0' => 1 }; |
804
|
665
|
|
100
|
|
|
2042
|
$subgrammar //= 'G1'; |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
Marpa::R2::exception(qq{No lexer named "$subgrammar"}) |
807
|
665
|
50
|
|
|
|
1371
|
if not defined $grammar_names->{$subgrammar}; |
808
|
|
|
|
|
|
|
|
809
|
665
|
100
|
|
|
|
1975
|
return $slg->[Marpa::R2::Internal::Scanless::G::THICK_G1_GRAMMAR] |
810
|
|
|
|
|
|
|
if $subgrammar eq 'G1'; |
811
|
|
|
|
|
|
|
|
812
|
203
|
|
|
|
|
453
|
return $slg->[Marpa::R2::Internal::Scanless::G::THICK_LEX_GRAMMARS] |
813
|
|
|
|
|
|
|
->[0]; |
814
|
|
|
|
|
|
|
} ## end sub thick_subgrammar_by_name |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::start_symbol_id { |
817
|
1
|
|
|
1
|
|
10
|
my ( $slg, $rule_id, $subgrammar ) = @_; |
818
|
1
|
|
|
|
|
4
|
return thick_subgrammar_by_name( $slg, $subgrammar )->start_symbol(); |
819
|
|
|
|
|
|
|
} |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::rule_name { |
822
|
5
|
|
|
5
|
|
21
|
my ( $slg, $rule_id, $subgrammar ) = @_; |
823
|
5
|
|
|
|
|
10
|
return thick_subgrammar_by_name( $slg, $subgrammar )->rule_name($rule_id); |
824
|
|
|
|
|
|
|
} |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::rule_expand { |
827
|
60
|
|
|
60
|
|
423
|
my ( $slg, $rule_id, $subgrammar ) = @_; |
828
|
60
|
|
|
|
|
103
|
return thick_subgrammar_by_name( $slg, $subgrammar )->tracer() |
829
|
|
|
|
|
|
|
->rule_expand($rule_id); |
830
|
|
|
|
|
|
|
} |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::symbol_name { |
833
|
171
|
|
|
171
|
|
836
|
my ( $slg, $symbol_id, $subgrammar ) = @_; |
834
|
171
|
|
|
|
|
313
|
return thick_subgrammar_by_name($slg, $subgrammar)->tracer() |
835
|
|
|
|
|
|
|
->symbol_name($symbol_id); |
836
|
|
|
|
|
|
|
} |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::symbol_display_form { |
839
|
139
|
|
|
139
|
|
462
|
my ( $slg, $symbol_id, $subgrammar ) = @_; |
840
|
139
|
|
|
|
|
285
|
return thick_subgrammar_by_name( $slg, $subgrammar ) |
841
|
|
|
|
|
|
|
->symbol_in_display_form($symbol_id); |
842
|
|
|
|
|
|
|
} |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::symbol_dsl_form { |
845
|
59
|
|
|
59
|
|
296
|
my ( $slg, $symbol_id, $subgrammar ) = @_; |
846
|
59
|
|
|
|
|
89
|
return thick_subgrammar_by_name( $slg, $subgrammar ) |
847
|
|
|
|
|
|
|
->symbol_dsl_form($symbol_id); |
848
|
|
|
|
|
|
|
} |
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::symbol_description { |
851
|
59
|
|
|
59
|
|
299
|
my ( $slg, $symbol_id, $subgrammar ) = @_; |
852
|
59
|
|
|
|
|
86
|
return thick_subgrammar_by_name($slg, $subgrammar) |
853
|
|
|
|
|
|
|
->symbol_description($symbol_id); |
854
|
|
|
|
|
|
|
} |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::rule_show |
857
|
|
|
|
|
|
|
{ |
858
|
136
|
|
|
136
|
|
497
|
my ( $slg, $rule_id, $subgrammar) = @_; |
859
|
136
|
|
|
|
|
261
|
return slg_rule_show($slg, $rule_id, thick_subgrammar_by_name($slg, $subgrammar)); |
860
|
|
|
|
|
|
|
} |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
sub slg_rule_show { |
863
|
136
|
|
|
136
|
|
232
|
my ( $slg, $rule_id, $subgrammar ) = @_; |
864
|
136
|
|
|
|
|
335
|
my $tracer = $subgrammar->tracer(); |
865
|
136
|
|
|
|
|
249
|
my $subgrammar_c = $subgrammar->[Marpa::R2::Internal::Grammar::C]; |
866
|
136
|
|
|
|
|
351
|
my @symbol_ids = $tracer->rule_expand($rule_id); |
867
|
136
|
50
|
|
|
|
314
|
return if not scalar @symbol_ids; |
868
|
|
|
|
|
|
|
my ( $lhs, @rhs ) = |
869
|
136
|
|
|
|
|
221
|
map { $subgrammar->symbol_in_display_form($_) } @symbol_ids; |
|
329
|
|
|
|
|
1047
|
|
870
|
136
|
|
|
|
|
376
|
my $minimum = $subgrammar_c->sequence_min($rule_id); |
871
|
136
|
|
|
|
|
199
|
my @quantifier = (); |
872
|
|
|
|
|
|
|
|
873
|
136
|
100
|
|
|
|
269
|
if ( defined $minimum ) { |
874
|
8
|
100
|
|
|
|
23
|
@quantifier = ( $minimum <= 0 ? q{*} : q{+} ); |
875
|
|
|
|
|
|
|
} |
876
|
136
|
|
|
|
|
708
|
return join q{ }, $lhs, q{::=}, @rhs, @quantifier; |
877
|
|
|
|
|
|
|
} ## end sub slg_rule_show |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::show_rules { |
880
|
10
|
|
|
10
|
|
4049
|
my ( $slg, $verbose, $subgrammar ) = @_; |
881
|
10
|
|
|
|
|
43
|
my $text = q{}; |
882
|
10
|
|
100
|
|
|
90
|
$verbose //= 0; |
883
|
10
|
|
100
|
|
|
51
|
$subgrammar //= 'G1'; |
884
|
|
|
|
|
|
|
|
885
|
10
|
|
|
|
|
47
|
my $thick_grammar = thick_subgrammar_by_name($slg, $subgrammar); |
886
|
|
|
|
|
|
|
|
887
|
10
|
|
|
|
|
25
|
my $rules = $thick_grammar->[Marpa::R2::Internal::Grammar::RULES]; |
888
|
10
|
|
|
|
|
21
|
my $grammar_c = $thick_grammar->[Marpa::R2::Internal::Grammar::C]; |
889
|
|
|
|
|
|
|
|
890
|
10
|
|
|
|
|
19
|
for my $rule ( @{$rules} ) { |
|
10
|
|
|
|
|
28
|
|
891
|
183
|
|
|
|
|
283
|
my $rule_id = $rule->[Marpa::R2::Internal::Rule::ID]; |
892
|
|
|
|
|
|
|
|
893
|
183
|
|
|
|
|
426
|
my $minimum = $grammar_c->sequence_min($rule_id); |
894
|
183
|
100
|
|
|
|
365
|
my @quantifier = |
|
|
100
|
|
|
|
|
|
895
|
|
|
|
|
|
|
defined $minimum ? $minimum <= 0 ? (q{*}) : (q{+}) : (); |
896
|
183
|
|
|
|
|
343
|
my $lhs_id = $grammar_c->rule_lhs($rule_id); |
897
|
183
|
|
|
|
|
340
|
my $rule_length = $grammar_c->rule_length($rule_id); |
898
|
|
|
|
|
|
|
my @rhs_ids = |
899
|
183
|
|
|
|
|
317
|
map { $grammar_c->rule_rhs( $rule_id, $_ ) } |
|
266
|
|
|
|
|
590
|
|
900
|
|
|
|
|
|
|
( 0 .. $rule_length - 1 ); |
901
|
|
|
|
|
|
|
$text .= join q{ }, $subgrammar, "R$rule_id", |
902
|
|
|
|
|
|
|
$thick_grammar->symbol_in_display_form($lhs_id), |
903
|
|
|
|
|
|
|
'::=', |
904
|
183
|
|
|
|
|
514
|
( map { $thick_grammar->symbol_in_display_form($_) } @rhs_ids ), |
|
266
|
|
|
|
|
490
|
|
905
|
|
|
|
|
|
|
@quantifier; |
906
|
183
|
|
|
|
|
326
|
$text .= "\n"; |
907
|
|
|
|
|
|
|
|
908
|
183
|
100
|
|
|
|
396
|
if ( $verbose >= 2 ) { |
909
|
|
|
|
|
|
|
|
910
|
48
|
|
|
|
|
74
|
my $description = $rule->[Marpa::R2::Internal::Rule::DESCRIPTION]; |
911
|
48
|
100
|
|
|
|
103
|
$text .= " $description\n" if $description; |
912
|
48
|
|
|
|
|
75
|
my @comment = (); |
913
|
48
|
50
|
|
|
|
127
|
$grammar_c->rule_length($rule_id) == 0 |
914
|
|
|
|
|
|
|
and push @comment, 'empty'; |
915
|
48
|
50
|
|
|
|
114
|
$thick_grammar->rule_is_used($rule_id) |
916
|
|
|
|
|
|
|
or push @comment, '!used'; |
917
|
48
|
50
|
|
|
|
127
|
$grammar_c->rule_is_productive($rule_id) |
918
|
|
|
|
|
|
|
or push @comment, 'unproductive'; |
919
|
48
|
50
|
|
|
|
114
|
$grammar_c->rule_is_accessible($rule_id) |
920
|
|
|
|
|
|
|
or push @comment, 'inaccessible'; |
921
|
48
|
50
|
|
|
|
82
|
$rule->[Marpa::R2::Internal::Rule::DISCARD_SEPARATION] |
922
|
|
|
|
|
|
|
and push @comment, 'discard_sep'; |
923
|
|
|
|
|
|
|
|
924
|
48
|
50
|
|
|
|
88
|
if (@comment) { |
925
|
0
|
|
|
|
|
0
|
$text .= q{ } . ( join q{ }, q{/*}, @comment, q{*/} ) . "\n"; |
926
|
|
|
|
|
|
|
} |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
$text .= " Symbol IDs: <$lhs_id> ::= " |
929
|
48
|
|
|
|
|
102
|
. ( join q{ }, map {"<$_>"} @rhs_ids ) . "\n"; |
|
72
|
|
|
|
|
220
|
|
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
} ## end if ( $verbose >= 2 ) |
932
|
|
|
|
|
|
|
|
933
|
183
|
100
|
|
|
|
398
|
if ( $verbose >= 3 ) { |
934
|
|
|
|
|
|
|
|
935
|
48
|
|
|
|
|
104
|
my $tracer = $thick_grammar->tracer(); |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
$text |
938
|
|
|
|
|
|
|
.= " Internal symbols: <" |
939
|
|
|
|
|
|
|
. $tracer->symbol_name($lhs_id) |
940
|
|
|
|
|
|
|
. q{> ::= } |
941
|
|
|
|
|
|
|
. ( |
942
|
|
|
|
|
|
|
join q{ }, |
943
|
48
|
|
|
|
|
100
|
map { '<' . $tracer->symbol_name($_) . '>' } @rhs_ids |
|
72
|
|
|
|
|
138
|
|
944
|
|
|
|
|
|
|
) . "\n"; |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
} ## end if ( $verbose >= 3 ) |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
} ## end for my $rule ( @{$rules} ) |
949
|
|
|
|
|
|
|
|
950
|
10
|
|
|
|
|
85
|
return $text; |
951
|
|
|
|
|
|
|
} ## end sub Marpa::R2::Scanless::G::show_rules |
952
|
|
|
|
|
|
|
|
953
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::show_symbols { |
954
|
4
|
|
|
4
|
|
718
|
my ( $slg, $verbose, $subgrammar ) = @_; |
955
|
4
|
|
|
|
|
13
|
my $text = q{}; |
956
|
4
|
|
100
|
|
|
19
|
$verbose //= 0; |
957
|
4
|
|
100
|
|
|
23
|
$subgrammar //= 'G1'; |
958
|
|
|
|
|
|
|
|
959
|
4
|
|
|
|
|
15
|
my $thick_grammar = thick_subgrammar_by_name($slg, $subgrammar); |
960
|
|
|
|
|
|
|
|
961
|
4
|
|
|
|
|
13
|
my $symbols = $thick_grammar->[Marpa::R2::Internal::Grammar::SYMBOLS]; |
962
|
4
|
|
|
|
|
9
|
my $grammar_c = $thick_grammar->[Marpa::R2::Internal::Grammar::C]; |
963
|
|
|
|
|
|
|
|
964
|
4
|
|
|
|
|
7
|
for my $symbol ( @{$symbols} ) { |
|
4
|
|
|
|
|
13
|
|
965
|
68
|
|
|
|
|
96
|
my $symbol_id = $symbol->[Marpa::R2::Internal::Symbol::ID]; |
966
|
|
|
|
|
|
|
|
967
|
68
|
|
|
|
|
152
|
$text .= join q{ }, $subgrammar, "S$symbol_id", |
968
|
|
|
|
|
|
|
$thick_grammar->symbol_in_display_form($symbol_id); |
969
|
|
|
|
|
|
|
|
970
|
68
|
|
|
|
|
128
|
my $description = $symbol->[Marpa::R2::Internal::Symbol::DESCRIPTION]; |
971
|
68
|
100
|
|
|
|
115
|
if ($description) { |
972
|
49
|
|
|
|
|
80
|
$text .= " -- $description"; |
973
|
|
|
|
|
|
|
} |
974
|
68
|
|
|
|
|
92
|
$text .= "\n"; |
975
|
|
|
|
|
|
|
|
976
|
68
|
100
|
|
|
|
118
|
if ( $verbose >= 2 ) { |
977
|
|
|
|
|
|
|
|
978
|
59
|
|
|
|
|
107
|
my @tag_list = (); |
979
|
59
|
50
|
|
|
|
141
|
$grammar_c->symbol_is_productive($symbol_id) |
980
|
|
|
|
|
|
|
or push @tag_list, 'unproductive'; |
981
|
59
|
50
|
|
|
|
136
|
$grammar_c->symbol_is_accessible($symbol_id) |
982
|
|
|
|
|
|
|
or push @tag_list, 'inaccessible'; |
983
|
59
|
50
|
|
|
|
127
|
$grammar_c->symbol_is_nulling($symbol_id) |
984
|
|
|
|
|
|
|
and push @tag_list, 'nulling'; |
985
|
59
|
100
|
|
|
|
139
|
$grammar_c->symbol_is_terminal($symbol_id) |
986
|
|
|
|
|
|
|
and push @tag_list, 'terminal'; |
987
|
|
|
|
|
|
|
|
988
|
59
|
100
|
|
|
|
106
|
if (@tag_list) { |
989
|
30
|
|
|
|
|
62
|
$text |
990
|
|
|
|
|
|
|
.= q{ } . ( join q{ }, q{/*}, @tag_list, q{*/} ) . "\n"; |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
|
993
|
59
|
|
|
|
|
113
|
my $tracer = $thick_grammar->tracer(); |
994
|
59
|
|
|
|
|
116
|
$text .= " Internal name: <" |
995
|
|
|
|
|
|
|
. $tracer->symbol_name($symbol_id) . qq{>\n}; |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
} ## end if ( $verbose >= 2 ) |
998
|
|
|
|
|
|
|
|
999
|
68
|
100
|
|
|
|
131
|
if ( $verbose >= 3 ) { |
1000
|
|
|
|
|
|
|
|
1001
|
59
|
|
|
|
|
87
|
my $dsl_form = $symbol->[Marpa::R2::Internal::Symbol::DSL_FORM]; |
1002
|
59
|
100
|
|
|
|
103
|
if ($dsl_form) { $text .= qq{ SLIF name: $dsl_form\n}; } |
|
42
|
|
|
|
|
86
|
|
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
} ## end if ( $verbose >= 3 ) |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
} ## end for my $symbol ( @{$symbols} ) |
1007
|
|
|
|
|
|
|
|
1008
|
4
|
|
|
|
|
35
|
return $text; |
1009
|
|
|
|
|
|
|
} ## end sub Marpa::R2::Scanless::G::show_symbols |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::show_dotted_rule { |
1012
|
428
|
|
|
428
|
|
4230
|
my ( $slg, $rule_id, $dot_position ) = @_; |
1013
|
428
|
|
|
|
|
652
|
my $grammar = $slg->[Marpa::R2::Internal::Scanless::G::THICK_G1_GRAMMAR]; |
1014
|
428
|
|
|
|
|
903
|
my $tracer = $grammar->tracer(); |
1015
|
428
|
|
|
|
|
612
|
my $grammar_c = $grammar->[Marpa::R2::Internal::Grammar::C]; |
1016
|
|
|
|
|
|
|
my ( $lhs, @rhs ) = |
1017
|
428
|
|
|
|
|
901
|
map { $grammar->symbol_in_display_form($_) } $tracer->rule_expand($rule_id); |
|
2870
|
|
|
|
|
5278
|
|
1018
|
428
|
|
|
|
|
852
|
my $rhs_length = scalar @rhs; |
1019
|
|
|
|
|
|
|
|
1020
|
428
|
|
|
|
|
914
|
my $minimum = $grammar_c->sequence_min($rule_id); |
1021
|
428
|
|
|
|
|
643
|
my @quantifier = (); |
1022
|
428
|
100
|
|
|
|
793
|
if (defined $minimum) { |
1023
|
4
|
50
|
|
|
|
16
|
@quantifier = ($minimum <= 0 ? q{*} : q{+} ); |
1024
|
|
|
|
|
|
|
} |
1025
|
428
|
100
|
|
|
|
761
|
$dot_position += ($rhs_length + 1) if $dot_position < 0; |
1026
|
428
|
50
|
|
|
|
718
|
$dot_position = 0 if $dot_position < 0; |
1027
|
428
|
100
|
|
|
|
735
|
if ($dot_position < $rhs_length) { |
1028
|
324
|
|
|
|
|
650
|
splice @rhs, $dot_position, 0, q{.}; |
1029
|
324
|
|
|
|
|
1448
|
return join q{ }, $lhs, q{->}, @rhs, @quantifier; |
1030
|
|
|
|
|
|
|
} else { |
1031
|
104
|
|
|
|
|
465
|
return join q{ }, $lhs, q{->}, @rhs, @quantifier, q{.}; |
1032
|
|
|
|
|
|
|
} |
1033
|
|
|
|
|
|
|
} ## end sub Marpa::R2::Grammar::show_dotted_rule |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::rule { |
1036
|
6
|
|
|
6
|
|
61
|
my ( $slg, @args ) = @_; |
1037
|
6
|
|
|
|
|
14
|
return $slg->[Marpa::R2::Internal::Scanless::G::THICK_G1_GRAMMAR] |
1038
|
|
|
|
|
|
|
->rule(@args); |
1039
|
|
|
|
|
|
|
} |
1040
|
|
|
|
|
|
|
|
1041
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::rule_ids { |
1042
|
11
|
|
|
11
|
|
4635
|
my ($slg, $subgrammar) = @_; |
1043
|
11
|
|
|
|
|
39
|
return thick_subgrammar_by_name($slg, $subgrammar)->rule_ids(); |
1044
|
|
|
|
|
|
|
} |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::symbol_ids { |
1047
|
6
|
|
|
6
|
|
2208
|
my ($slg, $subgrammar) = @_; |
1048
|
6
|
|
|
|
|
22
|
return thick_subgrammar_by_name($slg, $subgrammar)->symbol_ids(); |
1049
|
|
|
|
|
|
|
} |
1050
|
|
|
|
|
|
|
|
1051
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::g1_rule_ids { |
1052
|
1
|
|
|
1
|
|
1002
|
my ($slg) = @_; |
1053
|
1
|
|
|
|
|
3
|
return $slg->rule_ids(); |
1054
|
|
|
|
|
|
|
} |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::g0_rule_ids { |
1057
|
1
|
|
|
1
|
|
18
|
my ($slg) = @_; |
1058
|
1
|
|
|
|
|
7
|
return $slg->rule_ids('L0'); |
1059
|
|
|
|
|
|
|
} |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::g0_rule { |
1062
|
17
|
|
|
17
|
|
168
|
my ( $slg, @args ) = @_; |
1063
|
17
|
|
|
|
|
38
|
return $slg->[Marpa::R2::Internal::Scanless::G::THICK_LEX_GRAMMARS]->[0] |
1064
|
|
|
|
|
|
|
->rule(@args); |
1065
|
|
|
|
|
|
|
} |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
# Internal methods, not to be documented |
1068
|
|
|
|
|
|
|
|
1069
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::thick_g1_grammar { |
1070
|
0
|
|
|
0
|
|
0
|
my ($slg) = @_; |
1071
|
0
|
|
|
|
|
0
|
return $slg->[Marpa::R2::Internal::Scanless::G::THICK_G1_GRAMMAR]; |
1072
|
|
|
|
|
|
|
} |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::show_irls { |
1075
|
2
|
|
|
2
|
|
10
|
my ($slg, $subgrammar) = @_; |
1076
|
2
|
|
|
|
|
9
|
return thick_subgrammar_by_name($slg, $subgrammar)->show_irls(); |
1077
|
|
|
|
|
|
|
} |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::G::show_isys { |
1080
|
2
|
|
|
2
|
|
1311
|
my ($slg, $subgrammar) = @_; |
1081
|
2
|
|
|
|
|
8
|
return thick_subgrammar_by_name($slg, $subgrammar)->show_isys(); |
1082
|
|
|
|
|
|
|
} |
1083
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
1; |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
# vim: expandtab shiftwidth=4: |