File Coverage

blib/lib/Marpa/R3/SLG.pm
Criterion Covered Total %
statement 734 898 81.7
branch 228 352 64.7
condition 39 67 58.2
subroutine 67 77 87.0
pod 0 1 0.0
total 1068 1395 76.5


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::Grammar;
13              
14 104     104   2185 use 5.010001;
  104         326  
15 104     104   539 use strict;
  104         198  
  104         2383  
16 104     104   519 use warnings;
  104         187  
  104         3253  
17              
18 104     104   500 use vars qw($VERSION $STRING_VERSION);
  104         176  
  104         7610  
19             $VERSION = '4.001_054';
20             $STRING_VERSION = $VERSION;
21             ## no critic(BuiltinFunctions::ProhibitStringyEval)
22             $VERSION = eval $VERSION;
23             ## use critic
24              
25             package Marpa::R3::Internal_G;
26              
27 104     104   651 use Scalar::Util 'blessed';
  104         208  
  104         6423  
28 104     104   637 use English qw( -no_match_vars );
  104         207  
  104         883  
29              
30             # names of packages for strings
31             our $PACKAGE = 'Marpa::R3::Grammar';
32              
33             # The bare mininum Scanless grammer, suitable as a base
34             # for both metagrammar and user grammars.
35             sub pre_construct {
36 394     394   1013 my ($class) = @_;
37 394         1059 my $pre_slg = bless [], $class;
38 394         1580 $pre_slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE] = \*STDERR;
39 394         896 $pre_slg->[Marpa::R3::Internal_G::CONSTANTS] = [];
40              
41 394         1032041 my $lua = Marpa::R3::Lua->new();
42 394         1936 $pre_slg->[Marpa::R3::Internal_G::L] = $lua;
43              
44 394         15189 my ($regix) = $lua->call_by_tag (-1,
45             ('@' .__FILE__ . ':' . __LINE__),
46             <<'END_OF_LUA', '');
47             local slg = _M.slg_new()
48             return slg.regix
49             END_OF_LUA
50              
51 394         1330 $pre_slg->[Marpa::R3::Internal_G::REGIX] = $regix;
52 394         1287 return $pre_slg;
53             }
54              
55             sub Marpa::R3::Internal::meta_grammar {
56              
57 102     102 0 3423 my $meta_slg = pre_construct('Marpa::R3::Grammar');
58              
59 102         816 state $hashed_metag = Marpa::R3::Internal::MetaG::hashed_grammar();
60 102         473 $meta_slg->[Marpa::R3::Internal_G::BLESS_PACKAGE] =
61             'Marpa::R3::Internal::MetaAST_Nodes';
62 102         566 Marpa::R3::Internal_G::hash_to_runtime( $meta_slg, $hashed_metag );
63 102         619 my $registrations = registrations_find($meta_slg );
64 102         693 registrations_set($meta_slg, $registrations );
65              
66 102         7345 return $meta_slg;
67              
68             } ## end sub Marpa::R3::Internal::meta_grammar
69              
70             sub Marpa::R3::Grammar::new {
71 292     292   101941 my ( $class, @hash_ref_args ) = @_;
72              
73 292         1123 my $slg = pre_construct($class);
74              
75 292         1643 my ( $flat_args, $error_message ) =
76             Marpa::R3::flatten_hash_args( \@hash_ref_args );
77 292 50       1063 Marpa::R3::exception( sprintf $error_message, '$slg->new' )
78             if not $flat_args;
79              
80 292         1178 my $p_dsl = Marpa::R3::Internal_G::set( $slg, $flat_args );
81 292         2447 my $ast = Marpa::R3::Internal::MetaAST->new($p_dsl);
82 289         1720 my $hashed_ast = $ast->ast_to_hash($p_dsl);
83 276         1231 Marpa::R3::Internal_G::hash_to_runtime( $slg, $hashed_ast);
84 271         1135 my $registrations = registrations_find($slg );
85 270         2069 registrations_set($slg, $registrations );
86 270         31427 return $slg;
87             }
88              
89             sub Marpa::R3::Grammar::DESTROY {
90             # say STDERR "In Marpa::R3::Grammar::DESTROY before test";
91 272     272   139547 my $slg = shift;
92 272         972 my $lua = $slg->[Marpa::R3::Internal_G::L];
93              
94             # If we are destroying the Perl interpreter, then all the Marpa
95             # objects will be destroyed, including Marpa's Lua interpreter.
96             # We do not need to worry about cleaning up the
97             # grammar is an orderly manner, because the Lua interpreter
98             # containing the grammar will be destroyed.
99             # In fact, the Lua interpreter may already have been destroyed,
100             # so this test is necessary to avoid a warning message.
101 272 50       840 return if not $lua;
102             # say STDERR "In Marpa::R3::Grammar::DESTROY after test";
103              
104 272         546 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
105 272         330645 $lua->call_by_tag($regix,
106             ('@' . __FILE__ . ':' . __LINE__),
107             <<'END_OF_LUA', 'i', $regix);
108             local grammar, regix = ...
109             _M.unregister(_M.registry, regix)
110             END_OF_LUA
111             }
112              
113             sub Marpa::R3::Grammar::set {
114 2     2   1727 my ( $slg, @hash_ref_args ) = @_;
115 2         12 my ( $flat_args, $error_message ) =
116             Marpa::R3::flatten_hash_args( \@hash_ref_args );
117 2 50       8 Marpa::R3::exception( sprintf $error_message, '$slg->set' )
118             if not $flat_args;
119              
120 2         5 my $value = $flat_args->{trace_file_handle};
121 2 50       6 if ( defined $value ) {
122 2         5 $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE] = $value;
123 2         7 delete $flat_args->{trace_file_handle};
124             }
125              
126 2         190 my @bad_arguments = keys %{$flat_args};
  2         9  
127 2 50       7 if ( scalar @bad_arguments ) {
128 0         0 Marpa::R3::exception(
129             q{Bad named argument(s) to $slg->set() method} . join q{ },
130             @bad_arguments );
131             }
132 2         7 return;
133             }
134              
135             sub Marpa::R3::Internal_G::set {
136 292     292   810 my ( $slg, $flat_args ) = @_;
137              
138 292         722 my $dsl = $flat_args->{'source'};
139 292 50       932 Marpa::R3::exception(
140             qq{Marpa::R3::Grammar::new() called without a 'source' argument})
141             if not defined $dsl;
142 292         809 my $dsl_ref_type = ref $dsl;
143 292 50       960 if ( $dsl_ref_type ne 'SCALAR' ) {
144 0 0       0 my $desc = $dsl_ref_type ? "a ref to $dsl_ref_type" : 'not a ref';
145 0         0 Marpa::R3::exception(
146             qq{'source' name argument to Marpa::R3::Grammar->new() is $desc\n},
147             " It should be a ref to a string\n"
148             );
149             }
150 292 50       574 if ( not defined ${$dsl} ) {
  292         1499  
151 0         0 Marpa::R3::exception(
152             qq{'source' name argument to Marpa::R3::Grammar->new() is a ref to a an undef\n},
153             " It should be a ref to a string\n"
154             );
155             } ## end if ( $ref_type ne 'SCALAR' )
156 292         789 delete $flat_args->{'source'};
157              
158 292         719 my $value = $flat_args->{trace_file_handle};
159 292 50       931 if ( defined $value ) {
160 0         0 $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE] = $value;
161 0         0 delete $flat_args->{'trace_file_handle'};
162             }
163              
164 292         672 my $trace_file_handle =
165             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
166              
167 292 50       987 if ( exists $flat_args->{'trace_actions'} ) {
168 0         0 my $value = $flat_args->{'trace_actions'};
169 0         0 $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] = $value;
170 0 0       0 if ($value) {
171 0 0       0 say {$trace_file_handle} 'Setting trace_actions option'
  0         0  
172             or Marpa::R3::exception("Cannot print: $ERRNO");
173             }
174 0         0 delete $flat_args->{'trace_actions'};
175             }
176              
177 292 50       1065 if ( defined( exists $flat_args->{'bless_package'} ) ) {
178 292         684 my $value = $flat_args->{'bless_package'};
179 292         789 $slg->[Marpa::R3::Internal_G::BLESS_PACKAGE] = $value;
180 292         682 delete $flat_args->{'bless_package'};
181             }
182              
183 292 100       1044 if ( exists $flat_args->{'exhaustion'} ) {
184              
185 4   50     19 my $value = $flat_args->{'exhaustion'} // '';
186              
187 4         19 $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
188             <<'END_OF_LUA', 's', $value);
189             local slg, value = ...
190             local exhaustion_actions = {
191             fatal = true,
192             event = true
193             }
194             if not exhaustion_actions[value] then
195             if #value == 0 then value = 'undefined' end
196             error(string.format(
197             "'exhaustion' named arg value is %s \z
198             'event' or 'fatal'",
199             value
200             ))
201             end
202             slg.exhaustion_action = value
203             END_OF_LUA
204              
205 4         12 delete $flat_args->{'exhaustion'};
206              
207             }
208              
209 292 100       970 if ( exists $flat_args->{'rejection'} ) {
210              
211 6   50     22 my $value = $flat_args->{'rejection'} // '';
212              
213 6         25 $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
214             <<'END_OF_LUA', 's', $value);
215             local slg, value = ...
216             local rejection_actions = {
217             fatal = true,
218             event = true
219             }
220             if not rejection_actions[value] then
221             if #value == 0 then value = 'undefined' end
222             error(string.format(
223             "'rejection' named arg value is %s \z
224             'event' or 'fatal'",
225             value
226             ))
227             end
228             slg.rejection_action = value
229             END_OF_LUA
230              
231 6         18 delete $flat_args->{'rejection'};
232              
233             }
234              
235 292 100       1094 if ( exists $flat_args->{'semantics_package'} ) {
236 43         112 my $value = $flat_args->{'semantics_package'};
237 43         115 $slg->[Marpa::R3::Internal_G::SEMANTICS_PACKAGE] = $value;
238 43         110 delete $flat_args->{'semantics_package'};
239             }
240              
241 292 100       941 if ( exists $flat_args->{'ranking_method'} ) {
242              
243             # Only allowed in new method
244 18   50     62 my $value = $flat_args->{'ranking_method'} // 'undefined';
245              
246 18         92 $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
247             <<'END_OF_LUA', 's', $value);
248             local slg, value = ...
249             if not _M.ranking_methods[value] then
250             local list = {}
251             for method,_ in pairs(_M.ranking_methods) do
252             list[#list+1] = string.format('%q', method)
253             end
254             error(string.format(
255             'ranking_method value is %q (should be one of %s)',
256             value, table.concat(list, ', ')
257             ))
258             end
259             slg.ranking_method = value
260             END_OF_LUA
261              
262 18         152 delete $flat_args->{'ranking_method'};
263             }
264              
265 292 50       925 if ( exists $flat_args->{'debug_level'} ) {
266              
267 0   0     0 my $value = $flat_args->{'debug_level'} // 'undefined';
268              
269 0         0 $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
270             <<'END_OF_LUA', 'i', $value);
271             local slg, raw_value = ...
272             local value = math.tointeger(raw_value)
273             if not value then
274             _M.userX(
275             'debug_level value is %s -- it should be an integer',
276             inspect(value)
277             )
278             end
279             slg.debug_level = value
280             END_OF_LUA
281              
282 0         0 delete $flat_args->{'debug_level'};
283             }
284              
285 292         763 return $dsl;
286              
287             }
288              
289             # The object, in computing the hash, is to get as much
290             # precomputation in as possible, without using undue space.
291             # That means CPU-intensive processing should tend to be done
292             # before or during hash creation, and space-intensive processing
293             # should tend to be done here, in the code that converts the
294             # hash to its runtime equivalent.
295             sub Marpa::R3::Internal_G::hash_to_runtime {
296 378     378   1103 my ( $slg, $hashed_source ) = @_;
297              
298 378         910 my $trace_file_handle = $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
299             # Pre-lexer G1 processing
300              
301             $slg->coro_by_tag(
302             ( '@' . __FILE__ . ':' . __LINE__ ),
303             {
304             signature => 's',
305             args => [$hashed_source],
306             handlers => {
307             trace => sub {
308 0     0   0 my ($msg) = @_;
309 0         0 say {$trace_file_handle} $msg;
  0         0  
310 0         0 return 'ok';
311             },
312             }
313             },
314 378         5475 <<'END_OF_LUA');
315             local slg, source_hash = ...
316             _M.wrap(function ()
317             slg:seriable_to_runtime(source_hash)
318             end)
319             END_OF_LUA
320              
321             # For the Kollos interface, we need to create some kind
322             # of SLG method which allows access to the character_class,
323             # character_flags data. For now we just grab it from the
324             # structure
325             my ($character_pairs) = $slg->coro_by_tag(
326             ( '@' . __FILE__ . ':' . __LINE__ ),
327             {
328             signature => '',
329             args => [],
330             handlers => {
331             trace => sub {
332 0     0   0 my ($msg) = @_;
333 0         0 say {$trace_file_handle} $msg;
  0         0  
334 0         0 return 'ok';
335             },
336             }
337             },
338 373         6764 <<'END_OF_LUA');
339             local slg = ...
340             _M.wrap(function ()
341             local isys = slg.l0.isys
342             local character_pairs = {}
343             -- In reverse order, so when Perl pops them off,
344             -- they are back in symbol ID order
345             for isyid = #isys, 0, -1 do
346             local isy = isys[isyid]
347             local perl_re = isy.character_class
348             if perl_re then
349             local perl_re = isy.character_class
350             local flags = isy.character_flags
351             if flags then
352             perl_re = '(?' .. flags .. ')' .. perl_re
353             end
354             character_pairs[#character_pairs+1] = isyid
355             character_pairs[#character_pairs+1] = perl_re
356             end
357             end
358             return 'ok', character_pairs
359             end)
360             END_OF_LUA
361              
362 373         2231 my @class_table;
363             CLASS_SYMBOL:
364 373         865 while (scalar @{$character_pairs}) {
  7601         12819  
365 7228         7723 my $perl_re = pop @{$character_pairs};
  7228         8973  
366 7228         7691 my $symbol_id = pop @{$character_pairs};
  7228         8476  
367 7228         8719 my $compiled_re;
368             my $error;
369 7228 50       7728 if ( not defined eval { $compiled_re = qr/$perl_re/xms; 1; } ) {
  7228         64001  
  7228         16541  
370 0         0 $error = qq{Problem in evaluating character class: "$perl_re"\n};
371 0         0 $error .= $EVAL_ERROR;
372             }
373 7228 50       11040 if ( not $compiled_re ) {
374 0         0 $error =~ s/^/ /gxms; #indent all lines
375 0         0 Marpa::R3::exception(
376             "Failed belatedly to evaluate character class\n", $error );
377             }
378 7228         12696 push @class_table, [ $symbol_id, $compiled_re ];
379             } ## end CLASS_SYMBOL: for my $class_symbol ( sort keys %{...})
380 373         1093 $slg->[Marpa::R3::Internal_G::CHARACTER_CLASS_TABLE] = \@class_table;
381              
382 373         1029 return $slg;
383              
384             }
385              
386             our $kwgen_code_template = <<'END_OF_TEMPLATE';
387             END_OF_TEMPLATE
388              
389 0         0 sub kwgen {
390 4992     4992   8372 my ($line, $perl_name, $kollos_name, $signature) = @_;
391 4992         33581 my $tag = '@' . __FILE__ . ':' . $line;
392 4992         10530 my $code = sprintf( 'return _M.class_slg.%s(...)', $kollos_name );
393             # my $code = sprintf( 'io.stderr:write("Calling slg.%s ", table.concat(..., "")); return _M.class_slg.%s(...)', $kollos_name, $kollos_name );
394 104     104   180955 no strict 'refs';
  104         276  
  104         10363  
395 4992         20258 *{ 'Marpa::R3::Grammar::' . $perl_name }
396             = sub () {
397 21669     21669   48591 my ($slg, @args) = @_;
398 21669         44384 my ($retour) = $slg->call_by_tag($tag, $code, $signature, @args);
399 21669         42334 return $retour;
400 4992         17083 };
401 104     104   679 use strict;
  104         249  
  104         8108  
402             }
403              
404 0         0 sub kwgen_arr {
405 416     416   919 my ($line, $perl_name, $kollos_name, $signature) = @_;
406 416         958 my $tag = '@' . __FILE__ . ':' . $line;
407 416         1024 my $code = sprintf( 'return _M.class_slg.%s(...)', $kollos_name );
408             # my $code = sprintf( 'io.stderr:write("Calling slg.%s ", table.concat(..., "")); return _M.class_slg.%s(...)', $kollos_name, $kollos_name );
409 104     104   617 no strict 'refs';
  104         232  
  104         8795  
410 416         1901 *{ 'Marpa::R3::Grammar::' . $perl_name }
411             = sub () {
412 1693     1693   2957 my ($slg, @args) = @_;
413 1693         2982 my ($retour) = $slg->call_by_tag($tag, $code, $signature, @args);
414 1693         2139 return @{$retour};
  1693         3675  
415 416         1943 };
416 104     104   610 use strict;
  104         315  
  104         17674  
417             }
418              
419 0         0 sub kwgen_opt {
420 312     312   881 my ($line, $perl_name, $kollos_name, $signature, @defaults) = @_;
421 312         983 my $tag = '@' . __FILE__ . ':' . $line;
422 312         912 my $code = sprintf( 'return _M.class_slg.%s(...)', $kollos_name );
423             # my $code = sprintf( 'io.stderr:write("Calling slg.%s ", table.concat(..., "")); return _M.class_slg.%s(...)', $kollos_name, $kollos_name );
424 104     104   634 no strict 'refs';
  104         216  
  104         11486  
425 312         1830 *{ 'Marpa::R3::Grammar::' . $perl_name }
426             = sub () {
427 8     8   955 my ($slg, @args) = @_;
428 8   66     70 $args[$_] //= $defaults[$_] for 0 .. $#defaults;
429 8         34 my ($retour) = $slg->call_by_tag($tag, $code, $signature, @args);
430 8         43 return $retour;
431 312         1955 };
432 104     104   617 use strict;
  104         192  
  104         699825  
433             }
434              
435             sub Marpa::R3::Grammar::production_show {
436 94     94   299 my ($slg, $xprid, $options) = @_;
437 94 50       218 my $verbose = $options->{verbose} or 0;
438 94 100       154 my $diag = $options->{diag} ? 1 : 0;
439 94         116 my $tag = '@' . __FILE__ . ':' . __LINE__;
440 94         100 my $code = <<'END_OF_CODE';
441             local slg, xprid, verbose, diag = ...
442             diag = diag ~= 0 -- convert diag to a boolean
443             return slg:xpr_show(xprid, { verbose = verbose, diag = diag })
444             END_OF_CODE
445 94         227 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
446             $xprid, $verbose, $diag);
447 94         203 return $retour;
448             }
449              
450             sub Marpa::R3::Grammar::symbols_show {
451 15     15   5243 my ($slg, $options) = @_;
452 15 100       66 my $verbose = $options->{verbose} or 0;
453 15 50       235 my $diag = $options->{diag} ? 1 : 0;
454 15         41 my $tag = '@' . __FILE__ . ':' . __LINE__;
455 15         27 my $code = <<'END_OF_CODE';
456             local slg, verbose, diag = ...
457             diag = diag ~= 0 -- convert diag to a boolean
458             return slg:symbols_show({ verbose = verbose, diag = diag })
459             END_OF_CODE
460 15         54 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
461             $verbose, $diag);
462 15         87 return $retour;
463             }
464              
465             sub Marpa::R3::Grammar::symbol_show {
466 41     41   206 my ($slg, $xsyid, $options) = @_;
467 41 50       71 my $verbose = $options->{verbose} or 0;
468 41 50       58 my $diag = $options->{diag} ? 1 : 0;
469 41         50 my $tag = '@' . __FILE__ . ':' . __LINE__;
470 41         43 my $code = <<'END_OF_CODE';
471             local slg, xsyid, verbose, diag = ...
472             diag = diag ~= 0 -- convert diag to a boolean
473             return slg:symbol_show(xsyid, { verbose = verbose, diag = diag })
474             END_OF_CODE
475 41         57 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
476             $xsyid, $verbose, $diag);
477 41         102 return $retour;
478             }
479              
480             sub Marpa::R3::Grammar::lmg_rule_show {
481 0     0   0 my ($slg, $subg, $irlid, $options) = @_;
482 0 0       0 my $verbose = $options->{verbose} or 0;
483 0 0       0 my $diag = $options->{diag} ? 1 : 0;
484 0         0 my $tag = '@' . __FILE__ . ':' . __LINE__;
485 0         0 my $code = <<'END_OF_CODE';
486             local slg, subg, irlid, verbose, diag = ...
487             diag = diag ~= 0 -- convert diag to a boolean
488             return slg:lmg_rule_show(subg, irlid, { verbose = verbose, diag = diag })
489             END_OF_CODE
490 0         0 my ($retour) = $slg->call_by_tag($tag, $code, 'siii',
491             $subg, $irlid, $verbose, $diag);
492 0         0 return $retour;
493             }
494              
495             sub Marpa::R3::Grammar::g1_rule_show {
496 151     151   656 my ($slg, $irlid, $options) = @_;
497 151 50       494 my $verbose = $options->{verbose} or 0;
498 151 100       348 my $diag = $options->{diag} ? 1 : 0;
499 151         244 my $tag = '@' . __FILE__ . ':' . __LINE__;
500 151         302 my $code = <<'END_OF_CODE';
501             local slg, irlid, verbose, diag = ...
502             diag = diag ~= 0 -- convert diag to a boolean
503             return slg:g1_rule_show(irlid, { verbose = verbose, diag = diag })
504             END_OF_CODE
505 151         685 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
506             $irlid, $verbose, $diag);
507 151         683 return $retour;
508             }
509              
510             sub Marpa::R3::Grammar::l0_rule_show {
511 54     54   155 my ($slg, $irlid, $options) = @_;
512 54 50       95 my $verbose = $options->{verbose} or 0;
513 54 100       73 my $diag = $options->{diag} ? 1 : 0;
514 54         60 my $tag = '@' . __FILE__ . ':' . __LINE__;
515 54         55 my $code = <<'END_OF_CODE';
516             local slg, irlid, verbose, diag = ...
517             diag = diag ~= 0 -- convert diag to a boolean
518             return slg:l0_rule_show(irlid, { verbose = verbose, diag = diag })
519             END_OF_CODE
520 54         85 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
521             $irlid, $verbose, $diag);
522 54         117 return $retour;
523             }
524              
525             sub Marpa::R3::Grammar::productions_show {
526 22     22   7444 my ($slg, $options) = @_;
527 22 100       207 my $verbose = $options->{verbose} or 0;
528 22 100       138 my $diag = $options->{diag} ? 1 : 0;
529 22         61 my $tag = '@' . __FILE__ . ':' . __LINE__;
530 22         44 my $code = <<'END_OF_CODE';
531             local slg, verbose, diag = ...
532             diag = diag ~= 0 -- convert diag to a boolean
533             return slg:xprs_show({ verbose = verbose, diag = diag })
534             END_OF_CODE
535 22         70 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
536             $verbose, $diag);
537 22         122 return $retour;
538             }
539              
540             sub Marpa::R3::Grammar::lmg_rules_show {
541 0     0   0 my ($slg, $subg, $options) = @_;
542 0 0       0 my $verbose = $options->{verbose} or 0;
543 0 0       0 my $diag = $options->{diag} ? 1 : 0;
544 0         0 my $tag = '@' . __FILE__ . ':' . __LINE__;
545 0         0 my $code = <<'END_OF_CODE';
546             local slg, subg, verbose, diag = ...
547             diag = diag ~= 0 -- convert diag to a boolean
548             return slg:lmg_rules_show(subg, { verbose = verbose, diag = diag })
549             END_OF_CODE
550 0         0 my ($retour) = $slg->call_by_tag($tag, $code, 'sii',
551             $subg, $verbose, $diag);
552 0         0 return $retour;
553             }
554              
555             sub Marpa::R3::Grammar::g1_rules_show {
556 11     11   3001 my ($slg, $options) = @_;
557 11 100       46 my $verbose = $options->{verbose} or 0;
558 11 100       47 my $diag = $options->{diag} ? 1 : 0;
559 11         25 my $tag = '@' . __FILE__ . ':' . __LINE__;
560 11         23 my $code = <<'END_OF_CODE';
561             local slg, verbose, diag = ...
562             diag = diag ~= 0 -- convert diag to a boolean
563             return slg:g1_rules_show({ verbose = verbose, diag = diag })
564             END_OF_CODE
565 11         35 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
566             $verbose, $diag);
567 11         62 return $retour;
568             }
569              
570             sub Marpa::R3::Grammar::l0_rules_show {
571 5     5   2498 my ($slg, $options) = @_;
572 5 50       20 my $verbose = $options->{verbose} or 0;
573 5 100       18 my $diag = $options->{diag} ? 1 : 0;
574 5         11 my $tag = '@' . __FILE__ . ':' . __LINE__;
575 5         9 my $code = <<'END_OF_LUA';
576             local slg, verbose, diag = ...
577             diag = diag ~= 0 -- convert diag to a boolean
578             return slg:l0_rules_show({ verbose = verbose, diag = diag })
579             END_OF_LUA
580 5         17 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
581             $verbose, $diag);
582 5         21 return $retour;
583             }
584              
585             # TODO: Census all uses of Marpa::R3::Grammar::g1_symbol_name
586             # in pod and tests, and make sure that they are appropriate --
587             # that is, that they should not be symbol_name() instead.
588              
589             kwgen(__LINE__, qw(highest_symbol_id highest_symbol_id), '');
590             kwgen(__LINE__, qw(lmg_highest_symbol_id lmg_highest_symbol_id i));
591             kwgen(__LINE__, qw(g1_highest_symbol_id g1_highest_symbol_id), '');
592             kwgen(__LINE__, qw(l0_highest_symbol_id l0_highest_symbol_id), '');
593              
594             kwgen(__LINE__, qw(start_symbol_id start_symbol_id), '');
595             kwgen(__LINE__, qw(lmg_start_symbol_id lmg_start_symbol_id s));
596             kwgen(__LINE__, qw(g1_start_symbol_id g1_start_symbol_id), '');
597             kwgen(__LINE__, qw(l0_start_symbol_id l0_start_symbol_id), '');
598              
599             kwgen(__LINE__, qw(g1_xsymbol_id g1_xsyid i));
600             kwgen(__LINE__, qw(l0_xsymbol_id l0_xsyid i));
601              
602             kwgen(__LINE__, qw(symbol_name symbol_name i));
603             kwgen(__LINE__, qw(lmg_symbol_name lmg_symbol_name si));
604             kwgen(__LINE__, qw(g1_symbol_name g1_symbol_name i));
605             kwgen(__LINE__, qw(l0_symbol_name l0_symbol_name i));
606              
607             kwgen(__LINE__, qw(symbol_display_form symbol_display_form i));
608             kwgen(__LINE__, qw(lmg_symbol_display_form lmg_symbol_display_form si));
609             kwgen(__LINE__, qw(g1_symbol_display_form g1_symbol_display_form i));
610             kwgen(__LINE__, qw(l0_symbol_display_form l0_symbol_display_form i));
611              
612             kwgen(__LINE__, qw(symbol_angled_form symbol_angled_form i));
613             kwgen(__LINE__, qw(lmg_symbol_angled_form lmg_symbol_angled_form si));
614             kwgen(__LINE__, qw(g1_symbol_angled_form g1_symbol_angled_form i));
615             kwgen(__LINE__, qw(l0_symbol_angled_form l0_symbol_angled_form i));
616              
617             kwgen(__LINE__, qw(symbol_dsl_form symbol_dsl_form i));
618             kwgen(__LINE__, qw(lmg_symbol_dsl_form lmg_symbol_dsl_form si));
619             kwgen(__LINE__, qw(g1_symbol_dsl_form g1_symbol_dsl_form i));
620             kwgen(__LINE__, qw(l0_symbol_dsl_form l0_symbol_dsl_form i));
621              
622             kwgen_opt(__LINE__, qw(lmg_symbols_show lmg_symbols_show si), 0, 0);
623             kwgen_opt(__LINE__, qw(g1_symbols_show g1_symbols_show i), 0);
624             kwgen_opt(__LINE__, qw(l0_symbols_show l0_symbols_show i), 0);
625              
626             kwgen(__LINE__, qw(lmg_symbol_by_name lmg_symbol_by_name si));
627             kwgen(__LINE__, qw(g1_symbol_by_name g1_symbol_by_name i));
628             kwgen(__LINE__, qw(l0_symbol_by_name l0_symbol_by_name i));
629              
630             kwgen(__LINE__, qw(g1_symbol_is_accessible g1_symbol_is_accessible i));
631             kwgen(__LINE__, qw(g1_symbol_is_nulling g1_symbol_is_nulling i));
632             kwgen(__LINE__, qw(g1_symbol_is_productive g1_symbol_is_productive i));
633              
634             kwgen(__LINE__, qw(production_dotted_show xpr_dotted_show ii));
635             kwgen(__LINE__, qw(lmg_dotted_rule_show lmg_dotted_rule_show sii));
636             kwgen(__LINE__, qw(g1_dotted_rule_show g1_dotted_rule_show ii));
637             kwgen(__LINE__, qw(l0_dotted_rule_show l0_dotted_rule_show ii));
638              
639             kwgen(__LINE__, qw(production_name xpr_name i));
640              
641             kwgen(__LINE__, qw(lmg_rule_to_production_id lmg_rule_to_xprid si));
642             kwgen(__LINE__, qw(g1_rule_to_production_id g1_rule_to_xprid i));
643             kwgen(__LINE__, qw(l0_rule_to_production_id l0_rule_to_xprid i));
644              
645             kwgen(__LINE__, qw(lmg_rule_to_production_dot lmg_rule_to_xpr_dots si));
646             kwgen(__LINE__, qw(g1_rule_to_production_dot g1_rule_to_xpr_dots i));
647             kwgen(__LINE__, qw(l0_rule_to_production_dot l0_rule_to_xpr_dots i));
648              
649             kwgen(__LINE__, qw(highest_production_id highest_xprid), '');
650             kwgen(__LINE__, qw(lmg_highest_rule_id lmg_highest_rule_id), '');
651             kwgen(__LINE__, qw(g1_highest_rule_id g1_highest_rule_id), '');
652             kwgen(__LINE__, qw(l0_highest_rule_id l0_highest_rule_id), '');
653              
654             kwgen_arr(__LINE__, qw(production_expand xpr_expand i));
655             kwgen_arr(__LINE__, qw(lmg_rule_expand lmg_irl_isyids si));
656             kwgen_arr(__LINE__, qw(g1_rule_expand g1_irl_isyids i));
657             kwgen_arr(__LINE__, qw(l0_rule_expand l0_irl_isyids i));
658              
659             kwgen(__LINE__, qw(production_length xpr_length i));
660              
661             sub Marpa::R3::Grammar::call_by_tag {
662 161111     161111   262776 my ( $slg, $tag, $codestr, $sig, @args ) = @_;
663 161111         196498 my $lua = $slg->[Marpa::R3::Internal_G::L];
664 161111         196480 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
665             # $DB::single = 1 if not defined $lua;
666             # $DB::single = 1 if not defined $regix;
667             # $DB::single = 1 if not defined $tag;
668             # $DB::single = 1 if not defined $codestr;
669             # $DB::single = 1 if not defined $sig;
670             # $DB::single = 1 if grep { not defined $_ } @args;
671 161111         254837 my @results;
672             my $eval_error;
673 161111         0 my $eval_ok;
674             {
675 161111         164719 local $@;
  161111         171156  
676 161111         195367 $eval_ok = eval {
677             # say STDERR "About to call_by_tag($regix, $tag, $codestr, $sig, @args)";;
678 161111         1076728 @results = $lua->call_by_tag($regix, $tag, $codestr, $sig, @args);
679             # say STDERR "Returned from call_by_tag($regix, $tag, $codestr, $sig, @args)";;
680 161111         293318 return 1;
681             };
682 161111         238581 $eval_error = $@;
683             }
684 161111 50       246961 if ( not $eval_ok ) {
685 0         0 Marpa::R3::exception($eval_error);
686             }
687              
688 161111         282444 return @results;
689             }
690              
691             # not to be documented
692             sub Marpa::R3::Grammar::coro_by_tag {
693 1957     1957   5218 my ( $slg, $tag, $args, $codestr ) = @_;
694 1957         3340 my $lua = $slg->[Marpa::R3::Internal_G::L];
695 1957         3027 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
696 1957   50     5366 my $handler = $args->{handlers} // {};
697 1957         4116 my $resume_tag = $tag . '[R]';
698 1957   50     4515 my $signature = $args->{signature} // '';
699 1957   50     4890 my $p_args = $args->{args} // [];
700              
701 1957         4458 my @results;
702             my $eval_error;
703 1957         0 my $eval_ok;
704             {
705 1957         2662 local $@;
  1957         2796  
706 1957         3239 $eval_ok = eval {
707 1957         3295 $lua->call_by_tag( $regix, $tag, $codestr, $signature, @{$p_args} );
  1957         1124975  
708 1957         28393 my $coro_arg;
709 1957         3145 CORO_CALL: while (1) {
710 1965         2325238 my ( $cmd, $yield_data ) =
711             $lua->call_by_tag( $regix, $resume_tag,
712             'local slg, coro_arg = ...; return _M.resume(coro_arg)',
713             's', $coro_arg );
714              
715 1960 100       8775 if (not $cmd) {
716 1952         30016 @results = @{$yield_data};
  1952         4599  
717 1952         6101 return 1;
718             }
719 8         18 my $handler = $handler->{$cmd};
720 8 50       16 Marpa::R3::exception(qq{No coro handler for "$cmd"})
721             if not $handler;
722 8   50     19 $yield_data //= [];
723 8         9 my $handler_cmd;
724 8         11 ($handler_cmd, $coro_arg) = $handler->(@{$yield_data});
  8         24  
725             }
726 0         0 return 1;
727             };
728 1957         4673 $eval_error = $@;
729             }
730 1957 100       4829 if ( not $eval_ok ) {
731 5         28 Marpa::R3::exception($eval_error);
732             }
733 1952         6355 return @results;
734             }
735              
736             sub Marpa::R3::Grammar::symbol_ids_gen {
737 2     2   907 my ($slg) = @_;
738 2         4 my $next = 1;
739 2         7 my $last = $slg->highest_symbol_id();
740             return sub () {
741 84 100   84   290 return if $next > $last;
742 82         88 my $current;
743 82         97 ($current, $next) = ($next, $next+1);
744 82         112 return $current;
745             }
746 2         17 }
747              
748             sub Marpa::R3::Grammar::lmg_symbol_ids_gen {
749 0     0   0 my ($slg, $subg) = @_;
750 0         0 my $next = 0;
751 0         0 my $last = $slg->lmg_highest_symbol_id($subg);
752             return sub () {
753 0 0   0   0 return if $next > $last;
754 0         0 my $current;
755 0         0 ($current, $next) = ($next, $next+1);
756 0         0 return $current;
757             }
758 0         0 }
759              
760             sub Marpa::R3::Grammar::g1_symbol_ids_gen {
761 6     6   3005 my ($slg) = @_;
762 6         14 my $next = 0;
763 6         245 my $last = $slg->g1_highest_symbol_id();
764             return sub () {
765 65 100   65   235 return if $next > $last;
766 61         69 my $current;
767 61         77 ($current, $next) = ($next, $next+1);
768 61         89 return $current;
769             }
770 6         46 }
771              
772             sub Marpa::R3::Grammar::l0_symbol_ids_gen {
773 2     2   934 my ($slg) = @_;
774 2         4 my $next = 0;
775 2         7 my $last = $slg->l0_highest_symbol_id();
776             return sub () {
777 70 100   70   449 return if $next > $last;
778 68         76 my $current;
779 68         81 ($current, $next) = ($next, $next+1);
780 68         93 return $current;
781             }
782 2         16 }
783              
784             sub Marpa::R3::Grammar::production_ids_gen {
785 3     3   6639 my ($slg) = @_;
786 3         8 my $next = 1;
787 3         36 my $last = $slg->highest_production_id();
788             return sub () {
789 144 100   144   674 return if $next > $last;
790 141         139 my $current;
791 141         209 ($current, $next) = ($next, $next+1);
792 141         232 return $current;
793             }
794 3         68 }
795              
796             sub Marpa::R3::Grammar::lmg_rule_ids_gen {
797 0     0   0 my ($slg, $subg) = @_;
798 0         0 my $next = 0;
799 0         0 my $last = $slg->lmg_highest_rule_id($subg);
800             return sub () {
801 0 0   0   0 return if $next > $last;
802 0         0 my $current;
803 0         0 ($current, $next) = ($next, $next+1);
804 0         0 return $current;
805             }
806 0         0 }
807              
808             sub Marpa::R3::Grammar::g1_rule_ids_gen {
809 1867     1867   9196 my ($slg) = @_;
810 1867         3079 my $next = 0;
811 1867         4673 my $last = $slg->g1_highest_rule_id();
812             return sub () {
813 51968 100   51968   82401 return if $next > $last;
814 50476         65475 my $current;
815 50476         64966 ($current, $next) = ($next, $next+1);
816 50476         81245 return $current;
817             }
818 1867         12154 }
819              
820             sub Marpa::R3::Grammar::l0_rule_ids_gen {
821 4     4   4108 my ($slg) = @_;
822 4         9 my $next = 0;
823 4         10 my $last = $slg->l0_highest_rule_id();
824             return sub () {
825 112 100   112   460 return if $next > $last;
826 108         107 my $current;
827 108         136 ($current, $next) = ($next, $next+1);
828 108         147 return $current;
829             }
830 4         27 }
831              
832             # not to be documented
833             sub Marpa::R3::Grammar::nrls_show {
834 7     7   21 my ($slg) = @_;
835 7         26 my ($result) =
836             $slg->call_by_tag(
837             ('@' . __FILE__ . ':' . __LINE__),
838             <<'END_OF_LUA', '' );
839             local grammar = ...
840             local g1g = grammar.g1
841             local nrl_count = g1g:_nrl_count()
842             local pieces = {}
843             for nrl_id = 0, nrl_count - 1 do
844             pieces[#pieces+1] = g1g:brief_nrl(nrl_id)
845             end
846             pieces[#pieces+1] = ''
847             return table.concat(pieces, '\n')
848             END_OF_LUA
849 7         158 return $result;
850             }
851              
852             # not to be documented
853             sub Marpa::R3::Grammar::nsys_show {
854 4     4   13 my ($slg) = @_;
855 4         17 my ($result) =
856             $slg->call_by_tag(
857             ('@' . __FILE__ . ':' . __LINE__),
858             <<'END_OF_LUA', '' );
859             local grammar = ...
860             local g1g = grammar.g1
861             return g1g:nsys_show()
862             END_OF_LUA
863 4         20 return $result;
864             }
865              
866             # not to be documented
867             sub Marpa::R3::Grammar::ahms_show {
868 13     13   2913 my ( $slg, $options ) = @_;
869 13   100     86 $options //= {};
870 13 100       353 my $verbose = $options->{verbose} or 0;
871              
872 13         270 my ($text) = $slg->call_by_tag(
873             ('@' . __FILE__ . ':' . __LINE__),
874             <<'END_OF_LUA', 'i', $verbose );
875             local grammar, verbose = ...
876             local g1g = grammar.g1
877             return g1g:ahms_show({verbose = verbose})
878             END_OF_LUA
879              
880 13         73 return $text;
881              
882             }
883              
884             # not to be documented
885             sub Marpa::R3::Grammar::dotted_nrl_show {
886 452     452   675 my ( $slg, $nrl_id, $dot_position ) = @_;
887 452         859 my ($result) =
888             $slg->call_by_tag(
889             ('@' . __FILE__ . ':' . __LINE__),
890             <<'END_OF_LUA', 'ii', $nrl_id, $dot_position );
891             local grammar, nrl_id, dot_position = ...
892             local g1g = grammar.g1
893             return g1g:_dotted_nrl_show(nrl_id, dot_position)
894             END_OF_LUA
895 452         1188 return $result;
896             }
897              
898             # not to be documented
899             sub Marpa::R3::Grammar::briefer_ahm {
900 549     549   746 my ( $slg, $item_id ) = @_;
901              
902 549         938 my ($text) = $slg->call_by_tag(
903             ('@' . __FILE__ . ':' . __LINE__),
904             <<'END_OF_LUA', 'i', $item_id );
905             local grammar, item_id = ...
906             local g1g = grammar.g1
907             local irl_id = g1g:_ahm_nrl(item_id)
908             local dot_position = g1g:_ahm_position(item_id)
909             if (dot_position < 0 ) then
910             return string.format("R%d$", irl_id)
911             end
912             return string.format("R%d:%d", irl_id, dot_position)
913             END_OF_LUA
914              
915 549         1087 return $text;
916              
917             }
918              
919             # not to be documented
920             sub Marpa::R3::Grammar::brief_nrl {
921 0     0   0 my ( $slg, $nrl_id ) = @_;
922 0         0 my ($text) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
923             <<'END_OF_LUA', 'i', $nrl_id );
924             local grammar, nrl_id = ...
925             local g1g = grammar.g1
926             return g1g:brief_nrl(nrl_id)
927             END_OF_LUA
928              
929 0         0 return $text;
930             }
931              
932             # not to be documented
933             sub Marpa::R3::Grammar::regix {
934 1     1   6632 my ( $slg ) = @_;
935 1         3 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
936 1         2 return $regix;
937             }
938              
939             sub registrations_find {
940 373     373   969 my ($slg) = @_;
941 373         946 my $trace_file_handle =
942             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
943 373   50     1970 my $trace_actions =
944             $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] // 0;
945              
946 373         813 my @closure_by_irlid = ();
947 373         723 my @semantics_by_irlid = ();
948 373         796 my @blessing_by_irlid = ();
949              
950 373         1661 my ( $rule_resolutions, $lexeme_resolutions ) = resolve_grammar($slg);
951              
952             # Set the arrays, and perform various checks on the resolutions
953             # we received
954             {
955 372         833 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
  372         3789  
956             my ( $new_resolution, $closure, $semantics, $blessing ) =
957 12200         12995 @{ $rule_resolutions->[$irlid] };
  12200         24246  
958 12200         23839 my ($lhs_id) =
959             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
960             <<'END_OF_LUA', 'i>*', $irlid );
961             local grammar, irlid = ...
962             local g1g = grammar.g1
963             return g1g:rule_lhs(irlid)
964             END_OF_LUA
965              
966             REFINE_SEMANTICS: {
967              
968 12200 100 66     14504 if (
  12200         35100  
969             '[' eq substr $semantics,
970             0, 1 and ']' eq substr $semantics,
971             -1, 1
972             )
973             {
974             # Normalize array semantics
975 10777         92700 $semantics =~ s/ //gxms;
976 10777         15564 last REFINE_SEMANTICS;
977             } ## end if ( '[' eq substr $semantics, 0, 1 and ']' eq ...)
978              
979             state $allowed_semantics = {
980 1423         1968 map { ; ( $_, 1 ) } qw(::array ::undef ::first ::!default),
  510         1404  
981             q{}
982             };
983 1423 50       4015 last REFINE_SEMANTICS if $allowed_semantics->{$semantics};
984             last REFINE_SEMANTICS
985 0 0       0 if $semantics =~ m/ \A rhs \d+ \z /xms;
986              
987 0         0 Marpa::R3::exception(
988             q{Unknown semantics for rule },
989             $slg->g1_rule_show($irlid),
990             "\n",
991             qq{ Semantics were specified as "$semantics"\n}
992             );
993              
994             } ## end REFINE_SEMANTICS:
995              
996 12200         18605 $semantics_by_irlid[$irlid] = $semantics;
997 12200         15871 $blessing_by_irlid[$irlid] = $blessing;
998 12200         14351 $closure_by_irlid[$irlid] = $closure;
999              
1000             CHECK_BLESSING: {
1001 12200 100       12857 last CHECK_BLESSING if $blessing eq '::undef';
  12200         20236  
1002 10738 50       14678 if ($closure) {
1003 0         0 my $ref_type = Scalar::Util::reftype $closure;
1004 0 0       0 if ( $ref_type eq 'SCALAR' ) {
1005              
1006             # The constant's dump might be long so I repeat the error message
1007 0         0 Marpa::R3::exception(
1008             qq{Fatal error: Attempt to bless a rule that resolves to a scalar constant\n},
1009             qq{ Scalar constant is },
1010             Data::Dumper::Dumper($closure),
1011             qq{ Blessing is "$blessing"\n},
1012             q{ Rule is: },
1013             $slg->g1_rule_show($irlid),
1014             "\n",
1015             qq{ Cannot bless rule when it resolves to a scalar constant},
1016             "\n",
1017             );
1018             } ## end if ( $ref_type eq 'SCALAR' )
1019 0         0 last CHECK_BLESSING;
1020             } ## end if ($closure)
1021 10738 100       14521 last CHECK_BLESSING if $semantics eq '::array';
1022 10668 50       24883 last CHECK_BLESSING if ( substr $semantics, 0, 1 ) eq '[';
1023 0         0 Marpa::R3::exception(
1024             qq{Cannot bless rule when the semantics are "$semantics"},
1025             q{ Rule is: },
1026             $slg->g1_rule_show($irlid),
1027             "\n",
1028             qq{ Blessing is "$blessing"\n},
1029             qq{ Semantics are "$semantics"\n}
1030             );
1031             } ## end CHECK_BLESSING:
1032              
1033             }
1034              
1035             } ## end CHECK_FOR_WHATEVER_CONFLICT
1036              
1037             # A LHS can be nullable via more than one rule,
1038             # and that means more than one semantics might be specified for
1039             # the nullable symbol. This logic deals with that.
1040 372         942 my @nullable_rule_ids_by_lhs = ();
1041 372         1103 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1042              
1043 12200         22568 my ( $lhs_id, $rule_is_nullable ) =
1044             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1045             <<'END_OF_LUA', 'i>*', $irlid );
1046             local grammar, irlid = ...
1047             local g1g = grammar.g1
1048             return g1g:rule_lhs(irlid), g1g:rule_is_nullable(irlid)
1049             END_OF_LUA
1050              
1051 12200 100       26676 push @{ $nullable_rule_ids_by_lhs[$lhs_id] }, $irlid
  554         1975  
1052             if $rule_is_nullable;
1053             }
1054              
1055 372         785 my @null_symbol_closures;
1056             LHS:
1057 372         1690 for ( my $lhs_id = 0 ; $lhs_id <= $#nullable_rule_ids_by_lhs ; $lhs_id++ ) {
1058 8121         8711 my $irlids = $nullable_rule_ids_by_lhs[$lhs_id];
1059 8121         8549 my $resolution_rule;
1060              
1061             # No nullable rules for this LHS? No problem.
1062 8121 100       14204 next LHS if not defined $irlids;
1063 548         731 my $rule_count = scalar @{$irlids};
  548         825  
1064              
1065             # I am not sure if this test is necessary
1066 548 50       1346 next LHS if $rule_count <= 0;
1067              
1068             # Just one nullable rule? Then that's our semantics.
1069 548 100       1080 if ( $rule_count == 1 ) {
1070 542         780 $resolution_rule = $irlids->[0];
1071             my ( $resolution_name, $closure ) =
1072 542         746 @{ $rule_resolutions->[$resolution_rule] };
  542         1273  
1073 542 50       1182 if ($trace_actions) {
1074 0         0 my $lhs_name = $slg->g1_symbol_display_form($lhs_id);
1075 0 0       0 say {$trace_file_handle}
  0         0  
1076             qq{Nulled symbol "$lhs_name" },
1077             qq{ resolved to "$resolution_name" from rule },
1078             $slg->g1_rule_show($resolution_rule)
1079             or Marpa::R3::exception('print to trace handle failed');
1080             } ## end if ($trace_actions)
1081 542         1221 $null_symbol_closures[$lhs_id] = $resolution_rule;
1082 542         1281 next LHS;
1083             } ## end if ( $rule_count == 1 )
1084              
1085             # More than one rule? Are any empty?
1086             # If so, use the semantics of the empty rule
1087 6         23 my ($empty_rules) =
1088             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1089             <<'END_OF_LUA', 'i>*', $irlids );
1090             local grammar, irlids = ...
1091             local g1g = grammar.g1
1092             local empty_rules = {}
1093             for ix = 1, #irlids do
1094             local irlid = irlids[ix]
1095             local rule_length = g1g:rule_length(irlid)
1096             if rule_length and rule_length == 0 then
1097             empty_rules[#empty_rules+1] = irlid
1098             end
1099             end
1100             return empty_rules
1101             END_OF_LUA
1102              
1103 6 100       13 if ( scalar @{$empty_rules} ) {
  6         22  
1104 5         10 $resolution_rule = $empty_rules->[0];
1105             my ( $resolution_name, $closure ) =
1106 5         8 @{ $rule_resolutions->[$resolution_rule] };
  5         12  
1107 5 50       15 if ($trace_actions) {
1108 0         0 my $lhs_name = $slg->g1_symbol_display_form($lhs_id);
1109 0 0       0 say {$trace_file_handle}
  0         0  
1110             qq{Nulled symbol "$lhs_name" },
1111             qq{ resolved to "$resolution_name" from rule },
1112             $slg->g1_rule_show($resolution_rule)
1113             or Marpa::R3::exception('print to trace handle failed');
1114             } ## end if ($trace_actions)
1115 5         9 $null_symbol_closures[$lhs_id] = $resolution_rule;
1116 5         17 next LHS;
1117             }
1118              
1119             # Multiple rules, none of them empty.
1120             my ( $first_resolution, @other_resolutions ) =
1121 1         3 map { $rule_resolutions->[$_] } @{$irlids};
  2         6  
  1         3  
1122              
1123             # Do they have more than one semantics?
1124             # If so, just call it an error and let the user sort it out.
1125             my ( $first_closure_name, undef, $first_semantics, $first_blessing ) =
1126 1         3 @{$first_resolution};
  1         3  
1127 1         6 OTHER_RESOLUTION: for my $other_resolution (@other_resolutions) {
1128             my ( $other_closure_name, undef, $other_semantics, $other_blessing )
1129 1         2 = @{$other_resolution};
  1         4  
1130              
1131 1 50 33     12 if ( $first_closure_name ne $other_closure_name
      33        
1132             or $first_semantics ne $other_semantics
1133             or $first_blessing ne $other_blessing )
1134             {
1135 0         0 Marpa::R3::exception(
1136             'When nulled, symbol ',
1137             $slg->g1_symbol_display_form($lhs_id),
1138             qq{ can have more than one semantics\n},
1139             qq{ Marpa needs there to be only one semantics\n},
1140             qq{ The rules involved are:\n},
1141             g1_show_rule_list( $slg, $irlids )
1142             );
1143             } ## end if ( $first_closure_name ne $other_closure_name or ...)
1144             } ## end OTHER_RESOLUTION: for my $other_resolution (@other_resolutions)
1145              
1146             # Multiple rules, but they all have one semantics.
1147             # So (obviously) use that semantics
1148 1         2 $resolution_rule = $irlids->[0];
1149             my ( $resolution_name, $closure ) =
1150 1         3 @{ $rule_resolutions->[$resolution_rule] };
  1         3  
1151 1 50       4 if ($trace_actions) {
1152 0         0 my $lhs_name = $slg->g1_symbol_display_form($lhs_id);
1153 0 0       0 say {$trace_file_handle}
  0         0  
1154             qq{Nulled symbol "$lhs_name" },
1155             qq{ resolved to "$resolution_name" from rule },
1156             $slg->g1_rule_show($resolution_rule)
1157             or Marpa::R3::exception('print to trace handle failed');
1158             } ## end if ($trace_actions)
1159 1         4 $null_symbol_closures[$lhs_id] = $resolution_rule;
1160              
1161             } ## end LHS: for ( my $lhs_id = 0; $lhs_id <= $#nullable_rule_ids_by_lhs...)
1162              
1163             # Do consistency checks
1164              
1165             # Set the object values
1166 372         1266 my $null_values = $slg->[Marpa::R3::Internal_G::NULL_VALUES] =
1167             \@null_symbol_closures;
1168              
1169 372         757 my @semantics_by_lexeme_id = ();
1170 372         705 my @blessing_by_lexeme_id = ();
1171              
1172             # Check the lexeme semantics
1173             {
1174 372         742 my ($highest_symbol_id) =
  372         1298  
1175             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1176             <<'END_OF_LUA', '>*' );
1177             local grammar = ...
1178             local g1g = grammar.g1
1179             return g1g:highest_symbol_id()
1180             END_OF_LUA
1181              
1182 372         1557 LEXEME: for my $lexeme_id ( 0 .. $highest_symbol_id ) {
1183              
1184             my ( $semantics, $blessing ) =
1185 14483         14623 @{ $lexeme_resolutions->[$lexeme_id] };
  14483         21998  
1186 14483 50       21229 $blessing = '::undef' if not defined $blessing;
1187             CHECK_SEMANTICS: {
1188 14483 50       14602 if ( not $semantics ) {
  14483         18883  
1189 0         0 $semantics = '::!default';
1190 0         0 last CHECK_SEMANTICS;
1191             }
1192 14483 100       21877 if ( ( substr $semantics, 0, 1 ) eq '[' ) {
1193 7830         60508 $semantics =~ s/ //gxms;
1194 7830         10219 last CHECK_SEMANTICS;
1195             }
1196             state $allowed_semantics =
1197 6653         7071 { map { ; ( $_, 1 ) } qw(::array ::undef ::!default ) };
  306         824  
1198              
1199 6653 50       9942 if ( not $allowed_semantics->{$semantics} ) {
1200 0         0 Marpa::R3::exception(
1201             q{Unknown semantics for lexeme },
1202             $slg->g1_symbol_display_form($lexeme_id),
1203             "\n",
1204             qq{ Semantics were specified as "$semantics"\n}
1205             );
1206             } ## end if ( not $allowed_semantics->{$semantics} )
1207              
1208             } ## end CHECK_SEMANTICS:
1209 14483         23408 $semantics_by_lexeme_id[$lexeme_id] = $semantics;
1210 14483         20722 $blessing_by_lexeme_id[$lexeme_id] = $blessing;
1211              
1212             }
1213              
1214             }
1215              
1216             # state $op_lua = Marpa::R3::Thin::op('lua');
1217 372         1460 my ($op_lua) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1218             <<'END_OF_LUA', '' );
1219             return _M.defines.MARPA_OP_LUA
1220             END_OF_LUA
1221              
1222 372         1808 my ($op_debug_key) = op_fn_key_by_name( $slg, "debug" );
1223 372         966 my ($op_noop_key) = op_fn_key_by_name( $slg, "noop" );
1224 372         1047 my ($op_bail_key) = op_fn_key_by_name( $slg, "bail" );
1225 372         1011 my ($op_bless_key) = op_fn_key_by_name( $slg, "bless" );
1226 372         1005 my ($op_callback_key) = op_fn_key_by_name( $slg, "callback" );
1227 372         980 my ($result_is_undef_key) = op_fn_key_by_name( $slg, 'result_is_undef' );
1228 372         944 my ($result_is_constant_key) =
1229             op_fn_key_by_name( $slg, 'result_is_constant' );
1230 372         1319 my ($result_is_token_value_key) =
1231             op_fn_key_by_name( $slg, "result_is_token_value" );
1232 372         940 my ($result_is_n_of_rhs_key) =
1233             op_fn_key_by_name( $slg, "result_is_n_of_rhs" );
1234 372         1054 my ($result_is_n_of_sequence_key) =
1235             op_fn_key_by_name( $slg, "result_is_n_of_sequence" );
1236 372         956 my ($result_is_array_key) = op_fn_key_by_name( $slg, "result_is_array" );
1237 372         960 my ($op_push_constant_key) = op_fn_key_by_name( $slg, 'push_constant' );
1238 372         1003 my ($op_push_undef_key) = op_fn_key_by_name( $slg, 'push_undef' );
1239 372         960 my ($op_push_one_key) = op_fn_key_by_name( $slg, 'push_one' );
1240 372         1108 my ($op_push_values_key) = op_fn_key_by_name( $slg, 'push_values' );
1241 372         977 my ($op_push_g1_start_key) = op_fn_key_by_name( $slg, 'push_g1_start' );
1242 372         966 my ($op_push_g1_length_key) = op_fn_key_by_name( $slg, 'push_g1_length' );
1243 372         1058 my ($op_push_start_key) = op_fn_key_by_name( $slg, 'push_start' );
1244 372         916 my ($op_push_length_key) = op_fn_key_by_name( $slg, 'push_length' );
1245              
1246 372         727 my @nulling_symbol_by_semantic_rule;
1247 372         725 NULLING_SYMBOL: for my $nulling_symbol ( 0 .. $#{$null_values} ) {
  372         1616  
1248 8121         8612 my $semantic_rule = $null_values->[$nulling_symbol];
1249 8121 100       11545 next NULLING_SYMBOL if not defined $semantic_rule;
1250 548         1022 $nulling_symbol_by_semantic_rule[$semantic_rule] = $nulling_symbol;
1251             } ## end NULLING_SYMBOL: for my $nulling_symbol ( 0 .. $#{$null_values} )
1252              
1253 372         856 my @work_list = ();
1254 372         1105 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1255              
1256 12200         15024 my $semantics = $semantics_by_irlid[$irlid];
1257 12200         13929 my $blessing = $blessing_by_irlid[$irlid];
1258              
1259 12200 100       16378 $semantics = '[name,values]' if $semantics eq '::!default';
1260 12200 100       16371 $semantics = '[values]' if $semantics eq '::array';
1261 12200 100       17502 $semantics = '::rhs0' if $semantics eq '::first';
1262              
1263 12200         25286 push @work_list, [ $irlid, undef, $semantics, $blessing ];
1264             }
1265              
1266 372         1294 my ($highest_symbol_id) =
1267             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1268             <<'END_OF_LUA', '' );
1269             local grammar = ...
1270             return grammar.g1:highest_symbol_id()
1271             END_OF_LUA
1272              
1273 372         1375 LEXEME: for my $lexeme_id ( 0 .. $highest_symbol_id ) {
1274              
1275 14483         16939 my $semantics = $semantics_by_lexeme_id[$lexeme_id];
1276 14483         15167 my $blessing = $blessing_by_lexeme_id[$lexeme_id];
1277              
1278             next LEXEME
1279 14483 100 100     26830 if $semantics eq '::!default' and $blessing eq '::undef';
1280 12848 100       17053 $semantics = '::value' if $semantics eq '::!default';
1281 12848 50       16254 $semantics = '[value]' if $semantics eq '::array';
1282              
1283 12848         23294 push @work_list, [ undef, $lexeme_id, $semantics, $blessing ];
1284             }
1285              
1286             # Registering operations is postponed to this point, because
1287             # the valuator must exist for this to happen. In the future,
1288             # it may be best to have a separate semantics object.
1289 372         840 my @nulling_closures = ();
1290 372         728 my @registrations = ();
1291              
1292 372         879 WORK_ITEM: for my $work_item (@work_list) {
1293 25048         27598 my ( $irlid, $lexeme_id, $semantics, $blessing ) = @{$work_item};
  25048         43907  
1294              
1295 25048         33273 my ( $closure, $rule_length,
1296             $is_sequence_rule,
1297             $is_discard_sequence_rule,
1298             $nulling_symbol_id );
1299 25048 100       35556 if ( defined $irlid ) {
1300 12200         20114 $nulling_symbol_id = $nulling_symbol_by_semantic_rule[$irlid];
1301 12200         15602 $closure = $closure_by_irlid[$irlid];
1302              
1303 12200         33085 ( $rule_length, $is_sequence_rule,
1304             $is_discard_sequence_rule ) =
1305             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1306             <<'END_OF_LUA', 'i', $irlid );
1307             local slg, irlid = ...
1308             local g1g = slg.g1
1309             local is_sequence_rule = g1g:sequence_min(irlid) and 1 or 0
1310             local irl = slg.g1.irls[irlid]
1311             local xpr = irl.xpr
1312             local is_discard_sequence = false
1313             if xpr and xpr.discard_separation and is_sequence_rule then
1314             is_discard_sequence = true
1315             end
1316             return g1g:rule_length(irlid), is_sequence_rule, is_discard_sequence
1317             END_OF_LUA
1318              
1319             } ## end if ( defined $irlid )
1320              
1321             # Determine the "fate" of the array of child values
1322 25048         32672 my @array_fate = ();
1323             ARRAY_FATE: {
1324 25048 100 100     26333 if ( defined $closure and ref $closure eq 'CODE' ) {
  25048         40169  
1325 345         723 push @array_fate, $op_lua, $op_callback_key, $op_bail_key;
1326 345         560 last ARRAY_FATE;
1327              
1328             }
1329              
1330 24703 100       44469 if ( ( substr $semantics, 0, 1 ) eq '[' ) {
1331 19139         24785 push @array_fate, $op_lua, $result_is_array_key, $op_bail_key;
1332 19139         25095 last ARRAY_FATE;
1333             }
1334             } ## end ARRAY_FATE:
1335              
1336 25048         27753 my @ops = ();
1337              
1338             SET_OPS: {
1339              
1340 25048 100       26312 if ( $semantics eq '::undef' ) {
  25048         36105  
1341 31         49 @ops = ( $op_lua, $result_is_undef_key, $op_bail_key );
1342 31         43 last SET_OPS;
1343             }
1344              
1345             CHECK_TYPE: {
1346 25017 100       26292 last CHECK_TYPE if not defined $irlid;
  25017         36062  
1347 12169         15119 my $thingy_ref = $closure_by_irlid[$irlid];
1348 12169 100       20309 last CHECK_TYPE if not defined $thingy_ref;
1349 345         1358 my $ref_type = Scalar::Util::reftype $thingy_ref;
1350 345 50       692 if ( $ref_type eq q{} ) {
1351 0         0 my $rule_desc = $slg->g1_rule_show($irlid);
1352 0         0 Marpa::R3::exception(
1353             qq{An action resolved to a scalar.\n},
1354             qq{ This is not allowed.\n},
1355             qq{ A constant action must be a reference.\n},
1356             qq{ Rule was $rule_desc\n}
1357             );
1358             } ## end if ( $ref_type eq q{} )
1359              
1360 345 50       709 if ( $ref_type eq 'CODE' ) {
1361              
1362             # Set the nulling closure if this is the nulling symbol of a rule
1363 345 100 66     935 $nulling_closures[$nulling_symbol_id] = $thingy_ref
1364             if defined $nulling_symbol_id
1365             and defined $irlid;
1366 345         526 last CHECK_TYPE;
1367             } ## end if ( $ref_type eq 'CODE' )
1368              
1369 0         0 my $rule_desc = $slg->g1_rule_show($irlid);
1370 0         0 Marpa::R3::exception(
1371             qq{Constant action is not of an allowed type.\n},
1372             qq{ It was of type reference to $ref_type.\n},
1373             qq{ Rule was $rule_desc\n}
1374             );
1375             }
1376              
1377             # After this point, any closure will be a ref to 'CODE'
1378              
1379 25017 100 100     48763 if ( defined $lexeme_id and $semantics eq '::value' ) {
1380 5018         6273 @ops = ( $op_lua, $result_is_token_value_key, $op_bail_key );
1381 5018         5652 last SET_OPS;
1382             }
1383              
1384             PROCESS_SINGLETON_RESULT: {
1385 19999 100       20300 last PROCESS_SINGLETON_RESULT if not defined $irlid;
  19999         27618  
1386              
1387 12169         13191 my $singleton;
1388 12169 100       23705 if ( $semantics =~ m/\A [:][:] rhs (\d+) \z/xms ) {
1389 515         1679 $singleton = $1 + 0;
1390             }
1391              
1392 12169 100       19072 last PROCESS_SINGLETON_RESULT if not defined $singleton;
1393              
1394 515         809 my $singleton_element = $singleton;
1395 515 50       1163 if ($is_discard_sequence_rule) {
1396 0         0 @ops = (
1397             $op_lua, $result_is_n_of_sequence_key,
1398             $singleton_element
1399             );
1400 0         0 last SET_OPS;
1401             }
1402 515 50       1207 if ($is_sequence_rule) {
1403 0         0 @ops =
1404             ( $op_lua, $result_is_n_of_rhs_key, $singleton_element );
1405 0         0 last SET_OPS;
1406             }
1407              
1408 515         1699 my ($mask) = $slg->call_by_tag(
1409             ( '@' . __FILE__ . ':' . __LINE__ ),
1410             <<'END_OF_LUA', 'i>0', $irlid );
1411             local slg, irlid = ...
1412             return slg.g1.irls[irlid].mask
1413             END_OF_LUA
1414              
1415             my @elements =
1416 515         1653 grep { $mask->[$_] } 0 .. ( $rule_length - 1 );
  521         1546  
1417 515 50       1393 if ( not scalar @elements ) {
1418 0         0 my $original_semantics = $semantics_by_irlid[$irlid];
1419 0         0 Marpa::R3::exception(
1420             q{Impossible semantics for empty rule: },
1421             $slg->g1_rule_show($irlid),
1422             "\n",
1423             qq{ Semantics were specified as "$original_semantics"\n}
1424             );
1425             } ## end if ( not scalar @elements )
1426 515         1033 $singleton_element = $elements[$singleton];
1427              
1428 515 50       1273 if ( not defined $singleton_element ) {
1429 0         0 my $original_semantics = $semantics_by_irlid[$irlid];
1430 0         0 Marpa::R3::exception(
1431             q{Impossible semantics for rule: },
1432             $slg->g1_rule_show($irlid),
1433             "\n",
1434             qq{ Semantics were specified as "$original_semantics"\n}
1435             );
1436             } ## end if ( not defined $singleton_element )
1437 515         1001 @ops = ( $op_lua, $result_is_n_of_rhs_key, $singleton_element );
1438 515         1261 last SET_OPS;
1439             } ## end PROCESS_SINGLETON_RESULT:
1440              
1441 19484 50       34964 if ( not @array_fate ) {
1442 0         0 @ops = ( $op_lua, $result_is_undef_key, $op_bail_key );
1443 0         0 last SET_OPS;
1444             }
1445              
1446             # if here, @array_fate is non-empty
1447              
1448 19484         23038 my @bless_ops = ();
1449 19484 100       30055 if ( $blessing ne '::undef' ) {
1450 18440         37498 push @bless_ops, $op_lua, $op_bless_key, \[$irlid, $lexeme_id, $blessing];
1451             }
1452              
1453 19484 50       33801 Marpa::R3::exception(qq{Unknown semantics: "$semantics"})
1454             if ( substr $semantics, 0, 1 ) ne '[';
1455              
1456 19484         23311 my @push_ops = ();
1457 19484         26396 my $array_descriptor = substr $semantics, 1, -1;
1458 19484         118869 $array_descriptor =~ s/^\s*|\s*$//g;
1459             RESULT_DESCRIPTOR:
1460 19484         90732 for my $result_descriptor ( split /[,]\s*/xms, $array_descriptor ) {
1461 56815         208198 $result_descriptor =~ s/^\s*|\s*$//g;
1462 56815 100       96605 if ( $result_descriptor eq 'g1start' ) {
1463 70         121 push @push_ops, $op_lua, $op_push_g1_start_key,
1464             $op_bail_key;
1465 70         112 next RESULT_DESCRIPTOR;
1466             }
1467 56745 100       83858 if ( $result_descriptor eq 'g1length' ) {
1468 70         114 push @push_ops, $op_lua, $op_push_g1_length_key,
1469             $op_bail_key;
1470 70         98 next RESULT_DESCRIPTOR;
1471             }
1472 56675 100       73983 if ( $result_descriptor eq 'start' ) {
1473 18319         24262 push @push_ops, $op_lua, $op_push_start_key, $op_bail_key;
1474 18319         24482 next RESULT_DESCRIPTOR;
1475             }
1476 38356 100       66746 if ( $result_descriptor eq 'length' ) {
1477 18319         23099 push @push_ops, $op_lua, $op_push_length_key, $op_bail_key;
1478 18319         22978 next RESULT_DESCRIPTOR;
1479             }
1480              
1481 20037 100       28785 if ( $result_descriptor eq 'lhs' ) {
1482 8 100       14 if ( defined $irlid ) {
1483              
1484 3         10 my ($lhs_id) = $slg->call_by_tag(
1485             ( '@' . __FILE__ . ':' . __LINE__ ),
1486             <<'END_OF_LUA', 'i>*', $irlid );
1487             local grammar, irlid = ...
1488             local g1g = grammar.g1
1489             return g1g:rule_lhs(irlid)
1490             END_OF_LUA
1491 3         4 push @push_ops, $op_lua, $op_push_constant_key,
1492             \$lhs_id;
1493 3         7 next RESULT_DESCRIPTOR;
1494             }
1495 5 50       10 if ( defined $lexeme_id ) {
1496 5         6 push @push_ops, $op_lua, $op_push_constant_key,
1497             \$lexeme_id;
1498 5         8 next RESULT_DESCRIPTOR;
1499             }
1500 0         0 push @push_ops, $op_lua, $op_push_undef_key, $op_bail_key;
1501 0         0 next RESULT_DESCRIPTOR;
1502             } ## end if ( $result_descriptor eq 'lhs' )
1503              
1504 20029 100       28177 if ( $result_descriptor eq 'name' ) {
1505 522 100       957 if ( defined $irlid ) {
1506 444         2357 my $production_id =
1507             $slg->g1_rule_to_production_id($irlid);
1508 444         987 my $name = $slg->production_name($production_id);
1509 444         853 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1510 444         1045 next RESULT_DESCRIPTOR;
1511             }
1512 78 50       132 if ( defined $lexeme_id ) {
1513 78         164 my $name = $slg->g1_symbol_name($lexeme_id);
1514 78         126 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1515 78         142 next RESULT_DESCRIPTOR;
1516             }
1517 0 0       0 if ( defined $nulling_symbol_id ) {
1518 0         0 my $name = $slg->g1_symbol_name($nulling_symbol_id);
1519 0         0 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1520 0         0 next RESULT_DESCRIPTOR;
1521             }
1522 0         0 push @push_ops, $op_lua, $op_push_undef_key, $op_bail_key;
1523 0         0 next RESULT_DESCRIPTOR;
1524             } ## end if ( $result_descriptor eq 'name' )
1525              
1526 19507 100       27126 if ( $result_descriptor eq 'symbol' ) {
1527 16 100       29 if ( defined $irlid ) {
1528 6         17 my ($name) = $slg->call_by_tag(
1529             ( '@' . __FILE__ . ':' . __LINE__ ),
1530             <<'END_OF_LUA', 'i>*', $irlid );
1531             local grammar, irlid = ...
1532             local g1g = grammar.g1
1533             local lhs_id = g1g:rule_lhs(irlid)
1534             return g1g:symbol_name(lhs_id)
1535             END_OF_LUA
1536 6         13 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1537 6         10 next RESULT_DESCRIPTOR;
1538             } ## end if ( defined $irlid )
1539 10 50       14 if ( defined $lexeme_id ) {
1540 10         25 my $name = $slg->g1_symbol_name($lexeme_id);
1541 10         19 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1542 10         42 next RESULT_DESCRIPTOR;
1543             }
1544 0 0       0 if ( defined $nulling_symbol_id ) {
1545 0         0 my $name = $slg->g1_symbol_name($nulling_symbol_id);
1546 0         0 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1547 0         0 next RESULT_DESCRIPTOR;
1548             }
1549 0         0 push @push_ops, $op_lua, $op_push_undef_key, $op_bail_key;
1550 0         0 next RESULT_DESCRIPTOR;
1551             } ## end if ( $result_descriptor eq 'symbol' )
1552              
1553 19491 100       27854 if ( $result_descriptor eq 'rule' ) {
1554 8 100       13 if ( defined $irlid ) {
1555 3         4 push @push_ops, $op_lua, $op_push_constant_key, \$irlid;
1556 3         5 next RESULT_DESCRIPTOR;
1557             }
1558 5         6 push @push_ops, $op_lua, $op_push_undef_key, $op_bail_key;
1559 5         7 next RESULT_DESCRIPTOR;
1560             } ## end if ( $result_descriptor eq 'rule' )
1561 19483 50 66     52088 if ( $result_descriptor eq 'values'
1562             or $result_descriptor eq 'value' )
1563             {
1564 19483 100       28565 if ( defined $lexeme_id ) {
1565 7830         10368 push @push_ops, $op_lua, $op_push_values_key, 1;
1566 7830         10547 next RESULT_DESCRIPTOR;
1567             }
1568 11653 100       16965 if ($is_sequence_rule) {
1569 699 100       1643 push @push_ops, $op_lua, $op_push_values_key,
1570             ( $is_discard_sequence_rule ? 2 : 1 );
1571 699         1236 next RESULT_DESCRIPTOR;
1572             } ## end if ($is_sequence_rule)
1573              
1574 10954         25338 my ($mask) = $slg->call_by_tag(
1575             ( '@' . __FILE__ . ':' . __LINE__ ),
1576             <<'END_OF_LUA', 'i>0', $irlid );
1577             local slg, irlid = ...
1578             return slg.g1.irls[irlid].mask
1579             END_OF_LUA
1580              
1581 10954 100       20008 if ( $rule_length > 0 ) {
1582             push @push_ops, map {
1583 10771 100       20288 $mask->[$_]
  19972         41516  
1584             ? ( $op_lua, $op_push_one_key, $_ )
1585             : ()
1586             } 0 .. $rule_length - 1;
1587             }
1588 10954         23552 next RESULT_DESCRIPTOR;
1589             } ## end if ( $result_descriptor eq 'values' or ...)
1590             Marpa::R3::exception(
1591 0         0 qq{Unknown result descriptor: "$result_descriptor"\n},
1592             qq{ The full semantics were "$semantics"}
1593             );
1594             } ## end RESULT_DESCRIPTOR: for my $result_descriptor ( split /[,]\s*/xms, ...)
1595 19484         49811 @ops = ( @push_ops, @bless_ops, @array_fate );
1596              
1597             } ## end SET_OPS:
1598              
1599 25048 100       38408 if ( defined $irlid ) {
1600 12200         32010 push @registrations, [ 'rule', $irlid, @ops ];
1601             }
1602              
1603 25048 100       38279 if ( defined $nulling_symbol_id ) {
1604              
1605 548         1375 push @registrations, [ 'nulling', $nulling_symbol_id, @ops ];
1606             } ## end if ( defined $nulling_symbol_id )
1607              
1608 25048 100       43632 if ( defined $lexeme_id ) {
1609 12848         40347 push @registrations, [ 'token', $lexeme_id, @ops ];
1610             }
1611              
1612             } ## end WORK_ITEM: for my $work_item (@work_list)
1613              
1614             SLR_NULLING_GRAMMAR_HACK: {
1615              
1616             # A hack for nulling SLR grammars --
1617             # the nulling semantics of the start symbol should
1618             # be those of the symbol on the
1619             # RHS of the start rule --
1620             # so copy them.
1621              
1622 372         752 my $start_symbol_id = $slg->g1_symbol_by_name('[:start:]');
  372         1668  
1623              
1624 372         1382 my ($symbol_is_nullable) =
1625             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1626             <<'END_OF_LUA', 'i>*', $start_symbol_id );
1627             local grammar, irlid = ...
1628             local g1g = grammar.g1
1629             return (g1g:symbol_is_nullable(irlid) and 1 or 0)
1630             END_OF_LUA
1631              
1632 372 50       1188 last SLR_NULLING_GRAMMAR_HACK if not $symbol_is_nullable;
1633              
1634 372         731 my $start_rhs_symbol_id;
1635 372         1325 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1636 1592         3362 my ( $lhs, $rhs0 ) = $slg->g1_rule_expand($irlid);
1637 1592 100       3665 if ( $start_symbol_id == $lhs ) {
1638 372         626 $start_rhs_symbol_id = $rhs0;
1639 372         852 last RULE;
1640             }
1641             }
1642              
1643 372         986 REGISTRATION: for my $registration (@registrations) {
1644 24538         23982 my ( $type, $nulling_symbol_id ) = @{$registration};
  24538         33378  
1645 24538 100       37541 if ( $nulling_symbol_id == $start_rhs_symbol_id ) {
1646 320         571 my ( undef, undef, @ops ) = @{$registration};
  320         1012  
1647 320         1389 push @registrations, [ 'nulling', $start_symbol_id, @ops ];
1648 320         975 $nulling_closures[$start_symbol_id] =
1649             $nulling_closures[$start_rhs_symbol_id];
1650 320         1727 last REGISTRATION;
1651             } ## end if ( $nulling_symbol_id == $start_rhs_symbol_id )
1652             } ## end REGISTRATION: for my $registration (@registrations)
1653             } ## end SLR_NULLING_GRAMMAR_HACK:
1654              
1655 372         1107 $slg->[Marpa::R3::Internal_G::CLOSURE_BY_SYMBOL_ID] =
1656             \@nulling_closures;
1657 372         1090 $slg->[Marpa::R3::Internal_G::CLOSURE_BY_RULE_ID] =
1658             \@closure_by_irlid;
1659              
1660 372         23031 return \@registrations;
1661              
1662             }
1663              
1664             sub resolve_grammar {
1665              
1666 373     373   1033 my ($slg) = @_;
1667              
1668 373   50     1902 my $trace_actions =
1669             $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] // 0;
1670 373         1094 my $trace_file_handle =
1671             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
1672              
1673 373         707 my $resolve_error;
1674              
1675 373         1605 my $default_action_resolution =
1676             resolve_action( $slg, undef, \$resolve_error );
1677 373 50 0     1178 Marpa::R3::exception( "Could not resolve default action\n",
1678             q{ }, ( $resolve_error // 'Failed to resolve action' ) )
1679             if not $default_action_resolution;
1680              
1681 373         951 my $rule_resolutions = [];
1682              
1683 373         1770 RULE_ID: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1684              
1685 12201         17930 my $rule_resolution = resolve_rule_by_id( $slg, $irlid );
1686 12200   66     19011 $rule_resolution //= $default_action_resolution;
1687              
1688 12200 50       16687 if ( not $rule_resolution ) {
1689 0         0 my $rule_desc = $slg->g1_rule_show($irlid);
1690              
1691 0         0 my ($action) =
1692             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1693             <<'END_OF_LUA', 'is>*', $irlid );
1694             local slg, irl_id, rule_desc = ...
1695             local action = slg.g1.irls[irl_id].action
1696             local message = string.format(
1697             "Could not resolve action\n Rule was %s\n",
1698             rule_desc)
1699             if action then
1700             message = message ..
1701             string.format(" Action was specified as %q\n", action)
1702             end
1703             error(message)
1704             END_OF_LUA
1705              
1706             } ## end if ( not $rule_resolution )
1707              
1708             DETERMINE_BLESSING: {
1709              
1710 12200         12994 my $blessing = rule_blessing_find( $slg, $irlid );
  12200         16391  
1711 12200         13899 my ( $closure_name, $closure, $semantics ) = @{$rule_resolution};
  12200         18624  
1712              
1713 12200 100       24142 if ( $blessing ne '::undef' ) {
1714 10738 50       15066 $semantics = '::array' if $semantics eq '::!default';
1715             CHECK_SEMANTICS: {
1716 10738 100       10786 last CHECK_SEMANTICS if $semantics eq '::array';
  10738         14390  
1717             last CHECK_SEMANTICS
1718 10668 50       18623 if ( substr $semantics, 0, 1 ) eq '[';
1719 0         0 Marpa::R3::exception(
1720             qq{Attempt to bless, but improper semantics: "$semantics"\n},
1721             qq{ Blessing: "$blessing"\n},
1722             ' Rule: ',
1723             $slg->g1_rule_show($irlid)
1724             );
1725             } ## end CHECK_SEMANTICS:
1726             } ## end if ( $blessing ne '::undef' )
1727              
1728             $rule_resolution =
1729 12200         28862 [ $closure_name, $closure, $semantics, $blessing ];
1730             } ## end DETERMINE_BLESSING:
1731              
1732 12200         24211 $rule_resolutions->[$irlid] = $rule_resolution;
1733              
1734             }
1735              
1736 372 50       1425 if ( $trace_actions >= 2 ) {
1737              
1738 0         0 my ($highest_irlid) =
1739             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1740             <<'END_OF_LUA', '>*' );
1741             local grammar = ...
1742             local g1g = grammar.g1
1743             return g1g:highest_rule_id()
1744             END_OF_LUA
1745              
1746 0         0 RULE: for my $rule_id ( 0 .. $highest_irlid ) {
1747             my ( $resolution_name, $closure ) =
1748 0         0 @{ $rule_resolutions->[$rule_id] };
  0         0  
1749 0 0       0 say {$trace_file_handle} 'Rule ',
  0         0  
1750             $slg->g1_rule_show($rule_id),
1751             qq{ resolves to "$resolution_name"}
1752             or Marpa::R3::exception('print to trace handle failed');
1753             }
1754             }
1755              
1756 372         914 my @lexeme_resolutions = ();
1757              
1758 372         1322 my ($highest_symbol_id) =
1759             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1760             <<'END_OF_LUA', '>*' );
1761             local grammar = ...
1762             local g1g = grammar.g1
1763             return g1g:highest_symbol_id()
1764             END_OF_LUA
1765              
1766 372         1520 SYMBOL: for my $lexeme_id ( 0 .. $highest_symbol_id ) {
1767              
1768 14483         21153 my $semantics = lexeme_semantics_find( $slg, $lexeme_id );
1769 14483 50       22054 if ( not defined $semantics ) {
1770 0         0 my $message =
1771             "Could not determine lexeme's semantics\n"
1772             . q{ Lexeme was }
1773             . $slg->g1_symbol_display_form($lexeme_id) . "\n";
1774 0         0 Marpa::R3::exception($message);
1775             } ## end if ( not defined $semantics )
1776 14483         19724 my $blessing = lexeme_blessing_find( $slg, $lexeme_id );
1777 14483 50       21777 if ( not defined $blessing ) {
1778 0         0 my $message =
1779             "Could not determine lexeme's blessing\n"
1780             . q{ Lexeme was }
1781             . $slg->g1_symbol_display_form($lexeme_id) . "\n";
1782 0         0 Marpa::R3::exception($message);
1783             } ## end if ( not defined $blessing )
1784 14483         31744 $lexeme_resolutions[$lexeme_id] = [ $semantics, $blessing ];
1785              
1786             }
1787              
1788 372         2725 return ( $rule_resolutions, \@lexeme_resolutions );
1789             }
1790              
1791             # Given the grammar and an action name, resolve it to a closure,
1792             # or return undef
1793             sub resolve_action {
1794 12199     12199   17263 my ( $slg, $closure_name, $p_error ) = @_;
1795 12199         14934 my $trace_file_handle =
1796             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
1797 12199         13427 my $trace_actions = $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS];
1798              
1799             # A reserved closure name;
1800 12199 100       18413 return [ q{}, undef, '::!default' ] if not defined $closure_name;
1801              
1802 11826 50       17490 if ( $closure_name eq q{} ) {
1803 0 0       0 ${$p_error} = q{The action string cannot be the empty string}
  0         0  
1804             if defined $p_error;
1805 0         0 return;
1806             }
1807              
1808 11826 100       16383 return [ q{}, \undef, $closure_name ] if $closure_name eq '::undef';
1809 11795 100 100     34397 if ( substr( $closure_name, 0, 2 ) eq q{::}
1810             or substr( $closure_name, 0, 1 ) eq '[' )
1811             {
1812 11449         23992 return [ q{}, undef, $closure_name ];
1813             }
1814              
1815 346         456 my $fully_qualified_name;
1816 346 100       1671 if ( $closure_name =~ /([:][:])|[']/xms ) {
1817 211         345 $fully_qualified_name = $closure_name;
1818             }
1819              
1820 346 100       868 if ( not $fully_qualified_name ) {
1821 135         549 my $resolve_package =
1822             $slg->[Marpa::R3::Internal_G::SEMANTICS_PACKAGE];
1823 135 50       542 if ( not defined $resolve_package ) {
1824 0         0 ${$p_error} = Marpa::R3::Internal::X->new(
  0         0  
1825             {
1826             message =>
1827             qq{Could not fully qualify "$closure_name": no semantics package},
1828             name => 'NO RESOLVE PACKAGE'
1829             }
1830             );
1831 0         0 return;
1832             } ## end if ( not defined $resolve_package )
1833 135         326 $fully_qualified_name = $resolve_package . q{::} . $closure_name;
1834             } ## end if ( not $fully_qualified_name )
1835              
1836 346         690 my $closure;
1837             my $type;
1838             TYPE: {
1839 104     104   1051 no strict 'refs';
  104         254  
  104         4961  
  346         454  
1840 346         410 $closure = *{$fully_qualified_name}{'CODE'};
  346         1272  
1841 104     104   872 use strict;
  104         276  
  104         4064  
1842 346 100       893 if ( defined $closure ) {
1843 345         626 $type = 'CODE';
1844 345         642 last TYPE;
1845             }
1846 104     104   531 no strict 'refs';
  104         213  
  104         3534  
1847 1         2 $closure = *{$fully_qualified_name}{'SCALAR'};
  1         2  
1848 104     104   541 use strict;
  104         216  
  104         13875  
1849              
1850             # Currently $closure is always defined, but this
1851             # behavior is said to be subject to change in perlref
1852 1 50 33     4 if ( defined $closure and defined ${$closure} ) {
  1         4  
1853 0         0 $type = 'SCALAR';
1854 0         0 Marpa::R3::exception(
1855             "$closure_name resolves to SCALAR, which is not yet implemented"
1856             );
1857 0         0 last TYPE;
1858             }
1859              
1860 1         2 $closure = undef;
1861             } ## end TYPE:
1862              
1863 346 100       670 if ( defined $closure ) {
1864 345 50       640 if ($trace_actions) {
1865 0 0       0 print {$trace_file_handle}
  0         0  
1866             qq{Successful resolution of action "$closure_name" as $type },
1867             'to ', $fully_qualified_name, "\n"
1868             or Marpa::R3::exception('Could not print to trace file');
1869             } ## end if ($trace_actions)
1870 345         1282 return [ $fully_qualified_name, $closure, '::array' ];
1871             } ## end if ( defined $closure )
1872              
1873 1 50 33     4 if ( $trace_actions or defined $p_error ) {
1874 1         5 for my $slot (qw(ARRAY HASH IO FORMAT)) {
1875 104     104   642 no strict 'refs';
  104         208  
  104         95641  
1876 4 50       5 if ( defined *{$fully_qualified_name}{$slot} ) {
  4         10  
1877 0         0 my $error =
1878             qq{Failed resolution of action "$closure_name" to $fully_qualified_name\n}
1879             . qq{ $fully_qualified_name is present as a $slot, but a $slot is not an acceptable resolution\n};
1880 0 0       0 if ($trace_actions) {
1881 0 0       0 print {$trace_file_handle} $error
  0         0  
1882             or Marpa::R3::exception('Could not print to trace file');
1883             }
1884 0 0       0 ${$p_error} = $error if defined $p_error;
  0         0  
1885 0         0 return;
1886             } ## end if ( defined *{$fully_qualified_name}{$slot} )
1887             } ## end for my $slot (qw(ARRAY HASH IO FORMAT))
1888             } ## end if ( $trace_actions or defined $p_error )
1889              
1890             {
1891 1         8 my $error =
  1         7  
1892             qq{Failed resolution of action "$closure_name" to $fully_qualified_name\n};
1893 1 50       3 ${$p_error} = $error if defined $p_error;
  1         2  
1894 1 50       3 if ($trace_actions) {
1895 0 0       0 print {$trace_file_handle} $error
  0         0  
1896             or Marpa::R3::exception('Could not print to trace file');
1897             }
1898             }
1899 1         2 return;
1900              
1901             }
1902              
1903             sub resolve_rule_by_id {
1904 12201     12201   16318 my ( $slg, $irlid ) = @_;
1905              
1906 12201         22538 my ($action_name) =
1907             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1908             <<'END_OF_LUA', 'i>*', $irlid );
1909             local slg, irl_id = ...
1910             return slg.g1.irls[irl_id].action
1911             END_OF_LUA
1912              
1913 12201         14968 my $resolve_error;
1914 12201 100       18291 return if not defined $action_name;
1915 11826         17968 my $resolution = resolve_action( $slg, $action_name, \$resolve_error );
1916              
1917 11826 100       19357 if ( not $resolution ) {
1918 1         5 my $rule_desc = $slg->g1_rule_show($irlid);
1919 1   50     10 Marpa::R3::exception(
1920             "Could not resolve rule action named '$action_name'\n",
1921             " Rule was $rule_desc\n",
1922             q{ },
1923             ( $resolve_error // 'Failed to resolve action' )
1924             );
1925             } ## end if ( not $resolution )
1926 11825         15738 return $resolution;
1927             } ## end sub resolve_rule_by_id
1928              
1929             # Find the blessing for a rule.
1930             sub rule_blessing_find {
1931 12200     12200   16560 my ( $slg, $irlid ) = @_;
1932 12200         37807 my ($blessing) =
1933             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1934             <<'END_OF_LUA', 'i', $irlid);
1935             local slg, irlid = ...
1936             local irl = slg.g1.irls[irlid]
1937             local blessing = '::undef'
1938             local xpr = irl.xpr
1939             if xpr then
1940             blessing = xpr.bless or '::undef'
1941             end
1942             return blessing
1943             END_OF_LUA
1944 12200         18667 return $blessing;
1945             }
1946              
1947             # Find the semantics for a lexeme.
1948             sub lexeme_semantics_find {
1949 14483     14483   18661 my ( $slg, $lexeme_id ) = @_;
1950              
1951 14483         24362 my ($semantics) =
1952             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1953             <<'END_OF_LUA', 'i>*', $lexeme_id);
1954             local slg, isyid = ...
1955             local xsy = slg.g1.xsys[isyid]
1956             if not xsy then return '::!default' end
1957             local semantics = xsy.lexeme_semantics
1958             return semantics or '::!default'
1959             END_OF_LUA
1960              
1961 14483         21024 return $semantics;
1962             }
1963              
1964             # Find the blessing for a lexeme.
1965             sub lexeme_blessing_find {
1966 14483     14483   19321 my ( $slg, $lexeme_id ) = @_;
1967              
1968 14483         24481 my ($result) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1969             <<'END_OF_LUA', 'i', $lexeme_id );
1970             local slg, isyid = ...
1971             local xsy = slg.g1.xsys[isyid]
1972             if not xsy then return '::undef' end
1973             local blessing = xsy.blessing
1974             return blessing or '::undef'
1975             END_OF_LUA
1976              
1977 14483         21339 return $result;
1978             }
1979              
1980             sub op_fn_key_by_name {
1981 7068     7068   10009 my ( $slg, $name ) = @_;
1982 7068         12184 my ($key) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1983             <<'END_OF_LUA', 's', $name );
1984             local recce, name = ...
1985             return _M.get_op_fn_key_by_name(name)
1986             END_OF_LUA
1987              
1988 7068         11754 return $key;
1989             }
1990              
1991             sub op_fn_name_by_key {
1992 0     0   0 my ( $slg, $key ) = @_;
1993 0         0 my ($name) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1994             <<'END_OF_LUA', 'i', $key );
1995             local recce, key = ...
1996             return _M.get_op_fn_name_by_key(key)
1997             END_OF_LUA
1998              
1999 0         0 return $name;
2000             }
2001              
2002             sub registrations_set {
2003 372     372   1059 my ( $slg, $registrations ) = @_;
2004 372         975 my $trace_file_handle =
2005             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
2006 372   50     1956 my $trace_actions =
2007             $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] // 0;
2008              
2009 372         1438 REGISTRATION: for my $registration ( @{$registrations} ) {
  372         1237  
2010 25916         29153 my ( $type, $id, @raw_ops ) = @{$registration};
  25916         51841  
2011 25916         30873 my @ops = ();
2012             PRINT_TRACES: {
2013 25916 50       26706 last PRINT_TRACES if $trace_actions <= 2;
  25916         39787  
2014 0 0       0 if ( $type eq 'nulling' ) {
2015 0 0       0 say {$trace_file_handle}
  0         0  
2016             "Registering semantics for nulling symbol: ",
2017             $slg->g1_symbol_display_form($id),
2018             "\n", ' Semantics are ', $slg->show_semantics(@raw_ops)
2019             or Marpa::R3::exception('Cannot say to trace file handle');
2020 0         0 last PRINT_TRACES;
2021             } ## end if ( $type eq 'nulling' )
2022 0 0       0 if ( $type eq 'rule' ) {
2023 0 0       0 say {$trace_file_handle}
  0         0  
2024             "Registering semantics for $type: ",
2025             $slg->g1_rule_show($id),
2026             ' Semantics are ', $slg->show_semantics(@raw_ops)
2027             or Marpa::R3::exception('Cannot say to trace file handle');
2028 0         0 last PRINT_TRACES;
2029             }
2030 0 0       0 if ( $type eq 'token' ) {
2031 0 0       0 say {$trace_file_handle}
  0         0  
2032             "Registering semantics for $type: ",
2033             $slg->g1_symbol_display_form($id),
2034             "\n", ' Semantics are ', $slg->show_semantics(@raw_ops)
2035             or Marpa::R3::exception('Cannot say to trace file handle');
2036 0         0 last PRINT_TRACES;
2037             }
2038 0 0       0 say {$trace_file_handle} "Registration has unknown type: $type"
  0         0  
2039             or Marpa::R3::exception('Cannot say to trace file handle');
2040             } ## end PRINT_TRACES:
2041              
2042 25916         31911 OP: for my $raw_op (@raw_ops) {
2043 317004 100       403199 if ( ref $raw_op ) {
2044              
2045 19571         24761 my $constants = $slg->[Marpa::R3::Internal_G::CONSTANTS];
2046 19571         22850 my $next_ix = scalar @{$constants};
  19571         21870  
2047 19571         23150 push @ops, $next_ix;
2048             $slg->[Marpa::R3::Internal_G::CONSTANTS]->[$next_ix]
2049 19571         19816 = ${$raw_op};
  19571         27011  
2050 19571         30325 next OP;
2051             }
2052 297433         338995 push @ops, $raw_op;
2053             } ## end OP: for my $raw_op (@raw_ops)
2054              
2055 25916         51538 my ($constant_ix) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
2056             << 'END_OF_LUA', 'sii', $type, $id, \@ops );
2057             local grammar, type, id, ops = ...
2058             if type == 'token' then
2059             grammar.token_semantics[id] = ops
2060             elseif type == 'nulling' then
2061             grammar.nulling_semantics[id] = ops
2062             elseif type == 'rule' then
2063             grammar.rule_semantics[id] = ops
2064             end
2065             END_OF_LUA
2066              
2067 25916         53795 next REGISTRATION;
2068              
2069             # Marpa::R3::exception(
2070             # 'Registration: with unknown type: ',
2071             # Data::Dumper::Dumper($registration)
2072             # );
2073              
2074             } ## end REGISTRATION: for my $registration ( @{ $recce->[...]})
2075             }
2076              
2077             1;
2078              
2079             # vim: expandtab shiftwidth=4: