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   2179 use 5.010001;
  104         378  
15 104     104   616 use strict;
  104         214  
  104         2372  
16 104     104   516 use warnings;
  104         217  
  104         3272  
17              
18 104     104   554 use vars qw($VERSION $STRING_VERSION);
  104         228  
  104         8382  
19             $VERSION = '4.001_053';
20             $STRING_VERSION = $VERSION;
21             ## no critic(BuiltinFunctions::ProhibitStringyEval)
22             $VERSION = eval $VERSION;
23             ## use critic
24              
25             package Marpa::R3::Internal_G;
26              
27 104     104   760 use Scalar::Util 'blessed';
  104         223  
  104         6615  
28 104     104   675 use English qw( -no_match_vars );
  104         225  
  104         789  
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 393     393   1102 my ($class) = @_;
37 393         1169 my $pre_slg = bless [], $class;
38 393         1732 $pre_slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE] = \*STDERR;
39 393         1047 $pre_slg->[Marpa::R3::Internal_G::CONSTANTS] = [];
40              
41 393         1125023 my $lua = Marpa::R3::Lua->new();
42 393         2262 $pre_slg->[Marpa::R3::Internal_G::L] = $lua;
43              
44 393         14219 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 393         1552 $pre_slg->[Marpa::R3::Internal_G::REGIX] = $regix;
52 393         1484 return $pre_slg;
53             }
54              
55             sub Marpa::R3::Internal::meta_grammar {
56              
57 102     102 0 2902 my $meta_slg = pre_construct('Marpa::R3::Grammar');
58              
59 102         754 state $hashed_metag = Marpa::R3::Internal::MetaG::hashed_grammar();
60 102         533 $meta_slg->[Marpa::R3::Internal_G::BLESS_PACKAGE] =
61             'Marpa::R3::Internal::MetaAST_Nodes';
62 102         639 Marpa::R3::Internal_G::hash_to_runtime( $meta_slg, $hashed_metag );
63 102         592 my $registrations = registrations_find($meta_slg );
64 102         738 registrations_set($meta_slg, $registrations );
65              
66 102         7072 return $meta_slg;
67              
68             } ## end sub Marpa::R3::Internal::meta_grammar
69              
70             sub Marpa::R3::Grammar::new {
71 291     291   92221 my ( $class, @hash_ref_args ) = @_;
72              
73 291         1152 my $slg = pre_construct($class);
74              
75 291         1633 my ( $flat_args, $error_message ) =
76             Marpa::R3::flatten_hash_args( \@hash_ref_args );
77 291 50       1087 Marpa::R3::exception( sprintf $error_message, '$slg->new' )
78             if not $flat_args;
79              
80 291         1263 my $p_dsl = Marpa::R3::Internal_G::set( $slg, $flat_args );
81 291         2190 my $ast = Marpa::R3::Internal::MetaAST->new($p_dsl);
82 288         1925 my $hashed_ast = $ast->ast_to_hash($p_dsl);
83 275         1356 Marpa::R3::Internal_G::hash_to_runtime( $slg, $hashed_ast);
84 270         1245 my $registrations = registrations_find($slg );
85 269         2030 registrations_set($slg, $registrations );
86 269         23417 return $slg;
87             }
88              
89             sub Marpa::R3::Grammar::DESTROY {
90             # say STDERR "In Marpa::R3::Grammar::DESTROY before test";
91 271     271   108301 my $slg = shift;
92 271         781 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 271 50       1108 return if not $lua;
102             # say STDERR "In Marpa::R3::Grammar::DESTROY after test";
103              
104 271         597 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
105 271         282000 $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   1150 my ( $slg, @hash_ref_args ) = @_;
115 2         9 my ( $flat_args, $error_message ) =
116             Marpa::R3::flatten_hash_args( \@hash_ref_args );
117 2 50       9 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       8 if ( defined $value ) {
122 2         7 $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE] = $value;
123 2         4 delete $flat_args->{trace_file_handle};
124             }
125              
126 2         167 my @bad_arguments = keys %{$flat_args};
  2         9  
127 2 50       9 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         9 return;
133             }
134              
135             sub Marpa::R3::Internal_G::set {
136 291     291   915 my ( $slg, $flat_args ) = @_;
137              
138 291         769 my $dsl = $flat_args->{'source'};
139 291 50       994 Marpa::R3::exception(
140             qq{Marpa::R3::Grammar::new() called without a 'source' argument})
141             if not defined $dsl;
142 291         869 my $dsl_ref_type = ref $dsl;
143 291 50       1032 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 291 50       611 if ( not defined ${$dsl} ) {
  291         1552  
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 291         804 delete $flat_args->{'source'};
157              
158 291         771 my $value = $flat_args->{trace_file_handle};
159 291 50       981 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 291         762 my $trace_file_handle =
165             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
166              
167 291 50       1126 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 291 50       1094 if ( defined( exists $flat_args->{'bless_package'} ) ) {
178 291         732 my $value = $flat_args->{'bless_package'};
179 291         880 $slg->[Marpa::R3::Internal_G::BLESS_PACKAGE] = $value;
180 291         864 delete $flat_args->{'bless_package'};
181             }
182              
183 291 100       1041 if ( exists $flat_args->{'exhaustion'} ) {
184              
185 4   50     15 my $value = $flat_args->{'exhaustion'} // '';
186              
187 4         21 $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         16 delete $flat_args->{'exhaustion'};
206              
207             }
208              
209 291 100       1077 if ( exists $flat_args->{'rejection'} ) {
210              
211 6   50     22 my $value = $flat_args->{'rejection'} // '';
212              
213 6         28 $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         31 delete $flat_args->{'rejection'};
232              
233             }
234              
235 291 100       1062 if ( exists $flat_args->{'semantics_package'} ) {
236 42         121 my $value = $flat_args->{'semantics_package'};
237 42         114 $slg->[Marpa::R3::Internal_G::SEMANTICS_PACKAGE] = $value;
238 42         129 delete $flat_args->{'semantics_package'};
239             }
240              
241 291 100       983 if ( exists $flat_args->{'ranking_method'} ) {
242              
243             # Only allowed in new method
244 18   50     73 my $value = $flat_args->{'ranking_method'} // 'undefined';
245              
246 18         93 $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         56 delete $flat_args->{'ranking_method'};
263             }
264              
265 291 50       984 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 291         831 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 377     377   1571 my ( $slg, $hashed_source ) = @_;
297              
298 377         986 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 377         5852 <<'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 372         7379 <<'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 372         2598 my @class_table;
363             CLASS_SYMBOL:
364 372         879 while (scalar @{$character_pairs}) {
  7593         15079  
365 7221         9137 my $perl_re = pop @{$character_pairs};
  7221         11092  
366 7221         8959 my $symbol_id = pop @{$character_pairs};
  7221         9466  
367 7221         10202 my $compiled_re;
368             my $error;
369 7221 50       9017 if ( not defined eval { $compiled_re = qr/$perl_re/xms; 1; } ) {
  7221         76487  
  7221         19584  
370 0         0 $error = qq{Problem in evaluating character class: "$perl_re"\n};
371 0         0 $error .= $EVAL_ERROR;
372             }
373 7221 50       12898 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 7221         15152 push @class_table, [ $symbol_id, $compiled_re ];
379             } ## end CLASS_SYMBOL: for my $class_symbol ( sort keys %{...})
380 372         1264 $slg->[Marpa::R3::Internal_G::CHARACTER_CLASS_TABLE] = \@class_table;
381              
382 372         1102 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   9304 my ($line, $perl_name, $kollos_name, $signature) = @_;
391 4992         10044 my $tag = '@' . __FILE__ . ':' . $line;
392 4992         12616 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   202574 no strict 'refs';
  104         286  
  104         10790  
395 4992         22939 *{ 'Marpa::R3::Grammar::' . $perl_name }
396             = sub () {
397 21584     21584   55639 my ($slg, @args) = @_;
398 21584         48715 my ($retour) = $slg->call_by_tag($tag, $code, $signature, @args);
399 21584         48691 return $retour;
400 4992         18197 };
401 104     104   789 use strict;
  104         276  
  104         9529  
402             }
403              
404 0         0 sub kwgen_arr {
405 416     416   970 my ($line, $perl_name, $kollos_name, $signature) = @_;
406 416         1085 my $tag = '@' . __FILE__ . ':' . $line;
407 416         1130 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   737 no strict 'refs';
  104         277  
  104         9547  
410 416         2562 *{ 'Marpa::R3::Grammar::' . $perl_name }
411             = sub () {
412 1683     1683   3408 my ($slg, @args) = @_;
413 1683         3355 my ($retour) = $slg->call_by_tag($tag, $code, $signature, @args);
414 1683         2595 return @{$retour};
  1683         4279  
415 416         2115 };
416 104     104   777 use strict;
  104         241  
  104         10653  
417             }
418              
419 0         0 sub kwgen_opt {
420 312     312   950 my ($line, $perl_name, $kollos_name, $signature, @defaults) = @_;
421 312         902 my $tag = '@' . __FILE__ . ':' . $line;
422 312         985 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   738 no strict 'refs';
  104         248  
  104         13194  
425 312         2055 *{ 'Marpa::R3::Grammar::' . $perl_name }
426             = sub () {
427 8     8   1419 my ($slg, @args) = @_;
428 8   66     78 $args[$_] //= $defaults[$_] for 0 .. $#defaults;
429 8         35 my ($retour) = $slg->call_by_tag($tag, $code, $signature, @args);
430 8         51 return $retour;
431 312         2121 };
432 104     104   753 use strict;
  104         232  
  104         791298  
433             }
434              
435             sub Marpa::R3::Grammar::production_show {
436 94     94   330 my ($slg, $xprid, $options) = @_;
437 94 50       190 my $verbose = $options->{verbose} or 0;
438 94 100       153 my $diag = $options->{diag} ? 1 : 0;
439 94         123 my $tag = '@' . __FILE__ . ':' . __LINE__;
440 94         108 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         151 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
446             $xprid, $verbose, $diag);
447 94         217 return $retour;
448             }
449              
450             sub Marpa::R3::Grammar::symbols_show {
451 15     15   4843 my ($slg, $options) = @_;
452 15 100       76 my $verbose = $options->{verbose} or 0;
453 15 50       326 my $diag = $options->{diag} ? 1 : 0;
454 15         48 my $tag = '@' . __FILE__ . ':' . __LINE__;
455 15         34 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         56 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
461             $verbose, $diag);
462 15         114 return $retour;
463             }
464              
465             sub Marpa::R3::Grammar::symbol_show {
466 41     41   252 my ($slg, $xsyid, $options) = @_;
467 41 50       85 my $verbose = $options->{verbose} or 0;
468 41 50       75 my $diag = $options->{diag} ? 1 : 0;
469 41         53 my $tag = '@' . __FILE__ . ':' . __LINE__;
470 41         50 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         72 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
476             $xsyid, $verbose, $diag);
477 41         117 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   467 my ($slg, $irlid, $options) = @_;
497 151 50       380 my $verbose = $options->{verbose} or 0;
498 151 100       324 my $diag = $options->{diag} ? 1 : 0;
499 151         263 my $tag = '@' . __FILE__ . ':' . __LINE__;
500 151         204 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         344 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
506             $irlid, $verbose, $diag);
507 151         771 return $retour;
508             }
509              
510             sub Marpa::R3::Grammar::l0_rule_show {
511 54     54   194 my ($slg, $irlid, $options) = @_;
512 54 50       105 my $verbose = $options->{verbose} or 0;
513 54 100       99 my $diag = $options->{diag} ? 1 : 0;
514 54         67 my $tag = '@' . __FILE__ . ':' . __LINE__;
515 54         74 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         92 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
521             $irlid, $verbose, $diag);
522 54         123 return $retour;
523             }
524              
525             sub Marpa::R3::Grammar::productions_show {
526 22     22   8598 my ($slg, $options) = @_;
527 22 100       246 my $verbose = $options->{verbose} or 0;
528 22 100       96 my $diag = $options->{diag} ? 1 : 0;
529 22         59 my $tag = '@' . __FILE__ . ':' . __LINE__;
530 22         51 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         90 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
536             $verbose, $diag);
537 22         166 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   3790 my ($slg, $options) = @_;
557 11 100       54 my $verbose = $options->{verbose} or 0;
558 11 100       51 my $diag = $options->{diag} ? 1 : 0;
559 11         32 my $tag = '@' . __FILE__ . ':' . __LINE__;
560 11         26 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         38 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
566             $verbose, $diag);
567 11         78 return $retour;
568             }
569              
570             sub Marpa::R3::Grammar::l0_rules_show {
571 5     5   3085 my ($slg, $options) = @_;
572 5 50       25 my $verbose = $options->{verbose} or 0;
573 5 100       19 my $diag = $options->{diag} ? 1 : 0;
574 5         11 my $tag = '@' . __FILE__ . ':' . __LINE__;
575 5         10 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         19 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
581             $verbose, $diag);
582 5         31 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 160891     160891   298533 my ( $slg, $tag, $codestr, $sig, @args ) = @_;
663 160891         228286 my $lua = $slg->[Marpa::R3::Internal_G::L];
664 160891         202965 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 160891         297575 my @results;
672             my $eval_error;
673 160891         0 my $eval_ok;
674             {
675 160891         192135 local $@;
  160891         199474  
676 160891         227209 $eval_ok = eval {
677             # say STDERR "About to call_by_tag($regix, $tag, $codestr, $sig, @args)";;
678 160891         1224143 @results = $lua->call_by_tag($regix, $tag, $codestr, $sig, @args);
679             # say STDERR "Returned from call_by_tag($regix, $tag, $codestr, $sig, @args)";;
680 160891         313942 return 1;
681             };
682 160891         282749 $eval_error = $@;
683             }
684 160891 50       292748 if ( not $eval_ok ) {
685 0         0 Marpa::R3::exception($eval_error);
686             }
687              
688 160891         327324 return @results;
689             }
690              
691             # not to be documented
692             sub Marpa::R3::Grammar::coro_by_tag {
693 1953     1953   5381 my ( $slg, $tag, $args, $codestr ) = @_;
694 1953         3613 my $lua = $slg->[Marpa::R3::Internal_G::L];
695 1953         3296 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
696 1953   50     5465 my $handler = $args->{handlers} // {};
697 1953         4521 my $resume_tag = $tag . '[R]';
698 1953   50     4709 my $signature = $args->{signature} // '';
699 1953   50     4645 my $p_args = $args->{args} // [];
700              
701 1953         4664 my @results;
702             my $eval_error;
703 1953         0 my $eval_ok;
704             {
705 1953         2722 local $@;
  1953         2977  
706 1953         3500 $eval_ok = eval {
707 1953         3239 $lua->call_by_tag( $regix, $tag, $codestr, $signature, @{$p_args} );
  1953         1194319  
708 1953         30633 my $coro_arg;
709 1953         3076 CORO_CALL: while (1) {
710 1961         2623285 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 1956 100       9327 if (not $cmd) {
716 1948         3114 @results = @{$yield_data};
  1948         4893  
717 1948         6789 return 1;
718             }
719 8         23 my $handler = $handler->{$cmd};
720 8 50       19 Marpa::R3::exception(qq{No coro handler for "$cmd"})
721             if not $handler;
722 8   50     18 $yield_data //= [];
723 8         11 my $handler_cmd;
724 8         15 ($handler_cmd, $coro_arg) = $handler->(@{$yield_data});
  8         27  
725             }
726 0         0 return 1;
727             };
728 1953         5071 $eval_error = $@;
729             }
730 1953 100       4721 if ( not $eval_ok ) {
731 5         26 Marpa::R3::exception($eval_error);
732             }
733 1948         6980 return @results;
734             }
735              
736             sub Marpa::R3::Grammar::symbol_ids_gen {
737 2     2   1346 my ($slg) = @_;
738 2         4 my $next = 1;
739 2         7 my $last = $slg->highest_symbol_id();
740             return sub () {
741 84 100   84   392 return if $next > $last;
742 82         103 my $current;
743 82         127 ($current, $next) = ($next, $next+1);
744 82         122 return $current;
745             }
746 2         18 }
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   2477 my ($slg) = @_;
762 6         16 my $next = 0;
763 6         253 my $last = $slg->g1_highest_symbol_id();
764             return sub () {
765 65 100   65   269 return if $next > $last;
766 61         73 my $current;
767 61         111 ($current, $next) = ($next, $next+1);
768 61         101 return $current;
769             }
770 6         53 }
771              
772             sub Marpa::R3::Grammar::l0_symbol_ids_gen {
773 2     2   1381 my ($slg) = @_;
774 2         5 my $next = 0;
775 2         7 my $last = $slg->l0_highest_symbol_id();
776             return sub () {
777 70 100   70   285 return if $next > $last;
778 68         87 my $current;
779 68         96 ($current, $next) = ($next, $next+1);
780 68         102 return $current;
781             }
782 2         20 }
783              
784             sub Marpa::R3::Grammar::production_ids_gen {
785 3     3   2120 my ($slg) = @_;
786 3         6 my $next = 1;
787 3         9 my $last = $slg->highest_production_id();
788             return sub () {
789 144 100   144   669 return if $next > $last;
790 141         169 my $current;
791 141         206 ($current, $next) = ($next, $next+1);
792 141         206 return $current;
793             }
794 3         22 }
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 1862     1862   6399 my ($slg) = @_;
810 1862         2950 my $next = 0;
811 1862         4583 my $last = $slg->g1_highest_rule_id();
812             return sub () {
813 51914 100   51914   93393 return if $next > $last;
814 50426         60650 my $current;
815 50426         76937 ($current, $next) = ($next, $next+1);
816 50426         96040 return $current;
817             }
818 1862         14472 }
819              
820             sub Marpa::R3::Grammar::l0_rule_ids_gen {
821 4     4   2768 my ($slg) = @_;
822 4         8 my $next = 0;
823 4         13 my $last = $slg->l0_highest_rule_id();
824             return sub () {
825 112 100   112   554 return if $next > $last;
826 108         126 my $current;
827 108         166 ($current, $next) = ($next, $next+1);
828 108         179 return $current;
829             }
830 4         37 }
831              
832             # not to be documented
833             sub Marpa::R3::Grammar::nrls_show {
834 7     7   22 my ($slg) = @_;
835 7         30 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         149 return $result;
850             }
851              
852             # not to be documented
853             sub Marpa::R3::Grammar::nsys_show {
854 4     4   13 my ($slg) = @_;
855 4         18 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         23 return $result;
864             }
865              
866             # not to be documented
867             sub Marpa::R3::Grammar::ahms_show {
868 13     13   3730 my ( $slg, $options ) = @_;
869 13   100     102 $options //= {};
870 13 100       170 my $verbose = $options->{verbose} or 0;
871              
872 13         260 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         112 return $text;
881              
882             }
883              
884             # not to be documented
885             sub Marpa::R3::Grammar::dotted_nrl_show {
886 452     452   876 my ( $slg, $nrl_id, $dot_position ) = @_;
887 452         1012 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         1486 return $result;
896             }
897              
898             # not to be documented
899             sub Marpa::R3::Grammar::briefer_ahm {
900 549     549   894 my ( $slg, $item_id ) = @_;
901              
902 549         1183 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         1324 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   8350 my ( $slg ) = @_;
935 1         3 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
936 1         3 return $regix;
937             }
938              
939             sub registrations_find {
940 372     372   1112 my ($slg) = @_;
941 372         1002 my $trace_file_handle =
942             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
943 372   50     2096 my $trace_actions =
944             $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] // 0;
945              
946 372         939 my @closure_by_irlid = ();
947 372         894 my @semantics_by_irlid = ();
948 372         749 my @blessing_by_irlid = ();
949              
950 372         1665 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 371         932 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
  371         1116  
956             my ( $new_resolution, $closure, $semantics, $blessing ) =
957 12190         15340 @{ $rule_resolutions->[$irlid] };
  12190         24913  
958 12190         28859 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 12190 100 66     17366 if (
  12190         40825  
969             '[' eq substr $semantics,
970             0, 1 and ']' eq substr $semantics,
971             -1, 1
972             )
973             {
974             # Normalize array semantics
975 10768         105323 $semantics =~ s/ //gxms;
976 10768         18209 last REFINE_SEMANTICS;
977             } ## end if ( '[' eq substr $semantics, 0, 1 and ']' eq ...)
978              
979             state $allowed_semantics = {
980 1422         2376 map { ; ( $_, 1 ) } qw(::array ::undef ::first ::!default),
  510         1680  
981             q{}
982             };
983 1422 50       4145 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 12190         22131 $semantics_by_irlid[$irlid] = $semantics;
997 12190         17967 $blessing_by_irlid[$irlid] = $blessing;
998 12190         16567 $closure_by_irlid[$irlid] = $closure;
999              
1000             CHECK_BLESSING: {
1001 12190 100       15090 last CHECK_BLESSING if $blessing eq '::undef';
  12190         24126  
1002 10738 50       17418 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       17092 last CHECK_BLESSING if $semantics eq '::array';
1022 10668 50       28217 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 371         1168 my @nullable_rule_ids_by_lhs = ();
1041 371         1174 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1042              
1043 12190         26401 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 12190 100       28839 push @{ $nullable_rule_ids_by_lhs[$lhs_id] }, $irlid
  554         2278  
1052             if $rule_is_nullable;
1053             }
1054              
1055 371         1038 my @null_symbol_closures;
1056             LHS:
1057 371         1656 for ( my $lhs_id = 0 ; $lhs_id <= $#nullable_rule_ids_by_lhs ; $lhs_id++ ) {
1058 8121         10285 my $irlids = $nullable_rule_ids_by_lhs[$lhs_id];
1059 8121         9369 my $resolution_rule;
1060              
1061             # No nullable rules for this LHS? No problem.
1062 8121 100       17147 next LHS if not defined $irlids;
1063 548         871 my $rule_count = scalar @{$irlids};
  548         1023  
1064              
1065             # I am not sure if this test is necessary
1066 548 50       1297 next LHS if $rule_count <= 0;
1067              
1068             # Just one nullable rule? Then that's our semantics.
1069 548 100       1251 if ( $rule_count == 1 ) {
1070 542         873 $resolution_rule = $irlids->[0];
1071             my ( $resolution_name, $closure ) =
1072 542         830 @{ $rule_resolutions->[$resolution_rule] };
  542         1312  
1073 542 50       1167 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         1339 $null_symbol_closures[$lhs_id] = $resolution_rule;
1082 542         1480 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         27 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       19 if ( scalar @{$empty_rules} ) {
  6         22  
1104 5         10 $resolution_rule = $empty_rules->[0];
1105             my ( $resolution_name, $closure ) =
1106 5         18 @{ $rule_resolutions->[$resolution_rule] };
  5         16  
1107 5 50       14 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         11 $null_symbol_closures[$lhs_id] = $resolution_rule;
1116 5         16 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         8  
  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         5  
1127 1         3 OTHER_RESOLUTION: for my $other_resolution (@other_resolutions) {
1128             my ( $other_closure_name, undef, $other_semantics, $other_blessing )
1129 1         3 = @{$other_resolution};
  1         4  
1130              
1131 1 50 33     13 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         3 $resolution_rule = $irlids->[0];
1149             my ( $resolution_name, $closure ) =
1150 1         3 @{ $rule_resolutions->[$resolution_rule] };
  1         4  
1151 1 50       5 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 371         1419 my $null_values = $slg->[Marpa::R3::Internal_G::NULL_VALUES] =
1167             \@null_symbol_closures;
1168              
1169 371         813 my @semantics_by_lexeme_id = ();
1170 371         733 my @blessing_by_lexeme_id = ();
1171              
1172             # Check the lexeme semantics
1173             {
1174 371         652 my ($highest_symbol_id) =
  371         1381  
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 371         1818 LEXEME: for my $lexeme_id ( 0 .. $highest_symbol_id ) {
1183              
1184             my ( $semantics, $blessing ) =
1185 14471         17184 @{ $lexeme_resolutions->[$lexeme_id] };
  14471         24731  
1186 14471 50       24895 $blessing = '::undef' if not defined $blessing;
1187             CHECK_SEMANTICS: {
1188 14471 50       16811 if ( not $semantics ) {
  14471         21970  
1189 0         0 $semantics = '::!default';
1190 0         0 last CHECK_SEMANTICS;
1191             }
1192 14471 100       25478 if ( ( substr $semantics, 0, 1 ) eq '[' ) {
1193 7822         67034 $semantics =~ s/ //gxms;
1194 7822         12011 last CHECK_SEMANTICS;
1195             }
1196             state $allowed_semantics =
1197 6649         8221 { map { ; ( $_, 1 ) } qw(::array ::undef ::!default ) };
  306         941  
1198              
1199 6649 50       11959 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 14471         21773 $semantics_by_lexeme_id[$lexeme_id] = $semantics;
1210 14471         23962 $blessing_by_lexeme_id[$lexeme_id] = $blessing;
1211              
1212             }
1213              
1214             }
1215              
1216             # state $op_lua = Marpa::R3::Thin::op('lua');
1217 371         1825 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 371         1707 my ($op_debug_key) = op_fn_key_by_name( $slg, "debug" );
1223 371         1123 my ($op_noop_key) = op_fn_key_by_name( $slg, "noop" );
1224 371         1387 my ($op_bail_key) = op_fn_key_by_name( $slg, "bail" );
1225 371         1276 my ($op_bless_key) = op_fn_key_by_name( $slg, "bless" );
1226 371         1369 my ($op_callback_key) = op_fn_key_by_name( $slg, "callback" );
1227 371         1214 my ($result_is_undef_key) = op_fn_key_by_name( $slg, 'result_is_undef' );
1228 371         1239 my ($result_is_constant_key) =
1229             op_fn_key_by_name( $slg, 'result_is_constant' );
1230 371         1187 my ($result_is_token_value_key) =
1231             op_fn_key_by_name( $slg, "result_is_token_value" );
1232 371         1215 my ($result_is_n_of_rhs_key) =
1233             op_fn_key_by_name( $slg, "result_is_n_of_rhs" );
1234 371         1333 my ($result_is_n_of_sequence_key) =
1235             op_fn_key_by_name( $slg, "result_is_n_of_sequence" );
1236 371         1229 my ($result_is_array_key) = op_fn_key_by_name( $slg, "result_is_array" );
1237 371         1272 my ($op_push_constant_key) = op_fn_key_by_name( $slg, 'push_constant' );
1238 371         1307 my ($op_push_undef_key) = op_fn_key_by_name( $slg, 'push_undef' );
1239 371         1296 my ($op_push_one_key) = op_fn_key_by_name( $slg, 'push_one' );
1240 371         1326 my ($op_push_values_key) = op_fn_key_by_name( $slg, 'push_values' );
1241 371         1232 my ($op_push_g1_start_key) = op_fn_key_by_name( $slg, 'push_g1_start' );
1242 371         1239 my ($op_push_g1_length_key) = op_fn_key_by_name( $slg, 'push_g1_length' );
1243 371         1317 my ($op_push_start_key) = op_fn_key_by_name( $slg, 'push_start' );
1244 371         1212 my ($op_push_length_key) = op_fn_key_by_name( $slg, 'push_length' );
1245              
1246 371         892 my @nulling_symbol_by_semantic_rule;
1247 371         839 NULLING_SYMBOL: for my $nulling_symbol ( 0 .. $#{$null_values} ) {
  371         1791  
1248 8121         10136 my $semantic_rule = $null_values->[$nulling_symbol];
1249 8121 100       13823 next NULLING_SYMBOL if not defined $semantic_rule;
1250 548         1297 $nulling_symbol_by_semantic_rule[$semantic_rule] = $nulling_symbol;
1251             } ## end NULLING_SYMBOL: for my $nulling_symbol ( 0 .. $#{$null_values} )
1252              
1253 371         1101 my @work_list = ();
1254 371         1213 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1255              
1256 12190         16583 my $semantics = $semantics_by_irlid[$irlid];
1257 12190         15514 my $blessing = $blessing_by_irlid[$irlid];
1258              
1259 12190 100       19915 $semantics = '[name,values]' if $semantics eq '::!default';
1260 12190 100       18943 $semantics = '[values]' if $semantics eq '::array';
1261 12190 100       18820 $semantics = '::rhs0' if $semantics eq '::first';
1262              
1263 12190         30032 push @work_list, [ $irlid, undef, $semantics, $blessing ];
1264             }
1265              
1266 371         1592 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 371         1596 LEXEME: for my $lexeme_id ( 0 .. $highest_symbol_id ) {
1274              
1275 14471         19246 my $semantics = $semantics_by_lexeme_id[$lexeme_id];
1276 14471         17553 my $blessing = $blessing_by_lexeme_id[$lexeme_id];
1277              
1278             next LEXEME
1279 14471 100 100     31723 if $semantics eq '::!default' and $blessing eq '::undef';
1280 12840 100       19734 $semantics = '::value' if $semantics eq '::!default';
1281 12840 50       19612 $semantics = '[value]' if $semantics eq '::array';
1282              
1283 12840         27362 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 371         1109 my @nulling_closures = ();
1290 371         823 my @registrations = ();
1291              
1292 371         981 WORK_ITEM: for my $work_item (@work_list) {
1293 25030         32947 my ( $irlid, $lexeme_id, $semantics, $blessing ) = @{$work_item};
  25030         49485  
1294              
1295 25030         36195 my ( $closure, $rule_length,
1296             $is_sequence_rule,
1297             $is_discard_sequence_rule,
1298             $nulling_symbol_id );
1299 25030 100       41523 if ( defined $irlid ) {
1300 12190         18258 $nulling_symbol_id = $nulling_symbol_by_semantic_rule[$irlid];
1301 12190         16608 $closure = $closure_by_irlid[$irlid];
1302              
1303 12190         30663 ( $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 25030         37048 my @array_fate = ();
1323             ARRAY_FATE: {
1324 25030 100 100     31301 if ( defined $closure and ref $closure eq 'CODE' ) {
  25030         46985  
1325 345         872 push @array_fate, $op_lua, $op_callback_key, $op_bail_key;
1326 345         625 last ARRAY_FATE;
1327              
1328             }
1329              
1330 24685 100       50918 if ( ( substr $semantics, 0, 1 ) eq '[' ) {
1331 19122         28963 push @array_fate, $op_lua, $result_is_array_key, $op_bail_key;
1332 19122         27733 last ARRAY_FATE;
1333             }
1334             } ## end ARRAY_FATE:
1335              
1336 25030         32056 my @ops = ();
1337              
1338             SET_OPS: {
1339              
1340 25030 100       31112 if ( $semantics eq '::undef' ) {
  25030         42334  
1341 31         42 @ops = ( $op_lua, $result_is_undef_key, $op_bail_key );
1342 31         41 last SET_OPS;
1343             }
1344              
1345             CHECK_TYPE: {
1346 24999 100       30224 last CHECK_TYPE if not defined $irlid;
  24999         42913  
1347 12159         17621 my $thingy_ref = $closure_by_irlid[$irlid];
1348 12159 100       22896 last CHECK_TYPE if not defined $thingy_ref;
1349 345         1228 my $ref_type = Scalar::Util::reftype $thingy_ref;
1350 345 50       816 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       860 if ( $ref_type eq 'CODE' ) {
1361              
1362             # Set the nulling closure if this is the nulling symbol of a rule
1363 345 100 66     1043 $nulling_closures[$nulling_symbol_id] = $thingy_ref
1364             if defined $nulling_symbol_id
1365             and defined $irlid;
1366 345         584 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 24999 100 100     57584 if ( defined $lexeme_id and $semantics eq '::value' ) {
1380 5018         7401 @ops = ( $op_lua, $result_is_token_value_key, $op_bail_key );
1381 5018         6462 last SET_OPS;
1382             }
1383              
1384             PROCESS_SINGLETON_RESULT: {
1385 19981 100       24512 last PROCESS_SINGLETON_RESULT if not defined $irlid;
  19981         32496  
1386              
1387 12159         15167 my $singleton;
1388 12159 100       28728 if ( $semantics =~ m/\A [:][:] rhs (\d+) \z/xms ) {
1389 514         2374 $singleton = $1 + 0;
1390             }
1391              
1392 12159 100       21949 last PROCESS_SINGLETON_RESULT if not defined $singleton;
1393              
1394 514         911 my $singleton_element = $singleton;
1395 514 50       1312 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 514 50       1352 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 514         1920 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 514         1941 grep { $mask->[$_] } 0 .. ( $rule_length - 1 );
  520         1698  
1417 514 50       1612 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 514         1070 $singleton_element = $elements[$singleton];
1427              
1428 514 50       1357 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 514         1213 @ops = ( $op_lua, $result_is_n_of_rhs_key, $singleton_element );
1438 514         1449 last SET_OPS;
1439             } ## end PROCESS_SINGLETON_RESULT:
1440              
1441 19467 50       36061 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 19467         27098 my @bless_ops = ();
1449 19467 100       34374 if ( $blessing ne '::undef' ) {
1450 18440         41669 push @bless_ops, $op_lua, $op_bless_key, \[$irlid, $lexeme_id, $blessing];
1451             }
1452              
1453 19467 50       39803 Marpa::R3::exception(qq{Unknown semantics: "$semantics"})
1454             if ( substr $semantics, 0, 1 ) ne '[';
1455              
1456 19467         25653 my @push_ops = ();
1457 19467         31551 my $array_descriptor = substr $semantics, 1, -1;
1458 19467         139552 $array_descriptor =~ s/^\s*|\s*$//g;
1459             RESULT_DESCRIPTOR:
1460 19467         79131 for my $result_descriptor ( split /[,]\s*/xms, $array_descriptor ) {
1461 56781         224569 $result_descriptor =~ s/^\s*|\s*$//g;
1462 56781 100       109350 if ( $result_descriptor eq 'g1start' ) {
1463 70         115 push @push_ops, $op_lua, $op_push_g1_start_key,
1464             $op_bail_key;
1465 70         112 next RESULT_DESCRIPTOR;
1466             }
1467 56711 100       88773 if ( $result_descriptor eq 'g1length' ) {
1468 70         109 push @push_ops, $op_lua, $op_push_g1_length_key,
1469             $op_bail_key;
1470 70         94 next RESULT_DESCRIPTOR;
1471             }
1472 56641 100       87755 if ( $result_descriptor eq 'start' ) {
1473 18319         28175 push @push_ops, $op_lua, $op_push_start_key, $op_bail_key;
1474 18319         28528 next RESULT_DESCRIPTOR;
1475             }
1476 38322 100       61407 if ( $result_descriptor eq 'length' ) {
1477 18319         26891 push @push_ops, $op_lua, $op_push_length_key, $op_bail_key;
1478 18319         27579 next RESULT_DESCRIPTOR;
1479             }
1480              
1481 20003 100       32357 if ( $result_descriptor eq 'lhs' ) {
1482 8 100       17 if ( defined $irlid ) {
1483              
1484 3         11 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         7 push @push_ops, $op_lua, $op_push_constant_key,
1492             \$lhs_id;
1493 3         8 next RESULT_DESCRIPTOR;
1494             }
1495 5 50       11 if ( defined $lexeme_id ) {
1496 5         10 push @push_ops, $op_lua, $op_push_constant_key,
1497             \$lexeme_id;
1498 5         9 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 19995 100       32837 if ( $result_descriptor eq 'name' ) {
1505 505 100       1097 if ( defined $irlid ) {
1506 435         1169 my $production_id =
1507             $slg->g1_rule_to_production_id($irlid);
1508 435         1212 my $name = $slg->production_name($production_id);
1509 435         1035 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1510 435         1032 next RESULT_DESCRIPTOR;
1511             }
1512 70 50       148 if ( defined $lexeme_id ) {
1513 70         172 my $name = $slg->g1_symbol_name($lexeme_id);
1514 70         152 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1515 70         148 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 19490 100       31988 if ( $result_descriptor eq 'symbol' ) {
1527 16 100       35 if ( defined $irlid ) {
1528 6         26 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         16 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1537 6         18 next RESULT_DESCRIPTOR;
1538             } ## end if ( defined $irlid )
1539 10 50       25 if ( defined $lexeme_id ) {
1540 10         25 my $name = $slg->g1_symbol_name($lexeme_id);
1541 10         23 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1542 10         20 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 19474 100       32612 if ( $result_descriptor eq 'rule' ) {
1554 8 100       16 if ( defined $irlid ) {
1555 3         6 push @push_ops, $op_lua, $op_push_constant_key, \$irlid;
1556 3         7 next RESULT_DESCRIPTOR;
1557             }
1558 5         8 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 19466 50 66     45118 if ( $result_descriptor eq 'values'
1562             or $result_descriptor eq 'value' )
1563             {
1564 19466 100       32115 if ( defined $lexeme_id ) {
1565 7822         11975 push @push_ops, $op_lua, $op_push_values_key, 1;
1566 7822         12452 next RESULT_DESCRIPTOR;
1567             }
1568 11644 100       19297 if ($is_sequence_rule) {
1569 697 100       1938 push @push_ops, $op_lua, $op_push_values_key,
1570             ( $is_discard_sequence_rule ? 2 : 1 );
1571 697         1396 next RESULT_DESCRIPTOR;
1572             } ## end if ($is_sequence_rule)
1573              
1574 10947         28283 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 10947 100       23345 if ( $rule_length > 0 ) {
1582             push @push_ops, map {
1583 10764 100       23110 $mask->[$_]
  19961         47221  
1584             ? ( $op_lua, $op_push_one_key, $_ )
1585             : ()
1586             } 0 .. $rule_length - 1;
1587             }
1588 10947         27456 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 19467         57968 @ops = ( @push_ops, @bless_ops, @array_fate );
1596              
1597             } ## end SET_OPS:
1598              
1599 25030 100       45442 if ( defined $irlid ) {
1600 12190         38045 push @registrations, [ 'rule', $irlid, @ops ];
1601             }
1602              
1603 25030 100       43335 if ( defined $nulling_symbol_id ) {
1604              
1605 548         1682 push @registrations, [ 'nulling', $nulling_symbol_id, @ops ];
1606             } ## end if ( defined $nulling_symbol_id )
1607              
1608 25030 100       50465 if ( defined $lexeme_id ) {
1609 12840         46143 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 371         968 my $start_symbol_id = $slg->g1_symbol_by_name('[:start:]');
  371         1743  
1623              
1624 371         1710 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 371 50       1415 last SLR_NULLING_GRAMMAR_HACK if not $symbol_is_nullable;
1633              
1634 371         871 my $start_rhs_symbol_id;
1635 371         1324 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1636 1582         3759 my ( $lhs, $rhs0 ) = $slg->g1_rule_expand($irlid);
1637 1582 100       4351 if ( $start_symbol_id == $lhs ) {
1638 371         816 $start_rhs_symbol_id = $rhs0;
1639 371         1043 last RULE;
1640             }
1641             }
1642              
1643 371         1127 REGISTRATION: for my $registration (@registrations) {
1644 24537         28488 my ( $type, $nulling_symbol_id ) = @{$registration};
  24537         36956  
1645 24537 100       42931 if ( $nulling_symbol_id == $start_rhs_symbol_id ) {
1646 319         728 my ( undef, undef, @ops ) = @{$registration};
  319         1085  
1647 319         1476 push @registrations, [ 'nulling', $start_symbol_id, @ops ];
1648 319         1025 $nulling_closures[$start_symbol_id] =
1649             $nulling_closures[$start_rhs_symbol_id];
1650 319         1978 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 371         1241 $slg->[Marpa::R3::Internal_G::CLOSURE_BY_SYMBOL_ID] =
1656             \@nulling_closures;
1657 371         1185 $slg->[Marpa::R3::Internal_G::CLOSURE_BY_RULE_ID] =
1658             \@closure_by_irlid;
1659              
1660 371         18290 return \@registrations;
1661              
1662             }
1663              
1664             sub resolve_grammar {
1665              
1666 372     372   1063 my ($slg) = @_;
1667              
1668 372   50     1983 my $trace_actions =
1669             $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] // 0;
1670 372         1071 my $trace_file_handle =
1671             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
1672              
1673 372         702 my $resolve_error;
1674              
1675 372         1659 my $default_action_resolution =
1676             resolve_action( $slg, undef, \$resolve_error );
1677 372 50 0     1276 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 372         997 my $rule_resolutions = [];
1682              
1683 372         1708 RULE_ID: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1684              
1685 12191         20172 my $rule_resolution = resolve_rule_by_id( $slg, $irlid );
1686 12190   66     22233 $rule_resolution //= $default_action_resolution;
1687              
1688 12190 50       19850 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 12190         15285 my $blessing = rule_blessing_find( $slg, $irlid );
  12190         19310  
1711 12190         16835 my ( $closure_name, $closure, $semantics ) = @{$rule_resolution};
  12190         21914  
1712              
1713 12190 100       24361 if ( $blessing ne '::undef' ) {
1714 10738 50       17987 $semantics = '::array' if $semantics eq '::!default';
1715             CHECK_SEMANTICS: {
1716 10738 100       13055 last CHECK_SEMANTICS if $semantics eq '::array';
  10738         17054  
1717             last CHECK_SEMANTICS
1718 10668 50       22137 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 12190         32743 [ $closure_name, $closure, $semantics, $blessing ];
1730             } ## end DETERMINE_BLESSING:
1731              
1732 12190         29150 $rule_resolutions->[$irlid] = $rule_resolution;
1733              
1734             }
1735              
1736 371 50       1659 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 371         952 my @lexeme_resolutions = ();
1757              
1758 371         1376 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 371         2056 SYMBOL: for my $lexeme_id ( 0 .. $highest_symbol_id ) {
1767              
1768 14471         24489 my $semantics = lexeme_semantics_find( $slg, $lexeme_id );
1769 14471 50       25549 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 14471         23457 my $blessing = lexeme_blessing_find( $slg, $lexeme_id );
1777 14471 50       25539 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 14471         37199 $lexeme_resolutions[$lexeme_id] = [ $semantics, $blessing ];
1785              
1786             }
1787              
1788 371         2869 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 12188     12188   20523 my ( $slg, $closure_name, $p_error ) = @_;
1795 12188         17484 my $trace_file_handle =
1796             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
1797 12188         15711 my $trace_actions = $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS];
1798              
1799             # A reserved closure name;
1800 12188 100       21210 return [ q{}, undef, '::!default' ] if not defined $closure_name;
1801              
1802 11816 50       20829 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 11816 100       19125 return [ q{}, \undef, $closure_name ] if $closure_name eq '::undef';
1809 11785 100 100     39741 if ( substr( $closure_name, 0, 2 ) eq q{::}
1810             or substr( $closure_name, 0, 1 ) eq '[' )
1811             {
1812 11439         28345 return [ q{}, undef, $closure_name ];
1813             }
1814              
1815 346         558 my $fully_qualified_name;
1816 346 100       2038 if ( $closure_name =~ /([:][:])|[']/xms ) {
1817 211         375 $fully_qualified_name = $closure_name;
1818             }
1819              
1820 346 100       1014 if ( not $fully_qualified_name ) {
1821 135         651 my $resolve_package =
1822             $slg->[Marpa::R3::Internal_G::SEMANTICS_PACKAGE];
1823 135 50       602 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         418 $fully_qualified_name = $resolve_package . q{::} . $closure_name;
1834             } ## end if ( not $fully_qualified_name )
1835              
1836 346         789 my $closure;
1837             my $type;
1838             TYPE: {
1839 104     104   1052 no strict 'refs';
  104         315  
  104         5766  
  346         524  
1840 346         497 $closure = *{$fully_qualified_name}{'CODE'};
  346         1528  
1841 104     104   760 use strict;
  104         269  
  104         4695  
1842 346 100       964 if ( defined $closure ) {
1843 345         705 $type = 'CODE';
1844 345         670 last TYPE;
1845             }
1846 104     104   650 no strict 'refs';
  104         244  
  104         4175  
1847 1         2 $closure = *{$fully_qualified_name}{'SCALAR'};
  1         4  
1848 104     104   667 use strict;
  104         274  
  104         15909  
1849              
1850             # Currently $closure is always defined, but this
1851             # behavior is said to be subject to change in perlref
1852 1 50 33     5 if ( defined $closure and defined ${$closure} ) {
  1         6  
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         3 $closure = undef;
1861             } ## end TYPE:
1862              
1863 346 100       735 if ( defined $closure ) {
1864 345 50       725 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         1304 return [ $fully_qualified_name, $closure, '::array' ];
1871             } ## end if ( defined $closure )
1872              
1873 1 50 33     5 if ( $trace_actions or defined $p_error ) {
1874 1         4 for my $slot (qw(ARRAY HASH IO FORMAT)) {
1875 104     104   759 no strict 'refs';
  104         253  
  104         110181  
1876 4 50       6 if ( defined *{$fully_qualified_name}{$slot} ) {
  4         14  
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         10 my $error =
  1         6  
1892             qq{Failed resolution of action "$closure_name" to $fully_qualified_name\n};
1893 1 50       4 ${$p_error} = $error if defined $p_error;
  1         3  
1894 1 50       5 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         3 return;
1900              
1901             }
1902              
1903             sub resolve_rule_by_id {
1904 12191     12191   18673 my ( $slg, $irlid ) = @_;
1905              
1906 12191         27297 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 12191         17453 my $resolve_error;
1914 12191 100       21435 return if not defined $action_name;
1915 11816         21087 my $resolution = resolve_action( $slg, $action_name, \$resolve_error );
1916              
1917 11816 100       22627 if ( not $resolution ) {
1918 1         6 my $rule_desc = $slg->g1_rule_show($irlid);
1919 1   50     11 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 11815         17946 return $resolution;
1927             } ## end sub resolve_rule_by_id
1928              
1929             # Find the blessing for a rule.
1930             sub rule_blessing_find {
1931 12190     12190   18873 my ( $slg, $irlid ) = @_;
1932 12190         26227 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 12190         22250 return $blessing;
1945             }
1946              
1947             # Find the semantics for a lexeme.
1948             sub lexeme_semantics_find {
1949 14471     14471   22141 my ( $slg, $lexeme_id ) = @_;
1950              
1951 14471         29582 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 14471         25451 return $semantics;
1962             }
1963              
1964             # Find the blessing for a lexeme.
1965             sub lexeme_blessing_find {
1966 14471     14471   22098 my ( $slg, $lexeme_id ) = @_;
1967              
1968 14471         28585 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 14471         25104 return $result;
1978             }
1979              
1980             sub op_fn_key_by_name {
1981 7049     7049   11909 my ( $slg, $name ) = @_;
1982 7049         14218 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 7049         14320 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 371     371   1160 my ( $slg, $registrations ) = @_;
2004 371         1033 my $trace_file_handle =
2005             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
2006 371   50     2226 my $trace_actions =
2007             $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] // 0;
2008              
2009 371         910 REGISTRATION: for my $registration ( @{$registrations} ) {
  371         1258  
2010 25897         34180 my ( $type, $id, @raw_ops ) = @{$registration};
  25897         58776  
2011 25897         36381 my @ops = ();
2012             PRINT_TRACES: {
2013 25897 50       31167 last PRINT_TRACES if $trace_actions <= 2;
  25897         46533  
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 25897         37871 OP: for my $raw_op (@raw_ops) {
2043 316827 100       473640 if ( ref $raw_op ) {
2044              
2045 19553         27926 my $constants = $slg->[Marpa::R3::Internal_G::CONSTANTS];
2046 19553         23023 my $next_ix = scalar @{$constants};
  19553         26245  
2047 19553         26703 push @ops, $next_ix;
2048             $slg->[Marpa::R3::Internal_G::CONSTANTS]->[$next_ix]
2049 19553         22961 = ${$raw_op};
  19553         31610  
2050 19553         31667 next OP;
2051             }
2052 297274         387918 push @ops, $raw_op;
2053             } ## end OP: for my $raw_op (@raw_ops)
2054              
2055 25897         63820 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 25897         61976 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: