File Coverage

blib/lib/Marpa/R2/MetaAST.pm
Criterion Covered Total %
statement 827 977 84.6
branch 177 280 63.2
condition 68 105 64.7
subroutine 103 112 91.9
pod n/a
total 1175 1474 79.7


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::MetaAST;
17              
18 135     135   3575 use 5.010001;
  135         566  
19 135     135   847 use strict;
  135         359  
  135         3218  
20 135     135   791 use warnings;
  135         353  
  135         4723  
21              
22 135     135   765 use vars qw($VERSION $STRING_VERSION);
  135         312  
  135         11590  
23             $VERSION = '13.002_000';
24             $STRING_VERSION = $VERSION;
25             ## no critic(BuiltinFunctions::ProhibitStringyEval)
26             $VERSION = eval $VERSION;
27             ## use critic
28              
29             package Marpa::R2::Internal::MetaAST;
30              
31 135     135   907 use English qw( -no_match_vars );
  135         351  
  135         1154  
32              
33             sub new {
34 207     207   739 my ( $class, $p_rules_source ) = @_;
35 207         953 my $meta_recce = Marpa::R2::Internal::Scanless::meta_recce();
36 207 100       561 eval { $meta_recce->read($p_rules_source) }
  207         1079  
37             or Marpa::R2::exception( "Parse of BNF/Scanless source failed\n",
38             $EVAL_ERROR );
39 205 100       1557 if ( my $ambiguity_status = $meta_recce->ambiguous() ) {
40 1         13 Marpa::R2::exception( "Parse of BNF/Scanless source failed:\n",
41             $ambiguity_status );
42             }
43 204         1099 my $value_ref = $meta_recce->value();
44 204 50       916 Marpa::R2::exception('Parse of BNF/Scanless source failed')
45             if not defined $value_ref;
46 204         599 my $ast = { meta_recce => $meta_recce, top_node => ${$value_ref} };
  204         1324  
47 204         1364 return bless $ast, $class;
48             } ## end sub new
49              
50             sub Marpa::R2::Internal::MetaAST::Parse::substring {
51 13     13   32 my ( $parse, $start, $length ) = @_;
52 13         28 my $meta_slr = $parse->{meta_recce};
53 13         31 my $thin_meta_slr = $meta_slr->[Marpa::R2::Internal::Scanless::R::C];
54 13         67 my $string = $thin_meta_slr->substring( $start, $length );
55 13         34 chomp $string;
56 13         33 return $string;
57             } ## end sub Marpa::R2::Internal::MetaAST::Parse::substring
58              
59             sub ast_to_hash {
60 204     204   613 my ($ast) = @_;
61 204         505 my $hashed_ast = {};
62              
63 204         1172 $hashed_ast->{meta_recce} = $ast->{meta_recce};
64 204         919 bless $hashed_ast, 'Marpa::R2::Internal::MetaAST::Parse';
65              
66 204         868 $hashed_ast->{current_lexer} = 'L0';
67 204         878 $hashed_ast->{rules}->{G1} = [];
68 204         859 my $g1_symbols = $hashed_ast->{symbols}->{G1} = {};
69              
70 204         436 my ( undef, undef, @statements ) = @{ $ast->{top_node} };
  204         1100  
71              
72             # This is the last ditch exception catcher
73             # It forces all Marpa exceptions to be die's,
74             # then catches them and rethrows using Carp.
75             #
76             # The plan is to use die(), with higher levels
77             # catching and re-die()'ing after adding
78             # helpful location information. After the
79             # re-throw it is caught here and passed to
80             # Carp.
81 204         548 my $eval_ok = eval {
82 204         618 local $Marpa::R2::JUST_DIE = 1;
83 204         1321 $_->evaluate($hashed_ast) for @statements;
84 204         867 1;
85             };
86 204 50       929 Marpa::R2::exception($EVAL_ERROR) if not $eval_ok;
87              
88 204         577 my %grammars = ();
89 204         454 $grammars{$_} = 1 for keys %{ $hashed_ast->{rules} };
  204         1256  
90             my @lexers =
91 204         871 grep { ( substr $_, 0, 1 ) eq 'L' } keys %grammars;
  398         1414  
92              
93 204         829 for my $lexer (@lexers) {
94 194         505 my $lexer_name = $lexer;
95             NAME_LEXER: {
96 194 50       398 if ( $lexer eq 'L0' ) {
  194         736  
97 194         437 $lexer_name = "L0 (the default)";
98 194         576 last NAME_LEXER;
99             }
100 0 0       0 last NAME_LEXER if ( substr $lexer_name, 0, 2 ) ne 'L-';
101 0         0 $lexer_name = substr $lexer_name, 2;
102             } ## end NAME_LEXER:
103             } ## end for my $lexer (@lexers)
104              
105 204         560 my %stripped_character_classes = ();
106             {
107 204         425 my $character_classes = $hashed_ast->{character_classes};
  204         543  
108 204         430 for my $symbol_name ( sort keys %{$character_classes} ) {
  204         1610  
109 942         1345 my ($re) = @{ $character_classes->{$symbol_name} };
  942         1640  
110 942         1977 $stripped_character_classes{$symbol_name} = $re;
111             }
112             }
113 204         1646 $hashed_ast->{character_classes} = \%stripped_character_classes;
114              
115 204         1261 return $hashed_ast;
116             } ## end sub ast_to_hash
117              
118             sub Marpa::R2::Internal::MetaAST::Parse::start_rule_setup {
119 0     0   0 my ($ast) = @_;
120 0   0     0 my $start_lhs = $ast->{'start_lhs'} // $ast->{'first_lhs'};
121 0 0       0 Marpa::R2::exception('No rules in SLIF grammar')
122             if not defined $start_lhs;
123 0         0 Marpa::R2::Internal::MetaAST::start_rule_create( $ast, $start_lhs );
124             } ## end sub Marpa::R2::Internal::MetaAST::Parse::start_rule_setup
125              
126             # This class is for pieces of RHS alternatives, as they are
127             # being constructed
128             my $PROTO_ALTERNATIVE = 'Marpa::R2::Internal::MetaAST::Proto_Alternative';
129              
130             sub Marpa::R2::Internal::MetaAST::Proto_Alternative::combine {
131 635     635   1384 my ( $class, @hashes ) = @_;
132 635         1255 my $self = bless {}, $class;
133 635         1332 for my $hash_to_add (@hashes) {
134 770         1132 for my $key ( keys %{$hash_to_add} ) {
  770         2447  
135             ## expect to be caught and rethrown
136             die qq{A Marpa rule contained a duplicate key\n},
137             qq{ The key was "$key"\n}
138 764 50       1891 if exists $self->{$key};
139 764         2235 $self->{$key} = $hash_to_add->{$key};
140             } ## end for my $key ( keys %{$hash_to_add} )
141             } ## end for my $hash_to_add (@hashes)
142 635         2588 return $self;
143             } ## end sub Marpa::R2::Internal::MetaAST::Proto_Alternative::combine
144              
145             sub Marpa::R2::Internal::MetaAST::Parse::bless_hash_rule {
146 1639     1639   3567 my ( $parse, $hash_rule, $blessing, $naming, $original_lhs ) = @_;
147 1639 100       4166 return if (substr $Marpa::R2::Internal::SUBGRAMMAR, 0, 1) eq 'L';
148              
149 924   66     3447 $naming //= $original_lhs;
150 924         1911 $hash_rule->{name} = $naming;
151              
152 924 100       2371 return if not defined $blessing;
153             FIND_BLESSING: {
154 100 100       146 last FIND_BLESSING if $blessing =~ /\A [\w] /xms;
  100         396  
155 28 50       56 return if $blessing eq '::undef';
156              
157             # Rule may be half-formed, but assume we have lhs
158 28 50       62 if ( $blessing eq '::lhs' ) {
159 28         44 $blessing = $original_lhs;
160 28 50       83 if ( $blessing =~ / [^ [:alnum:]] /xms ) {
161 0         0 Marpa::R2::exception(
162             qq{"::lhs" blessing only allowed if LHS is whitespace and alphanumerics\n},
163             qq{ LHS was <$original_lhs>\n}
164             );
165             } ## end if ( $blessing =~ / [^ [:alnum:]] /xms )
166 28         69 $blessing =~ s/[ ]/_/gxms;
167 28         55 last FIND_BLESSING;
168             } ## end if ( $blessing eq '::lhs' )
169 0         0 Marpa::R2::exception( qq{Unknown blessing "$blessing"\n} );
170             } ## end FIND_BLESSING:
171 100         191 $hash_rule->{bless} = $blessing;
172 100         165 return 1;
173             } ## end sub Marpa::R2::Internal::MetaAST::Parse::bless_hash_rule
174              
175 3068     3068   9737 sub Marpa::R2::Internal::MetaAST_Nodes::bare_name::name { return $_[0]->[2] }
176              
177             sub Marpa::R2::Internal::MetaAST_Nodes::reserved_action_name::name {
178 60     60   164 my ( $self, $parse ) = @_;
179 60         369 return $self->[2];
180             }
181              
182             sub Marpa::R2::Internal::MetaAST_Nodes::reserved_event_name::name {
183 33     33   96 my ( $self, $parse ) = @_;
184 33         85 my $name = $self->[2];
185 33         230 $name =~ s/\A : /'/xms;
186 33         206 return $name;
187             }
188              
189             sub Marpa::R2::Internal::MetaAST_Nodes::action_name::name {
190 365     365   795 my ( $self, $parse ) = @_;
191 365         1287 return $self->[2]->name($parse);
192             }
193              
194             sub Marpa::R2::Internal::MetaAST_Nodes::alternative_name::name {
195 5     5   13 my ( $self, $parse ) = @_;
196 5         30 return $self->[2]->name($parse);
197             }
198              
199             sub Marpa::R2::Internal::MetaAST_Nodes::event_name::name {
200 279     279   548 my ( $self, $parse ) = @_;
201 279         1005 return $self->[2]->name($parse);
202             }
203              
204             sub Marpa::R2::Internal::MetaAST_Nodes::lexer_name::name {
205 0     0   0 my ( $self, $parse ) = @_;
206 0         0 return $self->[2]->name($parse);
207             }
208              
209             sub Marpa::R2::Internal::MetaAST_Nodes::array_descriptor::name {
210 98     98   604 return $_[0]->[2];
211             }
212              
213             sub Marpa::R2::Internal::MetaAST_Nodes::reserved_blessing_name::name {
214 12     12   60 return $_[0]->[2];
215             }
216              
217             sub Marpa::R2::Internal::MetaAST_Nodes::blessing_name::name {
218 84     84   141 my ( $self, $parse ) = @_;
219 84         217 return $self->[2]->name($parse);
220             }
221              
222             sub Marpa::R2::Internal::MetaAST_Nodes::standard_name::name {
223 129     129   493 return $_[0]->[2];
224             }
225              
226             sub Marpa::R2::Internal::MetaAST_Nodes::Perl_name::name {
227 207     207   963 return $_[0]->[2];
228             }
229              
230             sub Marpa::R2::Internal::MetaAST_Nodes::lhs::name {
231 1265     1265   2815 my ( $values, $parse ) = @_;
232 1265         1889 my ( undef, undef, $symbol ) = @{$values};
  1265         2338  
233 1265         3092 return $symbol->name($parse);
234             }
235              
236             # After development, delete this
237             sub Marpa::R2::Internal::MetaAST_Nodes::lhs::evaluate {
238 0     0   0 my ( $values, $parse ) = @_;
239 0         0 return $values->name($parse);
240             }
241              
242             sub Marpa::R2::Internal::MetaAST_Nodes::quantifier::evaluate {
243 194     194   497 my ($data) = @_;
244 194         1209 return $data->[2];
245             }
246              
247             sub Marpa::R2::Internal::MetaAST_Nodes::op_declare::op {
248 1265     1265   2250 my ($values) = @_;
249 1265         3367 return $values->[2]->op();
250             }
251              
252             sub Marpa::R2::Internal::MetaAST_Nodes::op_declare_match::op {
253 609     609   1250 my ($values) = @_;
254 609         2112 return $values->[2];
255             }
256              
257             sub Marpa::R2::Internal::MetaAST_Nodes::op_declare_bnf::op {
258 768     768   1443 my ($values) = @_;
259 768         3193 return $values->[2];
260             }
261              
262             sub Marpa::R2::Internal::MetaAST_Nodes::bracketed_name::name {
263 410     410   835 my ($values) = @_;
264 410         604 my ( undef, undef, $bracketed_name ) = @{$values};
  410         870  
265              
266             # normalize whitespace
267 410         2044 $bracketed_name =~ s/\A [<] \s*//xms;
268 410         2031 $bracketed_name =~ s/ \s* [>] \z//xms;
269 410         1413 $bracketed_name =~ s/ \s+ / /gxms;
270 410         1238 return $bracketed_name;
271             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::bracketed_name::name
272              
273             sub Marpa::R2::Internal::MetaAST_Nodes::single_quoted_name::name {
274 194     194   318 my ($values) = @_;
275 194         266 my ( undef, undef, $single_quoted_name ) = @{$values};
  194         363  
276              
277             # normalize whitespace
278 194         757 $single_quoted_name =~ s/\A ['] \s*//xms;
279 194         749 $single_quoted_name =~ s/ \s* ['] \z//xms;
280 194         428 $single_quoted_name =~ s/ \s+ / /gxms;
281 194         581 return $single_quoted_name;
282             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::single_quoted_name::name
283              
284             sub Marpa::R2::Internal::MetaAST_Nodes::parenthesized_rhs_primary_list::evaluate
285             {
286 77     77   167 my ( $data, $parse ) = @_;
287 77         120 my ( undef, undef, @values ) = @{$data};
  77         204  
288 77         149 my @symbol_lists = map { $_->evaluate($parse); } @values;
  77         183  
289 77         289 my $flattened_list =
290             Marpa::R2::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
291 77         349 $flattened_list->mask_set(0);
292 77         258 return $flattened_list;
293             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::parenthesized_rhs_primary_list::evaluate
294              
295             sub Marpa::R2::Internal::MetaAST_Nodes::rhs::evaluate {
296 1383     1383   2513 my ( $data, $parse ) = @_;
297 1383         1971 my ( $start, $length, @values ) = @{$data};
  1383         2865  
298 1383         2084 my $rhs = eval {
299 1383         2464 my @symbol_lists = map { $_->evaluate($parse) } @values;
  2287         4580  
300 1383         3393 my $flattened_list =
301             Marpa::R2::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
302 1383         3438 bless {
303             rhs => $flattened_list->names($parse),
304             mask => $flattened_list->mask()
305             },
306             $PROTO_ALTERNATIVE;
307             };
308 1383 50       3572 if ( not $rhs ) {
309 0         0 my $eval_error = $EVAL_ERROR;
310 0         0 chomp $eval_error;
311 0         0 Marpa::R2::exception(
312             qq{$eval_error\n},
313             q{ RHS involved was },
314             $parse->substring( $start, $length )
315             );
316             } ## end if ( not $rhs )
317 1383         2968 return $rhs;
318             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::rhs::evaluate
319              
320             sub Marpa::R2::Internal::MetaAST_Nodes::rhs_primary::evaluate {
321 2374     2374   3923 my ( $data, $parse ) = @_;
322 2374         3234 my ( undef, undef, @values ) = @{$data};
  2374         4052  
323 2374         3611 my @symbol_lists = map { $_->evaluate($parse) } @values;
  2374         5662  
324 2374         5629 return Marpa::R2::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
325             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::rhs_primary::evaluate
326              
327             sub Marpa::R2::Internal::MetaAST_Nodes::rhs_primary_list::evaluate {
328 77     77   158 my ( $data, $parse ) = @_;
329 77         117 my ( undef, undef, @values ) = @{$data};
  77         197  
330 77         140 my @symbol_lists = map { $_->evaluate($parse) } @values;
  87         282  
331 77         228 return Marpa::R2::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
332             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::rhs_primary_list::evaluate
333              
334             sub Marpa::R2::Internal::MetaAST_Nodes::action::evaluate {
335 365     365   812 my ( $values, $parse ) = @_;
336 365         587 my ( undef, undef, $child ) = @{$values};
  365         762  
337 365         1126 return bless { action => $child->name($parse) }, $PROTO_ALTERNATIVE;
338             }
339              
340             sub Marpa::R2::Internal::MetaAST_Nodes::blessing::evaluate {
341 84     84   155 my ( $values, $parse ) = @_;
342 84         128 my ( undef, undef, $child ) = @{$values};
  84         141  
343 84         209 return bless { bless => $child->name($parse) }, $PROTO_ALTERNATIVE;
344             }
345              
346             sub Marpa::R2::Internal::MetaAST_Nodes::naming::evaluate {
347 5     5   12 my ( $values, $parse ) = @_;
348 5         10 my ( undef, undef, $child ) = @{$values};
  5         20  
349 5         21 return bless { name => $child->name($parse) }, $PROTO_ALTERNATIVE;
350             }
351              
352             sub Marpa::R2::Internal::MetaAST_Nodes::right_association::evaluate {
353 10     10   37 my ($values) = @_;
354 10         53 return bless { assoc => 'R' }, $PROTO_ALTERNATIVE;
355             }
356              
357             sub Marpa::R2::Internal::MetaAST_Nodes::left_association::evaluate {
358 0     0   0 my ($values) = @_;
359 0         0 return bless { assoc => 'L' }, $PROTO_ALTERNATIVE;
360             }
361              
362             sub Marpa::R2::Internal::MetaAST_Nodes::group_association::evaluate {
363 11     11   54 my ($values) = @_;
364 11         51 return bless { assoc => 'G' }, $PROTO_ALTERNATIVE;
365             }
366              
367             sub Marpa::R2::Internal::MetaAST_Nodes::event_specification::evaluate {
368 127     127   313 my ($values) = @_;
369 127         499 return bless { event => ( $values->[2]->event() ) }, $PROTO_ALTERNATIVE;
370             }
371              
372             sub Marpa::R2::Internal::MetaAST_Nodes::event_initialization::event {
373 279     279   513 my ($values) = @_;
374 279         525 my $event_name = $values->[2];
375 279         441 my $event_initializer = $values->[3];
376 279         759 return [$event_name->name(), $event_initializer->on_or_off()],
377             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::event_specification::evaluate
378              
379             sub Marpa::R2::Internal::MetaAST_Nodes::proper_specification::evaluate {
380 1     1   3 my ($values) = @_;
381 1         5 my $child = $values->[2];
382 1         10 return bless { proper => $child->value() }, $PROTO_ALTERNATIVE;
383             }
384              
385             sub Marpa::R2::Internal::MetaAST_Nodes::latm_specification::evaluate {
386 45     45   188 my ($values) = @_;
387 45         176 my $child = $values->[2];
388 45         273 return bless { latm => $child->value() }, $PROTO_ALTERNATIVE;
389             }
390              
391             sub Marpa::R2::Internal::MetaAST_Nodes::pause_specification::evaluate {
392 54     54   106 my ($values) = @_;
393 54         109 my $child = $values->[2];
394 54         237 return bless { pause => $child->value() }, $PROTO_ALTERNATIVE;
395             }
396              
397             sub Marpa::R2::Internal::MetaAST_Nodes::priority_specification::evaluate {
398 2     2   5 my ($values) = @_;
399 2         6 my $child = $values->[2];
400 2         10 return bless { priority => $child->value() }, $PROTO_ALTERNATIVE;
401             }
402              
403             sub Marpa::R2::Internal::MetaAST_Nodes::rank_specification::evaluate {
404 45     45   93 my ($values) = @_;
405 45         127 my $child = $values->[2];
406 45         155 return bless { rank => $child->value() }, $PROTO_ALTERNATIVE;
407             }
408              
409             sub Marpa::R2::Internal::MetaAST_Nodes::null_ranking_specification::evaluate {
410 2     2   5 my ($values) = @_;
411 2         8 my $child = $values->[2];
412 2         6 return bless { null_ranking => $child->value() }, $PROTO_ALTERNATIVE;
413             }
414              
415             sub Marpa::R2::Internal::MetaAST_Nodes::null_ranking_constant::value {
416 2     2   9 return $_[0]->[2];
417             }
418              
419             sub Marpa::R2::Internal::MetaAST_Nodes::before_or_after::value {
420 54     54   303 return $_[0]->[2];
421             }
422              
423             sub Marpa::R2::Internal::MetaAST_Nodes::event_initializer::on_or_off
424             {
425             # die Data::Dumper::Dumper(\@_);
426 279     279   550 my ($values) = @_;
427 279         531 my $is_activated = $values->[2];
428 279 100       1141 return 1 if not defined $is_activated;
429 102         276 return $is_activated->value();
430             }
431              
432             sub Marpa::R2::Internal::MetaAST_Nodes::on_or_off::value {
433 102 100   102   587 return $_[0]->[2] eq 'off' ? 0 : 1;
434             }
435              
436             sub Marpa::R2::Internal::MetaAST_Nodes::boolean::value {
437 46     46   262 return $_[0]->[2];
438             }
439              
440             sub Marpa::R2::Internal::MetaAST_Nodes::signed_integer::value {
441 47     47   184 return $_[0]->[2];
442             }
443              
444             sub Marpa::R2::Internal::MetaAST_Nodes::separator_specification::evaluate {
445 13     13   41 my ( $values, $parse ) = @_;
446 13         51 my $child = $values->[2];
447 13         69 return bless { separator => $child->name($parse) }, $PROTO_ALTERNATIVE;
448             }
449              
450             sub Marpa::R2::Internal::MetaAST_Nodes::adverb_item::evaluate {
451 770     770   1420 my ( $values, $parse ) = @_;
452 770         2905 my $child = $values->[2]->evaluate($parse);
453 770         2421 return bless $child, $PROTO_ALTERNATIVE;
454             }
455              
456             sub Marpa::R2::Internal::MetaAST_Nodes::default_rule::evaluate {
457 112     112   745 my ( $values, $parse ) = @_;
458 112         339 my ( $start, $length, undef, $op_declare, $raw_adverb_list ) = @{$values};
  112         460  
459 112 50       553 my $subgrammar = $op_declare->op() eq q{::=} ? 'G1' : $parse->{current_lexer};
460 112         561 my $adverb_list = $raw_adverb_list->evaluate($parse);
461              
462             # A default rule clears the previous default
463 112         369 my %default_adverbs = ();
464 112         423 $parse->{default_adverbs}->{$subgrammar} = \%default_adverbs;
465              
466 112         284 ADVERB: for my $key ( keys %{$adverb_list} ) {
  112         388  
467 120         350 my $value = $adverb_list->{$key};
468 120 100 66     938 if ( $key eq 'action' and $subgrammar eq 'G1' ) {
469 112         372 $default_adverbs{$key} = $adverb_list->{$key};
470 112         386 next ADVERB;
471             }
472 8 50 33     79 if ( $key eq 'bless' and $subgrammar eq 'G1' ) {
473 8         39 $default_adverbs{$key} = $adverb_list->{$key};
474 8         24 next ADVERB;
475             }
476 0         0 die qq{Adverb "$key" not allowed in $subgrammar default rule\n},
477             ' Rule was ', $parse->substring( $start, $length ), "\n";
478             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
479             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
480 112         400 return undef;
481             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::default_rule::evaluate
482              
483             sub Marpa::R2::Internal::MetaAST_Nodes::discard_default_statement::evaluate {
484 27     27   93 my ( $data, $parse ) = @_;
485 27         67 my ( $start, $length, $raw_adverb_list ) = @{$data};
  27         90  
486 27         87 local $Marpa::R2::Internal::SUBGRAMMAR = 'G1';
487              
488 27         75 my $adverb_list = $raw_adverb_list->evaluate($parse);
489 27 50       152 if ( exists $parse->{discard_default_adverbs} ) {
490 0         0 my $problem_rule = $parse->substring( $start, $length );
491 0         0 Marpa::R2::exception(
492             qq{More than one discard default statement is not allowed\n},
493             qq{ This was the rule that caused the problem:\n},
494             qq{ $problem_rule\n}
495             );
496             } ## end if ( exists $parse->{discard_default_adverbs} )
497 27         126 $parse->{discard_default_adverbs} = {};
498 27         59 ADVERB: for my $key ( keys %{$adverb_list} ) {
  27         101  
499 27         74 my $value = $adverb_list->{$key};
500 27 50 33     151 if ( $key eq 'event' and defined $value ) {
501 27         88 $parse->{discard_default_adverbs}->{$key} = $value;
502 27         101 next ADVERB;
503             }
504             Marpa::R2::exception(
505 0         0 qq{"$key" adverb not allowed as discard default"});
506             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
507             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
508 27         86 return undef;
509             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::discard_default_statement::evaluate
510              
511             sub Marpa::R2::Internal::MetaAST_Nodes::lexeme_default_statement::evaluate {
512 53     53   223 my ( $data, $parse ) = @_;
513 53         146 my ( $start, $length, $raw_adverb_list ) = @{$data};
  53         264  
514 53         191 local $Marpa::R2::Internal::SUBGRAMMAR = 'G1';
515              
516 53         228 my $adverb_list = $raw_adverb_list->evaluate($parse);
517 53 50       339 if ( exists $parse->{lexeme_default_adverbs} ) {
518 0         0 my $problem_rule = $parse->substring( $start, $length );
519 0         0 Marpa::R2::exception(
520             qq{More than one lexeme default statement is not allowed\n},
521             qq{ This was the rule that caused the problem:\n},
522             qq{ $problem_rule\n}
523             );
524             } ## end if ( exists $parse->{lexeme_default_adverbs} )
525 53         236 $parse->{lexeme_default_adverbs} = {};
526 53         137 ADVERB: for my $key ( keys %{$adverb_list} ) {
  53         197  
527 87         235 my $value = $adverb_list->{$key};
528 87 100       310 if ( $key eq 'action' ) {
529 40         135 $parse->{lexeme_default_adverbs}->{$key} = $value;
530 40         129 next ADVERB;
531             }
532 47 100       170 if ( $key eq 'bless' ) {
533 4         12 $parse->{lexeme_default_adverbs}->{$key} = $value;
534 4         9 next ADVERB;
535             }
536 43 50       146 if ( $key eq 'latm' ) {
537 43         122 $parse->{lexeme_default_adverbs}->{$key} = $value;
538 43         122 next ADVERB;
539             }
540             Marpa::R2::exception(
541 0         0 qq{"$key" adverb not allowed as lexeme default"});
542             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
543             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
544 53         164 return undef;
545             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::lexeme_default_statement::evaluate
546              
547             sub Marpa::R2::Internal::MetaAST_Nodes::inaccessible_statement::evaluate {
548 7     7   27 my ( $data, $parse ) = @_;
549 7         17 my ( $start, $length, $inaccessible_treatment ) = @{$data};
  7         49  
550 7         25 local $Marpa::R2::Internal::SUBGRAMMAR = 'G1';
551              
552 7 50       38 if ( exists $parse->{defaults}->{if_inaccessible} ) {
553 0         0 my $problem_rule = $parse->substring( $start, $length );
554 0         0 Marpa::R2::exception(
555             qq{More than one inaccessible default statement is not allowed\n},
556             qq{ This was the rule that caused the problem:\n},
557             qq{ $problem_rule\n}
558             );
559             }
560 7         77 $parse->{defaults}->{if_inaccessible} = $inaccessible_treatment->value();
561 7         30 return undef;
562             }
563              
564             sub Marpa::R2::Internal::MetaAST_Nodes::inaccessible_treatment::value {
565 7     7   37 return $_[0]->[2];
566             }
567              
568             sub Marpa::R2::Internal::MetaAST_Nodes::priority_rule::evaluate {
569 1009     1009   2087 my ( $values, $parse ) = @_;
570             my ( $start, $length, $raw_lhs, $op_declare, $raw_priorities ) =
571 1009         1521 @{$values};
  1009         2283  
572              
573 1009         1999 my $current_lexer = $parse->{current_lexer};
574 1009         1525 my $subgrammar;
575 1009 100       2429 if ( $op_declare->op() eq q{::=} ) {
576 542 50       1512 if ( $current_lexer ne 'L0' ) {
577 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
578 0         0 die "G1 rules currently allowed only when L0 is current lexer\n",
579             qq{ A prioritized rule was found when "$current_lexer" was the current lexer\n"},
580             " Location was line $line, column $column\n",
581             ' Rule was ', $parse->substring( $start, $length ), "\n";
582             } ## end if ( $current_lexer ne 'L0' )
583 542         1025 $subgrammar = 'G1';
584             } ## end if ( $op_declare->op() eq q{::=} )
585             else {
586 467         848 $subgrammar = $current_lexer;
587             }
588              
589 1009         2596 my $lhs = $raw_lhs->name($parse);
590 1009 100 66     3951 $parse->{'first_lhs'} //= $lhs if $subgrammar eq 'G1';
591 1009         1904 local $Marpa::R2::Internal::SUBGRAMMAR = $subgrammar;
592              
593 1009         1526 my ( undef, undef, @priorities ) = @{$raw_priorities};
  1009         2180  
594 1009         1757 my $priority_count = scalar @priorities;
595 1009         1668 my @working_rules = ();
596              
597 1009   100     2873 $parse->{rules}->{$subgrammar} //= [];
598 1009         1943 my $rules = $parse->{rules}->{$subgrammar};
599              
600 1009         1870 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
601              
602 1009 100       2338 if ( $priority_count <= 1 ) {
603             ## If there is only one priority
604 990         1425 my ( undef, undef, @alternatives ) = @{ $priorities[0] };
  990         2193  
605 990         2208 for my $alternative (@alternatives) {
606             my ($alternative_start, $alternative_end,
607             $raw_rhs, $raw_adverb_list
608 1269         1914 ) = @{$alternative};
  1269         2750  
609 1269         2068 my ( $proto_rule, $adverb_list );
610 1269         2043 my $eval_ok = eval {
611 1269         3112 $proto_rule = $raw_rhs->evaluate($parse);
612 1269         2930 $adverb_list = $raw_adverb_list->evaluate($parse);
613 1269         2260 1;
614             };
615 1269 50       2774 if ( not $eval_ok ) {
616 0         0 my $eval_error = $EVAL_ERROR;
617 0         0 chomp $eval_error;
618 0         0 Marpa::R2::exception(
619             qq{$eval_error\n},
620             qq{ The problem was in this RHS alternative:\n},
621             q{ },
622             $parse->substring( $alternative_start, $alternative_end ),
623             "\n"
624             );
625             } ## end if ( not $eval_ok )
626 1269         1875 my @rhs_names = @{ $proto_rule->{rhs} };
  1269         3285  
627 1269         1968 my @mask = @{ $proto_rule->{mask} };
  1269         2514  
628 1269 50 66     4548 if ( ( substr $subgrammar, 0, 1 ) eq 'L'
629 948         3162 and grep { !$_ } @mask )
630             {
631 0         0 Marpa::R2::exception(
632             qq{hidden symbols are not allowed in lexical rules (rule's LHS was "$lhs")}
633             );
634             }
635 1269         4618 my %hash_rule =
636             ( lhs => $lhs, rhs => \@rhs_names, mask => \@mask );
637              
638 1269         5110 my $action;
639             my $blessing;
640 1269         0 my $naming;
641 1269         0 my $null_ranking;
642 1269         0 my $rank;
643 1269         1723 ADVERB: for my $key ( keys %{$adverb_list} ) {
  1269         3431  
644 219         445 my $value = $adverb_list->{$key};
645 219 100       541 if ( $key eq 'action' ) {
646 141         306 $action = $adverb_list->{$key};
647 141         405 next ADVERB;
648             }
649 78 50       197 if ( $key eq 'assoc' ) {
650              
651             # OK, but ignored
652 0         0 next ADVERB;
653             }
654 78 100       169 if ( $key eq 'bless' ) {
655 26         43 $blessing = $adverb_list->{$key};
656 26         55 next ADVERB;
657             }
658 52 100       137 if ( $key eq 'name' ) {
659 5         12 $naming = $adverb_list->{$key};
660 5         12 next ADVERB;
661             }
662 47 100       125 if ( $key eq 'null_ranking' ) {
663 2         5 $null_ranking = $adverb_list->{$key};
664 2         5 next ADVERB;
665             }
666 45 50       113 if ( $key eq 'rank' ) {
667 45         72 $rank = $adverb_list->{$key};
668 45         99 next ADVERB;
669             }
670             my ( $line, $column ) =
671 0         0 $parse->{meta_recce}->line_column($start);
672 0         0 die qq{Adverb "$key" not allowed in an prioritized rule\n},
673             ' Rule was ', $parse->substring( $start, $length ), "\n";
674             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
675              
676 1269   100     5290 $action //= $default_adverbs->{action};
677 1269 100       2624 if ( defined $action ) {
678 409 50       1152 Marpa::R2::exception(
679             qq{actions not allowed in lexical rules (rule's LHS was "$lhs")}
680             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
681 409         891 $hash_rule{action} = $action;
682             } ## end if ( defined $action )
683              
684 1269   66     4722 $rank //= $default_adverbs->{rank};
685 1269 100       2532 if ( defined $rank ) {
686 45 50       116 Marpa::R2::exception(
687             qq{ranks not allowed in lexical rules (rule's LHS was "$lhs")}
688             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
689 45         84 $hash_rule{rank} = $rank;
690             } ## end if ( defined $rank )
691              
692 1269   66     4692 $null_ranking //= $default_adverbs->{null_ranking};
693 1269 100       2416 if ( defined $null_ranking ) {
694 2 50       9 Marpa::R2::exception(
695             qq{null-ranking allowed in lexical rules (rule's LHS was "$lhs")}
696             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
697 2         5 $hash_rule{null_ranking} = $null_ranking;
698             } ## end if ( defined $rank )
699              
700 1269   100     4489 $blessing //= $default_adverbs->{bless};
701 1269 50 66     2892 if (defined $blessing
702             and
703             ( substr $subgrammar, 0, 1 ) eq 'L'
704             )
705             {
706 0         0 Marpa::R2::exception(
707             'bless option not allowed in lexical rules (rules LHS was "',
708             $lhs, '")'
709             );
710             }
711              
712 1269         4030 $parse->bless_hash_rule( \%hash_rule, $blessing, $naming, $lhs );
713              
714 1269         1922 push @{$rules}, \%hash_rule;
  1269         5688  
715             } ## end for my $alternative (@alternatives)
716             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
717 990         2951 return undef;
718             } ## end if ( $priority_count <= 1 )
719              
720 19         138 for my $priority_ix ( 0 .. $priority_count - 1 ) {
721 75         179 my $priority = $priority_count - ( $priority_ix + 1 );
722 75         118 my ( undef, undef, @alternatives ) = @{ $priorities[$priority_ix] };
  75         194  
723 75         155 for my $alternative (@alternatives) {
724             my ($alternative_start, $alternative_end,
725             $raw_rhs, $raw_adverb_list
726 114         186 ) = @{$alternative};
  114         229  
727 114         187 my ( $adverb_list, $rhs );
728 114         159 my $eval_ok = eval {
729 114         246 $adverb_list = $raw_adverb_list->evaluate($parse);
730 114         318 $rhs = $raw_rhs->evaluate($parse);
731 114         204 1;
732             };
733 114 50       260 if ( not $eval_ok ) {
734 0         0 my $eval_error = $EVAL_ERROR;
735 0         0 chomp $eval_error;
736 0         0 Marpa::R2::exception(
737             qq{$eval_error\n},
738             qq{ The problem was in this RHS alternative:\n},
739             q{ },
740             $parse->substring( $alternative_start, $alternative_end ),
741             "\n"
742             );
743             } ## end if ( not $eval_ok )
744 114         379 push @working_rules, [ $priority, $rhs, $adverb_list ];
745             } ## end for my $alternative (@alternatives)
746             } ## end for my $priority_ix ( 0 .. $priority_count - 1 )
747              
748             # Default mask (all ones) is OK for this rule
749 19         80 my @arg0_action = ();
750 19 50       120 @arg0_action = ( action => '::first' ) if $subgrammar eq 'G1';
751 19         103 push @{$rules},
752             {
753             lhs => $lhs,
754             rhs => [ $parse->prioritized_symbol( $lhs, 0 ) ],
755             @arg0_action,
756             description => qq{Internal rule top priority rule for <$lhs>},
757             },
758             (
759             map {
760 19         41 ;
761 56         163 { lhs => $parse->prioritized_symbol( $lhs, $_ - 1 ),
762             rhs => [ $parse->prioritized_symbol( $lhs, $_ ) ],
763             description => (
764             qq{Internal rule for symbol <$lhs> priority transition from }
765             . ( $_ - 1 )
766             . qq{ to $_}
767             ),
768             @arg0_action
769             }
770             } 1 .. $priority_count - 1
771             );
772 19         109 RULE: for my $working_rule (@working_rules) {
773 114         190 my ( $priority, $rhs, $adverb_list ) = @{$working_rule};
  114         248  
774 114         170 my @new_rhs = @{ $rhs->{rhs} };
  114         303  
775 114         283 my @arity = grep { $new_rhs[$_] eq $lhs } 0 .. $#new_rhs;
  286         675  
776 114         206 my $rhs_length = scalar @new_rhs;
777              
778 114         289 my $current_exp = $parse->prioritized_symbol( $lhs, $priority );
779 114         211 my @mask = @{ $rhs->{mask} };
  114         305  
780 114 50 33     398 if ( ( substr $subgrammar, 0, 1 ) eq 'L' and grep { !$_ } @mask )
  0         0  
781             {
782 0         0 Marpa::R2::exception(
783             'hidden symbols are not allowed in lexical rules (rules LHS was "',
784             $lhs, '")'
785             );
786             }
787 114         336 my %new_xs_rule = ( lhs => $current_exp );
788 114         251 $new_xs_rule{mask} = \@mask;
789              
790 114         510 my $action;
791             my $assoc;
792 114         0 my $blessing;
793 114         0 my $naming;
794 114         0 my $rank;
795 114         0 my $null_ranking;
796 114         151 ADVERB: for my $key ( keys %{$adverb_list} ) {
  114         355  
797 108         195 my $value = $adverb_list->{$key};
798 108 100       249 if ( $key eq 'action' ) {
799 44         70 $action = $adverb_list->{$key};
800 44         86 next ADVERB;
801             }
802 64 100       141 if ( $key eq 'assoc' ) {
803 21         44 $assoc = $adverb_list->{$key};
804 21         56 next ADVERB;
805             }
806 43 50       98 if ( $key eq 'bless' ) {
807 43         90 $blessing = $adverb_list->{$key};
808 43         90 next ADVERB;
809             }
810 0 0       0 if ( $key eq 'name' ) {
811 0         0 $naming = $adverb_list->{$key};
812 0         0 next ADVERB;
813             }
814 0 0       0 if ( $key eq 'null_ranking' ) {
815 0         0 $null_ranking = $adverb_list->{$key};
816 0         0 next ADVERB;
817             }
818 0 0       0 if ( $key eq 'rank' ) {
819 0         0 $rank = $adverb_list->{$key};
820 0         0 next ADVERB;
821             }
822 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
823 0         0 die qq{Adverb "$key" not allowed in a prioritized rule\n},
824             ' Rule was ', $parse->substring( $start, $length ), "\n";
825             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
826              
827 114   100     466 $assoc //= 'L';
828              
829 114   100     363 $action //= $default_adverbs->{action};
830 114 100       228 if ( defined $action ) {
831 107 50       259 Marpa::R2::exception(
832             qq{actions not allowed in lexical rules (rule's LHS was "$lhs")}
833             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
834 107         211 $new_xs_rule{action} = $action;
835             } ## end if ( defined $action )
836              
837 114   33     445 $null_ranking //= $default_adverbs->{null_ranking};
838 114 50       234 if ( defined $null_ranking ) {
839 0 0       0 Marpa::R2::exception(
840             qq{null-ranking not allowed in lexical rules (rule's LHS was "$lhs")}
841             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
842 0         0 $new_xs_rule{null_ranking} = $null_ranking;
843             } ## end if ( defined $rank )
844              
845 114   33     479 $rank //= $default_adverbs->{rank};
846 114 50       235 if ( defined $rank ) {
847 0 0       0 Marpa::R2::exception(
848             qq{ranks not allowed in lexical rules (rule's LHS was "$lhs")}
849             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
850 0         0 $new_xs_rule{rank} = $rank;
851             } ## end if ( defined $rank )
852              
853 114   100     367 $blessing //= $default_adverbs->{bless};
854 114 50 66     348 if ( defined $blessing
855             and ( substr $subgrammar, 0, 1 ) eq 'L' )
856             {
857 0         0 Marpa::R2::exception(
858             'bless option not allowed in lexical rules (rules LHS was "',
859             $lhs, '")'
860             );
861             }
862              
863 114         366 $parse->bless_hash_rule( \%new_xs_rule, $blessing, $naming, $lhs );
864              
865 114         220 my $next_priority = $priority + 1;
866              
867             # This is probably a mis-feature. It probably should be
868             # $next_priority = $priority if $next_priority >= $priority_count;
869             # However, I probably will not change this, because some apps
870             # may be relying on this behavior.
871 114 100       294 $next_priority = 0 if $next_priority >= $priority_count;
872              
873 114         254 my $next_exp = $parse->prioritized_symbol( $lhs, $next_priority);
874              
875 114 100       311 if ( not scalar @arity ) {
876 29         74 $new_xs_rule{rhs} = \@new_rhs;
877 29         73 push @{$rules}, \%new_xs_rule;
  29         95  
878 29         120 next RULE;
879             }
880              
881 85 100       267 if ( scalar @arity == 1 ) {
882 19 50       72 die 'Unnecessary unit rule in priority rule' if $rhs_length == 1;
883 19         62 $new_rhs[ $arity[0] ] = $current_exp;
884             }
885             DO_ASSOCIATION: {
886 85 100       146 if ( $assoc eq 'L' ) {
  85         228  
887 64         144 $new_rhs[ $arity[0] ] = $current_exp;
888 64         199 for my $rhs_ix ( @arity[ 1 .. $#arity ] ) {
889 56         127 $new_rhs[$rhs_ix] = $next_exp;
890             }
891 64         125 last DO_ASSOCIATION;
892             } ## end if ( $assoc eq 'L' )
893 21 100       99 if ( $assoc eq 'R' ) {
894 10         49 $new_rhs[ $arity[-1] ] = $current_exp;
895 10         64 for my $rhs_ix ( @arity[ 0 .. $#arity - 1 ] ) {
896 10         53 $new_rhs[$rhs_ix] = $next_exp;
897             }
898 10         30 last DO_ASSOCIATION;
899             } ## end if ( $assoc eq 'R' )
900 11 50       44 if ( $assoc eq 'G' ) {
901 11         60 for my $rhs_ix ( @arity[ 0 .. $#arity ] ) {
902 11         71 $new_rhs[$rhs_ix] = $parse->prioritized_symbol( $lhs, 0 );
903             }
904 11         56 last DO_ASSOCIATION;
905             } ## end if ( $assoc eq 'G' )
906 0         0 die qq{Unknown association type: "$assoc"};
907             } ## end DO_ASSOCIATION:
908              
909 85         181 $new_xs_rule{rhs} = \@new_rhs;
910 85         138 push @{$rules}, \%new_xs_rule;
  85         318  
911             } ## end RULE: for my $working_rule (@working_rules)
912             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
913 19         217 return undef;
914             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::priority_rule::evaluate
915              
916             sub Marpa::R2::Internal::MetaAST_Nodes::empty_rule::evaluate {
917 62     62   228 my ( $values, $parse ) = @_;
918             my ( $start, $length, $raw_lhs, $op_declare, $raw_adverb_list ) =
919 62         141 @{$values};
  62         333  
920              
921 62         201 my $current_lexer = $parse->{current_lexer};
922 62         133 my $subgrammar;
923 62 100       241 if ( $op_declare->op() eq q{::=} ) {
924 61 50       246 if ( $current_lexer ne 'L0' ) {
925 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
926 0         0 die "G1 rules currently allowed only when L0 is current lexer\n",
927             qq{ An empty rule was found when "$current_lexer" was the current lexer\n"},
928             " Location was line $line, column $column\n",
929             ' Rule was ', $parse->substring( $start, $length ), "\n";
930             } ## end if ( $current_lexer ne 'L0' )
931 61         175 $subgrammar = 'G1';
932             } ## end if ( $op_declare->op() eq q{::=} )
933             else {
934 1         4 $subgrammar = $current_lexer;
935             }
936              
937 62         248 my $lhs = $raw_lhs->name($parse);
938 62 100 66     573 $parse->{'first_lhs'} //= $lhs if $subgrammar eq 'G1';
939 62         167 local $Marpa::R2::Internal::SUBGRAMMAR = $subgrammar;
940              
941 62         477 my %rule = ( lhs => $lhs,
942             description => qq{Empty rule for <$lhs>},
943             rhs => [] );
944 62         272 my $adverb_list = $raw_adverb_list->evaluate($parse);
945              
946 62         217 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
947              
948 62         386 my $action;
949             my $blessing;
950 62         0 my $naming;
951 62         0 my $rank;
952 62         0 my $null_ranking;
953 62         136 ADVERB: for my $key ( keys %{$adverb_list} ) {
  62         220  
954 8         16 my $value = $adverb_list->{$key};
955 8 50       24 if ( $key eq 'action' ) {
956 8         12 $action = $adverb_list->{$key};
957 8         21 next ADVERB;
958             }
959 0 0       0 if ( $key eq 'bless' ) {
960 0         0 $blessing = $adverb_list->{$key};
961 0         0 next ADVERB;
962             }
963 0 0       0 if ( $key eq 'name' ) {
964 0         0 $naming = $adverb_list->{$key};
965 0         0 next ADVERB;
966             }
967 0 0       0 if ( $key eq 'null_ranking' ) {
968 0         0 $null_ranking = $adverb_list->{$key};
969 0         0 next ADVERB;
970             }
971 0 0       0 if ( $key eq 'rank' ) {
972 0         0 $rank = $adverb_list->{$key};
973 0         0 next ADVERB;
974             }
975 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
976 0         0 die qq{Adverb "$key" not allowed in an empty rule\n},
977             ' Rule was ', $parse->substring( $start, $length ), "\n";
978             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
979              
980 62   100     389 $action //= $default_adverbs->{action};
981 62 100       178 if ( defined $action ) {
982 33 50       163 Marpa::R2::exception(
983             qq{actions not allowed in lexical rules (rule's LHS was "$lhs")}
984             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
985 33         127 $rule{action} = $action;
986             } ## end if ( defined $action )
987              
988 62   33     356 $null_ranking //= $default_adverbs->{null_ranking};
989 62 50       188 if ( defined $null_ranking ) {
990 0 0       0 Marpa::R2::exception(
991             qq{null-ranking not allowed in lexical rules (rule's LHS was "$lhs")}
992             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
993 0         0 $rule{null_ranking} = $null_ranking;
994             } ## end if ( defined $null_ranking )
995              
996 62   33     357 $rank //= $default_adverbs->{rank};
997 62 50       194 if ( defined $rank ) {
998 0 0       0 Marpa::R2::exception(
999             qq{ranks not allowed in lexical rules (rule's LHS was "$lhs")}
1000             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
1001 0         0 $rule{rank} = $rank;
1002             } ## end if ( defined $rank )
1003              
1004 62   33     483 $blessing //= $default_adverbs->{bless};
1005 62 50 33     229 if ( defined $blessing
1006             and ( substr $subgrammar, 0, 1 ) eq 'L' )
1007             {
1008 0         0 Marpa::R2::exception(
1009             qq{bless option not allowed in lexical rules (rule's LHS was "$lhs")}
1010             );
1011             }
1012 62         284 $parse->bless_hash_rule( \%rule, $blessing, $naming, $lhs );
1013              
1014             # mask not needed
1015 62         142 push @{ $parse->{rules}->{$subgrammar} }, \%rule;
  62         278  
1016              
1017             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1018 62         251 return undef;
1019             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::empty_rule::evaluate
1020              
1021             sub Marpa::R2::Internal::MetaAST_Nodes::lexeme_rule::evaluate {
1022 63     63   219 my ( $values, $parse ) = @_;
1023 63         104 my ( $start, $length, $symbol, $unevaluated_adverb_list ) = @{$values};
  63         209  
1024              
1025 63         165 my $symbol_name = $symbol->name();
1026 63         226 my $declarations = $parse->{lexeme_declarations}->{$symbol_name};
1027 63 50       189 if ( defined $declarations ) {
1028 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1029 0         0 die "Duplicate lexeme rule for <$symbol_name>\n",
1030             " Only one lexeme rule is allowed for each symbol\n",
1031             " Location was line $line, column $column\n",
1032             ' Rule was ', $parse->substring( $start, $length ), "\n";
1033             } ## end if ( defined $declarations )
1034              
1035 63         207 my $adverb_list = $unevaluated_adverb_list->evaluate();
1036 63         183 my %declarations;
1037 63         119 ADVERB: for my $key ( keys %{$adverb_list} ) {
  63         186  
1038 107         215 my $raw_value = $adverb_list->{$key};
1039 107 100       261 if ( $key eq 'priority' ) {
1040 2         8 $declarations{$key} = $raw_value + 0;
1041 2         7 next ADVERB;
1042             }
1043 105 100       245 if ( $key eq 'pause' ) {
1044 54 100       159 if ( $raw_value eq 'before' ) {
1045 10         24 $declarations{$key} = -1;
1046 10         23 next ADVERB;
1047             }
1048 44 50       163 if ( $raw_value eq 'after' ) {
1049 44         100 $declarations{$key} = 1;
1050 44         107 next ADVERB;
1051             }
1052 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1053 0         0 die qq{Bad value for "pause" adverb: "$raw_value"},
1054             " Location was line $line, column $column\n",
1055             ' Rule was ', $parse->substring( $start, $length ), "\n";
1056             } ## end if ( $key eq 'pause' )
1057 51 100       150 if ( $key eq 'event' ) {
1058 49         125 $declarations{$key} = $raw_value;
1059 49         124 next ADVERB;
1060             }
1061 2 50       8 if ( $key eq 'latm' ) {
1062 2         9 $declarations{$key} = $raw_value;
1063 2         6 next ADVERB;
1064             }
1065 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1066 0         0 die qq{"$key" adverb not allowed in lexeme rule"\n},
1067             " Location was line $line, column $column\n",
1068             ' Rule was ', $parse->substring( $start, $length ), "\n";
1069             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
1070 63 50 66     305 if ( exists $declarations{'event'} and not exists $declarations{'pause'} )
1071             {
1072 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1073 0         0 die
1074             qq{"event" adverb not allowed without "pause" adverb in lexeme rule"\n},
1075             " Location was line $line, column $column\n",
1076             ' Rule was ', $parse->substring( $start, $length ), "\n";
1077             } ## end if ( exists $declarations{'event'} and not exists $declarations...)
1078 63         233 $parse->{lexeme_declarations}->{$symbol_name} = \%declarations;
1079             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1080 63         199 return undef;
1081             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::lexeme_rule::evaluate
1082              
1083             sub Marpa::R2::Internal::MetaAST_Nodes::statements::evaluate {
1084 12     12   26 my ( $data, $parse ) = @_;
1085 12         23 my ( undef, undef, @statement_list ) = @{$data};
  12         32  
1086 12         20 map { $_->evaluate($parse) } @statement_list;
  22         72  
1087 12         22 return undef;
1088             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::statements::evaluate
1089              
1090             sub Marpa::R2::Internal::MetaAST_Nodes::statement::evaluate {
1091 1966     1966   3846 my ( $data, $parse ) = @_;
1092 1966         2851 my ( undef, undef, $child ) = @{$data};
  1966         3560  
1093 1966         8041 $child->evaluate($parse);
1094             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1095 1966         5331 return undef;
1096             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::statement::evaluate
1097              
1098             sub Marpa::R2::Internal::MetaAST_Nodes::null_statement::evaluate {
1099 22     22   41 return undef;
1100             }
1101              
1102             sub Marpa::R2::Internal::MetaAST_Nodes::statement_group::evaluate {
1103 12     12   22 my ( $data, $parse ) = @_;
1104 12         18 my ( undef, undef, $statements ) = @{$data};
  12         35  
1105 12         82 $statements->evaluate($parse);
1106             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1107 12         20 return undef;
1108             }
1109              
1110             sub Marpa::R2::Internal::MetaAST::start_rule_create {
1111 275     275   915 my ( $parse, $symbol_name ) = @_;
1112 275         767 my $start_lhs = '[:start]';
1113             $parse->{'default_g1_start_action'} =
1114 275         1624 $parse->{'default_adverbs'}->{'G1'}->{'action'};
1115 275         1468 $parse->{'symbols'}->{'G1'}->{$start_lhs} = {
1116             display_form => ':start',
1117             description => 'Internal G1 start symbol'
1118             };
1119 275         663 push @{ $parse->{rules}->{G1} },
  275         2240  
1120             {
1121             lhs => $start_lhs,
1122             rhs => [$symbol_name],
1123             action => '::first'
1124             };
1125             } ## end sub Marpa::R2::Internal::MetaAST::start_rule_create
1126              
1127             sub Marpa::R2::Internal::MetaAST_Nodes::start_rule::evaluate {
1128 104     104   404 my ( $values, $parse ) = @_;
1129 104         220 my ( $start, $length, $symbol ) = @{$values};
  104         449  
1130 104 50       466 if ( defined $parse->{'start_lhs'} ) {
1131 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1132 0         0 die qq{There are two start rules\n},
1133             qq{ That is not allowed\n},
1134             ' The second start rule is ',
1135             $parse->substring( $start, $length ),
1136             "\n",
1137             " Problem occurred at line $line, column $column\n";
1138             } ## end if ( defined $parse->{'start_lhs'} )
1139 104         532 $parse->{'start_lhs'} = $symbol->name($parse);
1140             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1141 104         268 return undef;
1142             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::start_rule::evaluate
1143              
1144             sub Marpa::R2::Internal::MetaAST_Nodes::discard_rule::evaluate {
1145 149     149   610 my ( $values, $parse ) = @_;
1146 149         320 my ( $start, $length, $symbol, $raw_adverb_list ) = @{$values};
  149         615  
1147              
1148 149         434 my $lexer_name = $parse->{current_lexer};
1149 149         318 local $Marpa::R2::Internal::SUBGRAMMAR = $lexer_name;
1150 149         324 my $discard_lhs = '[:discard]';
1151 149         1108 $parse->symbol_names_set(
1152             $discard_lhs,
1153             'L',
1154             { display_form => ':discard',
1155             description => qq{Internal LHS for lexer "$lexer_name" discard}
1156             }
1157             );
1158 149         1073 my $rhs = $symbol->names($parse);
1159 149         936 my $rhs_as_event = $symbol->event_name($parse);
1160 149         740 my $adverb_list = $raw_adverb_list->evaluate($parse);
1161 149         434 my $event;
1162 149         405 ADVERB: for my $key ( keys %{$adverb_list} ) {
  149         639  
1163 51         128 my $value = $adverb_list->{$key};
1164 51 50       170 if ( $key eq 'event' ) {
1165 51         91 $event = $value;
1166 51         157 next ADVERB;
1167             }
1168             Marpa::R2::exception(
1169 0         0 qq{"$key" adverb not allowed as discard default"});
1170             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
1171             my %rule_hash = (
1172             description => (
1173             "Discard rule for " . join q{ },
1174 149         430 map { '<' . $_ . '>' } @{$rhs}
  149         1539  
  149         360  
1175             ),
1176             lhs => $discard_lhs,
1177             rhs => $rhs,
1178             symbol_as_event => $rhs_as_event
1179             );
1180 149 100       588 $rule_hash{event} = $event if defined $event;
1181 149         311 push @{ $parse->{rules}->{$lexer_name} }, \%rule_hash;
  149         566  
1182             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1183 149         521 return undef;
1184             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::discard_rule::evaluate
1185              
1186             sub Marpa::R2::Internal::MetaAST_Nodes::quantified_rule::evaluate {
1187 194     194   535 my ( $values, $parse ) = @_;
1188             my ( $start, $length, $lhs, $op_declare, $rhs, $quantifier,
1189             $proto_adverb_list )
1190 194         370 = @{$values};
  194         782  
1191              
1192 194         349 my $subgrammar;
1193 194         463 my $current_lexer = $parse->{current_lexer};
1194 194 100       641 if ( $op_declare->op() eq q{::=} ) {
1195 53 50       227 if ( $current_lexer ne 'L0' ) {
1196 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1197 0         0 die "G1 rules currently allowed only when L0 is current lexer\n",
1198             qq{ A quantified rule was found when "$current_lexer" was the current lexer\n"},
1199             " Location was line $line, column $column\n",
1200             ' Rule was ', $parse->substring( $start, $length ), "\n";
1201             } ## end if ( $current_lexer ne 'L0' )
1202 53         166 $subgrammar = 'G1';
1203             } ## end if ( $op_declare->op() eq q{::=} )
1204             else {
1205 141         307 $subgrammar = $current_lexer;
1206             }
1207              
1208 194         731 my $lhs_name = $lhs->name($parse);
1209 194 100 66     1014 $parse->{'first_lhs'} //= $lhs_name if $subgrammar eq 'G1';
1210 194         442 local $Marpa::R2::Internal::SUBGRAMMAR = $subgrammar;
1211              
1212 194         537 my $adverb_list = $proto_adverb_list->evaluate($parse);
1213 194         564 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
1214              
1215             # Some properties of the sequence rule will not be altered
1216             # no matter how complicated this gets
1217 194 100       781 my %sequence_rule = (
1218             rhs => [ $rhs->name($parse) ],
1219             min => ( $quantifier->evaluate($parse) eq q{+} ? 1 : 0 )
1220             );
1221              
1222 194         597 my @rules = ( \%sequence_rule );
1223              
1224 194         1272 my $action;
1225             my $blessing;
1226 194         0 my $naming;
1227 194         0 my $separator;
1228 194         0 my $proper;
1229 194         0 my $rank;
1230 194         0 my $null_ranking;
1231 194         378 ADVERB: for my $key ( keys %{$adverb_list} ) {
  194         603  
1232 37         97 my $value = $adverb_list->{$key};
1233 37 100       130 if ( $key eq 'action' ) {
1234 20         58 $action = $adverb_list->{$key};
1235 20         64 next ADVERB;
1236             }
1237 17 100       62 if ( $key eq 'bless' ) {
1238 3         8 $blessing = $adverb_list->{$key};
1239 3         10 next ADVERB;
1240             }
1241 14 50       64 if ( $key eq 'name' ) {
1242 0         0 $naming = $adverb_list->{$key};
1243 0         0 next ADVERB;
1244             }
1245 14 100       56 if ( $key eq 'proper' ) {
1246 1         4 $proper = $adverb_list->{$key};
1247 1         4 next ADVERB;
1248             }
1249 13 50       44 if ( $key eq 'rank' ) {
1250 0         0 $rank = $adverb_list->{$key};
1251 0         0 next ADVERB;
1252             }
1253 13 50       55 if ( $key eq 'null_ranking' ) {
1254 0         0 $null_ranking = $adverb_list->{$key};
1255 0         0 next ADVERB;
1256             }
1257 13 50       54 if ( $key eq 'separator' ) {
1258 13         35 $separator = $adverb_list->{$key};
1259 13         43 next ADVERB;
1260             }
1261 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1262 0         0 die qq{Adverb "$key" not allowed in quantified rule\n},
1263             ' Rule was ', $parse->substring( $start, $length ), "\n";
1264             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
1265              
1266             # mask not needed
1267 194         539 $sequence_rule{lhs} = $lhs_name;
1268              
1269 194 100       601 $sequence_rule{separator} = $separator
1270             if defined $separator;
1271 194 100       576 $sequence_rule{proper} = $proper if defined $proper;
1272              
1273 194   100     1032 $action //= $default_adverbs->{action};
1274 194 100       551 if ( defined $action ) {
1275 41 50       246 Marpa::R2::exception(
1276             qq{actions not allowed in lexical rules (rule's LHS was "$lhs")}
1277             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
1278 41         122 $sequence_rule{action} = $action;
1279             } ## end if ( defined $action )
1280              
1281 194   33     966 $null_ranking //= $default_adverbs->{null_ranking};
1282 194 50       543 if ( defined $null_ranking ) {
1283 0 0       0 Marpa::R2::exception(
1284             qq{null-ranking not allowed in lexical rules (rule's LHS was "$lhs")}
1285             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
1286 0         0 $sequence_rule{null_ranking} = $null_ranking;
1287             } ## end if ( defined $null_ranking )
1288              
1289 194   33     950 $rank //= $default_adverbs->{rank};
1290 194 50       500 if ( defined $rank ) {
1291 0 0       0 Marpa::R2::exception(
1292             qq{ranks not allowed in lexical rules (rule's LHS was "$lhs")}
1293             ) if ( substr $subgrammar, 0, 1 ) eq 'L';
1294 0         0 $sequence_rule{rank} = $rank;
1295             } ## end if ( defined $rank )
1296              
1297 194   100     916 $blessing //= $default_adverbs->{bless};
1298 194 50 66     617 if ( defined $blessing and ( substr $subgrammar, 0, 1 ) eq 'L' )
1299             {
1300 0         0 Marpa::R2::exception(
1301             qq{bless option not allowed in lexical rules (rule's LHS was "$lhs")}
1302             );
1303             }
1304 194         723 $parse->bless_hash_rule( \%sequence_rule, $blessing, $naming, $lhs_name );
1305              
1306 194         357 push @{ $parse->{rules}->{$subgrammar} }, @rules;
  194         717  
1307             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1308 194         694 return undef;
1309              
1310             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::quantified_rule::evaluate
1311              
1312             sub Marpa::R2::Internal::MetaAST_Nodes::completion_event_declaration::evaluate
1313             {
1314 54     54   123 my ( $values, $parse ) = @_;
1315 54         77 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  54         151  
1316 54         132 my $symbol_name = $raw_symbol_name->name();
1317 54   100     224 my $completion_events = $parse->{completion_events} //= {};
1318 54 50       135 if ( defined $completion_events->{$symbol_name} ) {
1319 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1320 0         0 die qq{Completion event for symbol "$symbol_name" declared twice\n},
1321             qq{ That is not allowed\n},
1322             ' Second declaration was ', $parse->substring( $start, $length ),
1323             "\n",
1324             " Problem occurred at line $line, column $column\n";
1325             } ## end if ( defined $completion_events->{$symbol_name} )
1326 54         142 $completion_events->{$symbol_name} = $raw_event->event();
1327             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1328 54         141 return undef;
1329             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::completion_event_declaration::evaluate
1330              
1331             sub Marpa::R2::Internal::MetaAST_Nodes::nulled_event_declaration::evaluate {
1332 46     46   83 my ( $values, $parse ) = @_;
1333 46         57 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  46         103  
1334 46         90 my $symbol_name = $raw_symbol_name->name();
1335 46   100     147 my $nulled_events = $parse->{nulled_events} //= {};
1336 46 50       104 if ( defined $nulled_events->{$symbol_name} ) {
1337 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1338 0         0 die qq{nulled event for symbol "$symbol_name" declared twice\n},
1339             qq{ That is not allowed\n},
1340             ' Second declaration was ', $parse->substring( $start, $length ),
1341             "\n",
1342             " Problem occurred at line $line, column $column\n";
1343             } ## end if ( defined $nulled_events->{$symbol_name} )
1344 46         91 $nulled_events->{$symbol_name} = $raw_event->event();
1345             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1346 46         88 return undef;
1347             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::nulled_event_declaration::evaluate
1348              
1349             sub Marpa::R2::Internal::MetaAST_Nodes::prediction_event_declaration::evaluate
1350             {
1351 52     52   93 my ( $values, $parse ) = @_;
1352 52         74 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  52         119  
1353 52         136 my $symbol_name = $raw_symbol_name->name();
1354 52   100     163 my $prediction_events = $parse->{prediction_events} //= {};
1355 52 50       145 if ( defined $prediction_events->{$symbol_name} ) {
1356 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1357 0         0 die qq{prediction event for symbol "$symbol_name" declared twice\n},
1358             qq{ That is not allowed\n},
1359             ' Second declaration was ', $parse->substring( $start, $length ),
1360             "\n",
1361             " Problem occurred at line $line, column $column\n";
1362             } ## end if ( defined $prediction_events->{$symbol_name} )
1363 52         122 $prediction_events->{$symbol_name} = $raw_event->event();
1364             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1365 52         102 return undef;
1366             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::prediction_event_declaration::evaluate
1367              
1368             sub Marpa::R2::Internal::MetaAST_Nodes::current_lexer_statement::evaluate
1369             {
1370 0     0   0 my ( $values, $parse ) = @_;
1371 0         0 my ( $start, $length, $lexer_name_object ) = @{$values};
  0         0  
1372 0         0 my $raw_lexer_name = $lexer_name_object->name();
1373 0 0       0 if ( $raw_lexer_name eq 'L0' ) {
1374 0         0 $parse->{current_lexer} = $raw_lexer_name;
1375             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1376 0         0 return undef;
1377             }
1378 0 0       0 if ( $raw_lexer_name =~ m/\A [[:upper:]] [[:digit:]]+ \z/xms) {
1379 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1380 0         0 die qq{Attempt to name a new lexer "$raw_lexer_name"\n},
1381             qq{ Lexer names of the form [A-Z][0-9]+ are reserved\n},
1382             qq{ Please choose another name\n},
1383             " Problem occurred at line $line, column $column\n";
1384             } ## end if ( defined $prediction_events->{$symbol_name} )
1385 0         0 my $lexer_name .= 'L-' . $raw_lexer_name;
1386 0         0 $parse->{current_lexer} = $lexer_name;
1387             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1388 0         0 return undef;
1389             }
1390              
1391             sub Marpa::R2::Internal::MetaAST_Nodes::alternatives::evaluate {
1392 0     0   0 my ( $values, $parse ) = @_;
1393 0         0 return bless [ map { $_->evaluate( $_, $parse ) } @{$values} ],
  0         0  
  0         0  
1394             ref $values;
1395             }
1396              
1397             sub Marpa::R2::Internal::MetaAST_Nodes::alternative::evaluate {
1398 0     0   0 my ( $values, $parse ) = @_;
1399 0         0 my ( $start, $length, $rhs, $adverbs ) = @{$values};
  0         0  
1400 0         0 my $alternative = eval {
1401             Marpa::R2::Internal::MetaAST::Proto_Alternative->combine(
1402 0         0 map { $_->evaluate($parse) } $rhs, $adverbs );
  0         0  
1403             };
1404 0 0       0 if ( not $alternative ) {
1405 0         0 Marpa::R2::exception(
1406             $EVAL_ERROR, "\n",
1407             q{ Alternative involved was },
1408             $parse->substring( $start, $length )
1409             );
1410             } ## end if ( not $alternative )
1411 0         0 return $alternative;
1412             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::alternative::evaluate
1413              
1414             sub Marpa::R2::Internal::MetaAST_Nodes::single_symbol::names {
1415 149     149   564 my ( $values, $parse ) = @_;
1416 149         267 my ( undef, undef, $symbol ) = @{$values};
  149         427  
1417 149         686 return $symbol->names($parse);
1418             }
1419              
1420             sub Marpa::R2::Internal::MetaAST_Nodes::single_symbol::name {
1421 207     207   509 my ( $values, $parse ) = @_;
1422 207         336 my ( undef, undef, $symbol ) = @{$values};
  207         537  
1423 207         649 return $symbol->name($parse);
1424             }
1425              
1426             sub Marpa::R2::Internal::MetaAST_Nodes::single_symbol::event_name {
1427 149     149   425 my ( $values, $parse ) = @_;
1428 149         260 my ( undef, undef, $symbol ) = @{$values};
  149         366  
1429 149         675 return $symbol->event_name($parse);
1430             }
1431              
1432             sub Marpa::R2::Internal::MetaAST_Nodes::single_symbol::literal {
1433 0     0   0 my ( $values, $parse ) = @_;
1434 0         0 my ( $start, $length ) = @{$values};
  0         0  
1435 0         0 return $parse->substring($start, $length);
1436             }
1437              
1438             sub Marpa::R2::Internal::MetaAST_Nodes::single_symbol::evaluate {
1439 1717     1717   2911 my ( $values, $parse ) = @_;
1440 1717         2367 my ( undef, undef, $symbol ) = @{$values};
  1717         2876  
1441 1717         3871 return Marpa::R2::Internal::MetaAST::Symbol_List->new(
1442             $symbol->name($parse) );
1443             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::single_symbol::evaluate
1444              
1445             sub Marpa::R2::Internal::MetaAST_Nodes::Symbol::evaluate {
1446 0     0   0 my ( $values, $parse ) = @_;
1447 0         0 my ( undef, undef, $symbol ) = @{$values};
  0         0  
1448 0         0 return $symbol->evaluate($parse);
1449             }
1450              
1451             sub Marpa::R2::Internal::MetaAST_Nodes::symbol::name {
1452 1789     1789   3128 my ( $self, $parse ) = @_;
1453 1789         3990 return $self->[2]->name($parse);
1454             }
1455              
1456             sub Marpa::R2::Internal::MetaAST_Nodes::symbol::event_name {
1457 136     136   381 my ( $self, $parse ) = @_;
1458 136         393 return $self->[2]->name($parse);
1459             }
1460              
1461             sub Marpa::R2::Internal::MetaAST_Nodes::symbol::names {
1462 136     136   373 my ( $self, $parse ) = @_;
1463 136         559 return $self->[2]->names($parse);
1464             }
1465              
1466             sub Marpa::R2::Internal::MetaAST_Nodes::symbol_name::evaluate {
1467 3478     3478   5354 my ($self) = @_;
1468 3478         7928 return $self->[2];
1469             }
1470              
1471             sub Marpa::R2::Internal::MetaAST_Nodes::symbol_name::name {
1472 3478     3478   5752 my ( $self, $parse ) = @_;
1473 3478         6369 return $self->evaluate($parse)->name($parse);
1474             }
1475              
1476             sub Marpa::R2::Internal::MetaAST_Nodes::symbol_name::names {
1477 136     136   380 my ( $self, $parse ) = @_;
1478 136         576 return [ $self->name($parse) ];
1479             }
1480              
1481             sub Marpa::R2::Internal::MetaAST_Nodes::adverb_list::evaluate {
1482 2043     2043   3783 my ( $data, $parse ) = @_;
1483 2043         2925 my ( undef, undef, $adverb_list_items ) = @{$data};
  2043         3750  
1484 2043 100       5063 return undef if not defined $adverb_list_items;
1485 635         1698 return $adverb_list_items->evaluate($parse);
1486             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::adverb_list::evaluate
1487              
1488             sub Marpa::R2::Internal::MetaAST_Nodes::null_adverb::evaluate {
1489 6     6   13 return {};
1490             }
1491              
1492             sub Marpa::R2::Internal::MetaAST_Nodes::adverb_list_items::evaluate {
1493 635     635   1285 my ( $data, $parse ) = @_;
1494 635         1027 my ( undef, undef, @raw_items ) = @{$data};
  635         1460  
1495 635         1213 my (@adverb_items) = map { $_->evaluate($parse) } @raw_items;
  770         1908  
1496 635         1970 return Marpa::R2::Internal::MetaAST::Proto_Alternative->combine(
1497             @adverb_items);
1498             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::adverb_list::evaluate
1499              
1500             sub Marpa::R2::Internal::MetaAST_Nodes::character_class::event_name {
1501 13     13   60 my ( $data, $parse ) = @_;
1502 13         36 my ( $start, $length ) = @{$data};
  13         43  
1503 13         64 return $parse->substring( $start, $length );
1504             }
1505              
1506             sub Marpa::R2::Internal::MetaAST_Nodes::character_class::names {
1507 13     13   61 my ( $self, $parse ) = @_;
1508 13         40 return [ $self->name($parse) ];
1509             }
1510              
1511             sub Marpa::R2::Internal::MetaAST_Nodes::character_class::name {
1512 315     315   813 my ( $self, $parse ) = @_;
1513 315         1040 return $self->evaluate($parse)->name($parse);
1514             }
1515              
1516             sub Marpa::R2::Internal::MetaAST_Nodes::character_class::evaluate {
1517 315     315   675 my ( $values, $parse ) = @_;
1518 315         824 my $character_class = $values->[2];
1519 315         692 my $subgrammar = $Marpa::R2::Internal::SUBGRAMMAR;
1520 315 100       1036 if (( substr $subgrammar, 0, 1 ) eq 'L') {
1521 307         1140 return Marpa::R2::Internal::MetaAST::Symbol_List->char_class_to_symbol(
1522             $parse, $character_class );
1523             }
1524             # If here, in G1
1525             # Character classes and strings always go into L0, for now
1526 8         16 my $lexer_symbol = do {
1527 8         17 local $Marpa::R2::Internal::SUBGRAMMAR = 'L0';
1528 8         38 Marpa::R2::Internal::MetaAST::Symbol_List->char_class_to_symbol(
1529             $parse, $character_class );
1530             };
1531 8         34 my $lexical_lhs = $parse->internal_lexeme($character_class);
1532 8         31 my $lexical_rhs = $lexer_symbol->names($parse);
1533 8         36 my %lexical_rule = (
1534             lhs => $lexical_lhs,
1535             rhs => $lexical_rhs,
1536             mask => [1],
1537             );
1538 8         26 push @{ $parse->{rules}->{L0} }, \%lexical_rule;
  8         59  
1539 8         35 my $g1_symbol =
1540             Marpa::R2::Internal::MetaAST::Symbol_List->new($lexical_lhs);
1541 8         36 return $g1_symbol;
1542             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::character_class::evaluate
1543              
1544             sub Marpa::R2::Internal::MetaAST_Nodes::single_quoted_string::evaluate {
1545 580     580   1432 my ( $values, $parse ) = @_;
1546 580         998 my ( undef, undef, $string ) = @{$values};
  580         1488  
1547 580         1079 my @symbols = ();
1548              
1549 580         1447 my $end_of_string = rindex $string, q{'};
1550 580         1496 my $unmodified_string = substr $string, 0, $end_of_string+1;
1551 580         1244 my $raw_flags = substr $string, $end_of_string+1;
1552 580         1542 my $flags = Marpa::R2::Internal::MetaAST::flag_string_to_flags($raw_flags);
1553 580         1111 my $subgrammar = $Marpa::R2::Internal::SUBGRAMMAR;
1554              
1555             # If we are currently in a lexical grammar, the strings go there
1556             # If we are currently in G1, the strings always go into L0
1557 580 100       1583 my $lexical_grammar = $subgrammar eq 'G1' ? 'L0' : $subgrammar;
1558              
1559 580         2082 for my $char_class (
1560 938         3192 map { '[' . ( quotemeta $_ ) . ']' . $flags } split //xms,
1561             substr $unmodified_string,
1562             1, -1
1563             )
1564             {
1565 938         1703 local $Marpa::R2::Internal::SUBGRAMMAR = $lexical_grammar;
1566 938         2582 my $symbol =
1567             Marpa::R2::Internal::MetaAST::Symbol_List->char_class_to_symbol(
1568             $parse, $char_class );
1569 938         2262 push @symbols, $symbol;
1570             } ## end for my $char_class ( map { '[' . ( quotemeta $_ ) . ']'...})
1571 580         1907 my $list = Marpa::R2::Internal::MetaAST::Symbol_List->combine(@symbols);
1572 580 100       2415 return $list if $Marpa::R2::Internal::SUBGRAMMAR ne 'G1';
1573 272         959 my $lexical_lhs = $parse->internal_lexeme($string);
1574 272         806 my $lexical_rhs = $list->names($parse);
1575             my %lexical_rule = (
1576             lhs => $lexical_lhs,
1577             rhs => $lexical_rhs,
1578             description => "Internal rule for single-quoted string $string",
1579 272         961 mask => [ map { ; 1 } @{$lexical_rhs} ],
  376         1404  
  272         557  
1580             );
1581 272         561 push @{ $parse->{rules}->{$lexical_grammar} }, \%lexical_rule;
  272         917  
1582 272         775 my $g1_symbol =
1583             Marpa::R2::Internal::MetaAST::Symbol_List->new($lexical_lhs);
1584 272         1306 return $g1_symbol;
1585             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::single_quoted_string::evaluate
1586              
1587             package Marpa::R2::Internal::MetaAST::Symbol_List;
1588              
1589 135     135   1482117 use English qw( -no_match_vars );
  135         447  
  135         978  
1590              
1591             sub new {
1592 3250     3250   6237 my ( $class, $name ) = @_;
1593 3250         15174 return bless { names => [ q{} . $name ], mask => [1] }, $class;
1594             }
1595              
1596             sub combine {
1597 4491     4491   8110 my ( $class, @lists ) = @_;
1598 4491         6671 my $self = {};
1599 4491         7167 $self->{names} = [ map { @{ $_->names() } } @lists ];
  5763         7338  
  5763         9591  
1600 4491         8316 $self->{mask} = [ map { @{ $_->mask() } } @lists ];
  5763         7165  
  5763         9658  
1601 4491         13258 return bless $self, $class;
1602             } ## end sub combine
1603              
1604             sub Marpa::R2::Internal::MetaAST::char_class_to_re {
1605 6535     6535   10008 my ($cc_components) = @_;
1606 6535 50       13490 die if ref $cc_components ne 'ARRAY';
1607 6535         8693 my ( $char_class, $flags ) = @{$cc_components};
  6535         20661  
1608 6535 100       12247 $flags = $flags ? '(' . q{?} . $flags . ')' : q{};
1609 6535         9213 my $regex;
1610             my $error;
1611 6535 50       8869 if ( not defined eval { $regex = qr/$flags$char_class/xms; 1; } ) {
  6535         75396  
  6535         19127  
1612 0         0 $error = qq{Problem in evaluating character class: "$char_class"\n};
1613 0 0       0 $error .= qq{ Flags were "$flags"\n} if $flags;
1614 0         0 $error .= $EVAL_ERROR;
1615             }
1616 6535         15738 return $regex, $error;
1617             }
1618              
1619             sub Marpa::R2::Internal::MetaAST::flag_string_to_flags {
1620 1833     1833   3114 my ($raw_flag_string) = @_;
1621 1833 100       4759 return q{} if not $raw_flag_string;
1622 29         100 my @raw_flags = split m/:/xms, $raw_flag_string;
1623 29         50 my %flags = ();
1624 29         49 RAW_FLAG: for my $raw_flag (@raw_flags) {
1625 35 100       72 next RAW_FLAG if not $raw_flag;
1626 29 100       64 if ( $raw_flag eq 'i' ) {
1627 28         42 $flags{'i'} = 1;
1628 28         67 next RAW_FLAG;
1629             }
1630 1 50       4 if ( $raw_flag eq 'ic' ) {
1631 1         5 $flags{'i'} = 1;
1632 1         3 next RAW_FLAG;
1633             }
1634             Carp::croak(
1635 0         0 qq{Bad flag for character class\n},
1636             qq{ Flag string was $raw_flag_string\n},
1637             qq{ Bad flag was $raw_flag\n}
1638             );
1639             } ## end RAW_FLAG: for my $raw_flag (@raw_flags)
1640 29         78 my $cooked_flags = join q{}, sort keys %flags;
1641 29         93 return $cooked_flags;
1642             } ## end sub flag_string_to_flags
1643              
1644             # Return the character class symbol name,
1645             # after ensuring everything is set up properly
1646             sub char_class_to_symbol {
1647 1253     1253   2609 my ( $class, $parse, $char_class ) = @_;
1648              
1649 1253         2368 my $end_of_char_class = rindex $char_class, q{]};
1650 1253         2550 my $unmodified_char_class = substr $char_class, 0, $end_of_char_class+1;
1651 1253         2137 my $raw_flags = substr $char_class, $end_of_char_class+1;
1652 1253         2372 my $flags = Marpa::R2::Internal::MetaAST::flag_string_to_flags($raw_flags);
1653 1253         2080 my $subgrammar = $Marpa::R2::Internal::SUBGRAMMAR;
1654              
1655             # character class symbol name always start with TWO left square brackets
1656 1253         2726 my $symbol_name = '[' . $unmodified_char_class . $flags . ']';
1657 1253   100     3923 $parse->{character_classes} //= {};
1658 1253         2017 my $cc_hash = $parse->{character_classes};
1659 1253         2571 my ( undef, $symbol ) = $cc_hash->{$symbol_name};
1660 1253 50       2594 if ( not defined $symbol ) {
1661              
1662 1253         2691 my $cc_components = [$unmodified_char_class, $flags];
1663              
1664             # Fast fail on badly formed char_class -- we re-evaluate the regex just in time
1665             # before we register characters.
1666 1253         2884 my ( $regex, $eval_error ) =
1667             Marpa::R2::Internal::MetaAST::char_class_to_re($cc_components);
1668 1253 50       2971 Carp::croak( 'Bad Character class: ',
1669             $char_class, "\n", 'Perl said ', $eval_error )
1670             if not $regex;
1671              
1672 1253         3119 $symbol =
1673             Marpa::R2::Internal::MetaAST::Symbol_List->new($symbol_name);
1674 1253         4224 $cc_hash->{$symbol_name} = [ $cc_components, $symbol ];
1675 1253         6437 $parse->symbol_names_set(
1676             $symbol_name,
1677             $subgrammar,
1678             { dsl_form => $char_class,
1679             display_form => $char_class,
1680             description => "Character class: $char_class"
1681             }
1682             );
1683             } ## end if ( not defined $symbol )
1684 1253         4832 return $symbol;
1685             } ## end sub char_class_to_symbol
1686              
1687             sub Marpa::R2::Internal::MetaAST::Parse::symbol_names_set {
1688 2034     2034   4498 my ( $parse, $symbol, $subgrammar, $args ) = @_;
1689 2034 100       4397 my $symbol_type = $subgrammar eq 'G1' ? 'G1' : 'L';
1690 2034         2909 for my $arg_type (keys %{$args}) {
  2034         5983  
1691 6025         9205 my $value = $args->{$arg_type};
1692 6025         16977 $parse->{symbols}->{$symbol_type}->{$symbol}->{$arg_type} = $value;
1693             }
1694             }
1695              
1696             # Return the priotized symbol name,
1697             # after ensuring everything is set up properly
1698             sub Marpa::R2::Internal::MetaAST::Parse::prioritized_symbol {
1699 370     370   697 my ( $parse, $base_symbol, $priority ) = @_;
1700              
1701             # character class symbol name always start with TWO left square brackets
1702 370         795 my $symbol_name = $base_symbol . '[' . $priority . ']';
1703             my $symbol_data =
1704 370 50       913 $parse->{symbols}->{$Marpa::R2::Internal::SUBGRAMMAR eq 'G1' ? 'G1' : 'L'}->{$symbol_name};
1705 370 100       988 return $symbol_name if defined $symbol_data;
1706 72 100       243 my $display_form =
1707             ( $base_symbol =~ m/\s/xms ) ? "<$base_symbol>" : $base_symbol;
1708 72         467 $parse->symbol_names_set(
1709             $symbol_name,
1710             $Marpa::R2::Internal::SUBGRAMMAR,
1711             { legacy_name => $base_symbol,
1712             dsl_form => $base_symbol,
1713             display_form => $display_form,
1714             description => "<$base_symbol> at priority $priority"
1715             }
1716             );
1717 72         684 return $symbol_name;
1718             } ## end sub Marpa::R2::Internal::MetaAST::Parse::prioritized_symbol
1719              
1720             # Return the prioritized symbol name,
1721             # after ensuring everything is set up properly
1722             sub Marpa::R2::Internal::MetaAST::Parse::internal_lexeme {
1723 280     280   774 my ( $parse, $dsl_form, @grammars ) = @_;
1724              
1725             # character class symbol name always start with TWO left square brackets
1726 280         823 my $lexical_lhs_index = $parse->{lexical_lhs_index}++;
1727 280         784 my $lexical_symbol = "[Lex-$lexical_lhs_index]";
1728 280         1335 my %names = (
1729             dsl_form => $dsl_form,
1730             display_form => $dsl_form,
1731             description => qq{Internal lexical symbol for "$dsl_form"}
1732             );
1733 280         1078 $parse->symbol_names_set( $lexical_symbol, $_, \%names ) for qw(G1 L);
1734 280         1002 return $lexical_symbol;
1735             } ## end sub Marpa::R2::Internal::MetaAST::Parse::internal_lexeme
1736              
1737             sub name {
1738 315     315   772 my ($self) = @_;
1739 315         1065 my $names = $self->{names};
1740             Marpa::R2::exception( 'list->name() on symbol list of length ',
1741 0         0 scalar @{$names} )
1742 315 50       533 if scalar @{$names} != 1;
  315         897  
1743 315         1435 return $self->{names}->[0];
1744             } ## end sub name
1745 7426     7426   20194 sub names { return shift->{names} }
1746 7146     7146   19043 sub mask { return shift->{mask} }
1747              
1748             sub mask_set {
1749 77     77   167 my ( $self, $mask ) = @_;
1750 77         136 return $self->{mask} = [ map {$mask} @{ $self->{mask} } ];
  87         216  
  77         164  
1751             }
1752              
1753             1;
1754              
1755             # vim: expandtab shiftwidth=4: