File Coverage

blib/lib/Marpa/R3/MetaAST.pm
Criterion Covered Total %
statement 1009 1137 88.7
branch 217 310 70.0
condition 87 128 67.9
subroutine 107 114 93.8
pod n/a
total 1420 1689 84.0


line stmt bran cond sub pod time code
1             # Marpa::R3 is Copyright (C) 2018, Jeffrey Kegler.
2             #
3             # This module is free software; you can redistribute it and/or modify it
4             # under the same terms as Perl 5.10.1. For more details, see the full text
5             # of the licenses in the directory LICENSES.
6             #
7             # This program is distributed in the hope that it will be
8             # useful, but it is provided "as is" and without any express
9             # or implied warranties. For details, see the full text of
10             # of the licenses in the directory LICENSES.
11              
12             package Marpa::R3::MetaAST;
13              
14 104     104   1952 use 5.010001;
  104         405  
15 104     104   640 use strict;
  104         218  
  104         2276  
16 104     104   557 use warnings;
  104         221  
  104         3123  
17              
18 104     104   561 use vars qw($VERSION $STRING_VERSION);
  104         228  
  104         8742  
19             $VERSION = '4.001_053';
20             $STRING_VERSION = $VERSION;
21             ## no critic(BuiltinFunctions::ProhibitStringyEval)
22             $VERSION = eval $VERSION;
23             ## use critic
24              
25             package Marpa::R3::Internal::MetaAST;
26              
27 104     104   743 use English qw( -no_match_vars );
  104         267  
  104         682  
28              
29             sub new {
30 291     291   1105 my ( $class, $p_rules_source ) = @_;
31 291         1398 my $meta_recce = Marpa::R3::Internal::meta_recce();
32 291         595 my $valuer;
33 291 100       588 eval { $meta_recce->read($p_rules_source) }
  291         1377  
34             or Marpa::R3::exception( "Parse of BNF/Scanless source failed\n",
35             $EVAL_ERROR );
36 289         3717 $valuer = Marpa::R3::Valuer->new( { recognizer => $meta_recce } );
37 289         1693 my $ambiguity_level = $valuer->ambiguity_level();
38 289 100       1137 if ( $ambiguity_level != 1 ) {
39 1         6 my $ambiguity_status = $valuer->ambiguous();
40 1         8 Marpa::R3::exception( "Parse of BNF/Scanless source failed:\n",
41             $ambiguity_status );
42             }
43 288         1347 my $value_ref = $valuer->value();
44 288 50       1182 Marpa::R3::exception('Parse of BNF/Scanless source failed')
45             if not defined $value_ref;
46 288         736 my $ast = { meta_recce => $meta_recce, top_node => ${$value_ref} };
  288         1513  
47 288         2432 return bless $ast, $class;
48             }
49              
50             sub Marpa::R3::Internal::MetaAST::Parse::substring {
51 18     18   58 my ( $parse, $start, $length ) = @_;
52 18         37 my $meta_slr = $parse->{meta_recce};
53 18         93 my ($block_id) = $meta_slr->block_progress();
54 18         88 my $string = $meta_slr->literal( $block_id, $start, $length );
55 18         50 chomp $string;
56 18         55 return $string;
57             } ## end sub Marpa::R3::Internal::MetaAST::Parse::substring
58              
59             sub Marpa::R3::Internal::MetaAST::Parse::line_column {
60 0     0   0 my ( $parse, $pos ) = @_;
61 0         0 return Marpa::R3::Internal::line_column($parse->{p_dsl}, $pos);
62             }
63              
64             # Assign symbols, creating "ordinary" symbols if no symbol
65             # already exists
66             sub Marpa::R3::Internal::MetaAST::Parse::symbol_assign_ordinary {
67 7267     7267   13287 my ( $parse, $symbol_name, $subg ) = @_;
68 7267         12576 my $wsym = $parse->{symbols}->{$subg}->{$symbol_name};
69 7267 100       16018 return $wsym if $wsym;
70             # say STDERR "symbol_assign_ordinary($symbol_name, $subg)";
71 2273         5963 my $symbol_data = {
72             dsl_form => $symbol_name,
73             name_source => 'lexical'
74             };
75 2273         6137 $parse->xsy_assign( $symbol_name, $symbol_data );
76 2273         6241 $symbol_data = { xsy => $symbol_name };
77 2273         5458 $parse->symbol_names_set( $symbol_name, $subg,
78             $symbol_data );
79             }
80              
81             sub ast_to_hash {
82 288     288   970 my ($ast, $p_dsl) = @_;
83 288         635 my $xpr_ordinal = 0;
84 288         703 my $hashed_ast = {};
85              
86 288         1644 $hashed_ast->{meta_recce} = $ast->{meta_recce};
87 288         1250 bless $hashed_ast, 'Marpa::R3::Internal::MetaAST::Parse';
88              
89 288         1255 $hashed_ast->{p_dsl} = $p_dsl;
90 288         1113 $hashed_ast->{xpr}->{l0} = {};
91 288         908 $hashed_ast->{xpr}->{g1} = {};
92 288         2753 $hashed_ast->{rules}->{l0} = [];
93 288         2763 $hashed_ast->{rules}->{g1} = [];
94 288         830 $hashed_ast->{lexeme_declarations} = {};
95 288         758 my $declarations = $hashed_ast->{lexeme_declarations};
96 288         1040 my $g1_symbols = $hashed_ast->{symbols}->{g1} = {};
97              
98 288         672 my ( undef, undef, @statements ) = @{ $ast->{top_node} };
  288         1509  
99              
100             # This is the last ditch exception catcher
101             # It forces all Marpa exceptions to be die's,
102             # then catches them and rethrows using Carp.
103             #
104             # The plan is to use die(), with higher levels
105             # catching and re-die()'ing after adding
106             # helpful location information. After the
107             # re-throw it is caught here and passed to
108             # Carp.
109 288         722 my $eval_ok = eval {
110 288         776 local $Marpa::R3::JUST_DIE = 1;
111 288         1704 $_->evaluate($hashed_ast) for @statements;
112 283         843 1;
113             };
114 288 100       1266 Marpa::R3::exception($EVAL_ERROR) if not $eval_ok;
115              
116             # Add the G1 augment rule
117             {
118 283         569 my $start_lhs = $hashed_ast->{'start_lhs'}
119 283   66     1565 // $hashed_ast->{'first_lhs'};
120 283 50       1035 Marpa::R3::exception('No rules in SLIF grammar')
121             if not defined $start_lhs;
122 283         618 my $augment_lhs = '[:start:]';
123 283         1010 my $symbol_data = {
124             dsl_form => $augment_lhs,
125             name_source => 'internal',
126             };
127 283         1130 $hashed_ast->xsy_create( $augment_lhs, $symbol_data );
128 283         1596 $hashed_ast->symbol_names_set( $augment_lhs, 'g1', { xsy => $augment_lhs } );
129              
130 283         2194 my $rule_data = {
131             start => 0,
132             length => 0,
133             lhs => $augment_lhs,
134             rhs => [$start_lhs],
135             subkey => $xpr_ordinal++,
136             action => '::first'
137             };
138 283         1031 $hashed_ast->symbol_assign_ordinary($start_lhs, 'g1');
139 283         915 my $wrl = $hashed_ast->xpr_create( $rule_data, 'g1' );
140 283         862 push @{ $hashed_ast->{rules}->{g1} }, $wrl;
  283         1584  
141             }
142              
143             # If the lexer is empty, create a fake one
144             # The fake lexer contains one rule.
145             # This rule discards everything it matches, but it
146             # never matches anything.
147 283 100       634 if ( not %{ $hashed_ast->{xpr}->{l0} } ) {
  283         1380  
148              
149             # the unicorn is a pattern which never matches
150 5         14 my $unicorn_class = '[[^\\d\\D]]';
151 5         11 my $unicorn;
152             {
153 5         10 local $Marpa::R3::Internal::SUBGRAMMAR = 'l0';
  5         10  
154 5         23 my $unicorn_symbol =
155             Marpa::R3::Internal::MetaAST::Symbol_List->char_class_to_symbol(
156             $hashed_ast, $unicorn_class );
157 5         22 $unicorn = $unicorn_symbol->name();
158             };
159 5         12 my $discard_lhs = '[:discard:]';
160 5         17 my $symbol_data = {
161             dsl_form => $discard_lhs,
162             name_source => 'internal',
163             };
164 5         20 $hashed_ast->xsy_assign( $discard_lhs, $symbol_data );
165 5         25 $hashed_ast->symbol_names_set( $discard_lhs, 'l0',
166             { xsy => $discard_lhs } );
167 5         35 my $rule_data = {
168             start => 0,
169             length => 0,
170             lhs => $discard_lhs,
171             rhs => [$unicorn],
172             symbol_as_event => $unicorn,
173             subkey => $xpr_ordinal++,
174              
175             # 'description' => 'Discard rule for <[[^\\d\\D]]>'
176             };
177 5         17 my $wrl = $hashed_ast->xpr_create( $rule_data, 'l0' );
178 5         13 push @{ $hashed_ast->{rules}->{l0} }, $wrl;
  5         20  
179             }
180              
181             # Add the L0 augment rule
182 283         767 if (1) {
183             # Target symbol assumed to exist already
184 283         744 my $target_lhs = '[:target:]';
185 283 50       1006 Marpa::R3::exception('No rules in SLIF L0 grammar')
186             if not defined $target_lhs;
187 283         578 my $augment_lhs = '[:lex_start:]';
188 283         950 my $symbol_data = {
189             dsl_form => $augment_lhs,
190             name_source => 'internal',
191             };
192 283         1248 $hashed_ast->xsy_create( $augment_lhs, $symbol_data );
193 283         1558 $hashed_ast->symbol_names_set( $augment_lhs, 'l0', { xsy => $augment_lhs } );
194              
195 283         1726 my $rule_data = {
196             start => 0,
197             length => 0,
198             lhs => $augment_lhs,
199             rhs => [$target_lhs],
200             };
201 283         1132 $hashed_ast->symbol_assign_ordinary($target_lhs, 'l0');
202 283         1009 my $wrl = $hashed_ast->xpr_create( $rule_data, 'l0' );
203 283         900 push @{ $hashed_ast->{rules}->{l0} }, $wrl;
  283         1509  
204             }
205              
206 283         791 my %l0_lhs = ();
207 283         735 my %l0_rhs = ();
208 283         546 RULE: for my $rule (values %{$hashed_ast->{xpr}->{l0}}) {
  283         1304  
209 1786         2884 my $lhs = $rule->{lhs};
210 1786         3085 $l0_lhs{$lhs} = 1;
211 1786         2349 $l0_rhs{$_} = 1 for @{$rule->{rhs}};
  1786         4791  
212 1786         2728 my $separator = $rule->{separator};
213 1786 50       3777 $l0_rhs{$separator} = 1 if $separator;
214             }
215 283         925 my %g1_lhs = ();
216 283         736 my %g1_rhs = ();
217 283         1052 RULE: for my $rule (values %{$hashed_ast->{xpr}->{g1}}) {
  283         1073  
218 1529         2445 my $lhs = $rule->{lhs};
219 1529         2454 $g1_lhs{$lhs} = 1;
220 1529         2106 $g1_rhs{$_} = 1 for @{$rule->{rhs}};
  1529         3972  
221 1529         2374 my $separator = $rule->{separator};
222 1529 100       3449 $g1_rhs{$separator} = 1 if $separator;
223             }
224              
225              
226 283         897 my %lexeme = ();
227 283         1154 $lexeme{$_} = 'a lexeme in L0' for grep { not $l0_rhs{$_} } keys %l0_lhs;
  1606         4252  
228 283         1135 $lexeme{$_} = 'a lexeme in G1' for grep { not $g1_lhs{$_} } keys %g1_rhs;
  1590         3417  
229 283         668 $lexeme{$_} = 'a declared lexeme' for keys %{$declarations};
  283         1340  
230 283         2574 LEXEME: for my $lexeme ( sort keys %lexeme ) {
231 1174 100       2970 next LEXEME if $lexeme eq '[:lex_start:]';
232 899   100     4071 $declarations->{$lexeme} //= {};
233 899 100       2613 if ( $lexeme ne '[:discard:]' ) {
234 740 100       1918 if ( not $l0_lhs{$lexeme} ) {
235 2         5 my $type = $lexeme{$lexeme};
236 2         13 Marpa::R3::exception(
237             "<$lexeme> is $type, but is not on the LHS of any L0 rule\n",
238             " A lexeme must be the LHS of some L0 rule\n"
239             );
240             }
241 738 100       1876 if ( $l0_rhs{$lexeme} ) {
242 2         5 my $type = $lexeme{$lexeme};
243 2         14 Marpa::R3::exception(
244             "<$lexeme> is $type, but is on the RHS of an L0 rule\n",
245             " A lexeme must not be in the RHS of any L0 rule\n"
246             );
247             }
248 736 100       1668 if ( $g1_lhs{$lexeme} ) {
249 2         4 my $type = $lexeme{$lexeme};
250 2         14 Marpa::R3::exception(
251             "<$lexeme> is $type, but is on the LHS of a G1 rule\n",
252             " A lexeme cannot be the LHS of any G1 rule\n"
253             );
254             }
255 734 100 66     2687 if ( not $g1_rhs{$lexeme} and $lexeme ne '[:lex_start:]') {
256 2         4 my $type = $lexeme{$lexeme};
257 2         13 Marpa::R3::exception(
258             "<$lexeme> is $type, but is not on the RHS of any G1 rule\n",
259             " A lexeme must be in the RHS of at least one G1 rule\n"
260             );
261             }
262             }
263              
264             {
265 891         1303 my $target_lhs = '[:target:]';
  891         1499  
266 891         2425 my $symbol_data = {
267             dsl_form => $target_lhs,
268             name_source => 'internal',
269             };
270 891         2503 $hashed_ast->xsy_assign( $target_lhs, $symbol_data );
271 891         4838 $hashed_ast->symbol_names_set( $target_lhs, 'l0',
272             { xsy => $target_lhs } );
273              
274 891         4146 my $rule_data = {
275             start => 0,
276             length => 0,
277             lhs => $target_lhs,
278             rhs => [$lexeme],
279             };
280 891         2588 $hashed_ast->symbol_assign_ordinary( $target_lhs, 'l0' );
281 891         1829 my $wrl = $hashed_ast->xpr_create( $rule_data, 'l0' );
282 891         1806 push @{ $hashed_ast->{rules}->{l0} }, $wrl;
  891         3252  
283             }
284             }
285              
286 275         843 my %stripped_character_classes = ();
287             {
288 275         795 my $character_classes = $hashed_ast->{character_classes};
  275         998  
289 275         1010 for my $symbol_name ( sort keys %{$character_classes} ) {
  275         1596  
290 1312         1779 my ($re) = @{ $character_classes->{$symbol_name} };
  1312         2262  
291 1312         3083 $stripped_character_classes{$symbol_name} = $re;
292             }
293             }
294 275         2101 $hashed_ast->{character_classes} = \%stripped_character_classes;
295              
296             # say STDERR Data::Dumper::Dumper($hashed_ast);
297              
298 275         2294 return $hashed_ast;
299             } ## end sub ast_to_hash
300              
301             # This class is for pieces of RHS alternatives, as they are
302             # being constructed
303             my $PROTO_ALTERNATIVE = 'Marpa::R3::Internal::MetaAST::Proto_Alternative';
304              
305             sub Marpa::R3::Internal::MetaAST::Proto_Alternative::combine {
306 821     821   1802 my ( $class, @hashes ) = @_;
307 821         1811 my $self = bless {}, $class;
308 821         1744 for my $hash_to_add (@hashes) {
309 941         1404 for my $key ( keys %{$hash_to_add} ) {
  941         2904  
310             ## expect to be caught and rethrown
311             die qq{A Marpa rule contained a duplicate key\n},
312             qq{ The key was "$key"\n}
313 935 50       2293 if exists $self->{$key};
314 935         2796 $self->{$key} = $hash_to_add->{$key};
315             } ## end for my $key ( keys %{$hash_to_add} )
316             } ## end for my $hash_to_add (@hashes)
317 821         3285 return $self;
318             } ## end sub Marpa::R3::Internal::MetaAST::Proto_Alternative::combine
319              
320             sub Marpa::R3::Internal::MetaAST::Parse::bless_hash_rule {
321 2211     2211   5005 my ( $parse, $hash_rule, $blessing, $naming, $original_lhs ) = @_;
322 2211 50       5403 return if (substr $Marpa::R3::Internal::SUBGRAMMAR, 0, 1) eq 'l0';
323              
324 2211   66     8004 $naming //= $original_lhs;
325 2211         5682 $hash_rule->{name} = $naming;
326              
327 2211 100       5161 return if not defined $blessing;
328             FIND_BLESSING: {
329 130 100       187 last FIND_BLESSING if $blessing =~ /\A [\w] /xms;
  130         545  
330 28 50       58 return if $blessing eq '::undef';
331              
332             # Rule may be half-formed, but assume we have lhs
333 28 50       65 if ( $blessing eq '::lhs' ) {
334 28         42 $blessing = $original_lhs;
335 28 50       74 if ( $blessing =~ / [^ [:alnum:]] /xms ) {
336 0         0 Marpa::R3::exception(
337             qq{"::lhs" blessing only allowed if LHS is whitespace and alphanumerics\n},
338             qq{ LHS was <$original_lhs>\n}
339             );
340             } ## end if ( $blessing =~ / [^ [:alnum:]] /xms )
341 28         79 $blessing =~ s/[ ]/_/gxms;
342 28         54 last FIND_BLESSING;
343             } ## end if ( $blessing eq '::lhs' )
344 0         0 Marpa::R3::exception( qq{Unknown blessing "$blessing"\n} );
345             } ## end FIND_BLESSING:
346 130         264 $hash_rule->{bless} = $blessing;
347 130         214 return 1;
348             } ## end sub Marpa::R3::Internal::MetaAST::Parse::bless_hash_rule
349              
350 4056     4056   13328 sub Marpa::R3::Internal::MetaAST_Nodes::bare_name::name { return $_[0]->[2] }
351              
352             sub Marpa::R3::Internal::MetaAST_Nodes::reserved_action_name::name {
353 110     110   303 my ( $self, $parse ) = @_;
354 110         712 return $self->[2];
355             }
356              
357             sub Marpa::R3::Internal::MetaAST_Nodes::reserved_event_name::name {
358 33     33   72 my ( $self, $parse ) = @_;
359 33         72 my $name = $self->[2];
360 33         225 $name =~ s/\A : /'/xms;
361 33         128 return $name;
362             }
363              
364             sub Marpa::R3::Internal::MetaAST_Nodes::action_name::name {
365 488     488   1012 my ( $self, $parse ) = @_;
366 488         1669 return $self->[2]->name($parse);
367             }
368              
369             sub Marpa::R3::Internal::MetaAST_Nodes::alternative_name::name {
370 10     10   21 my ( $self, $parse ) = @_;
371 10         39 return $self->[2]->name($parse);
372             }
373              
374             sub Marpa::R3::Internal::MetaAST_Nodes::event_name::name {
375 300     300   527 my ( $self, $parse ) = @_;
376 300         768 return $self->[2]->name($parse);
377             }
378              
379             sub Marpa::R3::Internal::MetaAST_Nodes::array_descriptor::name {
380 117     117   667 return $_[0]->[2];
381             }
382              
383             sub Marpa::R3::Internal::MetaAST_Nodes::reserved_blessing_name::name {
384 17     17   98 return $_[0]->[2];
385             }
386              
387             sub Marpa::R3::Internal::MetaAST_Nodes::blessing_name::name {
388 119     119   200 my ( $self, $parse ) = @_;
389 119         270 return $self->[2]->name($parse);
390             }
391              
392             sub Marpa::R3::Internal::MetaAST_Nodes::standard_name::name {
393 163     163   676 return $_[0]->[2];
394             }
395              
396             sub Marpa::R3::Internal::MetaAST_Nodes::Perl_name::name {
397 261     261   1390 return $_[0]->[2];
398             }
399              
400             sub Marpa::R3::Internal::MetaAST_Nodes::lhs::name {
401 1854     1854   3300 my ( $values, $parse ) = @_;
402 1854         2660 my ( undef, undef, $symbol ) = @{$values};
  1854         3480  
403 1854         4196 return $symbol->name($parse);
404             }
405              
406             # After development, delete this
407             sub Marpa::R3::Internal::MetaAST_Nodes::lhs::evaluate {
408 0     0   0 my ( $values, $parse ) = @_;
409 0         0 return $values->name($parse);
410             }
411              
412             sub Marpa::R3::Internal::MetaAST_Nodes::quantifier::evaluate {
413 318     318   660 my ($data) = @_;
414 318         1064 return $data->[2];
415             }
416              
417             sub Marpa::R3::Internal::MetaAST_Nodes::op_declare::op {
418 1854     1854   3116 my ($values) = @_;
419 1854         4836 return $values->[2]->op();
420             }
421              
422             sub Marpa::R3::Internal::MetaAST_Nodes::op_declare_match::op {
423 905     905   1649 my ($values) = @_;
424 905         3293 return $values->[2];
425             }
426              
427             sub Marpa::R3::Internal::MetaAST_Nodes::op_declare_bnf::op {
428 1087     1087   2167 my ($values) = @_;
429 1087         4510 return $values->[2];
430             }
431              
432             sub Marpa::R3::Internal::MetaAST_Nodes::bracketed_name::name {
433 581     581   1005 my ($values) = @_;
434 581         910 my ( undef, undef, $bracketed_name ) = @{$values};
  581         1165  
435              
436             # normalize whitespace
437 581         3137 $bracketed_name =~ s/\A [<] \s*//xms;
438 581         2715 $bracketed_name =~ s/ \s* [>] \z//xms;
439 581         1806 $bracketed_name =~ s/ \s+ / /gxms;
440 581         1857 return $bracketed_name;
441             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::bracketed_name::name
442              
443             sub Marpa::R3::Internal::MetaAST_Nodes::single_quoted_name::name {
444 216     216   357 my ($values) = @_;
445 216         310 my ( undef, undef, $single_quoted_name ) = @{$values};
  216         507  
446              
447             # normalize whitespace
448 216         827 $single_quoted_name =~ s/\A ['] \s*//xms;
449 216         755 $single_quoted_name =~ s/ \s* ['] \z//xms;
450 216         454 $single_quoted_name =~ s/ \s+ / /gxms;
451 216         626 return $single_quoted_name;
452             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::single_quoted_name::name
453              
454             sub Marpa::R3::Internal::MetaAST_Nodes::parenthesized_rhs_primary_list::evaluate
455             {
456 77     77   166 my ( $data, $parse ) = @_;
457 77         116 my ( undef, undef, @values ) = @{$data};
  77         203  
458 77         138 my @symbol_lists = map { $_->evaluate($parse); } @values;
  77         160  
459 77         214 my $flattened_list =
460             Marpa::R3::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
461 77         278 $flattened_list->mask_set(0);
462 77         276 return $flattened_list;
463             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::parenthesized_rhs_primary_list::evaluate
464              
465             sub Marpa::R3::Internal::MetaAST_Nodes::rhs::evaluate {
466 1798     1798   3209 my ( $data, $parse ) = @_;
467 1798         2529 my ( $start, $length, @values ) = @{$data};
  1798         4170  
468 1798         2748 my $rhs = eval {
469 1798         3234 my @symbol_lists = map { $_->evaluate($parse) } @values;
  2974         5992  
470 1798         4079 my $flattened_list =
471             Marpa::R3::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
472 1798         3948 bless {
473             rhs => $flattened_list->names($parse),
474             mask => $flattened_list->mask()
475             },
476             $PROTO_ALTERNATIVE;
477             };
478 1798 50       4733 if ( not $rhs ) {
479 0         0 my $eval_error = $EVAL_ERROR;
480 0         0 chomp $eval_error;
481 0         0 Marpa::R3::exception(
482             qq{$eval_error\n},
483             q{ RHS involved was },
484             $parse->substring( $start, $length )
485             );
486             } ## end if ( not $rhs )
487 1798         3577 return $rhs;
488             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::rhs::evaluate
489              
490             sub Marpa::R3::Internal::MetaAST_Nodes::rhs_primary::evaluate {
491 3069     3069   5108 my ( $data, $parse ) = @_;
492 3069         4188 my ( undef, undef, @values ) = @{$data};
  3069         5533  
493 3069         4647 my @symbol_lists = map { $_->evaluate($parse) } @values;
  3069         6704  
494 3069         6998 return Marpa::R3::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
495             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::rhs_primary::evaluate
496              
497             sub Marpa::R3::Internal::MetaAST_Nodes::rhs_primary_list::evaluate {
498 77     77   154 my ( $data, $parse ) = @_;
499 77         120 my ( undef, undef, @values ) = @{$data};
  77         187  
500 77         139 my @symbol_lists = map { $_->evaluate($parse) } @values;
  95         243  
501 77         207 return Marpa::R3::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
502             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::rhs_primary_list::evaluate
503              
504             sub Marpa::R3::Internal::MetaAST_Nodes::action::evaluate {
505 488     488   1001 my ( $values, $parse ) = @_;
506 488         838 my ( undef, undef, $child ) = @{$values};
  488         1137  
507 488         1480 return bless { action => $child->name($parse) }, $PROTO_ALTERNATIVE;
508             }
509              
510             sub Marpa::R3::Internal::MetaAST_Nodes::blessing::evaluate {
511 119     119   188 my ( $values, $parse ) = @_;
512 119         178 my ( undef, undef, $child ) = @{$values};
  119         251  
513 119         271 return bless { bless => $child->name($parse) }, $PROTO_ALTERNATIVE;
514             }
515              
516             sub Marpa::R3::Internal::MetaAST_Nodes::naming::evaluate {
517 10     10   25 my ( $values, $parse ) = @_;
518 10         18 my ( undef, undef, $child ) = @{$values};
  10         36  
519 10         33 return bless { name => $child->name($parse) }, $PROTO_ALTERNATIVE;
520             }
521              
522             sub Marpa::R3::Internal::MetaAST_Nodes::right_association::evaluate {
523 9     9   45 my ($values) = @_;
524 9         30 return bless { assoc => 'R' }, $PROTO_ALTERNATIVE;
525             }
526              
527             sub Marpa::R3::Internal::MetaAST_Nodes::left_association::evaluate {
528 0     0   0 my ($values) = @_;
529 0         0 return bless { assoc => 'L' }, $PROTO_ALTERNATIVE;
530             }
531              
532             sub Marpa::R3::Internal::MetaAST_Nodes::group_association::evaluate {
533 10     10   43 my ($values) = @_;
534 10         39 return bless { assoc => 'G' }, $PROTO_ALTERNATIVE;
535             }
536              
537             sub Marpa::R3::Internal::MetaAST_Nodes::eager_specification::evaluate {
538 21     21   63 my ($values) = @_;
539 21         70 my $child = $values->[2];
540 21         100 return bless { eager => $child->value() }, $PROTO_ALTERNATIVE;
541             }
542              
543             sub Marpa::R3::Internal::MetaAST_Nodes::event_specification::evaluate {
544 139     139   285 my ($values) = @_;
545 139         414 return bless { event => ( $values->[2]->event() ) }, $PROTO_ALTERNATIVE;
546             }
547              
548             sub Marpa::R3::Internal::MetaAST_Nodes::event_initialization::event {
549 300     300   520 my ($values) = @_;
550 300         556 my $event_name = $values->[2];
551 300         442 my $event_initializer = $values->[3];
552 300         669 return [$event_name->name(), $event_initializer->on_or_off()],
553             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::event_specification::evaluate
554              
555             sub Marpa::R3::Internal::MetaAST_Nodes::proper_specification::evaluate {
556 4     4   12 my ($values) = @_;
557 4         202 my $child = $values->[2];
558 4         24 return bless { proper => $child->value() }, $PROTO_ALTERNATIVE;
559             }
560              
561             sub Marpa::R3::Internal::MetaAST_Nodes::pause_specification::evaluate {
562 61     61   124 my ($values) = @_;
563 61         158 my $child = $values->[2];
564 61         184 return bless { pause => $child->value() }, $PROTO_ALTERNATIVE;
565             }
566              
567             sub Marpa::R3::Internal::MetaAST_Nodes::priority_specification::evaluate {
568 2     2   6 my ($values) = @_;
569 2         8 my $child = $values->[2];
570 2         7 return bless { priority => $child->value() }, $PROTO_ALTERNATIVE;
571             }
572              
573             sub Marpa::R3::Internal::MetaAST_Nodes::rank_specification::evaluate {
574 51     51   93 my ($values) = @_;
575 51         156 my $child = $values->[2];
576 51         138 return bless { rank => $child->value() }, $PROTO_ALTERNATIVE;
577             }
578              
579             sub Marpa::R3::Internal::MetaAST_Nodes::null_ranking_specification::evaluate {
580 2     2   6 my ($values) = @_;
581 2         7 my $child = $values->[2];
582 2         6 return bless { null_ranking => $child->value() }, $PROTO_ALTERNATIVE;
583             }
584              
585             sub Marpa::R3::Internal::MetaAST_Nodes::null_ranking_constant::value {
586 2     2   10 return $_[0]->[2];
587             }
588              
589             sub Marpa::R3::Internal::MetaAST_Nodes::before_or_after::value {
590 61     61   295 return $_[0]->[2];
591             }
592              
593             sub Marpa::R3::Internal::MetaAST_Nodes::event_initializer::on_or_off
594             {
595 300     300   527 my ($values) = @_;
596 300         412 my (undef, undef, $is_activated) = @{$values};
  300         586  
597 300 100       1139 return 1 if not defined $is_activated;
598 105         136 my (undef, undef, $on_or_off) = @{$is_activated};
  105         190  
599 105 100       526 return $on_or_off eq 'on' ? 1 : 0;
600             }
601              
602             sub Marpa::R3::Internal::MetaAST_Nodes::boolean::value {
603 25     25   151 return $_[0]->[2];
604             }
605              
606             sub Marpa::R3::Internal::MetaAST_Nodes::signed_integer::value {
607 53     53   194 return $_[0]->[2];
608             }
609              
610             sub Marpa::R3::Internal::MetaAST_Nodes::separator_specification::evaluate {
611 19     19   54 my ( $values, $parse ) = @_;
612 19         85 my $child = $values->[2];
613 19         96 return bless { separator => $child->name($parse) }, $PROTO_ALTERNATIVE;
614             }
615              
616             sub Marpa::R3::Internal::MetaAST_Nodes::adverb_item::evaluate {
617 941     941   1776 my ( $values, $parse ) = @_;
618 941         3094 my $child = $values->[2]->evaluate($parse);
619 941         3010 return bless $child, $PROTO_ALTERNATIVE;
620             }
621              
622             sub Marpa::R3::Internal::MetaAST_Nodes::default_rule::evaluate {
623 138     138   396 my ( $values, $parse ) = @_;
624 138         271 my ( $start, $length, undef, $op_declare, $raw_adverb_list ) = @{$values};
  138         629  
625 138 50       573 my $subgrammar = $op_declare->op() eq q{::=} ? 'g1' : 'l0';
626 138         769 my $adverb_list = $raw_adverb_list->evaluate($parse);
627              
628             # A default rule clears the previous default
629 138         383 my %default_adverbs = ();
630 138         540 $parse->{default_adverbs}->{$subgrammar} = \%default_adverbs;
631              
632 138         320 ADVERB: for my $key ( keys %{$adverb_list} ) {
  138         482  
633 149         387 my $value = $adverb_list->{$key};
634 149 100 66     1105 if ( $key eq 'action' and $subgrammar eq 'g1' ) {
635 138         448 $default_adverbs{$key} = $adverb_list->{$key};
636 138         411 next ADVERB;
637             }
638 11 50 33     97 if ( $key eq 'bless' and $subgrammar eq 'g1' ) {
639 11         34 $default_adverbs{$key} = $adverb_list->{$key};
640 11         28 next ADVERB;
641             }
642 0         0 die qq{Adverb "$key" not allowed in $subgrammar default rule\n},
643             ' Rule was ', $parse->substring( $start, $length ), "\n";
644             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
645             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
646 138         451 return undef;
647             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::default_rule::evaluate
648              
649             sub Marpa::R3::Internal::MetaAST_Nodes::discard_default_statement::evaluate {
650 27     27   62 my ( $data, $parse ) = @_;
651 27         43 my ( $start, $length, $raw_adverb_list ) = @{$data};
  27         66  
652 27         68 local $Marpa::R3::Internal::SUBGRAMMAR = 'g1';
653              
654 27         63 my $adverb_list = $raw_adverb_list->evaluate($parse);
655 27 50       84 if ( exists $parse->{discard_default_adverbs} ) {
656 0         0 my $problem_rule = $parse->substring( $start, $length );
657 0         0 Marpa::R3::exception(
658             qq{More than one discard default statement is not allowed\n},
659             qq{ This was the rule that caused the problem:\n},
660             qq{ $problem_rule\n}
661             );
662             } ## end if ( exists $parse->{discard_default_adverbs} )
663 27         83 $parse->{discard_default_adverbs} = {};
664 27         57 ADVERB: for my $key ( keys %{$adverb_list} ) {
  27         69  
665 27         49 my $value = $adverb_list->{$key};
666 27 50 33     116 if ( $key eq 'event' and defined $value ) {
667 27         67 $parse->{discard_default_adverbs}->{$key} = $value;
668 27         60 next ADVERB;
669             }
670             Marpa::R3::exception(
671 0         0 qq{"$key" adverb not allowed as discard default"});
672             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
673             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
674 27         69 return undef;
675             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::discard_default_statement::evaluate
676              
677             sub Marpa::R3::Internal::MetaAST_Nodes::lexeme_default_statement::evaluate {
678 43     43   139 my ( $data, $parse ) = @_;
679 43         87 my ( $start, $length, $raw_adverb_list ) = @{$data};
  43         175  
680 43         132 local $Marpa::R3::Internal::SUBGRAMMAR = 'g1';
681              
682 43         163 my $adverb_list = $raw_adverb_list->evaluate($parse);
683 43 50       166 if ( exists $parse->{lexeme_default_adverbs} ) {
684 0         0 my $problem_rule = $parse->substring( $start, $length );
685 0         0 Marpa::R3::exception(
686             qq{More than one lexeme default statement is not allowed\n},
687             qq{ This was the rule that caused the problem:\n},
688             qq{ $problem_rule\n}
689             );
690             } ## end if ( exists $parse->{lexeme_default_adverbs} )
691 43         129 $parse->{lexeme_default_adverbs} = {};
692 43         95 ADVERB: for my $key ( keys %{$adverb_list} ) {
  43         147  
693 49         114 my $value = $adverb_list->{$key};
694 49 100       155 if ( $key eq 'action' ) {
695 43         111 $parse->{lexeme_default_adverbs}->{$key} = $value;
696 43         102 next ADVERB;
697             }
698 6 50       28 if ( $key eq 'bless' ) {
699 6         16 $parse->{lexeme_default_adverbs}->{$key} = $value;
700 6         17 next ADVERB;
701             }
702             Marpa::R3::exception(
703 0         0 qq{"$key" adverb not allowed as lexeme default"});
704             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
705             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
706 43         121 return undef;
707             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::lexeme_default_statement::evaluate
708              
709             sub Marpa::R3::Internal::MetaAST_Nodes::inaccessible_statement::evaluate {
710 9     9   32 my ( $data, $parse ) = @_;
711 9         27 my ( $start, $length, $inaccessible_treatment ) = @{$data};
  9         78  
712 9         30 local $Marpa::R3::Internal::SUBGRAMMAR = 'g1';
713              
714 9 50       48 if ( exists $parse->{defaults}->{if_inaccessible} ) {
715 0         0 my $problem_rule = $parse->substring( $start, $length );
716 0         0 Marpa::R3::exception(
717             qq{More than one inaccessible default statement is not allowed\n},
718             qq{ This was the rule that caused the problem:\n},
719             qq{ $problem_rule\n}
720             );
721             }
722 9         53 $parse->{defaults}->{if_inaccessible} = $inaccessible_treatment->value();
723 9         29 return undef;
724             }
725              
726             sub Marpa::R3::Internal::MetaAST_Nodes::inaccessible_treatment::value {
727 9     9   53 return $_[0]->[2];
728             }
729              
730             sub Marpa::R3::Internal::MetaAST_Nodes::priority_rule::evaluate {
731 1440     1440   2726 my ( $values, $parse ) = @_;
732             my ( $start, $length, $raw_lhs, $op_declare, $raw_priorities ) =
733 1440         2056 @{$values};
  1440         3349  
734              
735 1440 100       3630 my $subgrammar = $op_declare->op() eq q{::=} ? 'g1' : 'l0';
736 1440         2664 my $xpr_ordinal = 0;
737              
738 1440         3150 my $lhs = $raw_lhs->name($parse);
739 1440 100 66     5607 $parse->{'first_lhs'} //= $lhs if $subgrammar eq 'g1';
740 1440         2702 local $Marpa::R3::Internal::SUBGRAMMAR = $subgrammar;
741              
742 1440         2024 my ( undef, undef, @priorities ) = @{$raw_priorities};
  1440         2956  
743 1440         2368 my $priority_count = scalar @priorities;
744 1440         2281 my @working_rules = ();
745              
746 1440   50     3750 $parse->{rules}->{$subgrammar} //= [];
747 1440         2534 my $rules = $parse->{rules}->{$subgrammar};
748              
749 1440         2680 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
750              
751 1440         6359 my $xrlid = xrl_create($parse, {
752             lhs => $lhs,
753             start => $start,
754             length => $length,
755             precedence_count => $priority_count,
756             }
757             );
758 1438 100       3713 if ( $priority_count <= 1 ) {
759             ## If there is only one priority
760 1419         2143 my ( undef, undef, @alternatives ) = @{ $priorities[0] };
  1419         3510  
761              
762 1419         3993 for my $alternative_ix (0 .. $#alternatives) {
763             my ($alternative_start, $alternative_length,
764             $raw_rhs, $raw_adverb_list
765 1693         2563 ) = @{$alternatives[$alternative_ix]};
  1693         4648  
766 1693         2796 my ( $proto_rule, $adverb_list );
767 1693         2723 my $eval_ok = eval {
768 1693         4447 $proto_rule = $raw_rhs->evaluate($parse);
769 1693         3911 $adverb_list = $raw_adverb_list->evaluate($parse);
770 1693         3077 1;
771             };
772 1693 50       3721 if ( not $eval_ok ) {
773 0         0 my $eval_error = $EVAL_ERROR;
774 0         0 chomp $eval_error;
775 0         0 Marpa::R3::exception(
776             qq{$eval_error\n},
777             qq{ The problem was in this RHS alternative:\n},
778             q{ },
779             $parse->substring( $alternative_start, $alternative_length ),
780             "\n"
781             );
782             } ## end if ( not $eval_ok )
783 1693         2388 my @rhs_names = @{ $proto_rule->{rhs} };
  1693         4540  
784 1693         2688 my @mask = @{ $proto_rule->{mask} };
  1693         3492  
785 1693 50 66     6159 if ( ( substr $subgrammar, 0, 1 ) eq 'l'
786 1382         4286 and grep { !$_ } @mask )
787             {
788 0         0 Marpa::R3::exception(
789             qq{hidden symbols are not allowed in lexical rules (rule's LHS was "$lhs")}
790             );
791             }
792 1693         5397 $parse->symbol_assign_ordinary($_, $subgrammar) for $lhs, @rhs_names;
793 1693 100       10564 my %hash_rule = (
    100          
794             start => ( $alternative_ix ? $alternative_start : $start ),
795             length => ( $alternative_ix ? $alternative_length : $length ),
796             subkey => ++$xpr_ordinal,
797             lhs => $lhs,
798             rhs => \@rhs_names,
799             mask => \@mask,
800             xrlid => $xrlid,
801             );
802              
803 1693         6651 my $action;
804             my $blessing;
805 1693         0 my $naming;
806 1693         0 my $null_ranking;
807 1693         0 my $rank;
808 1693         2375 ADVERB: for my $key ( keys %{$adverb_list} ) {
  1693         4144  
809 315         636 my $value = $adverb_list->{$key};
810 315 100       884 if ( $key eq 'action' ) {
811 204         506 $action = $adverb_list->{$key};
812 204         485 next ADVERB;
813             }
814 111 50       264 if ( $key eq 'assoc' ) {
815              
816             # OK, but ignored
817 0         0 next ADVERB;
818             }
819 111 100       343 if ( $key eq 'bless' ) {
820 48         82 $blessing = $adverb_list->{$key};
821 48         96 next ADVERB;
822             }
823 63 100       152 if ( $key eq 'name' ) {
824 10         22 $naming = $adverb_list->{$key};
825 10         24 next ADVERB;
826             }
827 53 100       137 if ( $key eq 'null_ranking' ) {
828 2         4 $null_ranking = $adverb_list->{$key};
829 2         6 next ADVERB;
830             }
831 51 50       121 if ( $key eq 'rank' ) {
832 51         80 $rank = $adverb_list->{$key};
833 51         111 next ADVERB;
834             }
835             my ( $line, $column ) =
836 0         0 $parse->{meta_recce}->line_column($start);
837 0         0 die qq{Adverb "$key" not allowed in an prioritized rule\n},
838             ' Rule was ', $parse->substring( $start, $length ), "\n";
839             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
840              
841 1693   100     7165 $action //= $default_adverbs->{action};
842 1693 100       3697 if ( defined $action ) {
843 538 50       1463 Marpa::R3::exception(
844             qq{actions not allowed in lexical rules (rule's LHS was "$lhs")}
845             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
846 538         1588 $hash_rule{action} = $action;
847             } ## end if ( defined $action )
848              
849 1693   66     6439 $rank //= $default_adverbs->{rank};
850 1693 100       3478 if ( defined $rank ) {
851 51 50       127 Marpa::R3::exception(
852             qq{ranks not allowed in lexical rules (rule's LHS was "$lhs")}
853             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
854 51         169 $hash_rule{rank} = $rank;
855             } ## end if ( defined $rank )
856              
857 1693   66     6005 $null_ranking //= $default_adverbs->{null_ranking};
858 1693 100       3275 if ( defined $null_ranking ) {
859 2 50       5 Marpa::R3::exception(
860             qq{null-ranking allowed in lexical rules (rule's LHS was "$lhs")}
861             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
862 2         4 $hash_rule{null_ranking} = $null_ranking;
863             } ## end if ( defined $rank )
864              
865 1693   100     6039 $blessing //= $default_adverbs->{bless};
866 1693 50 66     4057 if (defined $blessing
867             and
868             ( substr $subgrammar, 0, 1 ) eq 'l'
869             )
870             {
871 0         0 Marpa::R3::exception(
872             'bless option not allowed in lexical rules (rules LHS was "',
873             $lhs, '")'
874             );
875             }
876              
877 1693         5739 $parse->bless_hash_rule( \%hash_rule, $blessing, $naming, $lhs );
878              
879 1693         4307 my $wrl = $parse->xpr_create( \%hash_rule, $subgrammar );
880 1691         2911 push @{$rules}, $wrl;
  1691         10437  
881             } ## end for my $alternative (@alternatives)
882             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
883 1417         4613 return undef;
884             } ## end if ( $priority_count <= 1 )
885              
886 19         94 for my $priority_ix ( 0 .. $priority_count - 1 ) {
887 70         145 my $priority = $priority_count - ( $priority_ix + 1 );
888 70         110 my ( undef, undef, @alternatives ) = @{ $priorities[$priority_ix] };
  70         191  
889 70         145 for my $alternative (@alternatives) {
890             my ($alternative_start, $alternative_length,
891             $raw_rhs, $raw_adverb_list
892 105         175 ) = @{$alternative};
  105         237  
893 105         178 my ( $adverb_list, $rhs );
894 105         155 my $eval_ok = eval {
895 105         243 $adverb_list = $raw_adverb_list->evaluate($parse);
896 105         271 $rhs = $raw_rhs->evaluate($parse);
897 105         188 1;
898             };
899 105 50       228 if ( not $eval_ok ) {
900 0         0 my $eval_error = $EVAL_ERROR;
901 0         0 chomp $eval_error;
902 0         0 Marpa::R3::exception(
903             qq{$eval_error\n},
904             qq{ The problem was in this RHS alternative:\n},
905             q{ },
906             $parse->substring( $alternative_start, $alternative_length ),
907             "\n"
908             );
909             } ## end if ( not $eval_ok )
910 105         360 push @working_rules, [ $priority, $rhs, $adverb_list, $alternative_start, $alternative_length ];
911             } ## end for my $alternative (@alternatives)
912             } ## end for my $priority_ix ( 0 .. $priority_count - 1 )
913              
914             # Default mask (all ones) is OK for this rule
915 19         76 my @arg0_action = ();
916 19 50       102 @arg0_action = ( action => '::first' ) if $subgrammar eq 'g1';
917              
918             # Internal rule top priority rule for <$lhs>
919 19         86 $parse->symbol_assign_ordinary($lhs, $subgrammar);
920 19         112 my @priority_rules = (
921             {
922             start => $start,
923             length => $length,
924             lhs => $lhs,
925             rhs => [ $parse->prioritized_symbol( $lhs, 0 ) ],
926             precedence => -1,
927             subkey => ++$xpr_ordinal,
928             @arg0_action,
929             }
930             );
931              
932             # Internal rule for symbol <$lhs> priority transition
933             push @priority_rules,
934             {
935             start => $start,
936             length => $length,
937             lhs => $parse->prioritized_symbol( $lhs, $_ - 1 ),
938             rhs => [ $parse->prioritized_symbol( $lhs, $_ ) ],
939             precedence => ($_ - 1),
940             subkey => ++$xpr_ordinal,
941             @arg0_action
942             }
943 19         142 for 1 .. $priority_count - 1;
944 19         56 RULE: for my $priority_rule (@priority_rules) {
945 70         168 my $wrl = $parse->xpr_create( $priority_rule, $subgrammar );
946 70         123 push @{$rules}, $wrl;
  70         168  
947             }
948              
949 19         52 RULE: for my $working_rule (@working_rules) {
950 105         172 my ( $priority, $rhs, $adverb_list, $alternative_start, $alternative_length ) = @{$working_rule};
  105         229  
951 105         153 my @new_rhs = @{ $rhs->{rhs} };
  105         275  
952 105         253 my @arity = grep { $new_rhs[$_] eq $lhs } 0 .. $#new_rhs;
  262         663  
953 105         204 my $rhs_length = scalar @new_rhs;
954              
955 105         572 my $current_exp = $parse->prioritized_symbol( $lhs, $priority );
956 105         201 my @mask = @{ $rhs->{mask} };
  105         760  
957 105 50 33     349 if ( ( substr $subgrammar, 0, 1 ) eq 'l' and grep { !$_ } @mask )
  0         0  
958             {
959 0         0 Marpa::R3::exception(
960             'hidden symbols are not allowed in lexical rules (rules LHS was "',
961             $lhs, '")'
962             );
963             }
964 105         776 my %new_xs_rule = (
965             lhs => $current_exp,
966             start => $alternative_start,
967             length => $alternative_length,
968             subkey => ++$xpr_ordinal,
969             xrlid => $xrlid,
970             );
971 105         220 $new_xs_rule{mask} = \@mask;
972              
973 105         457 my $action;
974             my $assoc;
975 105         0 my $blessing;
976 105         0 my $naming;
977 105         0 my $rank;
978 105         0 my $null_ranking;
979 105         142 ADVERB: for my $key ( keys %{$adverb_list} ) {
  105         290  
980 98         176 my $value = $adverb_list->{$key};
981 98 100       417 if ( $key eq 'action' ) {
982 29         45 $action = $adverb_list->{$key};
983 29         60 next ADVERB;
984             }
985 69 100       142 if ( $key eq 'assoc' ) {
986 19         36 $assoc = $adverb_list->{$key};
987 19         43 next ADVERB;
988             }
989 50 50       102 if ( $key eq 'bless' ) {
990 50         77 $blessing = $adverb_list->{$key};
991 50         334 next ADVERB;
992             }
993 0 0       0 if ( $key eq 'name' ) {
994 0         0 $naming = $adverb_list->{$key};
995 0         0 next ADVERB;
996             }
997 0 0       0 if ( $key eq 'null_ranking' ) {
998 0         0 $null_ranking = $adverb_list->{$key};
999 0         0 next ADVERB;
1000             }
1001 0 0       0 if ( $key eq 'rank' ) {
1002 0         0 $rank = $adverb_list->{$key};
1003 0         0 next ADVERB;
1004             }
1005 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1006 0         0 die qq{Adverb "$key" not allowed in a prioritized rule\n},
1007             ' Rule was ', $parse->substring( $start, $length ), "\n";
1008             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
1009              
1010 105   100     476 $assoc //= 'L';
1011              
1012 105   100     748 $action //= $default_adverbs->{action};
1013 105 100       258 if ( defined $action ) {
1014 99 50       250 Marpa::R3::exception(
1015             qq{actions not allowed in lexical rules (rule's LHS was "$lhs")}
1016             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
1017 99         176 $new_xs_rule{action} = $action;
1018             } ## end if ( defined $action )
1019              
1020 105   33     415 $null_ranking //= $default_adverbs->{null_ranking};
1021 105 50       203 if ( defined $null_ranking ) {
1022 0 0       0 Marpa::R3::exception(
1023             qq{null-ranking not allowed in lexical rules (rule's LHS was "$lhs")}
1024             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
1025 0         0 $new_xs_rule{null_ranking} = $null_ranking;
1026             } ## end if ( defined $rank )
1027              
1028 105   33     388 $rank //= $default_adverbs->{rank};
1029 105 50       200 if ( defined $rank ) {
1030 0 0       0 Marpa::R3::exception(
1031             qq{ranks not allowed in lexical rules (rule's LHS was "$lhs")}
1032             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
1033 0         0 $new_xs_rule{rank} = $rank;
1034             } ## end if ( defined $rank )
1035              
1036 105   100     293 $blessing //= $default_adverbs->{bless};
1037 105 50 66     317 if ( defined $blessing
1038             and ( substr $subgrammar, 0, 1 ) eq 'l' )
1039             {
1040 0         0 Marpa::R3::exception(
1041             'bless option not allowed in lexical rules (rules LHS was "',
1042             $lhs, '")'
1043             );
1044             }
1045              
1046 105         307 $parse->bless_hash_rule( \%new_xs_rule, $blessing, $naming, $lhs );
1047              
1048 105         181 my $next_priority = $priority + 1;
1049              
1050             # This is probably a mis-feature. It probably should be
1051             # $next_priority = $priority if $next_priority >= $priority_count;
1052             # However, I probably will not change this, because some apps
1053             # may be relying on this behavior.
1054 105 100       236 $next_priority = 0 if $next_priority >= $priority_count;
1055              
1056 105         233 my $next_exp = $parse->prioritized_symbol( $lhs, $next_priority);
1057 105         375 $new_xs_rule{precedence} = $priority;
1058              
1059 105 100       270 if ( not scalar @arity ) {
1060 28         61 $new_xs_rule{rhs} = \@new_rhs;
1061 28         101 $parse->symbol_assign_ordinary($_, $subgrammar) for @new_rhs;
1062 28         118 my $wrl = $parse->xpr_create( \%new_xs_rule, $subgrammar );
1063 28         280 push @{$rules}, $wrl;
  28         73  
1064 28         108 next RULE;
1065             }
1066              
1067 77 100       199 if ( scalar @arity == 1 ) {
1068 15 50       50 die 'Unnecessary unit rule in priority rule' if $rhs_length == 1;
1069 15         52 $new_rhs[ $arity[0] ] = $current_exp;
1070             }
1071             DO_ASSOCIATION: {
1072 77 100       130 if ( $assoc eq 'L' ) {
  77         174  
1073 58         115 $new_rhs[ $arity[0] ] = $current_exp;
1074 58         154 for my $rhs_ix ( @arity[ 1 .. $#arity ] ) {
1075 53         291 $new_rhs[$rhs_ix] = $next_exp;
1076             }
1077 58         110 last DO_ASSOCIATION;
1078             } ## end if ( $assoc eq 'L' )
1079 19 100       58 if ( $assoc eq 'R' ) {
1080 9         58 $new_rhs[ $arity[-1] ] = $current_exp;
1081 9         41 for my $rhs_ix ( @arity[ 0 .. $#arity - 1 ] ) {
1082 9         28 $new_rhs[$rhs_ix] = $next_exp;
1083             }
1084 9         19 last DO_ASSOCIATION;
1085             } ## end if ( $assoc eq 'R' )
1086 10 50       37 if ( $assoc eq 'G' ) {
1087 10         38 for my $rhs_ix ( @arity[ 0 .. $#arity ] ) {
1088 10         166 $new_rhs[$rhs_ix] = $parse->prioritized_symbol( $lhs, 0 );
1089             }
1090 10         28 last DO_ASSOCIATION;
1091             } ## end if ( $assoc eq 'G' )
1092 0         0 die qq{Unknown association type: "$assoc"};
1093             } ## end DO_ASSOCIATION:
1094              
1095 77         222 $parse->symbol_assign_ordinary($_, $subgrammar) for @new_rhs;
1096 77         174 $new_xs_rule{rhs} = \@new_rhs;
1097 77         189 my $wrl = $parse->xpr_create( \%new_xs_rule, $subgrammar );
1098 77         133 push @{$rules}, $wrl;
  77         258  
1099             } ## end RULE: for my $working_rule (@working_rules)
1100             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1101 19         210 return undef;
1102             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::priority_rule::evaluate
1103              
1104             sub Marpa::R3::Internal::MetaAST_Nodes::empty_rule::evaluate {
1105 96     96   252 my ( $values, $parse ) = @_;
1106             my ( $start, $length, $raw_lhs, $op_declare, $raw_adverb_list ) =
1107 96         181 @{$values};
  96         380  
1108              
1109 96 100       311 my $subgrammar = $op_declare->op() eq q{::=} ? 'g1' : 'l0';
1110              
1111 96         289 my $lhs = $raw_lhs->name($parse);
1112 96 100 66     623 $parse->{'first_lhs'} //= $lhs if $subgrammar eq 'g1';
1113 96         202 local $Marpa::R3::Internal::SUBGRAMMAR = $subgrammar;
1114              
1115 96         497 my $xrlid = xrl_create($parse, {
1116             lhs => $lhs,
1117             start => $start,
1118             length => $length,
1119             }
1120             );
1121             # description => qq{Empty rule for <$lhs>},
1122 95         515 my %rule = (
1123             lhs => $lhs,
1124             start => $start,
1125             length => $length,
1126             rhs => [],
1127             xrlid => $xrlid,
1128             );
1129 95         327 my $adverb_list = $raw_adverb_list->evaluate($parse);
1130              
1131 95         275 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
1132              
1133 95         474 my $action;
1134             my $blessing;
1135 95         0 my $naming;
1136 95         0 my $rank;
1137 95         0 my $null_ranking;
1138 95         150 ADVERB: for my $key ( keys %{$adverb_list} ) {
  95         285  
1139 30         70 my $value = $adverb_list->{$key};
1140 30 50       80 if ( $key eq 'action' ) {
1141 30         58 $action = $adverb_list->{$key};
1142 30         69 next ADVERB;
1143             }
1144 0 0       0 if ( $key eq 'bless' ) {
1145 0         0 $blessing = $adverb_list->{$key};
1146 0         0 next ADVERB;
1147             }
1148 0 0       0 if ( $key eq 'name' ) {
1149 0         0 $naming = $adverb_list->{$key};
1150 0         0 next ADVERB;
1151             }
1152 0 0       0 if ( $key eq 'null_ranking' ) {
1153 0         0 $null_ranking = $adverb_list->{$key};
1154 0         0 next ADVERB;
1155             }
1156 0 0       0 if ( $key eq 'rank' ) {
1157 0         0 $rank = $adverb_list->{$key};
1158 0         0 next ADVERB;
1159             }
1160 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1161 0         0 die qq{Adverb "$key" not allowed in an empty rule\n},
1162             ' Rule was ', $parse->substring( $start, $length ), "\n";
1163             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
1164              
1165 95   100     437 $action //= $default_adverbs->{action};
1166 95 100       265 if ( defined $action ) {
1167 64 50       430 Marpa::R3::exception(
1168             qq{actions not allowed in lexical rules (rule's LHS was "$lhs")}
1169             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
1170 64         169 $rule{action} = $action;
1171             } ## end if ( defined $action )
1172              
1173 95   33     480 $null_ranking //= $default_adverbs->{null_ranking};
1174 95 50       256 if ( defined $null_ranking ) {
1175 0 0       0 Marpa::R3::exception(
1176             qq{null-ranking not allowed in lexical rules (rule's LHS was "$lhs")}
1177             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
1178 0         0 $rule{null_ranking} = $null_ranking;
1179             } ## end if ( defined $null_ranking )
1180              
1181 95   33     427 $rank //= $default_adverbs->{rank};
1182 95 50       252 if ( defined $rank ) {
1183 0 0       0 Marpa::R3::exception(
1184             qq{ranks not allowed in lexical rules (rule's LHS was "$lhs")}
1185             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
1186 0         0 $rule{rank} = $rank;
1187             } ## end if ( defined $rank )
1188              
1189 95   33     459 $blessing //= $default_adverbs->{bless};
1190 95 50 33     296 if ( defined $blessing
1191             and ( substr $subgrammar, 0, 1 ) eq 'l' )
1192             {
1193 0         0 Marpa::R3::exception(
1194             qq{bless option not allowed in lexical rules (rule's LHS was "$lhs")}
1195             );
1196             }
1197 95         357 $parse->bless_hash_rule( \%rule, $blessing, $naming, $lhs );
1198              
1199 95         346 $parse->symbol_assign_ordinary($lhs, $subgrammar);
1200 95         276 my $wrl = $parse->xpr_create( \%rule, $subgrammar );
1201             # mask not needed
1202 95         202 push @{ $parse->{rules}->{$subgrammar} }, $wrl;
  95         296  
1203              
1204             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1205 95         466 return undef;
1206             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::empty_rule::evaluate
1207              
1208             sub Marpa::R3::Internal::MetaAST_Nodes::lexeme_rule::evaluate {
1209 89     89   232 my ( $values, $parse ) = @_;
1210 89         149 my ( $start, $length, $symbol, $unevaluated_adverb_list ) = @{$values};
  89         312  
1211              
1212 89         255 my $symbol_name = $symbol->name();
1213 89         225 my $declarations = $parse->{lexeme_declarations}->{$symbol_name};
1214 89 50       275 if ( defined $declarations ) {
1215 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1216 0         0 die "Duplicate lexeme rule for <$symbol_name>\n",
1217             " Only one lexeme rule is allowed for each symbol\n",
1218             " Location was line $line, column $column\n",
1219             ' Rule was ', $parse->substring( $start, $length ), "\n";
1220             } ## end if ( defined $declarations )
1221              
1222 89         240 my $adverb_list = $unevaluated_adverb_list->evaluate();
1223 89         197 my %declarations;
1224 89         169 ADVERB: for my $key ( keys %{$adverb_list} ) {
  89         260  
1225 143         284 my $raw_value = $adverb_list->{$key};
1226 143 50       383 if ( $key eq 'action' ) {
1227 0         0 $declarations{$key} = $raw_value;
1228 0         0 next ADVERB;
1229             }
1230 143 50       393 if ( $key eq 'blessing' ) {
1231 0         0 $declarations{$key} = $raw_value;
1232 0         0 next ADVERB;
1233             }
1234 143 100       319 if ( $key eq 'eager' ) {
1235 19 100       80 $declarations{$key} = 1 if $raw_value;
1236 19         53 next ADVERB;
1237             }
1238 124 100       268 if ( $key eq 'event' ) {
1239 61         141 $declarations{$key} = $raw_value;
1240 61         351 next ADVERB;
1241             }
1242 63 100       153 if ( $key eq 'pause' ) {
1243 61 100       135 if ( $raw_value eq 'before' ) {
1244 12         27 $declarations{$key} = -1;
1245 12         24 next ADVERB;
1246             }
1247 49 50       116 if ( $raw_value eq 'after' ) {
1248 49         94 $declarations{$key} = 1;
1249 49         128 next ADVERB;
1250             }
1251 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1252 0         0 die qq{Bad value for "pause" adverb: "$raw_value"},
1253             " Location was line $line, column $column\n",
1254             ' Rule was ', $parse->substring( $start, $length ), "\n";
1255             } ## end if ( $key eq 'pause' )
1256 2 50       6 if ( $key eq 'priority' ) {
1257 2         8 $declarations{$key} = $raw_value + 0;
1258 2         5 next ADVERB;
1259             }
1260 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1261 0         0 die qq{"$key" adverb not allowed in lexeme rule"\n},
1262             " Location was line $line, column $column\n",
1263             ' Rule was ', $parse->substring( $start, $length ), "\n";
1264             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
1265 89 50 66     464 if ( exists $declarations{'event'} and not exists $declarations{'pause'} )
1266             {
1267 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1268 0         0 die
1269             qq{"event" adverb not allowed without "pause" adverb in lexeme rule"\n},
1270             " Location was line $line, column $column\n",
1271             ' Rule was ', $parse->substring( $start, $length ), "\n";
1272             } ## end if ( exists $declarations{'event'} and not exists $declarations...)
1273 89 50 66     399 if ( exists $declarations{'pause'} and not exists $declarations{'event'} )
1274             {
1275 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1276 0         0 die
1277             qq{"pause" adverb not allowed without "event" adverb in lexeme rule"\n},
1278             qq{ Events must be named with the "event" adverb\n},
1279             " Location was line $line, column $column\n",
1280             ' Rule was ', $parse->substring( $start, $length ), "\n";
1281             } ## end if ( exists $declarations{'event'} and not exists $declarations...)
1282 89         394 $parse->{lexeme_declarations}->{$symbol_name} = \%declarations;
1283             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1284 89         256 return undef;
1285             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::lexeme_rule::evaluate
1286              
1287             sub Marpa::R3::Internal::MetaAST_Nodes::statements::evaluate {
1288 12     12   53 my ( $data, $parse ) = @_;
1289 12         21 my ( undef, undef, @statement_list ) = @{$data};
  12         26  
1290 12         24 map { $_->evaluate($parse) } @statement_list;
  22         60  
1291 12         19 return undef;
1292             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::statements::evaluate
1293              
1294             sub Marpa::R3::Internal::MetaAST_Nodes::statement::evaluate {
1295 2668     2668   4948 my ( $data, $parse ) = @_;
1296 2668         4278 my ( undef, undef, $child ) = @{$data};
  2668         5039  
1297 2668         8782 $child->evaluate($parse);
1298             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1299 2663         7398 return undef;
1300             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::statement::evaluate
1301              
1302             sub Marpa::R3::Internal::MetaAST_Nodes::null_statement::evaluate {
1303 25     25   47 return undef;
1304             }
1305              
1306             sub Marpa::R3::Internal::MetaAST_Nodes::statement_group::evaluate {
1307 12     12   30 my ( $data, $parse ) = @_;
1308 12         19 my ( undef, undef, $statements ) = @{$data};
  12         34  
1309 12         40 $statements->evaluate($parse);
1310             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1311 12         16 return undef;
1312             }
1313              
1314             sub Marpa::R3::Internal::MetaAST_Nodes::start_rule::evaluate {
1315 114     114   603 my ( $values, $parse ) = @_;
1316 114         240 my ( $start, $length, $symbol ) = @{$values};
  114         490  
1317 114 50       737 if ( defined $parse->{'start_lhs'} ) {
1318 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1319 0         0 die qq{There are two start rules\n},
1320             qq{ That is not allowed\n},
1321             ' The second start rule is ',
1322             $parse->substring( $start, $length ),
1323             "\n",
1324             " Problem occurred at line $line, column $column\n";
1325             } ## end if ( defined $parse->{'start_lhs'} )
1326 114         530 $parse->{'start_lhs'} = $symbol->name($parse);
1327             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1328 114         309 return undef;
1329             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::start_rule::evaluate
1330              
1331             sub Marpa::R3::Internal::MetaAST_Nodes::discard_rule::evaluate {
1332 196     196   535 my ( $values, $parse ) = @_;
1333 196         365 my ( $start, $length, $symbol, $raw_adverb_list ) = @{$values};
  196         696  
1334              
1335 196         469 local $Marpa::R3::Internal::SUBGRAMMAR = 'l0';
1336 196         412 my $discard_lhs = '[:discard:]';
1337 196         711 my $symbol_data = {
1338             dsl_form => $discard_lhs,
1339             name_source => 'internal',
1340             };
1341 196         674 $parse->xsy_assign( $discard_lhs, $symbol_data );
1342 196         984 $parse->symbol_names_set( $discard_lhs, 'l0', { xsy => $discard_lhs } );
1343              
1344 196         954 my $rhs = $symbol->names($parse);
1345 196         488 my $discard_symbol = $rhs->[0];
1346 196         683 my $rhs_as_event = $symbol->event_name($parse);
1347 196         592 my $adverb_list = $raw_adverb_list->evaluate($parse);
1348 196         538 my $event;
1349             my $eager;
1350 196         359 ADVERB: for my $key ( keys %{$adverb_list} ) {
  196         658  
1351 53         109 my $value = $adverb_list->{$key};
1352 53 100       156 if ( $key eq 'eager' ) {
1353 2 50       13 $eager = 1 if $value;
1354 2         6 next ADVERB;
1355             }
1356 51 50       121 if ( $key eq 'event' ) {
1357 51         78 $event = $value;
1358 51         98 next ADVERB;
1359             }
1360             Marpa::R3::exception(
1361 0         0 qq{"$key" adverb not allowed with discard rule"});
1362             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
1363              
1364 196         703 my $discard_symbol_data = $parse->discard_symbol_assign($discard_symbol);
1365 196 100       646 if ($eager) {
1366 2         7 $discard_symbol_data->{eager} = $eager;
1367             }
1368              
1369             # Discard rule
1370 196         1119 my %rule_hash = (
1371             lhs => $discard_lhs,
1372             rhs => [$discard_symbol],
1373             start => $start,
1374             length => $length,
1375             symbol_as_event => $rhs_as_event
1376             );
1377 196 100       920 $rule_hash{event} = $event if defined $event;
1378 196         677 my $wrl = $parse->xpr_create( \%rule_hash, 'l0' );
1379 196         400 push @{ $parse->{rules}->{l0} }, $wrl;
  196         648  
1380             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1381 196         783 return undef;
1382             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::discard_rule::evaluate
1383              
1384             sub Marpa::R3::Internal::MetaAST_Nodes::quantified_rule::evaluate {
1385 318     318   763 my ( $values, $parse ) = @_;
1386             my ( $start, $length, $lhs, $op_declare, $rhs, $quantifier,
1387             $proto_adverb_list )
1388 318         730 = @{$values};
  318         1096  
1389              
1390 318 100       934 my $subgrammar = $op_declare->op() eq q{::=} ? 'g1' : 'l0';
1391              
1392 318         919 my $lhs_name = $lhs->name($parse);
1393 318 100 66     1472 $parse->{'first_lhs'} //= $lhs_name if $subgrammar eq 'g1';
1394 318         643 local $Marpa::R3::Internal::SUBGRAMMAR = $subgrammar;
1395              
1396 318         912 my $quantifier_string = $quantifier->evaluate($parse);
1397 318         1530 my $xrlid = xrl_create($parse, {
1398             lhs => $lhs_name,
1399             start => $start,
1400             length => $length,
1401             }
1402             );
1403              
1404 318         958 my $adverb_list = $proto_adverb_list->evaluate($parse);
1405 318         914 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
1406              
1407             # Some properties of the sequence rule will not be altered
1408             # no matter how complicated this gets
1409 318 100       1146 my %sequence_rule = (
1410             start => $start,
1411             length => $length,
1412             xrlid => $xrlid,
1413             rhs => [ $rhs->name($parse) ],
1414             min => ( $quantifier_string eq q{+} ? 1 : 0 )
1415             );
1416              
1417 318         2149 my $action;
1418             my $blessing;
1419 318         0 my $naming;
1420 318         0 my $separator;
1421 318         0 my $proper;
1422 318         0 my $rank;
1423 318         0 my $null_ranking;
1424 318         493 ADVERB: for my $key ( keys %{$adverb_list} ) {
  318         984  
1425 71         201 my $value = $adverb_list->{$key};
1426 71 100       292 if ( $key eq 'action' ) {
1427 44         123 $action = $adverb_list->{$key};
1428 44         149 next ADVERB;
1429             }
1430 27 100       89 if ( $key eq 'bless' ) {
1431 4         22 $blessing = $adverb_list->{$key};
1432 4         12 next ADVERB;
1433             }
1434 23 50       72 if ( $key eq 'name' ) {
1435 0         0 $naming = $adverb_list->{$key};
1436 0         0 next ADVERB;
1437             }
1438 23 100       82 if ( $key eq 'proper' ) {
1439 4         21 $proper = $adverb_list->{$key};
1440 4         11 next ADVERB;
1441             }
1442 19 50       78 if ( $key eq 'rank' ) {
1443 0         0 $rank = $adverb_list->{$key};
1444 0         0 next ADVERB;
1445             }
1446 19 50       78 if ( $key eq 'null_ranking' ) {
1447 0         0 $null_ranking = $adverb_list->{$key};
1448 0         0 next ADVERB;
1449             }
1450 19 50       71 if ( $key eq 'separator' ) {
1451 19         50 $separator = $adverb_list->{$key};
1452 19         51 next ADVERB;
1453             }
1454 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1455 0         0 die qq{Adverb "$key" not allowed in quantified rule\n},
1456             ' Rule was ', $parse->substring( $start, $length ), "\n";
1457             } ## end ADVERB: for my $key ( keys %{$adverb_list} )
1458              
1459             # mask not needed
1460 318         766 $sequence_rule{lhs} = $lhs_name;
1461              
1462 318 100       896 $sequence_rule{separator} = $separator
1463             if defined $separator;
1464 318 100       807 $sequence_rule{proper} = $proper if defined $proper;
1465              
1466 318   100     1576 $action //= $default_adverbs->{action};
1467 318 100       821 if ( defined $action ) {
1468 79 50       387 Marpa::R3::exception(
1469             qq{actions not allowed in lexical rules (rule's LHS was "$lhs")}
1470             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
1471 79         258 $sequence_rule{action} = $action;
1472             } ## end if ( defined $action )
1473              
1474 318   33     1481 $null_ranking //= $default_adverbs->{null_ranking};
1475 318 50       781 if ( defined $null_ranking ) {
1476 0 0       0 Marpa::R3::exception(
1477             qq{null-ranking not allowed in lexical rules (rule's LHS was "$lhs")}
1478             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
1479 0         0 $sequence_rule{null_ranking} = $null_ranking;
1480             } ## end if ( defined $null_ranking )
1481              
1482 318   33     1426 $rank //= $default_adverbs->{rank};
1483 318 50       930 if ( defined $rank ) {
1484 0 0       0 Marpa::R3::exception(
1485             qq{ranks not allowed in lexical rules (rule's LHS was "$lhs")}
1486             ) if ( substr $subgrammar, 0, 1 ) eq 'l';
1487 0         0 $sequence_rule{rank} = $rank;
1488             } ## end if ( defined $rank )
1489              
1490 318   100     1431 $blessing //= $default_adverbs->{bless};
1491 318 50 66     1024 if ( defined $blessing and ( substr $subgrammar, 0, 1 ) eq 'l' )
1492             {
1493 0         0 Marpa::R3::exception(
1494             qq{bless option not allowed in lexical rules (rule's LHS was "$lhs")}
1495             );
1496             }
1497 318         558 $parse->symbol_assign_ordinary($_, $subgrammar) for $lhs_name, @{$sequence_rule{rhs}};
  318         1294  
1498 318 100       1090 $parse->symbol_assign_ordinary($separator, $subgrammar) if defined $separator;
1499 318         1188 $parse->bless_hash_rule( \%sequence_rule, $blessing, $naming, $lhs_name );
1500              
1501 318         971 my $wrl = $parse->xpr_create( \%sequence_rule, $subgrammar );
1502 318         635 push @{ $parse->{rules}->{$subgrammar} }, $wrl;
  318         936  
1503             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1504 318         1157 return undef;
1505              
1506             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::quantified_rule::evaluate
1507              
1508             sub Marpa::R3::Internal::MetaAST_Nodes::completion_event_declaration::evaluate
1509             {
1510 60     60   107 my ( $values, $parse ) = @_;
1511 60         83 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  60         168  
1512 60         131 my $symbol_name = $raw_symbol_name->name();
1513 60   100     258 my $completion_events = $parse->{completion_events} //= {};
1514 60 50       199 if ( defined $completion_events->{$symbol_name} ) {
1515 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1516 0         0 die qq{Completion event for symbol "$symbol_name" declared twice\n},
1517             qq{ That is not allowed\n},
1518             ' Second declaration was ', $parse->substring( $start, $length ),
1519             "\n",
1520             " Problem occurred at line $line, column $column\n";
1521             } ## end if ( defined $completion_events->{$symbol_name} )
1522 60         156 $completion_events->{$symbol_name} = $raw_event->event();
1523             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1524 60         120 return undef;
1525             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::completion_event_declaration::evaluate
1526              
1527             sub Marpa::R3::Internal::MetaAST_Nodes::nulled_event_declaration::evaluate {
1528 46     46   86 my ( $values, $parse ) = @_;
1529 46         58 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  46         133  
1530 46         86 my $symbol_name = $raw_symbol_name->name();
1531 46   100     213 my $nulled_events = $parse->{nulled_events} //= {};
1532 46 50       96 if ( defined $nulled_events->{$symbol_name} ) {
1533 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1534 0         0 die qq{nulled event for symbol "$symbol_name" declared twice\n},
1535             qq{ That is not allowed\n},
1536             ' Second declaration was ', $parse->substring( $start, $length ),
1537             "\n",
1538             " Problem occurred at line $line, column $column\n";
1539             } ## end if ( defined $nulled_events->{$symbol_name} )
1540 46         90 $nulled_events->{$symbol_name} = $raw_event->event();
1541             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1542 46         84 return undef;
1543             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::nulled_event_declaration::evaluate
1544              
1545             sub Marpa::R3::Internal::MetaAST_Nodes::prediction_event_declaration::evaluate
1546             {
1547 55     55   94 my ( $values, $parse ) = @_;
1548 55         88 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  55         145  
1549 55         117 my $symbol_name = $raw_symbol_name->name();
1550 55   100     175 my $prediction_events = $parse->{prediction_events} //= {};
1551 55 50       124 if ( defined $prediction_events->{$symbol_name} ) {
1552 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column($start);
1553 0         0 die qq{prediction event for symbol "$symbol_name" declared twice\n},
1554             qq{ That is not allowed\n},
1555             ' Second declaration was ', $parse->substring( $start, $length ),
1556             "\n",
1557             " Problem occurred at line $line, column $column\n";
1558             } ## end if ( defined $prediction_events->{$symbol_name} )
1559 55         122 $prediction_events->{$symbol_name} = $raw_event->event();
1560             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1561 55         112 return undef;
1562             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::prediction_event_declaration::evaluate
1563              
1564             sub Marpa::R3::Internal::MetaAST_Nodes::alternatives::evaluate {
1565 0     0   0 my ( $values, $parse ) = @_;
1566 0         0 return bless [ map { $_->evaluate( $_, $parse ) } @{$values} ],
  0         0  
  0         0  
1567             ref $values;
1568             }
1569              
1570             sub Marpa::R3::Internal::MetaAST_Nodes::alternative::evaluate {
1571 0     0   0 my ( $values, $parse ) = @_;
1572 0         0 my ( $start, $length, $rhs, $adverbs ) = @{$values};
  0         0  
1573 0         0 my $alternative = eval {
1574             Marpa::R3::Internal::MetaAST::Proto_Alternative->combine(
1575 0         0 map { $_->evaluate($parse) } $rhs, $adverbs );
  0         0  
1576             };
1577 0 0       0 if ( not $alternative ) {
1578 0         0 Marpa::R3::exception(
1579             $EVAL_ERROR, "\n",
1580             q{ Alternative involved was },
1581             $parse->substring( $start, $length )
1582             );
1583             } ## end if ( not $alternative )
1584 0         0 return $alternative;
1585             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::alternative::evaluate
1586              
1587             sub Marpa::R3::Internal::MetaAST_Nodes::single_symbol::names {
1588 196     196   529 my ( $values, $parse ) = @_;
1589 196         345 my ( undef, undef, $symbol ) = @{$values};
  196         489  
1590 196         658 return $symbol->names($parse);
1591             }
1592              
1593             sub Marpa::R3::Internal::MetaAST_Nodes::single_symbol::name {
1594 337     337   707 my ( $values, $parse ) = @_;
1595 337         578 my ( undef, undef, $symbol ) = @{$values};
  337         773  
1596 337         1228 return $symbol->name($parse);
1597             }
1598              
1599             sub Marpa::R3::Internal::MetaAST_Nodes::single_symbol::event_name {
1600 196     196   466 my ( $values, $parse ) = @_;
1601 196         339 my ( undef, undef, $symbol ) = @{$values};
  196         454  
1602 196         585 return $symbol->event_name($parse);
1603             }
1604              
1605             sub Marpa::R3::Internal::MetaAST_Nodes::single_symbol::literal {
1606 0     0   0 my ( $values, $parse ) = @_;
1607 0         0 my ( $start, $length ) = @{$values};
  0         0  
1608 0         0 return $parse->substring($start, $length);
1609             }
1610              
1611             sub Marpa::R3::Internal::MetaAST_Nodes::single_symbol::evaluate {
1612 2155     2155   3708 my ( $values, $parse ) = @_;
1613 2155         3004 my ( undef, undef, $symbol ) = @{$values};
  2155         3764  
1614 2155         4935 return Marpa::R3::Internal::MetaAST::Symbol_List->new(
1615             $symbol->name($parse) );
1616             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::single_symbol::evaluate
1617              
1618             sub Marpa::R3::Internal::MetaAST_Nodes::Symbol::evaluate {
1619 0     0   0 my ( $values, $parse ) = @_;
1620 0         0 my ( undef, undef, $symbol ) = @{$values};
  0         0  
1621 0         0 return $symbol->evaluate($parse);
1622             }
1623              
1624             sub Marpa::R3::Internal::MetaAST_Nodes::symbol::name {
1625 2266     2266   3797 my ( $self, $parse ) = @_;
1626 2266         5043 return $self->[2]->name($parse);
1627             }
1628              
1629             sub Marpa::R3::Internal::MetaAST_Nodes::symbol::event_name {
1630 178     178   419 my ( $self, $parse ) = @_;
1631 178         446 return $self->[2]->name($parse);
1632             }
1633              
1634             sub Marpa::R3::Internal::MetaAST_Nodes::symbol::names {
1635 178     178   424 my ( $self, $parse ) = @_;
1636 178         639 return $self->[2]->names($parse);
1637             }
1638              
1639             sub Marpa::R3::Internal::MetaAST_Nodes::symbol_name::evaluate {
1640 4637     4637   7050 my ($self) = @_;
1641 4637         10621 return $self->[2];
1642             }
1643              
1644             sub Marpa::R3::Internal::MetaAST_Nodes::symbol_name::name {
1645 4637     4637   7381 my ( $self, $parse ) = @_;
1646 4637         8593 return $self->evaluate($parse)->name($parse);
1647             }
1648              
1649             sub Marpa::R3::Internal::MetaAST_Nodes::symbol_name::names {
1650 178     178   458 my ( $self, $parse ) = @_;
1651 178         465 return [ $self->name($parse) ];
1652             }
1653              
1654             sub Marpa::R3::Internal::MetaAST_Nodes::adverb_list::evaluate {
1655 2704     2704   4844 my ( $data, $parse ) = @_;
1656 2704         3736 my ( undef, undef, $adverb_list_items ) = @{$data};
  2704         4822  
1657 2704 100       7099 return undef if not defined $adverb_list_items;
1658 821         2044 return $adverb_list_items->evaluate($parse);
1659             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::adverb_list::evaluate
1660              
1661             sub Marpa::R3::Internal::MetaAST_Nodes::null_adverb::evaluate {
1662 6     6   14 return {};
1663             }
1664              
1665             sub Marpa::R3::Internal::MetaAST_Nodes::adverb_list_items::evaluate {
1666 821     821   1535 my ( $data, $parse ) = @_;
1667 821         1205 my ( undef, undef, @raw_items ) = @{$data};
  821         1914  
1668 821         1689 my (@adverb_items) = map { $_->evaluate($parse) } @raw_items;
  941         2235  
1669 821         2296 return Marpa::R3::Internal::MetaAST::Proto_Alternative->combine(
1670             @adverb_items);
1671             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::adverb_list::evaluate
1672              
1673             sub Marpa::R3::Internal::MetaAST_Nodes::character_class::event_name {
1674 18     18   44 my ( $data, $parse ) = @_;
1675 18         64 my ( $start, $length ) = @{$data};
  18         48  
1676 18         223 return $parse->substring( $start, $length );
1677             }
1678              
1679             sub Marpa::R3::Internal::MetaAST_Nodes::character_class::names {
1680 18     18   47 my ( $self, $parse ) = @_;
1681 18         60 return [ $self->name($parse) ];
1682             }
1683              
1684             sub Marpa::R3::Internal::MetaAST_Nodes::character_class::name {
1685 447     447   946 my ( $self, $parse ) = @_;
1686 447         1229 return $self->evaluate($parse)->name($parse);
1687             }
1688              
1689             sub Marpa::R3::Internal::MetaAST_Nodes::character_class::evaluate {
1690 447     447   887 my ( $values, $parse ) = @_;
1691 447         725 my ( $start, $length, $character_class ) = @{$values};
  447         1229  
1692 447         849 my $subgrammar = $Marpa::R3::Internal::SUBGRAMMAR;
1693 447 100       1482 if ( ( substr $subgrammar, 0, 1 ) eq 'l' ) {
1694 430         1319 return Marpa::R3::Internal::MetaAST::Symbol_List->char_class_to_symbol(
1695             $parse, $character_class );
1696             }
1697              
1698             # If here, in G1
1699             # Character classes and strings always go into L0, for now
1700 17         23 my $lexer_symbol = do {
1701 17         33 local $Marpa::R3::Internal::SUBGRAMMAR = 'l0';
1702 17         50 Marpa::R3::Internal::MetaAST::Symbol_List->char_class_to_symbol( $parse,
1703             $character_class );
1704             };
1705 17         42 my $lexical_lhs = $parse->internal_lexeme($character_class);
1706 17         42 my $lexical_rhs = $lexer_symbol->names($parse);
1707 17         70 my %lexical_rule = (
1708             start => $start,
1709             length => $length,
1710             lhs => $lexical_lhs,
1711             rhs => $lexical_rhs,
1712             mask => [1],
1713             );
1714 17         45 my $wrl = $parse->xpr_create( \%lexical_rule, 'l0' );
1715 17         24 push @{ $parse->{rules}->{l0} }, $wrl;
  17         39  
1716 17         42 my $g1_symbol =
1717             Marpa::R3::Internal::MetaAST::Symbol_List->new($lexical_lhs);
1718 17         54 return $g1_symbol;
1719             }
1720              
1721             sub Marpa::R3::Internal::MetaAST_Nodes::single_quoted_string::evaluate {
1722 837     837   1966 my ( $values, $parse ) = @_;
1723 837         1331 my ( $start, $length, $string ) = @{$values};
  837         2167  
1724 837         1529 my @symbols = ();
1725              
1726 837         1832 my $end_of_string = rindex $string, q{'};
1727 837         1958 my $unmodified_string = substr $string, 0, $end_of_string+1;
1728 837         1937 my $raw_flags = substr $string, $end_of_string+1;
1729 837         2092 my $flags = Marpa::R3::Internal::MetaAST::flag_string_to_flags($raw_flags);
1730 837         1579 my $subgrammar = $Marpa::R3::Internal::SUBGRAMMAR;
1731              
1732             # If we are currently in a lexical grammar, the strings go there
1733             # If we are currently in G1, the strings always go into L0
1734 837 100       2093 my $lexical_grammar = $subgrammar eq 'g1' ? 'l0' : $subgrammar;
1735              
1736 837         3210 for my $char_class (
1737 1299         4325 map { '[' . ( quotemeta $_ ) . ']' . $flags } split //xms,
1738             substr $unmodified_string,
1739             1, -1
1740             )
1741             {
1742 1299         2271 local $Marpa::R3::Internal::SUBGRAMMAR = $lexical_grammar;
1743 1299         3162 my $symbol =
1744             Marpa::R3::Internal::MetaAST::Symbol_List->char_class_to_symbol(
1745             $parse, $char_class );
1746 1299         2861 push @symbols, $symbol;
1747             } ## end for my $char_class ( map { '[' . ( quotemeta $_ ) . ']'...})
1748 837         2233 my $list = Marpa::R3::Internal::MetaAST::Symbol_List->combine(@symbols);
1749 837 100       3194 return $list if $Marpa::R3::Internal::SUBGRAMMAR ne 'g1';
1750 331         789 my $lexical_lhs = $parse->{lexeme_for_string}->{$string};
1751 331 100       930 if (not defined $lexical_lhs) {
1752 276         841 $lexical_lhs = $parse->internal_lexeme($string);
1753 276         837 $parse->{lexeme_for_string}->{$string}= $lexical_lhs;
1754 276         659 my $lexical_rhs = $list->names($parse);
1755             my %lexical_rule = (
1756             start => $start,
1757             length => $length,
1758             lhs => $lexical_lhs,
1759             rhs => $lexical_rhs,
1760             # description => "Internal rule for single-quoted string $string",
1761 276         630 mask => [ map { ; 1 } @{$lexical_rhs} ],
  382         1811  
  276         531  
1762             );
1763 276         869 my $wrl = $parse->xpr_create( \%lexical_rule, 'l0' );
1764 276         527 push @{ $parse->{rules}->{$lexical_grammar} }, $wrl;
  276         926  
1765             }
1766 331         910 my $g1_symbol =
1767             Marpa::R3::Internal::MetaAST::Symbol_List->new($lexical_lhs);
1768 331         1552 return $g1_symbol;
1769             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::single_quoted_string::evaluate
1770              
1771             package Marpa::R3::Internal::MetaAST::Symbol_List;
1772              
1773 104     104   1188198 use English qw( -no_match_vars );
  104         326  
  104         726  
1774              
1775             sub new {
1776 4254     4254   7612 my ( $class, $name ) = @_;
1777 4254         21896 return bless { names => [ q{} . $name ], mask => [1] }, $class;
1778             }
1779              
1780             sub combine {
1781 5858     5858   10259 my ( $class, @lists ) = @_;
1782 5858         8646 my $self = {};
1783 5858         9169 $self->{names} = [ map { @{ $_->names() } } @lists ];
  7514         9404  
  7514         12319  
1784 5858         10426 $self->{mask} = [ map { @{ $_->mask() } } @lists ];
  7514         9107  
  7514         11914  
1785 5858         18057 return bless $self, $class;
1786             } ## end sub combine
1787              
1788             sub Marpa::R3::Internal::MetaAST::flag_string_to_flags {
1789 2588     2588   4173 my ($raw_flag_string) = @_;
1790 2588 100       6462 return q{} if not $raw_flag_string;
1791 36         92 my @raw_flags = split m/:/xms, $raw_flag_string;
1792 36         57 my %flags = ();
1793 36         72 RAW_FLAG: for my $raw_flag (@raw_flags) {
1794 44 100       86 next RAW_FLAG if not $raw_flag;
1795 36 100       74 if ( $raw_flag eq 'i' ) {
1796 34         56 $flags{'i'} = 1;
1797 34         62 next RAW_FLAG;
1798             }
1799 2 50       21 if ( $raw_flag eq 'ic' ) {
1800 2         9 $flags{'i'} = 1;
1801 2         6 next RAW_FLAG;
1802             }
1803             Carp::croak(
1804 0         0 qq{Bad flag for character class\n},
1805             qq{ Flag string was $raw_flag_string\n},
1806             qq{ Bad flag was $raw_flag\n}
1807             );
1808             } ## end RAW_FLAG: for my $raw_flag (@raw_flags)
1809 36         102 my $cooked_flags = join q{}, sort keys %flags;
1810 36         93 return $cooked_flags;
1811             } ## end sub flag_string_to_flags
1812              
1813             # Return the character class symbol name,
1814             # after ensuring everything is set up properly
1815             sub char_class_to_symbol {
1816 1751     1751   3618 my ( $class, $parse, $char_class ) = @_;
1817              
1818 1751         3102 my $end_of_char_class = rindex $char_class, q{]};
1819 1751         3337 my $unmodified_char_class = substr $char_class, 0, $end_of_char_class + 1;
1820 1751         2905 my $raw_flags = substr $char_class, $end_of_char_class + 1;
1821 1751         3086 my $flags = Marpa::R3::Internal::MetaAST::flag_string_to_flags($raw_flags);
1822 1751         2783 my $subgrammar = $Marpa::R3::Internal::SUBGRAMMAR;
1823              
1824             # character class symbol name always start with TWO left square brackets
1825 1751         3696 my $symbol_name = '[' . $unmodified_char_class . $flags . ']';
1826 1751   100     5019 $parse->{character_classes} //= {};
1827 1751         2664 my $cc_hash = $parse->{character_classes};
1828 1751         3399 my ( undef, $symbol ) = $cc_hash->{$symbol_name};
1829 1751 50       3492 if ( not defined $symbol ) {
1830              
1831 1751         4060 my $cc_components = [ $unmodified_char_class, $flags ];
1832              
1833 1751         3976 $symbol = Marpa::R3::Internal::MetaAST::Symbol_List->new($symbol_name);
1834 1751         5477 $cc_hash->{$symbol_name} = [ $cc_components, $symbol ];
1835              
1836             # description => "Character class: $char_class"
1837 1751         5137 my $symbol_data = {
1838             dsl_form => $char_class,
1839             name_source => 'internal',
1840             };
1841              
1842             # description => "Character class: $char_class"
1843 1751         4832 $parse->xsy_create( $symbol_name, $symbol_data );
1844 1751         4994 $symbol_data = { xsy => $symbol_name };
1845 1751         4053 $parse->symbol_names_set( $symbol_name, $subgrammar, $symbol_data );
1846             } ## end if ( not defined $symbol )
1847 1751         4620 return $symbol;
1848             } ## end sub char_class_to_symbol
1849              
1850             sub Marpa::R3::Internal::MetaAST::Parse::symbol_names_set {
1851 6481     6481   12342 my ( $parse, $symbol, $subgrammar, $args ) = @_;
1852 6481 100       13008 my $symbol_type = $subgrammar eq 'g1' ? 'g1' : 'l0';
1853 6481         10378 my $wsyid = $parse->{next_wsyid}++;
1854 6481         14639 $parse->{symbols}->{$symbol_type}->{$symbol}->{wsyid} = $wsyid;
1855 6481         8625 for my $arg_type (keys %{$args}) {
  6481         14702  
1856 6551         10070 my $value = $args->{$arg_type};
1857 6551         14004 $parse->{symbols}->{$symbol_type}->{$symbol}->{$arg_type} = $value;
1858             }
1859 6481         17161 return $parse->{symbols}->{$symbol_type}->{$symbol};
1860             }
1861              
1862             # Return the priotized symbol name,
1863             # after ensuring everything is set up properly
1864             sub Marpa::R3::Internal::MetaAST::Parse::prioritized_symbol {
1865 341     341   632 my ( $parse, $base_symbol, $priority ) = @_;
1866              
1867             # character class symbol name always start with TWO left square brackets
1868 341         794 my $symbol_name = $base_symbol . '[' . $priority . ']';
1869             my $current_symbol_data =
1870             $parse->{symbols}
1871             ->{ $Marpa::R3::Internal::SUBGRAMMAR eq 'g1' ? 'g1' : 'l0' }
1872 341 50       870 ->{$symbol_name};
1873 341 100       916 return $symbol_name if defined $current_symbol_data;
1874              
1875             # description => "<$base_symbol> at priority $priority"
1876 70         220 my $symbol_data = {
1877             dsl_form => $base_symbol,
1878             name_source => 'lexical',
1879             };
1880 70         213 $parse->xsy_assign( $base_symbol, $symbol_data );
1881 70         240 $symbol_data = {
1882             xsy => $base_symbol,
1883             precedence => $priority,
1884             };
1885 70         197 $parse->symbol_names_set( $symbol_name, $Marpa::R3::Internal::SUBGRAMMAR,
1886             $symbol_data );
1887 70         512 return $symbol_name;
1888             } ## end sub Marpa::R3::Internal::MetaAST::Parse::prioritized_symbol
1889              
1890             sub Marpa::R3::Internal::MetaAST::Parse::discard_symbol_assign {
1891 196     196   510 my ( $parse, $symbol_name ) = @_;
1892              
1893             my $current_symbol_data =
1894 196         489 $parse->{symbols}->{'l0'}->{$symbol_name};
1895 196 100       653 return $symbol_name if defined $current_symbol_data;
1896              
1897 143         498 my $symbol_data = {
1898             dsl_form => $symbol_name,
1899             name_source => 'lexical',
1900             };
1901 143         468 $parse->xsy_assign( $symbol_name, $symbol_data );
1902 143         516 $symbol_data = { xsy => $symbol_name };
1903 143         471 return $parse->symbol_names_set( $symbol_name, 'l0', $symbol_data );
1904             } ## end sub Marpa::R3::Internal::MetaAST::Parse::prioritized_symbol
1905              
1906             sub Marpa::R3::Internal::MetaAST::Parse::xsy_create {
1907 4732     4732   8370 my ( $parse, $symbol_name, $args ) = @_;
1908 4732         11734 my $xsy_data = $parse->{xsy}->{$symbol_name} = {};
1909              
1910             # Do I need to copy any more?
1911             # Can't I just use $args?
1912 4732         6722 for my $datum (keys %{$args}) {
  4732         13103  
1913 9464         14366 my $value = $args->{$datum};
1914 9464         18512 $xsy_data->{$datum} = $value;
1915             }
1916 4732         8785 return $xsy_data;
1917             }
1918              
1919             sub Marpa::R3::Internal::MetaAST::Parse::xsy_assign {
1920 3871     3871   7215 my ( $parse, $symbol_name, $args ) = @_;
1921 3871         6701 my $xsy_data = $parse->{xsy}->{$symbol_name};
1922 3871 100       7727 return $xsy_data if $xsy_data;
1923 2415         5130 return $parse->xsy_create( $symbol_name, $args );
1924             }
1925              
1926             # eXternal RuLe
1927             # At the moment, these are only for rules which can share
1928             # a LHS with a precedenced rule.
1929             sub Marpa::R3::Internal::MetaAST::xrl_create {
1930 1854     1854   3466 my ( $parse, $new_xrl ) = @_;
1931 1854         3426 my $lhs = $new_xrl->{lhs};
1932 1854         2904 my $start = $new_xrl->{start};
1933 1854         2775 my $length = $new_xrl->{length};
1934 1854   100     4835 $new_xrl->{precedence_count} //= 1;
1935 1854         8382 my $xrlid = sprintf '%s@%d+%d', $lhs, $start, $length;
1936 1854         3673 my $xrls_by_lhs = $parse->{xrls_by_lhs}->{$lhs};
1937              
1938 1854         3274 my $earlier_xrl = $xrls_by_lhs->[0];
1939 1854 100 100     5029 if ( $earlier_xrl
      100        
1940             and $earlier_xrl->{precedence_count} > 1
1941             || $new_xrl->{precedence_count} > 1 )
1942             {
1943              
1944             # If there was an earlier precedenced xrl
1945             # that needed to be unique for this LHS,
1946             # it was the only pre-existing xrl.
1947             # That's because we will never add another one, once it is on
1948             # list of XRLs by LHS.
1949             Marpa::R3::Internal::X->new(
1950             {
1951             desc => 'LHS not unique when required',
1952             xrl1 => $earlier_xrl,
1953             xrl2 => $new_xrl,
1954             to_string => sub {
1955 3     3   8 my $self = shift;
1956 3         6 my @string = ('Precedenced LHS not unique');
1957              
1958 3         8 my $pos1 = $self->{xrl1}->{start};
1959 3         7 my $len1 = $self->{xrl1}->{length};
1960             push @string,
1961             Marpa::R3::Internal::substr_as_2lines(
1962             (
1963             $self->{xrl1}->{precedence_count} > 1
1964             ? 'First precedenced rule'
1965             : 'First rule'
1966             ),
1967             $parse->{p_dsl},
1968 3 100       17 $pos1, $len1, 74
1969             );
1970              
1971 3         10 my $pos2 = $self->{xrl2}->{start};
1972 3         6 my $len2 = $self->{xrl2}->{length};
1973             push @string,
1974             Marpa::R3::Internal::substr_as_2lines(
1975             (
1976             $self->{xrl2}->{precedence_count} > 1
1977             ? 'Second precedenced rule'
1978             : 'Second rule'
1979             ),
1980             $parse->{p_dsl},
1981 3 100       16 $pos2, $len2, 74
1982             );
1983 3         7 push @string, q{};
1984              
1985 3         26 return join "\n", @string;
1986             }
1987             }
1988 3         43 )->throw();
1989             }
1990              
1991 1851         5236 my $xrl_by_id = $parse->{xrl}->{$xrlid} = $new_xrl;
1992 1851         2676 push @{ $parse->{xrls_by_lhs}->{$lhs} }, $new_xrl;
  1851         5564  
1993 1851         4552 return $xrlid;
1994             }
1995              
1996             sub Marpa::R3::Internal::MetaAST::Parse::xpr_create {
1997 4232     4232   7695 my ( $parse, $args, $subgrammar ) = @_;
1998              
1999             # The eXternal ALTernative is the argument hash,
2000             # slightly adjusted.
2001 4232   50     8094 $subgrammar //= 'g1';
2002 4232   33     16977 $args->{subgrammar} //= $subgrammar;
2003 4232   100     11935 $args->{subkey} //= 0;
2004 4232         6575 my $rule_id = join q{,}, $subgrammar, $args->{lhs}, @{$args->{rhs}};
  4232         12496  
2005 4232         8055 my $hash_by_xprid = $parse->{xpr}->{$subgrammar};
2006 4232 100       9157 if ( exists $hash_by_xprid->{$rule_id} ) {
2007 2         4 my $other_xpr = $hash_by_xprid->{$rule_id};
2008 2         5 my $pos1 = $other_xpr->{start};
2009 2         4 my $len1 = $other_xpr->{length};
2010 2         4 my $pos2 = $args->{start};
2011 2         3 my $len2 = $args->{length};
2012             my @string = (
2013             "Duplicate rules:",
2014             Marpa::R3::Internal::substr_as_2lines(
2015             'First rule', $parse->{p_dsl}, $pos1, $len1, 74
2016             ),
2017             Marpa::R3::Internal::substr_as_2lines(
2018 2         10 'Second rule', $parse->{p_dsl}, $pos2, $len2, 74
2019             )
2020             );
2021 2         166 Marpa::R3::exception( join "\n", @string, q{} );
2022             }
2023 4230         9930 $hash_by_xprid->{$rule_id} = $args;
2024              
2025             # Now create the initial working rule
2026 4230         11940 my %wrl = (
2027             xprid => $rule_id,
2028             subgrammar => $subgrammar,
2029             );
2030             # Shallow copy
2031 4230         7781 for my $field (
2032             qw(lhs action priority rank
2033             null_ranking min separator proper )
2034             )
2035             {
2036 33840 100       63820 $wrl{$field} = $args->{$field} if defined $args->{$field};
2037             }
2038             # 'rhs' needs special treatment --
2039             # a deeper code and creation of the xpr_dot field
2040             {
2041 4230         5885 my $rhs = $args->{rhs};
  4230         6456  
2042 4230         5752 my $xpr_datum = $rhs;
2043 4230         5625 my @array = @{$rhs};
  4230         10356  
2044 4230         8185 $wrl{rhs} = \@array;
2045 4230         12707 $wrl{xpr_dot} = [0 .. (scalar @array) ];
2046 4230         9784 $wrl{xpr_top} = 1;
2047             }
2048              
2049             # Return the initial working rule
2050 4230         8681 return \%wrl;
2051              
2052             }
2053              
2054             # Return the prioritized symbol name,
2055             # after ensuring everything is set up properly
2056             sub Marpa::R3::Internal::MetaAST::Parse::internal_lexeme {
2057 293     293   702 my ( $parse, $dsl_form, @grammars ) = @_;
2058              
2059             # character class symbol name always start with TWO left square brackets
2060 293         805 my $lexical_lhs_index = $parse->{lexical_lhs_index}++;
2061 293         808 my $lexical_symbol = "[Lex-$lexical_lhs_index]";
2062              
2063             # description => qq{Internal lexical symbol for "$dsl_form"}
2064 293         1021 my $symbol_data = {
2065             dsl_form => $dsl_form,
2066             name_source => 'internal'
2067             };
2068 293         937 $parse->xsy_assign( $lexical_symbol, $symbol_data );
2069 293         957 $symbol_data = { xsy => $lexical_symbol };
2070 293         950 $parse->symbol_names_set( $lexical_symbol, $_, $symbol_data ) for qw(g1 l0);
2071 293         795 return $lexical_symbol;
2072             } ## end sub Marpa::R3::Internal::MetaAST::Parse::internal_lexeme
2073              
2074             sub name {
2075 452     452   1162 my ($self) = @_;
2076 452         1035 my $names = $self->{names};
2077             Marpa::R3::exception( 'list->name() on symbol list of length ',
2078 0         0 scalar @{$names} )
2079 452 50       695 if scalar @{$names} != 1;
  452         1311  
2080 452         2247 return $self->{names}->[0];
2081             } ## end sub name
2082 9605     9605   26723 sub names { return shift->{names} }
2083 9312     9312   25398 sub mask { return shift->{mask} }
2084              
2085             sub mask_set {
2086 77     77   151 my ( $self, $mask ) = @_;
2087 77         121 return $self->{mask} = [ map {$mask} @{ $self->{mask} } ];
  95         217  
  77         155  
2088             }
2089              
2090             1;
2091              
2092             # vim: expandtab shiftwidth=4: