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 132     132   3413 use 5.010001;
  132         512  
19 132     132   841 use strict;
  132         333  
  132         3131  
20 132     132   715 use warnings;
  132         365  
  132         4498  
21              
22 132     132   738 use vars qw($VERSION $STRING_VERSION);
  132         353  
  132         11475  
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::MetaAST;
30              
31 132     132   891 use English qw( -no_match_vars );
  132         307  
  132         1036  
32              
33             sub new {
34 203     203   723 my ( $class, $p_rules_source ) = @_;
35 203         888 my $meta_recce = Marpa::R2::Internal::Scanless::meta_recce();
36 203 100       534 eval { $meta_recce->read($p_rules_source) }
  203         1121  
37             or Marpa::R2::exception( "Parse of BNF/Scanless source failed\n",
38             $EVAL_ERROR );
39 201 100       1467 if ( my $ambiguity_status = $meta_recce->ambiguous() ) {
40 1         9 Marpa::R2::exception( "Parse of BNF/Scanless source failed:\n",
41             $ambiguity_status );
42             }
43 200         984 my $value_ref = $meta_recce->value();
44 200 50       846 Marpa::R2::exception('Parse of BNF/Scanless source failed')
45             if not defined $value_ref;
46 200         548 my $ast = { meta_recce => $meta_recce, top_node => ${$value_ref} };
  200         1180  
47 200         1223 return bless $ast, $class;
48             } ## end sub new
49              
50             sub Marpa::R2::Internal::MetaAST::Parse::substring {
51 13     13   38 my ( $parse, $start, $length ) = @_;
52 13         25 my $meta_slr = $parse->{meta_recce};
53 13         21 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         37 chomp $string;
56 13         30 return $string;
57             } ## end sub Marpa::R2::Internal::MetaAST::Parse::substring
58              
59             sub ast_to_hash {
60 200     200   661 my ($ast) = @_;
61 200         471 my $hashed_ast = {};
62              
63 200         1162 $hashed_ast->{meta_recce} = $ast->{meta_recce};
64 200         920 bless $hashed_ast, 'Marpa::R2::Internal::MetaAST::Parse';
65              
66 200         904 $hashed_ast->{current_lexer} = 'L0';
67 200         856 $hashed_ast->{rules}->{G1} = [];
68 200         839 my $g1_symbols = $hashed_ast->{symbols}->{G1} = {};
69              
70 200         442 my ( undef, undef, @statements ) = @{ $ast->{top_node} };
  200         995  
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 200         501 my $eval_ok = eval {
82 200         564 local $Marpa::R2::JUST_DIE = 1;
83 200         1129 $_->evaluate($hashed_ast) for @statements;
84 200         831 1;
85             };
86 200 50       872 Marpa::R2::exception($EVAL_ERROR) if not $eval_ok;
87              
88 200         549 my %grammars = ();
89 200         402 $grammars{$_} = 1 for keys %{ $hashed_ast->{rules} };
  200         1151  
90             my @lexers =
91 200         872 grep { ( substr $_, 0, 1 ) eq 'L' } keys %grammars;
  390         1349  
92              
93 200         668 for my $lexer (@lexers) {
94 190         447 my $lexer_name = $lexer;
95             NAME_LEXER: {
96 190 50       364 if ( $lexer eq 'L0' ) {
  190         759  
97 190         471 $lexer_name = "L0 (the default)";
98 190         572 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 200         581 my %stripped_character_classes = ();
106             {
107 200         393 my $character_classes = $hashed_ast->{character_classes};
  200         516  
108 200         405 for my $symbol_name ( sort keys %{$character_classes} ) {
  200         1843  
109 938         1310 my ($re) = @{ $character_classes->{$symbol_name} };
  938         1573  
110 938         2097 $stripped_character_classes{$symbol_name} = $re;
111             }
112             }
113 200         1591 $hashed_ast->{character_classes} = \%stripped_character_classes;
114              
115 200         1305 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 609     609   1297 my ( $class, @hashes ) = @_;
132 609         1198 my $self = bless {}, $class;
133 609         1256 for my $hash_to_add (@hashes) {
134 740         1081 for my $key ( keys %{$hash_to_add} ) {
  740         2337  
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 734 50       2154 if exists $self->{$key};
139 734         2605 $self->{$key} = $hash_to_add->{$key};
140             } ## end for my $key ( keys %{$hash_to_add} )
141             } ## end for my $hash_to_add (@hashes)
142 609         2549 return $self;
143             } ## end sub Marpa::R2::Internal::MetaAST::Proto_Alternative::combine
144              
145             sub Marpa::R2::Internal::MetaAST::Parse::bless_hash_rule {
146 1601     1601   3560 my ( $parse, $hash_rule, $blessing, $naming, $original_lhs ) = @_;
147 1601 100       3985 return if (substr $Marpa::R2::Internal::SUBGRAMMAR, 0, 1) eq 'L';
148              
149 886   66     3326 $naming //= $original_lhs;
150 886         1819 $hash_rule->{name} = $naming;
151              
152 886 100       2112 return if not defined $blessing;
153             FIND_BLESSING: {
154 100 100       140 last FIND_BLESSING if $blessing =~ /\A [\w] /xms;
  100         377  
155 28 50       58 return if $blessing eq '::undef';
156              
157             # Rule may be half-formed, but assume we have lhs
158 28 50       55 if ( $blessing eq '::lhs' ) {
159 28         46 $blessing = $original_lhs;
160 28 50       113 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         73 $blessing =~ s/[ ]/_/gxms;
167 28         72 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         204 $hash_rule->{bless} = $blessing;
172 100         202 return 1;
173             } ## end sub Marpa::R2::Internal::MetaAST::Parse::bless_hash_rule
174              
175 2981     2981   9402 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   157 my ( $self, $parse ) = @_;
179 60         357 return $self->[2];
180             }
181              
182             sub Marpa::R2::Internal::MetaAST_Nodes::reserved_event_name::name {
183 33     33   103 my ( $self, $parse ) = @_;
184 33         77 my $name = $self->[2];
185 33         182 $name =~ s/\A : /'/xms;
186 33         179 return $name;
187             }
188              
189             sub Marpa::R2::Internal::MetaAST_Nodes::action_name::name {
190 347     347   746 my ( $self, $parse ) = @_;
191 347         1202 return $self->[2]->name($parse);
192             }
193              
194             sub Marpa::R2::Internal::MetaAST_Nodes::alternative_name::name {
195 5     5   10 my ( $self, $parse ) = @_;
196 5         17 return $self->[2]->name($parse);
197             }
198              
199             sub Marpa::R2::Internal::MetaAST_Nodes::event_name::name {
200 279     279   514 my ( $self, $parse ) = @_;
201 279         907 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   566 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   164 my ( $self, $parse ) = @_;
219 84         241 return $self->[2]->name($parse);
220             }
221              
222             sub Marpa::R2::Internal::MetaAST_Nodes::standard_name::name {
223 129     129   516 return $_[0]->[2];
224             }
225              
226             sub Marpa::R2::Internal::MetaAST_Nodes::Perl_name::name {
227 189     189   817 return $_[0]->[2];
228             }
229              
230             sub Marpa::R2::Internal::MetaAST_Nodes::lhs::name {
231 1227     1227   2315 my ( $values, $parse ) = @_;
232 1227         1718 my ( undef, undef, $symbol ) = @{$values};
  1227         2272  
233 1227         2756 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   504 my ($data) = @_;
244 194         1101 return $data->[2];
245             }
246              
247             sub Marpa::R2::Internal::MetaAST_Nodes::op_declare::op {
248 1227     1227   2165 my ($values) = @_;
249 1227         3416 return $values->[2]->op();
250             }
251              
252             sub Marpa::R2::Internal::MetaAST_Nodes::op_declare_match::op {
253 609     609   1323 my ($values) = @_;
254 609         2065 return $values->[2];
255             }
256              
257             sub Marpa::R2::Internal::MetaAST_Nodes::op_declare_bnf::op {
258 726     726   1349 my ($values) = @_;
259 726         2954 return $values->[2];
260             }
261              
262             sub Marpa::R2::Internal::MetaAST_Nodes::bracketed_name::name {
263 410     410   789 my ($values) = @_;
264 410         591 my ( undef, undef, $bracketed_name ) = @{$values};
  410         878  
265              
266             # normalize whitespace
267 410         2039 $bracketed_name =~ s/\A [<] \s*//xms;
268 410         1960 $bracketed_name =~ s/ \s* [>] \z//xms;
269 410         1498 $bracketed_name =~ s/ \s+ / /gxms;
270 410         1197 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   304 my ($values) = @_;
275 194         274 my ( undef, undef, $single_quoted_name ) = @{$values};
  194         374  
276              
277             # normalize whitespace
278 194         701 $single_quoted_name =~ s/\A ['] \s*//xms;
279 194         658 $single_quoted_name =~ s/ \s* ['] \z//xms;
280 194         416 $single_quoted_name =~ s/ \s+ / /gxms;
281 194         561 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 71     71   156 my ( $data, $parse ) = @_;
287 71         107 my ( undef, undef, @values ) = @{$data};
  71         183  
288 71         120 my @symbol_lists = map { $_->evaluate($parse); } @values;
  71         174  
289 71         305 my $flattened_list =
290             Marpa::R2::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
291 71         306 $flattened_list->mask_set(0);
292 71         217 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 1345     1345   2369 my ( $data, $parse ) = @_;
297 1345         1897 my ( $start, $length, @values ) = @{$data};
  1345         2779  
298 1345         2061 my $rhs = eval {
299 1345         2345 my @symbol_lists = map { $_->evaluate($parse) } @values;
  2232         4456  
300 1345         3152 my $flattened_list =
301             Marpa::R2::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
302 1345         3274 bless {
303             rhs => $flattened_list->names($parse),
304             mask => $flattened_list->mask()
305             },
306             $PROTO_ALTERNATIVE;
307             };
308 1345 50       3465 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 1345         2680 return $rhs;
318             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::rhs::evaluate
319              
320             sub Marpa::R2::Internal::MetaAST_Nodes::rhs_primary::evaluate {
321 2313     2313   3841 my ( $data, $parse ) = @_;
322 2313         3060 my ( undef, undef, @values ) = @{$data};
  2313         4026  
323 2313         3580 my @symbol_lists = map { $_->evaluate($parse) } @values;
  2313         5382  
324 2313         5323 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 71     71   180 my ( $data, $parse ) = @_;
329 71         115 my ( undef, undef, @values ) = @{$data};
  71         187  
330 71         145 my @symbol_lists = map { $_->evaluate($parse) } @values;
  81         238  
331 71         224 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 347     347   738 my ( $values, $parse ) = @_;
336 347         577 my ( undef, undef, $child ) = @{$values};
  347         730  
337 347         1049 return bless { action => $child->name($parse) }, $PROTO_ALTERNATIVE;
338             }
339              
340             sub Marpa::R2::Internal::MetaAST_Nodes::blessing::evaluate {
341 84     84   209 my ( $values, $parse ) = @_;
342 84         125 my ( undef, undef, $child ) = @{$values};
  84         164  
343 84         254 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         6 my ( undef, undef, $child ) = @{$values};
  5         18  
349 5         17 return bless { name => $child->name($parse) }, $PROTO_ALTERNATIVE;
350             }
351              
352             sub Marpa::R2::Internal::MetaAST_Nodes::right_association::evaluate {
353 10     10   64 my ($values) = @_;
354 10         50 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   38 my ($values) = @_;
364 11         45 return bless { assoc => 'G' }, $PROTO_ALTERNATIVE;
365             }
366              
367             sub Marpa::R2::Internal::MetaAST_Nodes::event_specification::evaluate {
368 127     127   281 my ($values) = @_;
369 127         432 return bless { event => ( $values->[2]->event() ) }, $PROTO_ALTERNATIVE;
370             }
371              
372             sub Marpa::R2::Internal::MetaAST_Nodes::event_initialization::event {
373 279     279   528 my ($values) = @_;
374 279         524 my $event_name = $values->[2];
375 279         432 my $event_initializer = $values->[3];
376 279         679 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   4 my ($values) = @_;
381 1         6 my $child = $values->[2];
382 1         9 return bless { proper => $child->value() }, $PROTO_ALTERNATIVE;
383             }
384              
385             sub Marpa::R2::Internal::MetaAST_Nodes::latm_specification::evaluate {
386 45     45   142 my ($values) = @_;
387 45         217 my $child = $values->[2];
388 45         201 return bless { latm => $child->value() }, $PROTO_ALTERNATIVE;
389             }
390              
391             sub Marpa::R2::Internal::MetaAST_Nodes::pause_specification::evaluate {
392 54     54   117 my ($values) = @_;
393 54         128 my $child = $values->[2];
394 54         190 return bless { pause => $child->value() }, $PROTO_ALTERNATIVE;
395             }
396              
397             sub Marpa::R2::Internal::MetaAST_Nodes::priority_specification::evaluate {
398 2     2   8 my ($values) = @_;
399 2         7 my $child = $values->[2];
400 2         11 return bless { priority => $child->value() }, $PROTO_ALTERNATIVE;
401             }
402              
403             sub Marpa::R2::Internal::MetaAST_Nodes::rank_specification::evaluate {
404 33     33   71 my ($values) = @_;
405 33         71 my $child = $values->[2];
406 33         94 return bless { rank => $child->value() }, $PROTO_ALTERNATIVE;
407             }
408              
409             sub Marpa::R2::Internal::MetaAST_Nodes::null_ranking_specification::evaluate {
410 2     2   13 my ($values) = @_;
411 2         9 my $child = $values->[2];
412 2         12 return bless { null_ranking => $child->value() }, $PROTO_ALTERNATIVE;
413             }
414              
415             sub Marpa::R2::Internal::MetaAST_Nodes::null_ranking_constant::value {
416 2     2   10 return $_[0]->[2];
417             }
418              
419             sub Marpa::R2::Internal::MetaAST_Nodes::before_or_after::value {
420 54     54   241 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   499 my ($values) = @_;
427 279         582 my $is_activated = $values->[2];
428 279 100       1164 return 1 if not defined $is_activated;
429 102         258 return $is_activated->value();
430             }
431              
432             sub Marpa::R2::Internal::MetaAST_Nodes::on_or_off::value {
433 102 100   102   573 return $_[0]->[2] eq 'off' ? 0 : 1;
434             }
435              
436             sub Marpa::R2::Internal::MetaAST_Nodes::boolean::value {
437 46     46   259 return $_[0]->[2];
438             }
439              
440             sub Marpa::R2::Internal::MetaAST_Nodes::signed_integer::value {
441 35     35   132 return $_[0]->[2];
442             }
443              
444             sub Marpa::R2::Internal::MetaAST_Nodes::separator_specification::evaluate {
445 13     13   43 my ( $values, $parse ) = @_;
446 13         58 my $child = $values->[2];
447 13         72 return bless { separator => $child->name($parse) }, $PROTO_ALTERNATIVE;
448             }
449              
450             sub Marpa::R2::Internal::MetaAST_Nodes::adverb_item::evaluate {
451 740     740   1423 my ( $values, $parse ) = @_;
452 740         2612 my $child = $values->[2]->evaluate($parse);
453 740         2252 return bless $child, $PROTO_ALTERNATIVE;
454             }
455              
456             sub Marpa::R2::Internal::MetaAST_Nodes::default_rule::evaluate {
457 108     108   358 my ( $values, $parse ) = @_;
458 108         229 my ( $start, $length, undef, $op_declare, $raw_adverb_list ) = @{$values};
  108         420  
459 108 50       489 my $subgrammar = $op_declare->op() eq q{::=} ? 'G1' : $parse->{current_lexer};
460 108         508 my $adverb_list = $raw_adverb_list->evaluate($parse);
461              
462             # A default rule clears the previous default
463 108         335 my %default_adverbs = ();
464 108         399 $parse->{default_adverbs}->{$subgrammar} = \%default_adverbs;
465              
466 108         265 ADVERB: for my $key ( keys %{$adverb_list} ) {
  108         387  
467 116         291 my $value = $adverb_list->{$key};
468 116 100 66     829 if ( $key eq 'action' and $subgrammar eq 'G1' ) {
469 108         362 $default_adverbs{$key} = $adverb_list->{$key};
470 108         382 next ADVERB;
471             }
472 8 50 33     74 if ( $key eq 'bless' and $subgrammar eq 'G1' ) {
473 8         24 $default_adverbs{$key} = $adverb_list->{$key};
474 8         43 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 108         352 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   124 my ( $data, $parse ) = @_;
485 27         53 my ( $start, $length, $raw_adverb_list ) = @{$data};
  27         76  
486 27         64 local $Marpa::R2::Internal::SUBGRAMMAR = 'G1';
487              
488 27         62 my $adverb_list = $raw_adverb_list->evaluate($parse);
489 27 50       171 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         113 $parse->{discard_default_adverbs} = {};
498 27         63 ADVERB: for my $key ( keys %{$adverb_list} ) {
  27         79  
499 27         53 my $value = $adverb_list->{$key};
500 27 50 33     136 if ( $key eq 'event' and defined $value ) {
501 27         77 $parse->{discard_default_adverbs}->{$key} = $value;
502 27         79 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         80 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   188 my ( $data, $parse ) = @_;
513 53         128 my ( $start, $length, $raw_adverb_list ) = @{$data};
  53         223  
514 53         170 local $Marpa::R2::Internal::SUBGRAMMAR = 'G1';
515              
516 53         198 my $adverb_list = $raw_adverb_list->evaluate($parse);
517 53 50       315 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         229 $parse->{lexeme_default_adverbs} = {};
526 53         151 ADVERB: for my $key ( keys %{$adverb_list} ) {
  53         223  
527 87         201 my $value = $adverb_list->{$key};
528 87 100       299 if ( $key eq 'action' ) {
529 40         124 $parse->{lexeme_default_adverbs}->{$key} = $value;
530 40         116 next ADVERB;
531             }
532 47 100       167 if ( $key eq 'bless' ) {
533 4         12 $parse->{lexeme_default_adverbs}->{$key} = $value;
534 4         15 next ADVERB;
535             }
536 43 50       139 if ( $key eq 'latm' ) {
537 43         112 $parse->{lexeme_default_adverbs}->{$key} = $value;
538 43         115 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         167 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   25 my ( $data, $parse ) = @_;
549 7         16 my ( $start, $length, $inaccessible_treatment ) = @{$data};
  7         48  
550 7         29 local $Marpa::R2::Internal::SUBGRAMMAR = 'G1';
551              
552 7 50       32 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         88 $parse->{defaults}->{if_inaccessible} = $inaccessible_treatment->value();
561 7         19 return undef;
562             }
563              
564             sub Marpa::R2::Internal::MetaAST_Nodes::inaccessible_treatment::value {
565 7     7   35 return $_[0]->[2];
566             }
567              
568             sub Marpa::R2::Internal::MetaAST_Nodes::priority_rule::evaluate {
569 971     971   1873 my ( $values, $parse ) = @_;
570             my ( $start, $length, $raw_lhs, $op_declare, $raw_priorities ) =
571 971         1432 @{$values};
  971         2163  
572              
573 971         1920 my $current_lexer = $parse->{current_lexer};
574 971         1418 my $subgrammar;
575 971 100       2374 if ( $op_declare->op() eq q{::=} ) {
576 504 50       1408 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 504         948 $subgrammar = 'G1';
584             } ## end if ( $op_declare->op() eq q{::=} )
585             else {
586 467         897 $subgrammar = $current_lexer;
587             }
588              
589 971         2563 my $lhs = $raw_lhs->name($parse);
590 971 100 66     3777 $parse->{'first_lhs'} //= $lhs if $subgrammar eq 'G1';
591 971         1759 local $Marpa::R2::Internal::SUBGRAMMAR = $subgrammar;
592              
593 971         1382 my ( undef, undef, @priorities ) = @{$raw_priorities};
  971         2042  
594 971         1666 my $priority_count = scalar @priorities;
595 971         1557 my @working_rules = ();
596              
597 971   100     2816 $parse->{rules}->{$subgrammar} //= [];
598 971         1784 my $rules = $parse->{rules}->{$subgrammar};
599              
600 971         1804 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
601              
602 971 100       2287 if ( $priority_count <= 1 ) {
603             ## If there is only one priority
604 952         1446 my ( undef, undef, @alternatives ) = @{ $priorities[0] };
  952         2079  
605 952         1839 for my $alternative (@alternatives) {
606             my ($alternative_start, $alternative_end,
607             $raw_rhs, $raw_adverb_list
608 1231         1773 ) = @{$alternative};
  1231         2715  
609 1231         2069 my ( $proto_rule, $adverb_list );
610 1231         1872 my $eval_ok = eval {
611 1231         2897 $proto_rule = $raw_rhs->evaluate($parse);
612 1231         2850 $adverb_list = $raw_adverb_list->evaluate($parse);
613 1231         2313 1;
614             };
615 1231 50       2645 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 1231         1816 my @rhs_names = @{ $proto_rule->{rhs} };
  1231         3186  
627 1231         1923 my @mask = @{ $proto_rule->{mask} };
  1231         2406  
628 1231 50 66     4364 if ( ( substr $subgrammar, 0, 1 ) eq 'L'
629 948         3006 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 1231         4375 my %hash_rule =
636             ( lhs => $lhs, rhs => \@rhs_names, mask => \@mask );
637              
638 1231         4710 my $action;
639             my $blessing;
640 1231         0 my $naming;
641 1231         0 my $null_ranking;
642 1231         0 my $rank;
643 1231         1650 ADVERB: for my $key ( keys %{$adverb_list} ) {
  1231         3344  
644 193         409 my $value = $adverb_list->{$key};
645 193 100       505 if ( $key eq 'action' ) {
646 127         224 $action = $adverb_list->{$key};
647 127         298 next ADVERB;
648             }
649 66 50       167 if ( $key eq 'assoc' ) {
650              
651             # OK, but ignored
652 0         0 next ADVERB;
653             }
654 66 100       190 if ( $key eq 'bless' ) {
655 26         43 $blessing = $adverb_list->{$key};
656 26         57 next ADVERB;
657             }
658 40 100       101 if ( $key eq 'name' ) {
659 5         11 $naming = $adverb_list->{$key};
660 5         12 next ADVERB;
661             }
662 35 100       75 if ( $key eq 'null_ranking' ) {
663 2         4 $null_ranking = $adverb_list->{$key};
664 2         5 next ADVERB;
665             }
666 33 50       68 if ( $key eq 'rank' ) {
667 33         58 $rank = $adverb_list->{$key};
668 33         68 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 1231   100     5283 $action //= $default_adverbs->{action};
677 1231 100       2567 if ( defined $action ) {
678 371 50       1012 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 371         803 $hash_rule{action} = $action;
682             } ## end if ( defined $action )
683              
684 1231   66     4648 $rank //= $default_adverbs->{rank};
685 1231 100       2466 if ( defined $rank ) {
686 33 50       77 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 33         61 $hash_rule{rank} = $rank;
690             } ## end if ( defined $rank )
691              
692 1231   66     4494 $null_ranking //= $default_adverbs->{null_ranking};
693 1231 100       2356 if ( defined $null_ranking ) {
694 2 50       33 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         13 $hash_rule{null_ranking} = $null_ranking;
698             } ## end if ( defined $rank )
699              
700 1231   100     4313 $blessing //= $default_adverbs->{bless};
701 1231 50 66     2830 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 1231         3808 $parse->bless_hash_rule( \%hash_rule, $blessing, $naming, $lhs );
713              
714 1231         1869 push @{$rules}, \%hash_rule;
  1231         5589  
715             } ## end for my $alternative (@alternatives)
716             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
717 952         2887 return undef;
718             } ## end if ( $priority_count <= 1 )
719              
720 19         121 for my $priority_ix ( 0 .. $priority_count - 1 ) {
721 75         155 my $priority = $priority_count - ( $priority_ix + 1 );
722 75         117 my ( undef, undef, @alternatives ) = @{ $priorities[$priority_ix] };
  75         182  
723 75         148 for my $alternative (@alternatives) {
724             my ($alternative_start, $alternative_end,
725             $raw_rhs, $raw_adverb_list
726 114         180 ) = @{$alternative};
  114         231  
727 114         207 my ( $adverb_list, $rhs );
728 114         171 my $eval_ok = eval {
729 114         237 $adverb_list = $raw_adverb_list->evaluate($parse);
730 114         294 $rhs = $raw_rhs->evaluate($parse);
731 114         217 1;
732             };
733 114 50       264 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         395 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         81 my @arg0_action = ();
750 19 50       111 @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         52 ;
761 56         180 { 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         93 RULE: for my $working_rule (@working_rules) {
773 114         200 my ( $priority, $rhs, $adverb_list ) = @{$working_rule};
  114         235  
774 114         225 my @new_rhs = @{ $rhs->{rhs} };
  114         346  
775 114         276 my @arity = grep { $new_rhs[$_] eq $lhs } 0 .. $#new_rhs;
  286         655  
776 114         209 my $rhs_length = scalar @new_rhs;
777              
778 114         291 my $current_exp = $parse->prioritized_symbol( $lhs, $priority );
779 114         205 my @mask = @{ $rhs->{mask} };
  114         271  
780 114 50 33     388 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         283 my %new_xs_rule = ( lhs => $current_exp );
788 114         256 $new_xs_rule{mask} = \@mask;
789              
790 114         523 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         158 ADVERB: for my $key ( keys %{$adverb_list} ) {
  114         320  
797 108         203 my $value = $adverb_list->{$key};
798 108 100       232 if ( $key eq 'action' ) {
799 44         70 $action = $adverb_list->{$key};
800 44         87 next ADVERB;
801             }
802 64 100       170 if ( $key eq 'assoc' ) {
803 21         57 $assoc = $adverb_list->{$key};
804 21         49 next ADVERB;
805             }
806 43 50       98 if ( $key eq 'bless' ) {
807 43         79 $blessing = $adverb_list->{$key};
808 43         89 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     471 $assoc //= 'L';
828              
829 114   100     358 $action //= $default_adverbs->{action};
830 114 100       242 if ( defined $action ) {
831 107 50       255 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         214 $new_xs_rule{action} = $action;
835             } ## end if ( defined $action )
836              
837 114   33     452 $null_ranking //= $default_adverbs->{null_ranking};
838 114 50       227 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     426 $rank //= $default_adverbs->{rank};
846 114 50       232 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     352 $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         351 $parse->bless_hash_rule( \%new_xs_rule, $blessing, $naming, $lhs );
864              
865 114         222 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       273 $next_priority = 0 if $next_priority >= $priority_count;
872              
873 114         252 my $next_exp = $parse->prioritized_symbol( $lhs, $next_priority);
874              
875 114 100       335 if ( not scalar @arity ) {
876 29         76 $new_xs_rule{rhs} = \@new_rhs;
877 29         64 push @{$rules}, \%new_xs_rule;
  29         85  
878 29         128 next RULE;
879             }
880              
881 85 100       288 if ( scalar @arity == 1 ) {
882 19 50       80 die 'Unnecessary unit rule in priority rule' if $rhs_length == 1;
883 19         53 $new_rhs[ $arity[0] ] = $current_exp;
884             }
885             DO_ASSOCIATION: {
886 85 100       149 if ( $assoc eq 'L' ) {
  85         225  
887 64         169 $new_rhs[ $arity[0] ] = $current_exp;
888 64         186 for my $rhs_ix ( @arity[ 1 .. $#arity ] ) {
889 56         108 $new_rhs[$rhs_ix] = $next_exp;
890             }
891 64         153 last DO_ASSOCIATION;
892             } ## end if ( $assoc eq 'L' )
893 21 100       82 if ( $assoc eq 'R' ) {
894 10         32 $new_rhs[ $arity[-1] ] = $current_exp;
895 10         56 for my $rhs_ix ( @arity[ 0 .. $#arity - 1 ] ) {
896 10         33 $new_rhs[$rhs_ix] = $next_exp;
897             }
898 10         45 last DO_ASSOCIATION;
899             } ## end if ( $assoc eq 'R' )
900 11 50       43 if ( $assoc eq 'G' ) {
901 11         90 for my $rhs_ix ( @arity[ 0 .. $#arity ] ) {
902 11         50 $new_rhs[$rhs_ix] = $parse->prioritized_symbol( $lhs, 0 );
903             }
904 11         51 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         184 $new_xs_rule{rhs} = \@new_rhs;
910 85         136 push @{$rules}, \%new_xs_rule;
  85         302  
911             } ## end RULE: for my $working_rule (@working_rules)
912             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
913 19         248 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   196 my ( $values, $parse ) = @_;
918             my ( $start, $length, $raw_lhs, $op_declare, $raw_adverb_list ) =
919 62         174 @{$values};
  62         297  
920              
921 62         183 my $current_lexer = $parse->{current_lexer};
922 62         125 my $subgrammar;
923 62 100       208 if ( $op_declare->op() eq q{::=} ) {
924 61 50       244 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         170 $subgrammar = 'G1';
932             } ## end if ( $op_declare->op() eq q{::=} )
933             else {
934 1         3 $subgrammar = $current_lexer;
935             }
936              
937 62         226 my $lhs = $raw_lhs->name($parse);
938 62 100 66     472 $parse->{'first_lhs'} //= $lhs if $subgrammar eq 'G1';
939 62         170 local $Marpa::R2::Internal::SUBGRAMMAR = $subgrammar;
940              
941 62         420 my %rule = ( lhs => $lhs,
942             description => qq{Empty rule for <$lhs>},
943             rhs => [] );
944 62         215 my $adverb_list = $raw_adverb_list->evaluate($parse);
945              
946 62         217 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
947              
948 62         363 my $action;
949             my $blessing;
950 62         0 my $naming;
951 62         0 my $rank;
952 62         0 my $null_ranking;
953 62         130 ADVERB: for my $key ( keys %{$adverb_list} ) {
  62         222  
954 8         14 my $value = $adverb_list->{$key};
955 8 50       23 if ( $key eq 'action' ) {
956 8         14 $action = $adverb_list->{$key};
957 8         18 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     414 $action //= $default_adverbs->{action};
981 62 100       188 if ( defined $action ) {
982 33 50       133 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         102 $rule{action} = $action;
986             } ## end if ( defined $action )
987              
988 62   33     335 $null_ranking //= $default_adverbs->{null_ranking};
989 62 50       179 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     315 $rank //= $default_adverbs->{rank};
997 62 50       185 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     454 $blessing //= $default_adverbs->{bless};
1005 62 50 33     219 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         265 $parse->bless_hash_rule( \%rule, $blessing, $naming, $lhs );
1013              
1014             # mask not needed
1015 62         165 push @{ $parse->{rules}->{$subgrammar} }, \%rule;
  62         258  
1016              
1017             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1018 62         224 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   180 my ( $values, $parse ) = @_;
1023 63         107 my ( $start, $length, $symbol, $unevaluated_adverb_list ) = @{$values};
  63         230  
1024              
1025 63         218 my $symbol_name = $symbol->name();
1026 63         217 my $declarations = $parse->{lexeme_declarations}->{$symbol_name};
1027 63 50       225 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         166 my $adverb_list = $unevaluated_adverb_list->evaluate();
1036 63         172 my %declarations;
1037 63         135 ADVERB: for my $key ( keys %{$adverb_list} ) {
  63         244  
1038 107         233 my $raw_value = $adverb_list->{$key};
1039 107 100       254 if ( $key eq 'priority' ) {
1040 2         10 $declarations{$key} = $raw_value + 0;
1041 2         6 next ADVERB;
1042             }
1043 105 100       266 if ( $key eq 'pause' ) {
1044 54 100       146 if ( $raw_value eq 'before' ) {
1045 10         38 $declarations{$key} = -1;
1046 10         25 next ADVERB;
1047             }
1048 44 50       132 if ( $raw_value eq 'after' ) {
1049 44         96 $declarations{$key} = 1;
1050 44         89 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       157 if ( $key eq 'event' ) {
1058 49         117 $declarations{$key} = $raw_value;
1059 49         112 next ADVERB;
1060             }
1061 2 50       6 if ( $key eq 'latm' ) {
1062 2         7 $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     333 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         254 $parse->{lexeme_declarations}->{$symbol_name} = \%declarations;
1079             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1080 63         167 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   30 my ( $data, $parse ) = @_;
1085 12         22 my ( undef, undef, @statement_list ) = @{$data};
  12         24  
1086 12         21 map { $_->evaluate($parse) } @statement_list;
  22         57  
1087 12         27 return undef;
1088             } ## end sub Marpa::R2::Internal::MetaAST_Nodes::statements::evaluate
1089              
1090             sub Marpa::R2::Internal::MetaAST_Nodes::statement::evaluate {
1091 1924     1924   3714 my ( $data, $parse ) = @_;
1092 1924         2774 my ( undef, undef, $child ) = @{$data};
  1924         3535  
1093 1924         7092 $child->evaluate($parse);
1094             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1095 1924         5120 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   36 return undef;
1100             }
1101              
1102             sub Marpa::R2::Internal::MetaAST_Nodes::statement_group::evaluate {
1103 12     12   33 my ( $data, $parse ) = @_;
1104 12         20 my ( undef, undef, $statements ) = @{$data};
  12         40  
1105 12         49 $statements->evaluate($parse);
1106             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1107 12         27 return undef;
1108             }
1109              
1110             sub Marpa::R2::Internal::MetaAST::start_rule_create {
1111 268     268   934 my ( $parse, $symbol_name ) = @_;
1112 268         680 my $start_lhs = '[:start]';
1113             $parse->{'default_g1_start_action'} =
1114 268         1450 $parse->{'default_adverbs'}->{'G1'}->{'action'};
1115 268         1697 $parse->{'symbols'}->{'G1'}->{$start_lhs} = {
1116             display_form => ':start',
1117             description => 'Internal G1 start symbol'
1118             };
1119 268         615 push @{ $parse->{rules}->{G1} },
  268         2168  
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   323 my ( $values, $parse ) = @_;
1129 104         217 my ( $start, $length, $symbol ) = @{$values};
  104         387  
1130 104 50       481 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         514 $parse->{'start_lhs'} = $symbol->name($parse);
1140             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1141 104         304 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   539 my ( $values, $parse ) = @_;
1146 149         290 my ( $start, $length, $symbol, $raw_adverb_list ) = @{$values};
  149         577  
1147              
1148 149         393 my $lexer_name = $parse->{current_lexer};
1149 149         297 local $Marpa::R2::Internal::SUBGRAMMAR = $lexer_name;
1150 149         325 my $discard_lhs = '[:discard]';
1151 149         1039 $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         1004 my $rhs = $symbol->names($parse);
1159 149         794 my $rhs_as_event = $symbol->event_name($parse);
1160 149         691 my $adverb_list = $raw_adverb_list->evaluate($parse);
1161 149         348 my $event;
1162 149         318 ADVERB: for my $key ( keys %{$adverb_list} ) {
  149         515  
1163 51         102 my $value = $adverb_list->{$key};
1164 51 50       130 if ( $key eq 'event' ) {
1165 51         88 $event = $value;
1166 51         135 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         414 map { '<' . $_ . '>' } @{$rhs}
  149         1379  
  149         341  
1175             ),
1176             lhs => $discard_lhs,
1177             rhs => $rhs,
1178             symbol_as_event => $rhs_as_event
1179             );
1180 149 100       551 $rule_hash{event} = $event if defined $event;
1181 149         287 push @{ $parse->{rules}->{$lexer_name} }, \%rule_hash;
  149         569  
1182             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1183 149         472 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   509 my ( $values, $parse ) = @_;
1188             my ( $start, $length, $lhs, $op_declare, $rhs, $quantifier,
1189             $proto_adverb_list )
1190 194         364 = @{$values};
  194         752  
1191              
1192 194         355 my $subgrammar;
1193 194         457 my $current_lexer = $parse->{current_lexer};
1194 194 100       627 if ( $op_declare->op() eq q{::=} ) {
1195 53 50       226 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         155 $subgrammar = 'G1';
1203             } ## end if ( $op_declare->op() eq q{::=} )
1204             else {
1205 141         323 $subgrammar = $current_lexer;
1206             }
1207              
1208 194         659 my $lhs_name = $lhs->name($parse);
1209 194 100 66     943 $parse->{'first_lhs'} //= $lhs_name if $subgrammar eq 'G1';
1210 194         399 local $Marpa::R2::Internal::SUBGRAMMAR = $subgrammar;
1211              
1212 194         502 my $adverb_list = $proto_adverb_list->evaluate($parse);
1213 194         617 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       778 my %sequence_rule = (
1218             rhs => [ $rhs->name($parse) ],
1219             min => ( $quantifier->evaluate($parse) eq q{+} ? 1 : 0 )
1220             );
1221              
1222 194         585 my @rules = ( \%sequence_rule );
1223              
1224 194         1424 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         323 ADVERB: for my $key ( keys %{$adverb_list} ) {
  194         578  
1232 37         141 my $value = $adverb_list->{$key};
1233 37 100       143 if ( $key eq 'action' ) {
1234 20         54 $action = $adverb_list->{$key};
1235 20         60 next ADVERB;
1236             }
1237 17 100       80 if ( $key eq 'bless' ) {
1238 3         8 $blessing = $adverb_list->{$key};
1239 3         9 next ADVERB;
1240             }
1241 14 50       59 if ( $key eq 'name' ) {
1242 0         0 $naming = $adverb_list->{$key};
1243 0         0 next ADVERB;
1244             }
1245 14 100       64 if ( $key eq 'proper' ) {
1246 1         2 $proper = $adverb_list->{$key};
1247 1         4 next ADVERB;
1248             }
1249 13 50       51 if ( $key eq 'rank' ) {
1250 0         0 $rank = $adverb_list->{$key};
1251 0         0 next ADVERB;
1252             }
1253 13 50       39 if ( $key eq 'null_ranking' ) {
1254 0         0 $null_ranking = $adverb_list->{$key};
1255 0         0 next ADVERB;
1256             }
1257 13 50       53 if ( $key eq 'separator' ) {
1258 13         32 $separator = $adverb_list->{$key};
1259 13         41 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         541 $sequence_rule{lhs} = $lhs_name;
1268              
1269 194 100       529 $sequence_rule{separator} = $separator
1270             if defined $separator;
1271 194 100       529 $sequence_rule{proper} = $proper if defined $proper;
1272              
1273 194   100     1025 $action //= $default_adverbs->{action};
1274 194 100       516 if ( defined $action ) {
1275 41 50       205 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         135 $sequence_rule{action} = $action;
1279             } ## end if ( defined $action )
1280              
1281 194   33     947 $null_ranking //= $default_adverbs->{null_ranking};
1282 194 50       576 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     1013 $rank //= $default_adverbs->{rank};
1290 194 50       502 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     918 $blessing //= $default_adverbs->{bless};
1298 194 50 66     608 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         747 $parse->bless_hash_rule( \%sequence_rule, $blessing, $naming, $lhs_name );
1305              
1306 194         348 push @{ $parse->{rules}->{$subgrammar} }, @rules;
  194         677  
1307             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1308 194         682 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   105 my ( $values, $parse ) = @_;
1315 54         112 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  54         140  
1316 54         125 my $symbol_name = $raw_symbol_name->name();
1317 54   100     220 my $completion_events = $parse->{completion_events} //= {};
1318 54 50       152 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         137 $completion_events->{$symbol_name} = $raw_event->event();
1327             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1328 54         115 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   91 my ( $values, $parse ) = @_;
1333 46         69 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  46         99  
1334 46         96 my $symbol_name = $raw_symbol_name->name();
1335 46   100     171 my $nulled_events = $parse->{nulled_events} //= {};
1336 46 50       117 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         87 $nulled_events->{$symbol_name} = $raw_event->event();
1345             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1346 46         91 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   94 my ( $values, $parse ) = @_;
1352 52         66 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  52         193  
1353 52         93 my $symbol_name = $raw_symbol_name->name();
1354 52   100     211 my $prediction_events = $parse->{prediction_events} //= {};
1355 52 50       126 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         117 $prediction_events->{$symbol_name} = $raw_event->event();
1364             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1365 52         109 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   419 my ( $values, $parse ) = @_;
1416 149         288 my ( undef, undef, $symbol ) = @{$values};
  149         343  
1417 149         642 return $symbol->names($parse);
1418             }
1419              
1420             sub Marpa::R2::Internal::MetaAST_Nodes::single_symbol::name {
1421 207     207   482 my ( $values, $parse ) = @_;
1422 207         364 my ( undef, undef, $symbol ) = @{$values};
  207         475  
1423 207         682 return $symbol->name($parse);
1424             }
1425              
1426             sub Marpa::R2::Internal::MetaAST_Nodes::single_symbol::event_name {
1427 149     149   423 my ( $values, $parse ) = @_;
1428 149         300 my ( undef, undef, $symbol ) = @{$values};
  149         358  
1429 149         580 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 1668     1668   2964 my ( $values, $parse ) = @_;
1440 1668         2289 my ( undef, undef, $symbol ) = @{$values};
  1668         2840  
1441 1668         3751 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 1740     1740   2912 my ( $self, $parse ) = @_;
1453 1740         3934 return $self->[2]->name($parse);
1454             }
1455              
1456             sub Marpa::R2::Internal::MetaAST_Nodes::symbol::event_name {
1457 136     136   373 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   377 my ( $self, $parse ) = @_;
1463 136         513 return $self->[2]->names($parse);
1464             }
1465              
1466             sub Marpa::R2::Internal::MetaAST_Nodes::symbol_name::evaluate {
1467 3391     3391   5198 my ($self) = @_;
1468 3391         7484 return $self->[2];
1469             }
1470              
1471             sub Marpa::R2::Internal::MetaAST_Nodes::symbol_name::name {
1472 3391     3391   5521 my ( $self, $parse ) = @_;
1473 3391         6199 return $self->evaluate($parse)->name($parse);
1474             }
1475              
1476             sub Marpa::R2::Internal::MetaAST_Nodes::symbol_name::names {
1477 136     136   423 my ( $self, $parse ) = @_;
1478 136         540 return [ $self->name($parse) ];
1479             }
1480              
1481             sub Marpa::R2::Internal::MetaAST_Nodes::adverb_list::evaluate {
1482 2001     2001   3702 my ( $data, $parse ) = @_;
1483 2001         2938 my ( undef, undef, $adverb_list_items ) = @{$data};
  2001         3491  
1484 2001 100       4995 return undef if not defined $adverb_list_items;
1485 609         1593 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   15 return {};
1490             }
1491              
1492             sub Marpa::R2::Internal::MetaAST_Nodes::adverb_list_items::evaluate {
1493 609     609   1196 my ( $data, $parse ) = @_;
1494 609         893 my ( undef, undef, @raw_items ) = @{$data};
  609         1378  
1495 609         1158 my (@adverb_items) = map { $_->evaluate($parse) } @raw_items;
  740         1799  
1496 609         1758 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   45 my ( $data, $parse ) = @_;
1502 13         25 my ( $start, $length ) = @{$data};
  13         26  
1503 13         43 return $parse->substring( $start, $length );
1504             }
1505              
1506             sub Marpa::R2::Internal::MetaAST_Nodes::character_class::names {
1507 13     13   38 my ( $self, $parse ) = @_;
1508 13         30 return [ $self->name($parse) ];
1509             }
1510              
1511             sub Marpa::R2::Internal::MetaAST_Nodes::character_class::name {
1512 315     315   749 my ( $self, $parse ) = @_;
1513 315         875 return $self->evaluate($parse)->name($parse);
1514             }
1515              
1516             sub Marpa::R2::Internal::MetaAST_Nodes::character_class::evaluate {
1517 315     315   674 my ( $values, $parse ) = @_;
1518 315         857 my $character_class = $values->[2];
1519 315         581 my $subgrammar = $Marpa::R2::Internal::SUBGRAMMAR;
1520 315 100       988 if (( substr $subgrammar, 0, 1 ) eq 'L') {
1521 307         1062 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         17 my $lexer_symbol = do {
1527 8         26 local $Marpa::R2::Internal::SUBGRAMMAR = 'L0';
1528 8         53 Marpa::R2::Internal::MetaAST::Symbol_List->char_class_to_symbol(
1529             $parse, $character_class );
1530             };
1531 8         42 my $lexical_lhs = $parse->internal_lexeme($character_class);
1532 8         39 my $lexical_rhs = $lexer_symbol->names($parse);
1533 8         40 my %lexical_rule = (
1534             lhs => $lexical_lhs,
1535             rhs => $lexical_rhs,
1536             mask => [1],
1537             );
1538 8         15 push @{ $parse->{rules}->{L0} }, \%lexical_rule;
  8         39  
1539 8         31 my $g1_symbol =
1540             Marpa::R2::Internal::MetaAST::Symbol_List->new($lexical_lhs);
1541 8         39 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 574     574   1294 my ( $values, $parse ) = @_;
1546 574         948 my ( undef, undef, $string ) = @{$values};
  574         1450  
1547 574         1041 my @symbols = ();
1548              
1549 574         1520 my $end_of_string = rindex $string, q{'};
1550 574         1394 my $unmodified_string = substr $string, 0, $end_of_string+1;
1551 574         1189 my $raw_flags = substr $string, $end_of_string+1;
1552 574         1442 my $flags = Marpa::R2::Internal::MetaAST::flag_string_to_flags($raw_flags);
1553 574         1075 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 574 100       1480 my $lexical_grammar = $subgrammar eq 'G1' ? 'L0' : $subgrammar;
1558              
1559 574         1910 for my $char_class (
1560 932         3117 map { '[' . ( quotemeta $_ ) . ']' . $flags } split //xms,
1561             substr $unmodified_string,
1562             1, -1
1563             )
1564             {
1565 932         1613 local $Marpa::R2::Internal::SUBGRAMMAR = $lexical_grammar;
1566 932         2403 my $symbol =
1567             Marpa::R2::Internal::MetaAST::Symbol_List->char_class_to_symbol(
1568             $parse, $char_class );
1569 932         2282 push @symbols, $symbol;
1570             } ## end for my $char_class ( map { '[' . ( quotemeta $_ ) . ']'...})
1571 574         1735 my $list = Marpa::R2::Internal::MetaAST::Symbol_List->combine(@symbols);
1572 574 100       2289 return $list if $Marpa::R2::Internal::SUBGRAMMAR ne 'G1';
1573 266         930 my $lexical_lhs = $parse->internal_lexeme($string);
1574 266         731 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 266         817 mask => [ map { ; 1 } @{$lexical_rhs} ],
  370         1399  
  266         535  
1580             );
1581 266         566 push @{ $parse->{rules}->{$lexical_grammar} }, \%lexical_rule;
  266         952  
1582 266         731 my $g1_symbol =
1583             Marpa::R2::Internal::MetaAST::Symbol_List->new($lexical_lhs);
1584 266         1321 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 132     132   1446501 use English qw( -no_match_vars );
  132         451  
  132         1017  
1590              
1591             sub new {
1592 3189     3189   5893 my ( $class, $name ) = @_;
1593 3189         14698 return bless { names => [ q{} . $name ], mask => [1] }, $class;
1594             }
1595              
1596             sub combine {
1597 4374     4374   8218 my ( $class, @lists ) = @_;
1598 4374         6584 my $self = {};
1599 4374         6852 $self->{names} = [ map { @{ $_->names() } } @lists ];
  5629         7159  
  5629         9425  
1600 4374         7676 $self->{mask} = [ map { @{ $_->mask() } } @lists ];
  5629         7050  
  5629         9334  
1601 4374         12861 return bless $self, $class;
1602             } ## end sub combine
1603              
1604             sub Marpa::R2::Internal::MetaAST::char_class_to_re {
1605 6351     6351   9747 my ($cc_components) = @_;
1606 6351 50       12894 die if ref $cc_components ne 'ARRAY';
1607 6351         8320 my ( $char_class, $flags ) = @{$cc_components};
  6351         19369  
1608 6351 100       11866 $flags = $flags ? '(' . q{?} . $flags . ')' : q{};
1609 6351         8820 my $regex;
1610             my $error;
1611 6351 50       8460 if ( not defined eval { $regex = qr/$flags$char_class/xms; 1; } ) {
  6351         73340  
  6351         17959  
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 6351         15026 return $regex, $error;
1617             }
1618              
1619             sub Marpa::R2::Internal::MetaAST::flag_string_to_flags {
1620 1821     1821   3147 my ($raw_flag_string) = @_;
1621 1821 100       4622 return q{} if not $raw_flag_string;
1622 29         70 my @raw_flags = split m/:/xms, $raw_flag_string;
1623 29         41 my %flags = ();
1624 29         50 RAW_FLAG: for my $raw_flag (@raw_flags) {
1625 35 100       65 next RAW_FLAG if not $raw_flag;
1626 29 100       57 if ( $raw_flag eq 'i' ) {
1627 28         57 $flags{'i'} = 1;
1628 28         51 next RAW_FLAG;
1629             }
1630 1 50       5 if ( $raw_flag eq 'ic' ) {
1631 1         3 $flags{'i'} = 1;
1632 1         2 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         80 my $cooked_flags = join q{}, sort keys %flags;
1641 29         81 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 1247     1247   2664 my ( $class, $parse, $char_class ) = @_;
1648              
1649 1247         2417 my $end_of_char_class = rindex $char_class, q{]};
1650 1247         2478 my $unmodified_char_class = substr $char_class, 0, $end_of_char_class+1;
1651 1247         2134 my $raw_flags = substr $char_class, $end_of_char_class+1;
1652 1247         2233 my $flags = Marpa::R2::Internal::MetaAST::flag_string_to_flags($raw_flags);
1653 1247         2008 my $subgrammar = $Marpa::R2::Internal::SUBGRAMMAR;
1654              
1655             # character class symbol name always start with TWO left square brackets
1656 1247         2687 my $symbol_name = '[' . $unmodified_char_class . $flags . ']';
1657 1247   100     3874 $parse->{character_classes} //= {};
1658 1247         2048 my $cc_hash = $parse->{character_classes};
1659 1247         2486 my ( undef, $symbol ) = $cc_hash->{$symbol_name};
1660 1247 50       2635 if ( not defined $symbol ) {
1661              
1662 1247         2569 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 1247         2818 my ( $regex, $eval_error ) =
1667             Marpa::R2::Internal::MetaAST::char_class_to_re($cc_components);
1668 1247 50       2891 Carp::croak( 'Bad Character class: ',
1669             $char_class, "\n", 'Perl said ', $eval_error )
1670             if not $regex;
1671              
1672 1247         3040 $symbol =
1673             Marpa::R2::Internal::MetaAST::Symbol_List->new($symbol_name);
1674 1247         4236 $cc_hash->{$symbol_name} = [ $cc_components, $symbol ];
1675 1247         6383 $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 1247         4823 return $symbol;
1685             } ## end sub char_class_to_symbol
1686              
1687             sub Marpa::R2::Internal::MetaAST::Parse::symbol_names_set {
1688 2016     2016   4219 my ( $parse, $symbol, $subgrammar, $args ) = @_;
1689 2016 100       4336 my $symbol_type = $subgrammar eq 'G1' ? 'G1' : 'L';
1690 2016         2837 for my $arg_type (keys %{$args}) {
  2016         5791  
1691 5971         9058 my $value = $args->{$arg_type};
1692 5971         16774 $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   675 my ( $parse, $base_symbol, $priority ) = @_;
1700              
1701             # character class symbol name always start with TWO left square brackets
1702 370         822 my $symbol_name = $base_symbol . '[' . $priority . ']';
1703             my $symbol_data =
1704 370 50       929 $parse->{symbols}->{$Marpa::R2::Internal::SUBGRAMMAR eq 'G1' ? 'G1' : 'L'}->{$symbol_name};
1705 370 100       995 return $symbol_name if defined $symbol_data;
1706 72 100       242 my $display_form =
1707             ( $base_symbol =~ m/\s/xms ) ? "<$base_symbol>" : $base_symbol;
1708 72         430 $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         773 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 274     274   684 my ( $parse, $dsl_form, @grammars ) = @_;
1724              
1725             # character class symbol name always start with TWO left square brackets
1726 274         847 my $lexical_lhs_index = $parse->{lexical_lhs_index}++;
1727 274         803 my $lexical_symbol = "[Lex-$lexical_lhs_index]";
1728 274         1249 my %names = (
1729             dsl_form => $dsl_form,
1730             display_form => $dsl_form,
1731             description => qq{Internal lexical symbol for "$dsl_form"}
1732             );
1733 274         1012 $parse->symbol_names_set( $lexical_symbol, $_, \%names ) for qw(G1 L);
1734 274         1081 return $lexical_symbol;
1735             } ## end sub Marpa::R2::Internal::MetaAST::Parse::internal_lexeme
1736              
1737             sub name {
1738 315     315   776 my ($self) = @_;
1739 315         745 my $names = $self->{names};
1740             Marpa::R2::exception( 'list->name() on symbol list of length ',
1741 0         0 scalar @{$names} )
1742 315 50       473 if scalar @{$names} != 1;
  315         957  
1743 315         1335 return $self->{names}->[0];
1744             } ## end sub name
1745 7248     7248   19350 sub names { return shift->{names} }
1746 6974     6974   18609 sub mask { return shift->{mask} }
1747              
1748             sub mask_set {
1749 71     71   181 my ( $self, $mask ) = @_;
1750 71         125 return $self->{mask} = [ map {$mask} @{ $self->{mask} } ];
  81         216  
  71         131  
1751             }
1752              
1753             1;
1754              
1755             # vim: expandtab shiftwidth=4: