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   1817 use 5.010001;
  104         347  
15 104     104   614 use strict;
  104         277  
  104         2204  
16 104     104   554 use warnings;
  104         208  
  104         3420  
17              
18 104     104   642 use vars qw($VERSION $STRING_VERSION);
  104         206  
  104         7725  
19             $VERSION = '4.001_054';
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   627 use English qw( -no_match_vars );
  104         202  
  104         631  
28              
29             sub new {
30 292     292   1183 my ( $class, $p_rules_source ) = @_;
31 292         1507 my $meta_recce = Marpa::R3::Internal::meta_recce();
32 292         539 my $valuer;
33 292 100       530 eval { $meta_recce->read($p_rules_source) }
  292         1297  
34             or Marpa::R3::exception( "Parse of BNF/Scanless source failed\n",
35             $EVAL_ERROR );
36 290         3805 $valuer = Marpa::R3::Valuer->new( { recognizer => $meta_recce } );
37 290         1619 my $ambiguity_level = $valuer->ambiguity_level();
38 290 100       1069 if ( $ambiguity_level != 1 ) {
39 1         6 my $ambiguity_status = $valuer->ambiguous();
40 1         7 Marpa::R3::exception( "Parse of BNF/Scanless source failed:\n",
41             $ambiguity_status );
42             }
43 289         1364 my $value_ref = $valuer->value();
44 289 50       1115 Marpa::R3::exception('Parse of BNF/Scanless source failed')
45             if not defined $value_ref;
46 289         693 my $ast = { meta_recce => $meta_recce, top_node => ${$value_ref} };
  289         1345  
47 289         2266 return bless $ast, $class;
48             }
49              
50             sub Marpa::R3::Internal::MetaAST::Parse::substring {
51 18     18   54 my ( $parse, $start, $length ) = @_;
52 18         33 my $meta_slr = $parse->{meta_recce};
53 18         78 my ($block_id) = $meta_slr->block_progress();
54 18         70 my $string = $meta_slr->literal( $block_id, $start, $length );
55 18         37 chomp $string;
56 18         44 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 7310     7310   11413 my ( $parse, $symbol_name, $subg ) = @_;
68 7310         11194 my $wsym = $parse->{symbols}->{$subg}->{$symbol_name};
69 7310 100       14121 return $wsym if $wsym;
70             # say STDERR "symbol_assign_ordinary($symbol_name, $subg)";
71 2286         5193 my $symbol_data = {
72             dsl_form => $symbol_name,
73             name_source => 'lexical'
74             };
75 2286         5422 $parse->xsy_assign( $symbol_name, $symbol_data );
76 2286         5730 $symbol_data = { xsy => $symbol_name };
77 2286         4946 $parse->symbol_names_set( $symbol_name, $subg,
78             $symbol_data );
79             }
80              
81             sub ast_to_hash {
82 289     289   852 my ($ast, $p_dsl) = @_;
83 289         613 my $xpr_ordinal = 0;
84 289         700 my $hashed_ast = {};
85              
86 289         1326 $hashed_ast->{meta_recce} = $ast->{meta_recce};
87 289         1166 bless $hashed_ast, 'Marpa::R3::Internal::MetaAST::Parse';
88              
89 289         1480 $hashed_ast->{p_dsl} = $p_dsl;
90 289         1073 $hashed_ast->{xpr}->{l0} = {};
91 289         905 $hashed_ast->{xpr}->{g1} = {};
92 289         988 $hashed_ast->{rules}->{l0} = [];
93 289         850 $hashed_ast->{rules}->{g1} = [];
94 289         796 $hashed_ast->{lexeme_declarations} = {};
95 289         646 my $declarations = $hashed_ast->{lexeme_declarations};
96 289         1000 my $g1_symbols = $hashed_ast->{symbols}->{g1} = {};
97              
98 289         583 my ( undef, undef, @statements ) = @{ $ast->{top_node} };
  289         1407  
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 289         615 my $eval_ok = eval {
110 289         796 local $Marpa::R3::JUST_DIE = 1;
111 289         1652 $_->evaluate($hashed_ast) for @statements;
112 284         699 1;
113             };
114 289 100       1233 Marpa::R3::exception($EVAL_ERROR) if not $eval_ok;
115              
116             # Add the G1 augment rule
117             {
118 284         520 my $start_lhs = $hashed_ast->{'start_lhs'}
119 284   66     1491 // $hashed_ast->{'first_lhs'};
120 284 50       1059 Marpa::R3::exception('No rules in SLIF grammar')
121             if not defined $start_lhs;
122 284         550 my $augment_lhs = '[:start:]';
123 284         901 my $symbol_data = {
124             dsl_form => $augment_lhs,
125             name_source => 'internal',
126             };
127 284         1034 $hashed_ast->xsy_create( $augment_lhs, $symbol_data );
128 284         1216 $hashed_ast->symbol_names_set( $augment_lhs, 'g1', { xsy => $augment_lhs } );
129              
130 284         1930 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 284         978 $hashed_ast->symbol_assign_ordinary($start_lhs, 'g1');
139 284         773 my $wrl = $hashed_ast->xpr_create( $rule_data, 'g1' );
140 284         688 push @{ $hashed_ast->{rules}->{g1} }, $wrl;
  284         1462  
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 284 100       537 if ( not %{ $hashed_ast->{xpr}->{l0} } ) {
  284         1266  
148              
149             # the unicorn is a pattern which never matches
150 5         10 my $unicorn_class = '[[^\\d\\D]]';
151 5         11 my $unicorn;
152             {
153 5         9 local $Marpa::R3::Internal::SUBGRAMMAR = 'l0';
  5         11  
154 5         22 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         17 my $discard_lhs = '[:discard:]';
160 5         16 my $symbol_data = {
161             dsl_form => $discard_lhs,
162             name_source => 'internal',
163             };
164 5         16 $hashed_ast->xsy_assign( $discard_lhs, $symbol_data );
165 5         16 $hashed_ast->symbol_names_set( $discard_lhs, 'l0',
166             { xsy => $discard_lhs } );
167 5         28 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         16 my $wrl = $hashed_ast->xpr_create( $rule_data, 'l0' );
178 5         8 push @{ $hashed_ast->{rules}->{l0} }, $wrl;
  5         19  
179             }
180              
181             # Add the L0 augment rule
182 284         728 if (1) {
183             # Target symbol assumed to exist already
184 284         633 my $target_lhs = '[:target:]';
185 284 50       949 Marpa::R3::exception('No rules in SLIF L0 grammar')
186             if not defined $target_lhs;
187 284         531 my $augment_lhs = '[:lex_start:]';
188 284         887 my $symbol_data = {
189             dsl_form => $augment_lhs,
190             name_source => 'internal',
191             };
192 284         1063 $hashed_ast->xsy_create( $augment_lhs, $symbol_data );
193 284         1402 $hashed_ast->symbol_names_set( $augment_lhs, 'l0', { xsy => $augment_lhs } );
194              
195 284         1264 my $rule_data = {
196             start => 0,
197             length => 0,
198             lhs => $augment_lhs,
199             rhs => [$target_lhs],
200             };
201 284         907 $hashed_ast->symbol_assign_ordinary($target_lhs, 'l0');
202 284         776 my $wrl = $hashed_ast->xpr_create( $rule_data, 'l0' );
203 284         773 push @{ $hashed_ast->{rules}->{l0} }, $wrl;
  284         1283  
204             }
205              
206 284         681 my %l0_lhs = ();
207 284         668 my %l0_rhs = ();
208 284         537 RULE: for my $rule (values %{$hashed_ast->{xpr}->{l0}}) {
  284         1495  
209 1796         2695 my $lhs = $rule->{lhs};
210 1796         2678 $l0_lhs{$lhs} = 1;
211 1796         1996 $l0_rhs{$_} = 1 for @{$rule->{rhs}};
  1796         4408  
212 1796         2358 my $separator = $rule->{separator};
213 1796 50       3390 $l0_rhs{$separator} = 1 if $separator;
214             }
215 284         807 my %g1_lhs = ();
216 284         786 my %g1_rhs = ();
217 284         1001 RULE: for my $rule (values %{$hashed_ast->{xpr}->{g1}}) {
  284         1050  
218 1539         2464 my $lhs = $rule->{lhs};
219 1539         2114 $g1_lhs{$lhs} = 1;
220 1539         2079 $g1_rhs{$_} = 1 for @{$rule->{rhs}};
  1539         3681  
221 1539         2129 my $separator = $rule->{separator};
222 1539 100       3013 $g1_rhs{$separator} = 1 if $separator;
223             }
224              
225              
226 284         602 my %lexeme = ();
227 284         1121 $lexeme{$_} = 'a lexeme in L0' for grep { not $l0_rhs{$_} } keys %l0_lhs;
  1616         3581  
228 284         1056 $lexeme{$_} = 'a lexeme in G1' for grep { not $g1_lhs{$_} } keys %g1_rhs;
  1601         3081  
229 284         762 $lexeme{$_} = 'a declared lexeme' for keys %{$declarations};
  284         1249  
230 284         1799 LEXEME: for my $lexeme ( sort keys %lexeme ) {
231 1181 100       2649 next LEXEME if $lexeme eq '[:lex_start:]';
232 905   100     3776 $declarations->{$lexeme} //= {};
233 905 100       2309 if ( $lexeme ne '[:discard:]' ) {
234 745 100       1626 if ( not $l0_lhs{$lexeme} ) {
235 2         4 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 743 100       1676 if ( $l0_rhs{$lexeme} ) {
242 2         5 my $type = $lexeme{$lexeme};
243 2         11 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 741 100       1515 if ( $g1_lhs{$lexeme} ) {
249 2         4 my $type = $lexeme{$lexeme};
250 2         11 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 739 100 66     2423 if ( not $g1_rhs{$lexeme} and $lexeme ne '[:lex_start:]') {
256 2         5 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 897         1150 my $target_lhs = '[:target:]';
  897         1313  
266 897         2106 my $symbol_data = {
267             dsl_form => $target_lhs,
268             name_source => 'internal',
269             };
270 897         2160 $hashed_ast->xsy_assign( $target_lhs, $symbol_data );
271 897         2681 $hashed_ast->symbol_names_set( $target_lhs, 'l0',
272             { xsy => $target_lhs } );
273              
274 897         3342 my $rule_data = {
275             start => 0,
276             length => 0,
277             lhs => $target_lhs,
278             rhs => [$lexeme],
279             };
280 897         2445 $hashed_ast->symbol_assign_ordinary( $target_lhs, 'l0' );
281 897         1687 my $wrl = $hashed_ast->xpr_create( $rule_data, 'l0' );
282 897         1401 push @{ $hashed_ast->{rules}->{l0} }, $wrl;
  897         2721  
283             }
284             }
285              
286 276         711 my %stripped_character_classes = ();
287             {
288 276         747 my $character_classes = $hashed_ast->{character_classes};
  276         909  
289 276         952 for my $symbol_name ( sort keys %{$character_classes} ) {
  276         1391  
290 1319         2025 my ($re) = @{ $character_classes->{$symbol_name} };
  1319         2079  
291 1319         2348 $stripped_character_classes{$symbol_name} = $re;
292             }
293             }
294 276         1855 $hashed_ast->{character_classes} = \%stripped_character_classes;
295              
296             # say STDERR Data::Dumper::Dumper($hashed_ast);
297              
298 276         2098 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 823     823   1626 my ( $class, @hashes ) = @_;
307 823         1526 my $self = bless {}, $class;
308 823         1518 for my $hash_to_add (@hashes) {
309 943         1350 for my $key ( keys %{$hash_to_add} ) {
  943         2542  
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 937 50       2105 if exists $self->{$key};
314 937         2406 $self->{$key} = $hash_to_add->{$key};
315             } ## end for my $key ( keys %{$hash_to_add} )
316             } ## end for my $hash_to_add (@hashes)
317 823         3021 return $self;
318             } ## end sub Marpa::R3::Internal::MetaAST::Proto_Alternative::combine
319              
320             sub Marpa::R3::Internal::MetaAST::Parse::bless_hash_rule {
321 2225     2225   4384 my ( $parse, $hash_rule, $blessing, $naming, $original_lhs ) = @_;
322 2225 50       4721 return if (substr $Marpa::R3::Internal::SUBGRAMMAR, 0, 1) eq 'l0';
323              
324 2225   66     7224 $naming //= $original_lhs;
325 2225         5201 $hash_rule->{name} = $naming;
326              
327 2225 100       6284 return if not defined $blessing;
328             FIND_BLESSING: {
329 130 100       156 last FIND_BLESSING if $blessing =~ /\A [\w] /xms;
  130         518  
330 28 50       59 return if $blessing eq '::undef';
331              
332             # Rule may be half-formed, but assume we have lhs
333 28 50       43 if ( $blessing eq '::lhs' ) {
334 28         39 $blessing = $original_lhs;
335 28 50       71 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         77 $blessing =~ s/[ ]/_/gxms;
342 28         44 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         221 $hash_rule->{bless} = $blessing;
347 130         170 return 1;
348             } ## end sub Marpa::R3::Internal::MetaAST::Parse::bless_hash_rule
349              
350 4083     4083   12472 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   231 my ( $self, $parse ) = @_;
354 110         621 return $self->[2];
355             }
356              
357             sub Marpa::R3::Internal::MetaAST_Nodes::reserved_event_name::name {
358 33     33   73 my ( $self, $parse ) = @_;
359 33         81 my $name = $self->[2];
360 33         168 $name =~ s/\A : /'/xms;
361 33         166 return $name;
362             }
363              
364             sub Marpa::R3::Internal::MetaAST_Nodes::action_name::name {
365 490     490   936 my ( $self, $parse ) = @_;
366 490         1613 return $self->[2]->name($parse);
367             }
368              
369             sub Marpa::R3::Internal::MetaAST_Nodes::alternative_name::name {
370 10     10   26 my ( $self, $parse ) = @_;
371 10         36 return $self->[2]->name($parse);
372             }
373              
374             sub Marpa::R3::Internal::MetaAST_Nodes::event_name::name {
375 300     300   619 my ( $self, $parse ) = @_;
376 300         703 return $self->[2]->name($parse);
377             }
378              
379             sub Marpa::R3::Internal::MetaAST_Nodes::array_descriptor::name {
380 119     119   580 return $_[0]->[2];
381             }
382              
383             sub Marpa::R3::Internal::MetaAST_Nodes::reserved_blessing_name::name {
384 17     17   119 return $_[0]->[2];
385             }
386              
387             sub Marpa::R3::Internal::MetaAST_Nodes::blessing_name::name {
388 119     119   167 my ( $self, $parse ) = @_;
389 119         287 return $self->[2]->name($parse);
390             }
391              
392             sub Marpa::R3::Internal::MetaAST_Nodes::standard_name::name {
393 163     163   519 return $_[0]->[2];
394             }
395              
396             sub Marpa::R3::Internal::MetaAST_Nodes::Perl_name::name {
397 261     261   1224 return $_[0]->[2];
398             }
399              
400             sub Marpa::R3::Internal::MetaAST_Nodes::lhs::name {
401 1866     1866   3105 my ( $values, $parse ) = @_;
402 1866         2346 my ( undef, undef, $symbol ) = @{$values};
  1866         3191  
403 1866         3798 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 322     322   573 my ($data) = @_;
414 322         926 return $data->[2];
415             }
416              
417             sub Marpa::R3::Internal::MetaAST_Nodes::op_declare::op {
418 1866     1866   2804 my ($values) = @_;
419 1866         4632 return $values->[2]->op();
420             }
421              
422             sub Marpa::R3::Internal::MetaAST_Nodes::op_declare_match::op {
423 910     910   1543 my ($values) = @_;
424 910         2989 return $values->[2];
425             }
426              
427             sub Marpa::R3::Internal::MetaAST_Nodes::op_declare_bnf::op {
428 1095     1095   1848 my ($values) = @_;
429 1095         4075 return $values->[2];
430             }
431              
432             sub Marpa::R3::Internal::MetaAST_Nodes::bracketed_name::name {
433 581     581   889 my ($values) = @_;
434 581         737 my ( undef, undef, $bracketed_name ) = @{$values};
  581         1065  
435              
436             # normalize whitespace
437 581         2414 $bracketed_name =~ s/\A [<] \s*//xms;
438 581         2452 $bracketed_name =~ s/ \s* [>] \z//xms;
439 581         1562 $bracketed_name =~ s/ \s+ / /gxms;
440 581         1551 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   311 my ($values) = @_;
445 216         321 my ( undef, undef, $single_quoted_name ) = @{$values};
  216         431  
446              
447             # normalize whitespace
448 216         693 $single_quoted_name =~ s/\A ['] \s*//xms;
449 216         615 $single_quoted_name =~ s/ \s* ['] \z//xms;
450 216         446 $single_quoted_name =~ s/ \s+ / /gxms;
451 216         503 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   122 my ( $data, $parse ) = @_;
457 77         108 my ( undef, undef, @values ) = @{$data};
  77         210  
458 77         134 my @symbol_lists = map { $_->evaluate($parse); } @values;
  77         154  
459 77         165 my $flattened_list =
460             Marpa::R3::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
461 77         194 $flattened_list->mask_set(0);
462 77         269 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 1808     1808   2739 my ( $data, $parse ) = @_;
467 1808         2336 my ( $start, $length, @values ) = @{$data};
  1808         3785  
468 1808         2630 my $rhs = eval {
469 1808         2735 my @symbol_lists = map { $_->evaluate($parse) } @values;
  2991         5296  
470 1808         3584 my $flattened_list =
471             Marpa::R3::Internal::MetaAST::Symbol_List->combine(@symbol_lists);
472 1808         3230 bless {
473             rhs => $flattened_list->names($parse),
474             mask => $flattened_list->mask()
475             },
476             $PROTO_ALTERNATIVE;
477             };
478 1808 50       4483 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 1808         3322 return $rhs;
488             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::rhs::evaluate
489              
490             sub Marpa::R3::Internal::MetaAST_Nodes::rhs_primary::evaluate {
491 3086     3086   5010 my ( $data, $parse ) = @_;
492 3086         3996 my ( undef, undef, @values ) = @{$data};
  3086         5500  
493 3086         4225 my @symbol_lists = map { $_->evaluate($parse) } @values;
  3086         5971  
494 3086         6455 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   129 my ( $data, $parse ) = @_;
499 77         96 my ( undef, undef, @values ) = @{$data};
  77         159  
500 77         115 my @symbol_lists = map { $_->evaluate($parse) } @values;
  95         218  
501 77         157 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 490     490   977 my ( $values, $parse ) = @_;
506 490         704 my ( undef, undef, $child ) = @{$values};
  490         1057  
507 490         1480 return bless { action => $child->name($parse) }, $PROTO_ALTERNATIVE;
508             }
509              
510             sub Marpa::R3::Internal::MetaAST_Nodes::blessing::evaluate {
511 119     119   167 my ( $values, $parse ) = @_;
512 119         135 my ( undef, undef, $child ) = @{$values};
  119         198  
513 119         240 return bless { bless => $child->name($parse) }, $PROTO_ALTERNATIVE;
514             }
515              
516             sub Marpa::R3::Internal::MetaAST_Nodes::naming::evaluate {
517 10     10   17 my ( $values, $parse ) = @_;
518 10         13 my ( undef, undef, $child ) = @{$values};
  10         26  
519 10         30 return bless { name => $child->name($parse) }, $PROTO_ALTERNATIVE;
520             }
521              
522             sub Marpa::R3::Internal::MetaAST_Nodes::right_association::evaluate {
523 9     9   22 my ($values) = @_;
524 9         26 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   32 my ($values) = @_;
534 10         44 return bless { assoc => 'G' }, $PROTO_ALTERNATIVE;
535             }
536              
537             sub Marpa::R3::Internal::MetaAST_Nodes::eager_specification::evaluate {
538 21     21   46 my ($values) = @_;
539 21         51 my $child = $values->[2];
540 21         66 return bless { eager => $child->value() }, $PROTO_ALTERNATIVE;
541             }
542              
543             sub Marpa::R3::Internal::MetaAST_Nodes::event_specification::evaluate {
544 139     139   245 my ($values) = @_;
545 139         419 return bless { event => ( $values->[2]->event() ) }, $PROTO_ALTERNATIVE;
546             }
547              
548             sub Marpa::R3::Internal::MetaAST_Nodes::event_initialization::event {
549 300     300   552 my ($values) = @_;
550 300         504 my $event_name = $values->[2];
551 300         474 my $event_initializer = $values->[3];
552 300         624 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   10 my ($values) = @_;
557 4         162 my $child = $values->[2];
558 4         20 return bless { proper => $child->value() }, $PROTO_ALTERNATIVE;
559             }
560              
561             sub Marpa::R3::Internal::MetaAST_Nodes::pause_specification::evaluate {
562 61     61   135 my ($values) = @_;
563 61         181 my $child = $values->[2];
564 61         211 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         6 my $child = $values->[2];
570 2         9 return bless { priority => $child->value() }, $PROTO_ALTERNATIVE;
571             }
572              
573             sub Marpa::R3::Internal::MetaAST_Nodes::rank_specification::evaluate {
574 51     51   84 my ($values) = @_;
575 51         100 my $child = $values->[2];
576 51         112 return bless { rank => $child->value() }, $PROTO_ALTERNATIVE;
577             }
578              
579             sub Marpa::R3::Internal::MetaAST_Nodes::null_ranking_specification::evaluate {
580 2     2   4 my ($values) = @_;
581 2         7 my $child = $values->[2];
582 2         8 return bless { null_ranking => $child->value() }, $PROTO_ALTERNATIVE;
583             }
584              
585             sub Marpa::R3::Internal::MetaAST_Nodes::null_ranking_constant::value {
586 2     2   8 return $_[0]->[2];
587             }
588              
589             sub Marpa::R3::Internal::MetaAST_Nodes::before_or_after::value {
590 61     61   356 return $_[0]->[2];
591             }
592              
593             sub Marpa::R3::Internal::MetaAST_Nodes::event_initializer::on_or_off
594             {
595 300     300   548 my ($values) = @_;
596 300         377 my (undef, undef, $is_activated) = @{$values};
  300         547  
597 300 100       967 return 1 if not defined $is_activated;
598 105         175 my (undef, undef, $on_or_off) = @{$is_activated};
  105         191  
599 105 100       438 return $on_or_off eq 'on' ? 1 : 0;
600             }
601              
602             sub Marpa::R3::Internal::MetaAST_Nodes::boolean::value {
603 25     25   122 return $_[0]->[2];
604             }
605              
606             sub Marpa::R3::Internal::MetaAST_Nodes::signed_integer::value {
607 53     53   182 return $_[0]->[2];
608             }
609              
610             sub Marpa::R3::Internal::MetaAST_Nodes::separator_specification::evaluate {
611 19     19   46 my ( $values, $parse ) = @_;
612 19         76 my $child = $values->[2];
613 19         82 return bless { separator => $child->name($parse) }, $PROTO_ALTERNATIVE;
614             }
615              
616             sub Marpa::R3::Internal::MetaAST_Nodes::adverb_item::evaluate {
617 943     943   1547 my ( $values, $parse ) = @_;
618 943         3148 my $child = $values->[2]->evaluate($parse);
619 943         2588 return bless $child, $PROTO_ALTERNATIVE;
620             }
621              
622             sub Marpa::R3::Internal::MetaAST_Nodes::default_rule::evaluate {
623 139     139   366 my ( $values, $parse ) = @_;
624 139         260 my ( $start, $length, undef, $op_declare, $raw_adverb_list ) = @{$values};
  139         631  
625 139 50       653 my $subgrammar = $op_declare->op() eq q{::=} ? 'g1' : 'l0';
626 139         605 my $adverb_list = $raw_adverb_list->evaluate($parse);
627              
628             # A default rule clears the previous default
629 139         375 my %default_adverbs = ();
630 139         534 $parse->{default_adverbs}->{$subgrammar} = \%default_adverbs;
631              
632 139         285 ADVERB: for my $key ( keys %{$adverb_list} ) {
  139         421  
633 150         386 my $value = $adverb_list->{$key};
634 150 100 66     979 if ( $key eq 'action' and $subgrammar eq 'g1' ) {
635 139         361 $default_adverbs{$key} = $adverb_list->{$key};
636 139         426 next ADVERB;
637             }
638 11 50 33     86 if ( $key eq 'bless' and $subgrammar eq 'g1' ) {
639 11         32 $default_adverbs{$key} = $adverb_list->{$key};
640 11         25 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 139         406 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   60 my ( $data, $parse ) = @_;
651 27         49 my ( $start, $length, $raw_adverb_list ) = @{$data};
  27         73  
652 27         66 local $Marpa::R3::Internal::SUBGRAMMAR = 'g1';
653              
654 27         78 my $adverb_list = $raw_adverb_list->evaluate($parse);
655 27 50       92 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         106 $parse->{discard_default_adverbs} = {};
664 27         53 ADVERB: for my $key ( keys %{$adverb_list} ) {
  27         75  
665 27         62 my $value = $adverb_list->{$key};
666 27 50 33     134 if ( $key eq 'event' and defined $value ) {
667 27         66 $parse->{discard_default_adverbs}->{$key} = $value;
668 27         51 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         104 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 44     44   123 my ( $data, $parse ) = @_;
679 44         77 my ( $start, $length, $raw_adverb_list ) = @{$data};
  44         155  
680 44         125 local $Marpa::R3::Internal::SUBGRAMMAR = 'g1';
681              
682 44         117 my $adverb_list = $raw_adverb_list->evaluate($parse);
683 44 50       203 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 44         169 $parse->{lexeme_default_adverbs} = {};
692 44         96 ADVERB: for my $key ( keys %{$adverb_list} ) {
  44         132  
693 50         100 my $value = $adverb_list->{$key};
694 50 100       167 if ( $key eq 'action' ) {
695 44         113 $parse->{lexeme_default_adverbs}->{$key} = $value;
696 44         103 next ADVERB;
697             }
698 6 50       20 if ( $key eq 'bless' ) {
699 6         15 $parse->{lexeme_default_adverbs}->{$key} = $value;
700 6         13 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 44         124 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   24 my ( $data, $parse ) = @_;
711 9         29 my ( $start, $length, $inaccessible_treatment ) = @{$data};
  9         57  
712 9         31 local $Marpa::R3::Internal::SUBGRAMMAR = 'g1';
713              
714 9 50       49 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         38 $parse->{defaults}->{if_inaccessible} = $inaccessible_treatment->value();
723 9         23 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 1448     1448   2387 my ( $values, $parse ) = @_;
732             my ( $start, $length, $raw_lhs, $op_declare, $raw_priorities ) =
733 1448         1768 @{$values};
  1448         3462  
734              
735 1448 100       3274 my $subgrammar = $op_declare->op() eq q{::=} ? 'g1' : 'l0';
736 1448         2446 my $xpr_ordinal = 0;
737              
738 1448         3029 my $lhs = $raw_lhs->name($parse);
739 1448 100 66     5017 $parse->{'first_lhs'} //= $lhs if $subgrammar eq 'g1';
740 1448         2243 local $Marpa::R3::Internal::SUBGRAMMAR = $subgrammar;
741              
742 1448         1872 my ( undef, undef, @priorities ) = @{$raw_priorities};
  1448         2634  
743 1448         2160 my $priority_count = scalar @priorities;
744 1448         2064 my @working_rules = ();
745              
746 1448   50     3401 $parse->{rules}->{$subgrammar} //= [];
747 1448         2433 my $rules = $parse->{rules}->{$subgrammar};
748              
749 1448         2438 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
750              
751 1448         5742 my $xrlid = xrl_create($parse, {
752             lhs => $lhs,
753             start => $start,
754             length => $length,
755             precedence_count => $priority_count,
756             }
757             );
758 1446 100       3189 if ( $priority_count <= 1 ) {
759             ## If there is only one priority
760 1427         1831 my ( undef, undef, @alternatives ) = @{ $priorities[0] };
  1427         2966  
761              
762 1427         3860 for my $alternative_ix (0 .. $#alternatives) {
763             my ($alternative_start, $alternative_length,
764             $raw_rhs, $raw_adverb_list
765 1703         2349 ) = @{$alternatives[$alternative_ix]};
  1703         4008  
766 1703         2527 my ( $proto_rule, $adverb_list );
767 1703         2338 my $eval_ok = eval {
768 1703         3899 $proto_rule = $raw_rhs->evaluate($parse);
769 1703         3539 $adverb_list = $raw_adverb_list->evaluate($parse);
770 1703         2937 1;
771             };
772 1703 50       3241 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 1703         2245 my @rhs_names = @{ $proto_rule->{rhs} };
  1703         3929  
784 1703         2375 my @mask = @{ $proto_rule->{mask} };
  1703         3337  
785 1703 50 66     5138 if ( ( substr $subgrammar, 0, 1 ) eq 'l'
786 1388         3821 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 1703         4972 $parse->symbol_assign_ordinary($_, $subgrammar) for $lhs, @rhs_names;
793 1703 100       9305 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 1703         6021 my $action;
804             my $blessing;
805 1703         0 my $naming;
806 1703         0 my $null_ranking;
807 1703         0 my $rank;
808 1703         2026 ADVERB: for my $key ( keys %{$adverb_list} ) {
  1703         3623  
809 315         519 my $value = $adverb_list->{$key};
810 315 100       730 if ( $key eq 'action' ) {
811 204         429 $action = $adverb_list->{$key};
812 204         466 next ADVERB;
813             }
814 111 50       219 if ( $key eq 'assoc' ) {
815              
816             # OK, but ignored
817 0         0 next ADVERB;
818             }
819 111 100       270 if ( $key eq 'bless' ) {
820 48         68 $blessing = $adverb_list->{$key};
821 48         75 next ADVERB;
822             }
823 63 100       126 if ( $key eq 'name' ) {
824 10         20 $naming = $adverb_list->{$key};
825 10         21 next ADVERB;
826             }
827 53 100       106 if ( $key eq 'null_ranking' ) {
828 2         4 $null_ranking = $adverb_list->{$key};
829 2         5 next ADVERB;
830             }
831 51 50       100 if ( $key eq 'rank' ) {
832 51         87 $rank = $adverb_list->{$key};
833 51         86 next ADVERB;
834             }
835             my ( $line, $column ) =
836 0         0 $parse->{meta_recce}->line_column(undef, $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 1703   100     6452 $action //= $default_adverbs->{action};
842 1703 100       3136 if ( defined $action ) {
843 545 50       1290 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 545         1456 $hash_rule{action} = $action;
847             } ## end if ( defined $action )
848              
849 1703   66     5506 $rank //= $default_adverbs->{rank};
850 1703 100       2986 if ( defined $rank ) {
851 51 50       108 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         112 $hash_rule{rank} = $rank;
855             } ## end if ( defined $rank )
856              
857 1703   66     6277 $null_ranking //= $default_adverbs->{null_ranking};
858 1703 100       2955 if ( defined $null_ranking ) {
859 2 50       6 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         5 $hash_rule{null_ranking} = $null_ranking;
863             } ## end if ( defined $rank )
864              
865 1703   100     5082 $blessing //= $default_adverbs->{bless};
866 1703 50 66     3641 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 1703         4630 $parse->bless_hash_rule( \%hash_rule, $blessing, $naming, $lhs );
878              
879 1703         4606 my $wrl = $parse->xpr_create( \%hash_rule, $subgrammar );
880 1701         2200 push @{$rules}, $wrl;
  1701         7137  
881             } ## end for my $alternative (@alternatives)
882             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
883 1425         4074 return undef;
884             } ## end if ( $priority_count <= 1 )
885              
886 19         70 for my $priority_ix ( 0 .. $priority_count - 1 ) {
887 70         126 my $priority = $priority_count - ( $priority_ix + 1 );
888 70         97 my ( undef, undef, @alternatives ) = @{ $priorities[$priority_ix] };
  70         169  
889 70         120 for my $alternative (@alternatives) {
890             my ($alternative_start, $alternative_length,
891             $raw_rhs, $raw_adverb_list
892 105         135 ) = @{$alternative};
  105         217  
893 105         153 my ( $adverb_list, $rhs );
894 105         140 my $eval_ok = eval {
895 105         190 $adverb_list = $raw_adverb_list->evaluate($parse);
896 105         215 $rhs = $raw_rhs->evaluate($parse);
897 105         158 1;
898             };
899 105 50       190 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         319 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         44 my @arg0_action = ();
916 19 50       86 @arg0_action = ( action => '::first' ) if $subgrammar eq 'g1';
917              
918             # Internal rule top priority rule for <$lhs>
919 19         68 $parse->symbol_assign_ordinary($lhs, $subgrammar);
920 19         88 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         126 for 1 .. $priority_count - 1;
944 19         70 RULE: for my $priority_rule (@priority_rules) {
945 70         135 my $wrl = $parse->xpr_create( $priority_rule, $subgrammar );
946 70         102 push @{$rules}, $wrl;
  70         133  
947             }
948              
949 19         62 RULE: for my $working_rule (@working_rules) {
950 105         129 my ( $priority, $rhs, $adverb_list, $alternative_start, $alternative_length ) = @{$working_rule};
  105         194  
951 105         138 my @new_rhs = @{ $rhs->{rhs} };
  105         223  
952 105         214 my @arity = grep { $new_rhs[$_] eq $lhs } 0 .. $#new_rhs;
  262         621  
953 105         154 my $rhs_length = scalar @new_rhs;
954              
955 105         577 my $current_exp = $parse->prioritized_symbol( $lhs, $priority );
956 105         149 my @mask = @{ $rhs->{mask} };
  105         719  
957 105 50 33     306 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         352 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         190 $new_xs_rule{mask} = \@mask;
972              
973 105         380 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         122 ADVERB: for my $key ( keys %{$adverb_list} ) {
  105         265  
980 98         156 my $value = $adverb_list->{$key};
981 98 100       344 if ( $key eq 'action' ) {
982 29         40 $action = $adverb_list->{$key};
983 29         51 next ADVERB;
984             }
985 69 100       117 if ( $key eq 'assoc' ) {
986 19         29 $assoc = $adverb_list->{$key};
987 19         37 next ADVERB;
988             }
989 50 50       96 if ( $key eq 'bless' ) {
990 50         63 $blessing = $adverb_list->{$key};
991 50         289 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(undef, $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     359 $assoc //= 'L';
1011              
1012 105   100     667 $action //= $default_adverbs->{action};
1013 105 100       240 if ( defined $action ) {
1014 99 50       204 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         156 $new_xs_rule{action} = $action;
1018             } ## end if ( defined $action )
1019              
1020 105   33     355 $null_ranking //= $default_adverbs->{null_ranking};
1021 105 50       170 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     355 $rank //= $default_adverbs->{rank};
1029 105 50       184 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     258 $blessing //= $default_adverbs->{bless};
1037 105 50 66     270 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         268 $parse->bless_hash_rule( \%new_xs_rule, $blessing, $naming, $lhs );
1047              
1048 105         156 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       192 $next_priority = 0 if $next_priority >= $priority_count;
1055              
1056 105         183 my $next_exp = $parse->prioritized_symbol( $lhs, $next_priority);
1057 105         273 $new_xs_rule{precedence} = $priority;
1058              
1059 105 100       212 if ( not scalar @arity ) {
1060 28         56 $new_xs_rule{rhs} = \@new_rhs;
1061 28         99 $parse->symbol_assign_ordinary($_, $subgrammar) for @new_rhs;
1062 28         86 my $wrl = $parse->xpr_create( \%new_xs_rule, $subgrammar );
1063 28         211 push @{$rules}, $wrl;
  28         73  
1064 28         97 next RULE;
1065             }
1066              
1067 77 100       156 if ( scalar @arity == 1 ) {
1068 15 50       43 die 'Unnecessary unit rule in priority rule' if $rhs_length == 1;
1069 15         30 $new_rhs[ $arity[0] ] = $current_exp;
1070             }
1071             DO_ASSOCIATION: {
1072 77 100       97 if ( $assoc eq 'L' ) {
  77         151  
1073 58         101 $new_rhs[ $arity[0] ] = $current_exp;
1074 58         119 for my $rhs_ix ( @arity[ 1 .. $#arity ] ) {
1075 53         271 $new_rhs[$rhs_ix] = $next_exp;
1076             }
1077 58         90 last DO_ASSOCIATION;
1078             } ## end if ( $assoc eq 'L' )
1079 19 100       47 if ( $assoc eq 'R' ) {
1080 9         20 $new_rhs[ $arity[-1] ] = $current_exp;
1081 9         28 for my $rhs_ix ( @arity[ 0 .. $#arity - 1 ] ) {
1082 9         23 $new_rhs[$rhs_ix] = $next_exp;
1083             }
1084 9         26 last DO_ASSOCIATION;
1085             } ## end if ( $assoc eq 'R' )
1086 10 50       36 if ( $assoc eq 'G' ) {
1087 10         30 for my $rhs_ix ( @arity[ 0 .. $#arity ] ) {
1088 10         132 $new_rhs[$rhs_ix] = $parse->prioritized_symbol( $lhs, 0 );
1089             }
1090 10         26 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         177 $parse->symbol_assign_ordinary($_, $subgrammar) for @new_rhs;
1096 77         126 $new_xs_rule{rhs} = \@new_rhs;
1097 77         150 my $wrl = $parse->xpr_create( \%new_xs_rule, $subgrammar );
1098 77         93 push @{$rules}, $wrl;
  77         224  
1099             } ## end RULE: for my $working_rule (@working_rules)
1100             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1101 19         201 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   234 my ( $values, $parse ) = @_;
1106             my ( $start, $length, $raw_lhs, $op_declare, $raw_adverb_list ) =
1107 96         186 @{$values};
  96         346  
1108              
1109 96 100       261 my $subgrammar = $op_declare->op() eq q{::=} ? 'g1' : 'l0';
1110              
1111 96         288 my $lhs = $raw_lhs->name($parse);
1112 96 100 66     500 $parse->{'first_lhs'} //= $lhs if $subgrammar eq 'g1';
1113 96         210 local $Marpa::R3::Internal::SUBGRAMMAR = $subgrammar;
1114              
1115 96         533 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         446 my %rule = (
1123             lhs => $lhs,
1124             start => $start,
1125             length => $length,
1126             rhs => [],
1127             xrlid => $xrlid,
1128             );
1129 95         275 my $adverb_list = $raw_adverb_list->evaluate($parse);
1130              
1131 95         230 my $default_adverbs = $parse->{default_adverbs}->{$subgrammar};
1132              
1133 95         406 my $action;
1134             my $blessing;
1135 95         0 my $naming;
1136 95         0 my $rank;
1137 95         0 my $null_ranking;
1138 95         142 ADVERB: for my $key ( keys %{$adverb_list} ) {
  95         255  
1139 30         54 my $value = $adverb_list->{$key};
1140 30 50       85 if ( $key eq 'action' ) {
1141 30         49 $action = $adverb_list->{$key};
1142 30         64 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(undef, $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     580 $action //= $default_adverbs->{action};
1166 95 100       249 if ( defined $action ) {
1167 64 50       398 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         130 $rule{action} = $action;
1171             } ## end if ( defined $action )
1172              
1173 95   33     453 $null_ranking //= $default_adverbs->{null_ranking};
1174 95 50       233 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     459 $rank //= $default_adverbs->{rank};
1182 95 50       242 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     441 $blessing //= $default_adverbs->{bless};
1190 95 50 33     271 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         329 $parse->bless_hash_rule( \%rule, $blessing, $naming, $lhs );
1198              
1199 95         325 $parse->symbol_assign_ordinary($lhs, $subgrammar);
1200 95         256 my $wrl = $parse->xpr_create( \%rule, $subgrammar );
1201             # mask not needed
1202 95         177 push @{ $parse->{rules}->{$subgrammar} }, $wrl;
  95         260  
1203              
1204             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1205 95         383 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   197 my ( $values, $parse ) = @_;
1210 89         144 my ( $start, $length, $symbol, $unevaluated_adverb_list ) = @{$values};
  89         384  
1211              
1212 89         275 my $symbol_name = $symbol->name();
1213 89         196 my $declarations = $parse->{lexeme_declarations}->{$symbol_name};
1214 89 50       519 if ( defined $declarations ) {
1215 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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         228 my $adverb_list = $unevaluated_adverb_list->evaluate();
1223 89         178 my %declarations;
1224 89         128 ADVERB: for my $key ( keys %{$adverb_list} ) {
  89         230  
1225 143         288 my $raw_value = $adverb_list->{$key};
1226 143 50       377 if ( $key eq 'action' ) {
1227 0         0 $declarations{$key} = $raw_value;
1228 0         0 next ADVERB;
1229             }
1230 143 50       372 if ( $key eq 'blessing' ) {
1231 0         0 $declarations{$key} = $raw_value;
1232 0         0 next ADVERB;
1233             }
1234 143 100       463 if ( $key eq 'eager' ) {
1235 19 100       62 $declarations{$key} = 1 if $raw_value;
1236 19         46 next ADVERB;
1237             }
1238 124 100       265 if ( $key eq 'event' ) {
1239 61         109 $declarations{$key} = $raw_value;
1240 61         306 next ADVERB;
1241             }
1242 63 100       145 if ( $key eq 'pause' ) {
1243 61 100       173 if ( $raw_value eq 'before' ) {
1244 12         19 $declarations{$key} = -1;
1245 12         23 next ADVERB;
1246             }
1247 49 50       116 if ( $raw_value eq 'after' ) {
1248 49         229 $declarations{$key} = 1;
1249 49         111 next ADVERB;
1250             }
1251 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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       5 if ( $key eq 'priority' ) {
1257 2         6 $declarations{$key} = $raw_value + 0;
1258 2         5 next ADVERB;
1259             }
1260 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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     427 if ( exists $declarations{'event'} and not exists $declarations{'pause'} )
1266             {
1267 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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     334 if ( exists $declarations{'pause'} and not exists $declarations{'event'} )
1274             {
1275 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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         438 $parse->{lexeme_declarations}->{$symbol_name} = \%declarations;
1283             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1284 89         288 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   20 my ( $data, $parse ) = @_;
1289 12         20 my ( undef, undef, @statement_list ) = @{$data};
  12         22  
1290 12         17 map { $_->evaluate($parse) } @statement_list;
  22         50  
1291 12         21 return undef;
1292             } ## end sub Marpa::R3::Internal::MetaAST_Nodes::statements::evaluate
1293              
1294             sub Marpa::R3::Internal::MetaAST_Nodes::statement::evaluate {
1295 2683     2683   4383 my ( $data, $parse ) = @_;
1296 2683         3693 my ( undef, undef, $child ) = @{$data};
  2683         5110  
1297 2683         7640 $child->evaluate($parse);
1298             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1299 2678         6402 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   46 return undef;
1304             }
1305              
1306             sub Marpa::R3::Internal::MetaAST_Nodes::statement_group::evaluate {
1307 12     12   25 my ( $data, $parse ) = @_;
1308 12         16 my ( undef, undef, $statements ) = @{$data};
  12         32  
1309 12         36 $statements->evaluate($parse);
1310             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1311 12         15 return undef;
1312             }
1313              
1314             sub Marpa::R3::Internal::MetaAST_Nodes::start_rule::evaluate {
1315 114     114   513 my ( $values, $parse ) = @_;
1316 114         209 my ( $start, $length, $symbol ) = @{$values};
  114         733  
1317 114 50       687 if ( defined $parse->{'start_lhs'} ) {
1318 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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         526 $parse->{'start_lhs'} = $symbol->name($parse);
1327             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1328 114         283 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 197     197   478 my ( $values, $parse ) = @_;
1333 197         359 my ( $start, $length, $symbol, $raw_adverb_list ) = @{$values};
  197         625  
1334              
1335 197         435 local $Marpa::R3::Internal::SUBGRAMMAR = 'l0';
1336 197         362 my $discard_lhs = '[:discard:]';
1337 197         666 my $symbol_data = {
1338             dsl_form => $discard_lhs,
1339             name_source => 'internal',
1340             };
1341 197         672 $parse->xsy_assign( $discard_lhs, $symbol_data );
1342 197         751 $parse->symbol_names_set( $discard_lhs, 'l0', { xsy => $discard_lhs } );
1343              
1344 197         765 my $rhs = $symbol->names($parse);
1345 197         410 my $discard_symbol = $rhs->[0];
1346 197         604 my $rhs_as_event = $symbol->event_name($parse);
1347 197         501 my $adverb_list = $raw_adverb_list->evaluate($parse);
1348 197         424 my $event;
1349             my $eager;
1350 197         351 ADVERB: for my $key ( keys %{$adverb_list} ) {
  197         561  
1351 53         88 my $value = $adverb_list->{$key};
1352 53 100       118 if ( $key eq 'eager' ) {
1353 2 50       7 $eager = 1 if $value;
1354 2         5 next ADVERB;
1355             }
1356 51 50       138 if ( $key eq 'event' ) {
1357 51         77 $event = $value;
1358 51         104 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 197         659 my $discard_symbol_data = $parse->discard_symbol_assign($discard_symbol);
1365 197 100       546 if ($eager) {
1366 2         5 $discard_symbol_data->{eager} = $eager;
1367             }
1368              
1369             # Discard rule
1370 197         1094 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 197 100       877 $rule_hash{event} = $event if defined $event;
1378 197         587 my $wrl = $parse->xpr_create( \%rule_hash, 'l0' );
1379 197         338 push @{ $parse->{rules}->{l0} }, $wrl;
  197         692  
1380             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1381 197         785 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 322     322   636 my ( $values, $parse ) = @_;
1386             my ( $start, $length, $lhs, $op_declare, $rhs, $quantifier,
1387             $proto_adverb_list )
1388 322         649 = @{$values};
  322         1016  
1389              
1390 322 100       853 my $subgrammar = $op_declare->op() eq q{::=} ? 'g1' : 'l0';
1391              
1392 322         876 my $lhs_name = $lhs->name($parse);
1393 322 100 66     1532 $parse->{'first_lhs'} //= $lhs_name if $subgrammar eq 'g1';
1394 322         581 local $Marpa::R3::Internal::SUBGRAMMAR = $subgrammar;
1395              
1396 322         1031 my $quantifier_string = $quantifier->evaluate($parse);
1397 322         1421 my $xrlid = xrl_create($parse, {
1398             lhs => $lhs_name,
1399             start => $start,
1400             length => $length,
1401             }
1402             );
1403              
1404 322         855 my $adverb_list = $proto_adverb_list->evaluate($parse);
1405 322         798 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 322 100       1006 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 322         1909 my $action;
1418             my $blessing;
1419 322         0 my $naming;
1420 322         0 my $separator;
1421 322         0 my $proper;
1422 322         0 my $rank;
1423 322         0 my $null_ranking;
1424 322         479 ADVERB: for my $key ( keys %{$adverb_list} ) {
  322         790  
1425 71         168 my $value = $adverb_list->{$key};
1426 71 100       232 if ( $key eq 'action' ) {
1427 44         96 $action = $adverb_list->{$key};
1428 44         116 next ADVERB;
1429             }
1430 27 100       84 if ( $key eq 'bless' ) {
1431 4         28 $blessing = $adverb_list->{$key};
1432 4         16 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       79 if ( $key eq 'proper' ) {
1439 4         10 $proper = $adverb_list->{$key};
1440 4         11 next ADVERB;
1441             }
1442 19 50       80 if ( $key eq 'rank' ) {
1443 0         0 $rank = $adverb_list->{$key};
1444 0         0 next ADVERB;
1445             }
1446 19 50       58 if ( $key eq 'null_ranking' ) {
1447 0         0 $null_ranking = $adverb_list->{$key};
1448 0         0 next ADVERB;
1449             }
1450 19 50       72 if ( $key eq 'separator' ) {
1451 19         46 $separator = $adverb_list->{$key};
1452 19         55 next ADVERB;
1453             }
1454 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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 322         714 $sequence_rule{lhs} = $lhs_name;
1461              
1462 322 100       796 $sequence_rule{separator} = $separator
1463             if defined $separator;
1464 322 100       666 $sequence_rule{proper} = $proper if defined $proper;
1465              
1466 322   100     1378 $action //= $default_adverbs->{action};
1467 322 100       755 if ( defined $action ) {
1468 81 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 81         226 $sequence_rule{action} = $action;
1472             } ## end if ( defined $action )
1473              
1474 322   33     1291 $null_ranking //= $default_adverbs->{null_ranking};
1475 322 50       783 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 322   33     1611 $rank //= $default_adverbs->{rank};
1483 322 50       925 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 322   100     1242 $blessing //= $default_adverbs->{bless};
1491 322 50 66     911 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 322         477 $parse->symbol_assign_ordinary($_, $subgrammar) for $lhs_name, @{$sequence_rule{rhs}};
  322         1205  
1498 322 100       851 $parse->symbol_assign_ordinary($separator, $subgrammar) if defined $separator;
1499 322         1025 $parse->bless_hash_rule( \%sequence_rule, $blessing, $naming, $lhs_name );
1500              
1501 322         802 my $wrl = $parse->xpr_create( \%sequence_rule, $subgrammar );
1502 322         513 push @{ $parse->{rules}->{$subgrammar} }, $wrl;
  322         760  
1503             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1504 322         1031 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   89 my ( $values, $parse ) = @_;
1511 60         73 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  60         147  
1512 60         101 my $symbol_name = $raw_symbol_name->name();
1513 60   100     225 my $completion_events = $parse->{completion_events} //= {};
1514 60 50       149 if ( defined $completion_events->{$symbol_name} ) {
1515 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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         113 $completion_events->{$symbol_name} = $raw_event->event();
1523             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1524 60         119 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   67 my ( $values, $parse ) = @_;
1529 46         53 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  46         84  
1530 46         84 my $symbol_name = $raw_symbol_name->name();
1531 46   100     184 my $nulled_events = $parse->{nulled_events} //= {};
1532 46 50       184 if ( defined $nulled_events->{$symbol_name} ) {
1533 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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         84 $nulled_events->{$symbol_name} = $raw_event->event();
1541             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1542 46         66 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   78 my ( $values, $parse ) = @_;
1548 55         71 my ( $start, $length, $raw_event, $raw_symbol_name ) = @{$values};
  55         118  
1549 55         110 my $symbol_name = $raw_symbol_name->name();
1550 55   100     146 my $prediction_events = $parse->{prediction_events} //= {};
1551 55 50       127 if ( defined $prediction_events->{$symbol_name} ) {
1552 0         0 my ( $line, $column ) = $parse->{meta_recce}->line_column(undef, $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         114 $prediction_events->{$symbol_name} = $raw_event->event();
1560             ## no critic(Subroutines::ProhibitExplicitReturnUndef)
1561 55         92 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 197     197   485 my ( $values, $parse ) = @_;
1589 197         318 my ( undef, undef, $symbol ) = @{$values};
  197         412  
1590 197         653 return $symbol->names($parse);
1591             }
1592              
1593             sub Marpa::R3::Internal::MetaAST_Nodes::single_symbol::name {
1594 341     341   734 my ( $values, $parse ) = @_;
1595 341         504 my ( undef, undef, $symbol ) = @{$values};
  341         725  
1596 341         26690 return $symbol->name($parse);
1597             }
1598              
1599             sub Marpa::R3::Internal::MetaAST_Nodes::single_symbol::event_name {
1600 197     197   425 my ( $values, $parse ) = @_;
1601 197         333 my ( undef, undef, $symbol ) = @{$values};
  197         371  
1602 197         631 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 2167     2167   3261 my ( $values, $parse ) = @_;
1613 2167         2736 my ( undef, undef, $symbol ) = @{$values};
  2167         3841  
1614 2167         4178 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 2279     2279   3650 my ( $self, $parse ) = @_;
1626 2279         5085 return $self->[2]->name($parse);
1627             }
1628              
1629             sub Marpa::R3::Internal::MetaAST_Nodes::symbol::event_name {
1630 179     179   367 my ( $self, $parse ) = @_;
1631 179         418 return $self->[2]->name($parse);
1632             }
1633              
1634             sub Marpa::R3::Internal::MetaAST_Nodes::symbol::names {
1635 179     179   399 my ( $self, $parse ) = @_;
1636 179         600 return $self->[2]->names($parse);
1637             }
1638              
1639             sub Marpa::R3::Internal::MetaAST_Nodes::symbol_name::evaluate {
1640 4664     4664   6077 my ($self) = @_;
1641 4664         9821 return $self->[2];
1642             }
1643              
1644             sub Marpa::R3::Internal::MetaAST_Nodes::symbol_name::name {
1645 4664     4664   6563 my ( $self, $parse ) = @_;
1646 4664         7288 return $self->evaluate($parse)->name($parse);
1647             }
1648              
1649             sub Marpa::R3::Internal::MetaAST_Nodes::symbol_name::names {
1650 179     179   401 my ( $self, $parse ) = @_;
1651 179         440 return [ $self->name($parse) ];
1652             }
1653              
1654             sub Marpa::R3::Internal::MetaAST_Nodes::adverb_list::evaluate {
1655 2721     2721   4193 my ( $data, $parse ) = @_;
1656 2721         3269 my ( undef, undef, $adverb_list_items ) = @{$data};
  2721         4461  
1657 2721 100       5939 return undef if not defined $adverb_list_items;
1658 823         1919 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   13 return {};
1663             }
1664              
1665             sub Marpa::R3::Internal::MetaAST_Nodes::adverb_list_items::evaluate {
1666 823     823   1423 my ( $data, $parse ) = @_;
1667 823         1089 my ( undef, undef, @raw_items ) = @{$data};
  823         1807  
1668 823         1384 my (@adverb_items) = map { $_->evaluate($parse) } @raw_items;
  943         2116  
1669 823         2086 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   42 my ( $data, $parse ) = @_;
1675 18         32 my ( $start, $length ) = @{$data};
  18         36  
1676 18         156 return $parse->substring( $start, $length );
1677             }
1678              
1679             sub Marpa::R3::Internal::MetaAST_Nodes::character_class::names {
1680 18     18   43 my ( $self, $parse ) = @_;
1681 18         48 return [ $self->name($parse) ];
1682             }
1683              
1684             sub Marpa::R3::Internal::MetaAST_Nodes::character_class::name {
1685 450     450   859 my ( $self, $parse ) = @_;
1686 450         1086 return $self->evaluate($parse)->name($parse);
1687             }
1688              
1689             sub Marpa::R3::Internal::MetaAST_Nodes::character_class::evaluate {
1690 450     450   792 my ( $values, $parse ) = @_;
1691 450         650 my ( $start, $length, $character_class ) = @{$values};
  450         1127  
1692 450         823 my $subgrammar = $Marpa::R3::Internal::SUBGRAMMAR;
1693 450 100       1256 if ( ( substr $subgrammar, 0, 1 ) eq 'l' ) {
1694 433         1263 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         27 my $lexer_symbol = do {
1701 17         26 local $Marpa::R3::Internal::SUBGRAMMAR = 'l0';
1702 17         52 Marpa::R3::Internal::MetaAST::Symbol_List->char_class_to_symbol( $parse,
1703             $character_class );
1704             };
1705 17         49 my $lexical_lhs = $parse->internal_lexeme($character_class);
1706 17         42 my $lexical_rhs = $lexer_symbol->names($parse);
1707 17         65 my %lexical_rule = (
1708             start => $start,
1709             length => $length,
1710             lhs => $lexical_lhs,
1711             rhs => $lexical_rhs,
1712             mask => [1],
1713             );
1714 17         42 my $wrl = $parse->xpr_create( \%lexical_rule, 'l0' );
1715 17         25 push @{ $parse->{rules}->{l0} }, $wrl;
  17         33  
1716 17         43 my $g1_symbol =
1717             Marpa::R3::Internal::MetaAST::Symbol_List->new($lexical_lhs);
1718 17         51 return $g1_symbol;
1719             }
1720              
1721             sub Marpa::R3::Internal::MetaAST_Nodes::single_quoted_string::evaluate {
1722 842     842   1486 my ( $values, $parse ) = @_;
1723 842         1165 my ( $start, $length, $string ) = @{$values};
  842         2024  
1724 842         1354 my @symbols = ();
1725              
1726 842         1547 my $end_of_string = rindex $string, q{'};
1727 842         1692 my $unmodified_string = substr $string, 0, $end_of_string+1;
1728 842         1664 my $raw_flags = substr $string, $end_of_string+1;
1729 842         1834 my $flags = Marpa::R3::Internal::MetaAST::flag_string_to_flags($raw_flags);
1730 842         1424 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 842 100       1802 my $lexical_grammar = $subgrammar eq 'g1' ? 'l0' : $subgrammar;
1735              
1736 842         2845 for my $char_class (
1737 1304         3770 map { '[' . ( quotemeta $_ ) . ']' . $flags } split //xms,
1738             substr $unmodified_string,
1739             1, -1
1740             )
1741             {
1742 1304         1974 local $Marpa::R3::Internal::SUBGRAMMAR = $lexical_grammar;
1743 1304         2903 my $symbol =
1744             Marpa::R3::Internal::MetaAST::Symbol_List->char_class_to_symbol(
1745             $parse, $char_class );
1746 1304         2494 push @symbols, $symbol;
1747             } ## end for my $char_class ( map { '[' . ( quotemeta $_ ) . ']'...})
1748 842         2482 my $list = Marpa::R3::Internal::MetaAST::Symbol_List->combine(@symbols);
1749 842 100       2710 return $list if $Marpa::R3::Internal::SUBGRAMMAR ne 'g1';
1750 335         818 my $lexical_lhs = $parse->{lexeme_for_string}->{$string};
1751 335 100       793 if (not defined $lexical_lhs) {
1752 279         857 $lexical_lhs = $parse->internal_lexeme($string);
1753 279         730 $parse->{lexeme_for_string}->{$string}= $lexical_lhs;
1754 279         625 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 279         540 mask => [ map { ; 1 } @{$lexical_rhs} ],
  385         1420  
  279         470  
1762             );
1763 279         788 my $wrl = $parse->xpr_create( \%lexical_rule, 'l0' );
1764 279         423 push @{ $parse->{rules}->{$lexical_grammar} }, $wrl;
  279         768  
1765             }
1766 335         799 my $g1_symbol =
1767             Marpa::R3::Internal::MetaAST::Symbol_List->new($lexical_lhs);
1768 335         1425 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   1062317 use English qw( -no_match_vars );
  104         283  
  104         788  
1774              
1775             sub new {
1776 4278     4278   6668 my ( $class, $name ) = @_;
1777 4278         18438 return bless { names => [ q{} . $name ], mask => [1] }, $class;
1778             }
1779              
1780             sub combine {
1781 5890     5890   9229 my ( $class, @lists ) = @_;
1782 5890         7335 my $self = {};
1783 5890         7847 $self->{names} = [ map { @{ $_->names() } } @lists ];
  7553         8155  
  7553         10871  
1784 5890         9066 $self->{mask} = [ map { @{ $_->mask() } } @lists ];
  7553         7976  
  7553         10894  
1785 5890         15653 return bless $self, $class;
1786             } ## end sub combine
1787              
1788             sub Marpa::R3::Internal::MetaAST::flag_string_to_flags {
1789 2601     2601   3662 my ($raw_flag_string) = @_;
1790 2601 100       5783 return q{} if not $raw_flag_string;
1791 36         69 my @raw_flags = split m/:/xms, $raw_flag_string;
1792 36         42 my %flags = ();
1793 36         50 RAW_FLAG: for my $raw_flag (@raw_flags) {
1794 44 100       70 next RAW_FLAG if not $raw_flag;
1795 36 100       58 if ( $raw_flag eq 'i' ) {
1796 34         45 $flags{'i'} = 1;
1797 34         52 next RAW_FLAG;
1798             }
1799 2 50       7 if ( $raw_flag eq 'ic' ) {
1800 2         4 $flags{'i'} = 1;
1801 2         5 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         73 my $cooked_flags = join q{}, sort keys %flags;
1810 36         80 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 1759     1759   3116 my ( $class, $parse, $char_class ) = @_;
1817              
1818 1759         2933 my $end_of_char_class = rindex $char_class, q{]};
1819 1759         2941 my $unmodified_char_class = substr $char_class, 0, $end_of_char_class + 1;
1820 1759         2526 my $raw_flags = substr $char_class, $end_of_char_class + 1;
1821 1759         2778 my $flags = Marpa::R3::Internal::MetaAST::flag_string_to_flags($raw_flags);
1822 1759         2340 my $subgrammar = $Marpa::R3::Internal::SUBGRAMMAR;
1823              
1824             # character class symbol name always start with TWO left square brackets
1825 1759         3665 my $symbol_name = '[' . $unmodified_char_class . $flags . ']';
1826 1759   100     4541 $parse->{character_classes} //= {};
1827 1759         2452 my $cc_hash = $parse->{character_classes};
1828 1759         2933 my ( undef, $symbol ) = $cc_hash->{$symbol_name};
1829 1759 50       3341 if ( not defined $symbol ) {
1830              
1831 1759         3557 my $cc_components = [ $unmodified_char_class, $flags ];
1832              
1833 1759         3467 $symbol = Marpa::R3::Internal::MetaAST::Symbol_List->new($symbol_name);
1834 1759         5439 $cc_hash->{$symbol_name} = [ $cc_components, $symbol ];
1835              
1836             # description => "Character class: $char_class"
1837 1759         4451 my $symbol_data = {
1838             dsl_form => $char_class,
1839             name_source => 'internal',
1840             };
1841              
1842             # description => "Character class: $char_class"
1843 1759         4035 $parse->xsy_create( $symbol_name, $symbol_data );
1844 1759         4347 $symbol_data = { xsy => $symbol_name };
1845 1759         3399 $parse->symbol_names_set( $symbol_name, $subgrammar, $symbol_data );
1846             } ## end if ( not defined $symbol )
1847 1759         3957 return $symbol;
1848             } ## end sub char_class_to_symbol
1849              
1850             sub Marpa::R3::Internal::MetaAST::Parse::symbol_names_set {
1851 6518     6518   10741 my ( $parse, $symbol, $subgrammar, $args ) = @_;
1852 6518 100       11930 my $symbol_type = $subgrammar eq 'g1' ? 'g1' : 'l0';
1853 6518         8924 my $wsyid = $parse->{next_wsyid}++;
1854 6518         13284 $parse->{symbols}->{$symbol_type}->{$symbol}->{wsyid} = $wsyid;
1855 6518         7467 for my $arg_type (keys %{$args}) {
  6518         13074  
1856 6588         8482 my $value = $args->{$arg_type};
1857 6588         13534 $parse->{symbols}->{$symbol_type}->{$symbol}->{$arg_type} = $value;
1858             }
1859 6518         15055 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   512 my ( $parse, $base_symbol, $priority ) = @_;
1866              
1867             # character class symbol name always start with TWO left square brackets
1868 341         639 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       734 ->{$symbol_name};
1873 341 100       783 return $symbol_name if defined $current_symbol_data;
1874              
1875             # description => "<$base_symbol> at priority $priority"
1876 70         184 my $symbol_data = {
1877             dsl_form => $base_symbol,
1878             name_source => 'lexical',
1879             };
1880 70         200 $parse->xsy_assign( $base_symbol, $symbol_data );
1881 70         189 $symbol_data = {
1882             xsy => $base_symbol,
1883             precedence => $priority,
1884             };
1885 70         159 $parse->symbol_names_set( $symbol_name, $Marpa::R3::Internal::SUBGRAMMAR,
1886             $symbol_data );
1887 70         425 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 197     197   447 my ( $parse, $symbol_name ) = @_;
1892              
1893             my $current_symbol_data =
1894 197         459 $parse->{symbols}->{'l0'}->{$symbol_name};
1895 197 100       629 return $symbol_name if defined $current_symbol_data;
1896              
1897 144         443 my $symbol_data = {
1898             dsl_form => $symbol_name,
1899             name_source => 'lexical',
1900             };
1901 144         401 $parse->xsy_assign( $symbol_name, $symbol_data );
1902 144         387 $symbol_data = { xsy => $symbol_name };
1903 144         411 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 4758     4758   7279 my ( $parse, $symbol_name, $args ) = @_;
1908 4758         9980 my $xsy_data = $parse->{xsy}->{$symbol_name} = {};
1909              
1910             # Do I need to copy any more?
1911             # Can't I just use $args?
1912 4758         7236 for my $datum (keys %{$args}) {
  4758         11177  
1913 9516         12527 my $value = $args->{$datum};
1914 9516         16293 $xsy_data->{$datum} = $value;
1915             }
1916 4758         7281 return $xsy_data;
1917             }
1918              
1919             sub Marpa::R3::Internal::MetaAST::Parse::xsy_assign {
1920 3895     3895   6383 my ( $parse, $symbol_name, $args ) = @_;
1921 3895         5904 my $xsy_data = $parse->{xsy}->{$symbol_name};
1922 3895 100       6931 return $xsy_data if $xsy_data;
1923 2431         5023 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 1866     1866   3159 my ( $parse, $new_xrl ) = @_;
1931 1866         2957 my $lhs = $new_xrl->{lhs};
1932 1866         2654 my $start = $new_xrl->{start};
1933 1866         2485 my $length = $new_xrl->{length};
1934 1866   100     4281 $new_xrl->{precedence_count} //= 1;
1935 1866         6628 my $xrlid = sprintf '%s@%d+%d', $lhs, $start, $length;
1936 1866         3149 my $xrls_by_lhs = $parse->{xrls_by_lhs}->{$lhs};
1937              
1938 1866         2768 my $earlier_xrl = $xrls_by_lhs->[0];
1939 1866 100 100     4352 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   5 my $self = shift;
1956 3         8 my @string = ('Precedenced LHS not unique');
1957              
1958 3         5 my $pos1 = $self->{xrl1}->{start};
1959 3         6 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       16 $pos1, $len1, 74
1969             );
1970              
1971 3         8 my $pos2 = $self->{xrl2}->{start};
1972 3         5 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       14 $pos2, $len2, 74
1982             );
1983 3         6 push @string, q{};
1984              
1985 3         23 return join "\n", @string;
1986             }
1987             }
1988 3         42 )->throw();
1989             }
1990              
1991 1863         4341 my $xrl_by_id = $parse->{xrl}->{$xrlid} = $new_xrl;
1992 1863         2333 push @{ $parse->{xrls_by_lhs}->{$lhs} }, $new_xrl;
  1863         4926  
1993 1863         3979 return $xrlid;
1994             }
1995              
1996             sub Marpa::R3::Internal::MetaAST::Parse::xpr_create {
1997 4258     4258   6658 my ( $parse, $args, $subgrammar ) = @_;
1998              
1999             # The eXternal ALTernative is the argument hash,
2000             # slightly adjusted.
2001 4258   50     7105 $subgrammar //= 'g1';
2002 4258   33     14739 $args->{subgrammar} //= $subgrammar;
2003 4258   100     10764 $args->{subkey} //= 0;
2004 4258         5648 my $rule_id = join q{,}, $subgrammar, $args->{lhs}, @{$args->{rhs}};
  4258         11434  
2005 4258         7216 my $hash_by_xprid = $parse->{xpr}->{$subgrammar};
2006 4258 100       7530 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         2 my $pos2 = $args->{start};
2011 2         5 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         12 'Second rule', $parse->{p_dsl}, $pos2, $len2, 74
2019             )
2020             );
2021 2         187 Marpa::R3::exception( join "\n", @string, q{} );
2022             }
2023 4256         15625 $hash_by_xprid->{$rule_id} = $args;
2024              
2025             # Now create the initial working rule
2026 4256         10326 my %wrl = (
2027             xprid => $rule_id,
2028             subgrammar => $subgrammar,
2029             );
2030             # Shallow copy
2031 4256         6973 for my $field (
2032             qw(lhs action priority rank
2033             null_ranking min separator proper )
2034             )
2035             {
2036 34048 100       65481 $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 4256         4942 my $rhs = $args->{rhs};
  4256         5464  
2042 4256         4760 my $xpr_datum = $rhs;
2043 4256         5029 my @array = @{$rhs};
  4256         8590  
2044 4256         6923 $wrl{rhs} = \@array;
2045 4256         10495 $wrl{xpr_dot} = [0 .. (scalar @array) ];
2046 4256         8709 $wrl{xpr_top} = 1;
2047             }
2048              
2049             # Return the initial working rule
2050 4256         7187 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 296     296   698 my ( $parse, $dsl_form, @grammars ) = @_;
2058              
2059             # character class symbol name always start with TWO left square brackets
2060 296         710 my $lexical_lhs_index = $parse->{lexical_lhs_index}++;
2061 296         754 my $lexical_symbol = "[Lex-$lexical_lhs_index]";
2062              
2063             # description => qq{Internal lexical symbol for "$dsl_form"}
2064 296         853 my $symbol_data = {
2065             dsl_form => $dsl_form,
2066             name_source => 'internal'
2067             };
2068 296         838 $parse->xsy_assign( $lexical_symbol, $symbol_data );
2069 296         986 $symbol_data = { xsy => $lexical_symbol };
2070 296         1987 $parse->symbol_names_set( $lexical_symbol, $_, $symbol_data ) for qw(g1 l0);
2071 296         699 return $lexical_symbol;
2072             } ## end sub Marpa::R3::Internal::MetaAST::Parse::internal_lexeme
2073              
2074             sub name {
2075 455     455   1029 my ($self) = @_;
2076 455         1050 my $names = $self->{names};
2077             Marpa::R3::exception( 'list->name() on symbol list of length ',
2078 0         0 scalar @{$names} )
2079 455 50       652 if scalar @{$names} != 1;
  455         1274  
2080 455         2075 return $self->{names}->[0];
2081             } ## end sub name
2082 9657     9657   23241 sub names { return shift->{names} }
2083 9361     9361   21575 sub mask { return shift->{mask} }
2084              
2085             sub mask_set {
2086 77     77   147 my ( $self, $mask ) = @_;
2087 77         108 return $self->{mask} = [ map {$mask} @{ $self->{mask} } ];
  95         307  
  77         131  
2088             }
2089              
2090             1;
2091              
2092             # vim: expandtab shiftwidth=4: