File Coverage

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