File Coverage

blib/lib/Marpa/R3/SLG.pm
Criterion Covered Total %
statement 733 894 81.9
branch 227 350 64.8
condition 39 65 60.0
subroutine 67 77 87.0
pod 0 1 0.0
total 1066 1387 76.8


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 101     101   2348 use 5.010001;
  101         409  
15 101     101   678 use strict;
  101         250  
  101         2881  
16 101     101   611 use warnings;
  101         231  
  101         4024  
17              
18 101     101   633 use vars qw($VERSION $STRING_VERSION);
  101         259  
  101         9391  
19             $VERSION = '4.001_052';
20             $STRING_VERSION = $VERSION;
21             ## no critic(BuiltinFunctions::ProhibitStringyEval)
22             $VERSION = eval $VERSION;
23             ## use critic
24              
25             package Marpa::R3::Internal_G;
26              
27 101     101   815 use Scalar::Util 'blessed';
  101         303  
  101         7282  
28 101     101   765 use English qw( -no_match_vars );
  101         259  
  101         919  
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 387     387   1171 my ($class) = @_;
37 387         1236 my $pre_slg = bless [], $class;
38 387         1790 $pre_slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE] = \*STDERR;
39 387         1061 $pre_slg->[Marpa::R3::Internal_G::CONSTANTS] = [];
40              
41 387         1141977 my $lua = Marpa::R3::Lua->new();
42 387         2311 $pre_slg->[Marpa::R3::Internal_G::L] = $lua;
43              
44 387         14890 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 387         1664 $pre_slg->[Marpa::R3::Internal_G::REGIX] = $regix;
52 387         1488 return $pre_slg;
53             }
54              
55             sub Marpa::R3::Internal::meta_grammar {
56              
57 99     99 0 3349 my $meta_slg = pre_construct('Marpa::R3::Grammar');
58              
59 99         826 state $hashed_metag = Marpa::R3::Internal::MetaG::hashed_grammar();
60 99         618 $meta_slg->[Marpa::R3::Internal_G::BLESS_PACKAGE] =
61             'Marpa::R3::Internal::MetaAST_Nodes';
62 99         642 Marpa::R3::Internal_G::hash_to_runtime( $meta_slg, $hashed_metag );
63 99         605 my $registrations = registrations_find($meta_slg );
64 99         718 registrations_set($meta_slg, $registrations );
65              
66 99         9862 return $meta_slg;
67              
68             } ## end sub Marpa::R3::Internal::meta_grammar
69              
70             sub Marpa::R3::Grammar::new {
71 288     288   94878 my ( $class, @hash_ref_args ) = @_;
72              
73 288         1238 my $slg = pre_construct($class);
74              
75 288         2023 my ( $flat_args, $error_message ) =
76             Marpa::R3::flatten_hash_args( \@hash_ref_args );
77 288 50       1172 Marpa::R3::exception( sprintf $error_message, '$slg->new' )
78             if not $flat_args;
79              
80 288         1330 my $p_dsl = Marpa::R3::Internal_G::set( $slg, $flat_args );
81 288         2634 my $ast = Marpa::R3::Internal::MetaAST->new($p_dsl);
82 285         1732 my $hashed_ast = $ast->ast_to_hash($p_dsl);
83 272         1736 Marpa::R3::Internal_G::hash_to_runtime( $slg, $hashed_ast);
84 267         1850 my $registrations = registrations_find($slg );
85 266         1460 registrations_set($slg, $registrations );
86 266         39712 return $slg;
87             }
88              
89             sub Marpa::R3::Grammar::DESTROY {
90             # say STDERR "In Marpa::R3::Grammar::DESTROY before test";
91 269     269   111154 my $slg = shift;
92 269         733 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 269 50       1145 return if not $lua;
102             # say STDERR "In Marpa::R3::Grammar::DESTROY after test";
103              
104 269         651 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
105 269         341657 $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   915 my ( $slg, @hash_ref_args ) = @_;
115 2         12 my ( $flat_args, $error_message ) =
116             Marpa::R3::flatten_hash_args( \@hash_ref_args );
117 2 50       7 Marpa::R3::exception( sprintf $error_message, '$slg->set' )
118             if not $flat_args;
119              
120 2         6 my $value = $flat_args->{trace_file_handle};
121 2 50       7 if ( defined $value ) {
122 2         4 $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE] = $value;
123 2         4 delete $flat_args->{trace_file_handle};
124             }
125              
126 2         4 my @bad_arguments = keys %{$flat_args};
  2         5  
127 2 50       7 if ( scalar @bad_arguments ) {
128 0         0 Marpa::R3::exception(
129             q{Bad named argument(s) to $slg->set() method} . join q{ },
130             @bad_arguments );
131             }
132 2         6 return;
133             }
134              
135             sub Marpa::R3::Internal_G::set {
136 288     288   918 my ( $slg, $flat_args ) = @_;
137              
138 288         842 my $dsl = $flat_args->{'source'};
139 288 50       1035 Marpa::R3::exception(
140             qq{Marpa::R3::Grammar::new() called without a 'source' argument})
141             if not defined $dsl;
142 288         910 my $dsl_ref_type = ref $dsl;
143 288 50       1120 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 288 50       672 if ( not defined ${$dsl} ) {
  288         1637  
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 288         871 delete $flat_args->{'source'};
157              
158 288         818 my $value = $flat_args->{trace_file_handle};
159 288 50       1071 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 288         763 my $trace_file_handle =
165             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
166              
167 288 50       1088 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 288 50       1128 if ( defined( exists $flat_args->{'bless_package'} ) ) {
178 288         791 my $value = $flat_args->{'bless_package'};
179 288         924 $slg->[Marpa::R3::Internal_G::BLESS_PACKAGE] = $value;
180 288         829 delete $flat_args->{'bless_package'};
181             }
182              
183 288 100       1096 if ( exists $flat_args->{'exhaustion'} ) {
184              
185 4   50     16 my $value = $flat_args->{'exhaustion'} // '';
186              
187 4         24 $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
188             <<'END_OF_LUA', 's', $value);
189             local slg, value = ...
190             local exhaustion_actions = {
191             fatal = true,
192             event = true
193             }
194             if not exhaustion_actions[value] then
195             if #value == 0 then value = 'undefined' end
196             error(string.format(
197             "'exhaustion' named arg value is %s \z
198             'event' or 'fatal'",
199             value
200             ))
201             end
202             slg.exhaustion_action = value
203             END_OF_LUA
204              
205 4         12 delete $flat_args->{'exhaustion'};
206              
207             }
208              
209 288 100       1078 if ( exists $flat_args->{'rejection'} ) {
210              
211 6   50     28 my $value = $flat_args->{'rejection'} // '';
212              
213 6         57 $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         26 delete $flat_args->{'rejection'};
232              
233             }
234              
235 288 100       1086 if ( exists $flat_args->{'semantics_package'} ) {
236 42         116 my $value = $flat_args->{'semantics_package'};
237 42         128 $slg->[Marpa::R3::Internal_G::SEMANTICS_PACKAGE] = $value;
238 42         138 delete $flat_args->{'semantics_package'};
239             }
240              
241 288 100       1078 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         128 $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         49 delete $flat_args->{'ranking_method'};
263             }
264              
265 288         890 return $dsl;
266              
267             }
268              
269             # The object, in computing the hash, is to get as much
270             # precomputation in as possible, without using undue space.
271             # That means CPU-intensive processing should tend to be done
272             # before or during hash creation, and space-intensive processing
273             # should tend to be done here, in the code that converts the
274             # hash to its runtime equivalent.
275             sub Marpa::R3::Internal_G::hash_to_runtime {
276 371     371   1320 my ( $slg, $hashed_source ) = @_;
277              
278 371         1082 my $trace_file_handle = $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
279             # Pre-lexer G1 processing
280              
281             $slg->coro_by_tag(
282             ( '@' . __FILE__ . ':' . __LINE__ ),
283             {
284             signature => 's',
285             args => [$hashed_source],
286             handlers => {
287             trace => sub {
288 0     0   0 my ($msg) = @_;
289 0         0 say {$trace_file_handle} $msg;
  0         0  
290 0         0 return 'ok';
291             },
292             }
293             },
294 371         5662 <<'END_OF_LUA');
295             local slg, source_hash = ...
296             _M.wrap(function ()
297             slg:seriable_to_runtime(source_hash)
298             end)
299             END_OF_LUA
300              
301             # For the Kollos interface, we need to create some kind
302             # of SLG method which allows access to the character_class,
303             # character_flags data. For now we just grab it from the
304             # structure
305             my ($character_pairs) = $slg->coro_by_tag(
306             ( '@' . __FILE__ . ':' . __LINE__ ),
307             {
308             signature => '',
309             args => [],
310             handlers => {
311             trace => sub {
312 0     0   0 my ($msg) = @_;
313 0         0 say {$trace_file_handle} $msg;
  0         0  
314 0         0 return 'ok';
315             },
316             }
317             },
318 366         7510 <<'END_OF_LUA');
319             local slg = ...
320             _M.wrap(function ()
321             local isys = slg.l0.isys
322             local character_pairs = {}
323             -- In reverse order, so when Perl pops them off,
324             -- they are back in symbol ID order
325             for isyid = #isys, 0, -1 do
326             local isy = isys[isyid]
327             local perl_re = isy.character_class
328             if perl_re then
329             local perl_re = isy.character_class
330             local flags = isy.character_flags
331             if flags then
332             perl_re = '(?' .. flags .. ')' .. perl_re
333             end
334             character_pairs[#character_pairs+1] = isyid
335             character_pairs[#character_pairs+1] = perl_re
336             end
337             end
338             return 'ok', character_pairs
339             end)
340             END_OF_LUA
341              
342 366         2609 my @class_table;
343             CLASS_SYMBOL:
344 366         949 while (scalar @{$character_pairs}) {
  7407         17530  
345 7041         10102 my $perl_re = pop @{$character_pairs};
  7041         11828  
346 7041         10010 my $symbol_id = pop @{$character_pairs};
  7041         10449  
347 7041         11084 my $compiled_re;
348             my $error;
349 7041 50       9857 if ( not defined eval { $compiled_re = qr/$perl_re/xms; 1; } ) {
  7041         81104  
  7041         21414  
350 0         0 $error = qq{Problem in evaluating character class: "$perl_re"\n};
351 0         0 $error .= $EVAL_ERROR;
352             }
353 7041 50       14391 if ( not $compiled_re ) {
354 0         0 $error =~ s/^/ /gxms; #indent all lines
355 0         0 Marpa::R3::exception(
356             "Failed belatedly to evaluate character class\n", $error );
357             }
358 7041         17341 push @class_table, [ $symbol_id, $compiled_re ];
359             } ## end CLASS_SYMBOL: for my $class_symbol ( sort keys %{...})
360 366         1231 $slg->[Marpa::R3::Internal_G::CHARACTER_CLASS_TABLE] = \@class_table;
361              
362 366         1273 return $slg;
363              
364             }
365              
366             our $kwgen_code_template = <<'END_OF_TEMPLATE';
367             END_OF_TEMPLATE
368              
369 0         0 sub kwgen {
370 4848     4848   11532 my ($line, $perl_name, $kollos_name, $signature) = @_;
371 4848         11587 my $tag = '@' . __FILE__ . ':' . $line;
372 4848         14640 my $code = sprintf( 'return _M.class_slg.%s(...)', $kollos_name );
373             # my $code = sprintf( 'io.stderr:write("Calling slg.%s ", table.concat(..., "")); return _M.class_slg.%s(...)', $kollos_name, $kollos_name );
374 101     101   217765 no strict 'refs';
  101         294  
  101         11111  
375 4848         27746 *{ 'Marpa::R3::Grammar::' . $perl_name }
376             = sub () {
377 21499     21499   54783 my ($slg, @args) = @_;
378 21499         51157 my ($retour) = $slg->call_by_tag($tag, $code, $signature, @args);
379 21499         53752 return $retour;
380 4848         21638 };
381 101     101   814 use strict;
  101         314  
  101         10247  
382             }
383              
384 0         0 sub kwgen_arr {
385 404     404   1187 my ($line, $perl_name, $kollos_name, $signature) = @_;
386 404         1098 my $tag = '@' . __FILE__ . ':' . $line;
387 404         1413 my $code = sprintf( 'return _M.class_slg.%s(...)', $kollos_name );
388             # my $code = sprintf( 'io.stderr:write("Calling slg.%s ", table.concat(..., "")); return _M.class_slg.%s(...)', $kollos_name, $kollos_name );
389 101     101   761 no strict 'refs';
  101         292  
  101         10175  
390 404         2607 *{ 'Marpa::R3::Grammar::' . $perl_name }
391             = sub () {
392 1672     1672   3529 my ($slg, @args) = @_;
393 1672         3713 my ($retour) = $slg->call_by_tag($tag, $code, $signature, @args);
394 1672         2660 return @{$retour};
  1672         4625  
395 404         2489 };
396 101     101   769 use strict;
  101         291  
  101         11830  
397             }
398              
399 0         0 sub kwgen_opt {
400 303     303   1204 my ($line, $perl_name, $kollos_name, $signature, @defaults) = @_;
401 303         993 my $tag = '@' . __FILE__ . ':' . $line;
402 303         1142 my $code = sprintf( 'return _M.class_slg.%s(...)', $kollos_name );
403             # my $code = sprintf( 'io.stderr:write("Calling slg.%s ", table.concat(..., "")); return _M.class_slg.%s(...)', $kollos_name, $kollos_name );
404 101     101   778 no strict 'refs';
  101         260  
  101         14112  
405 303         2094 *{ 'Marpa::R3::Grammar::' . $perl_name }
406             = sub () {
407 8     8   2220 my ($slg, @args) = @_;
408 8   66     76 $args[$_] //= $defaults[$_] for 0 .. $#defaults;
409 8         287 my ($retour) = $slg->call_by_tag($tag, $code, $signature, @args);
410 8         53 return $retour;
411 303         2398 };
412 101     101   805 use strict;
  101         272  
  101         879814  
413             }
414              
415             sub Marpa::R3::Grammar::production_show {
416 92     92   395 my ($slg, $xprid, $options) = @_;
417 92 50       243 my $verbose = $options->{verbose} or 0;
418 92 100       191 my $diag = $options->{diag} ? 1 : 0;
419 92         154 my $tag = '@' . __FILE__ . ':' . __LINE__;
420 92         129 my $code = <<'END_OF_CODE';
421             local slg, xprid, verbose, diag = ...
422             diag = diag ~= 0 -- convert diag to a boolean
423             return slg:xpr_show(xprid, { verbose = verbose, diag = diag })
424             END_OF_CODE
425 92         195 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
426             $xprid, $verbose, $diag);
427 92         283 return $retour;
428             }
429              
430             sub Marpa::R3::Grammar::symbols_show {
431 15     15   5362 my ($slg, $options) = @_;
432 15 100       87 my $verbose = $options->{verbose} or 0;
433 15 50       66 my $diag = $options->{diag} ? 1 : 0;
434 15         48 my $tag = '@' . __FILE__ . ':' . __LINE__;
435 15         39 my $code = <<'END_OF_CODE';
436             local slg, verbose, diag = ...
437             diag = diag ~= 0 -- convert diag to a boolean
438             return slg:symbols_show({ verbose = verbose, diag = diag })
439             END_OF_CODE
440 15         263 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
441             $verbose, $diag);
442 15         269 return $retour;
443             }
444              
445             sub Marpa::R3::Grammar::symbol_show {
446 40     40   401 my ($slg, $xsyid, $options) = @_;
447 40 50       139 my $verbose = $options->{verbose} or 0;
448 40 50       106 my $diag = $options->{diag} ? 1 : 0;
449 40         116 my $tag = '@' . __FILE__ . ':' . __LINE__;
450 40         75 my $code = <<'END_OF_CODE';
451             local slg, xsyid, verbose, diag = ...
452             diag = diag ~= 0 -- convert diag to a boolean
453             return slg:symbol_show(xsyid, { verbose = verbose, diag = diag })
454             END_OF_CODE
455 40         114 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
456             $xsyid, $verbose, $diag);
457 40         219 return $retour;
458             }
459              
460             sub Marpa::R3::Grammar::lmg_rule_show {
461 0     0   0 my ($slg, $subg, $irlid, $options) = @_;
462 0 0       0 my $verbose = $options->{verbose} or 0;
463 0 0       0 my $diag = $options->{diag} ? 1 : 0;
464 0         0 my $tag = '@' . __FILE__ . ':' . __LINE__;
465 0         0 my $code = <<'END_OF_CODE';
466             local slg, subg, irlid, verbose, diag = ...
467             diag = diag ~= 0 -- convert diag to a boolean
468             return slg:lmg_rule_show(subg, irlid, { verbose = verbose, diag = diag })
469             END_OF_CODE
470 0         0 my ($retour) = $slg->call_by_tag($tag, $code, 'siii',
471             $subg, $irlid, $verbose, $diag);
472 0         0 return $retour;
473             }
474              
475             sub Marpa::R3::Grammar::g1_rule_show {
476 151     151   648 my ($slg, $irlid, $options) = @_;
477 151 50       479 my $verbose = $options->{verbose} or 0;
478 151 100       400 my $diag = $options->{diag} ? 1 : 0;
479 151         296 my $tag = '@' . __FILE__ . ':' . __LINE__;
480 151         269 my $code = <<'END_OF_CODE';
481             local slg, irlid, verbose, diag = ...
482             diag = diag ~= 0 -- convert diag to a boolean
483             return slg:g1_rule_show(irlid, { verbose = verbose, diag = diag })
484             END_OF_CODE
485 151         428 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
486             $irlid, $verbose, $diag);
487 151         845 return $retour;
488             }
489              
490             sub Marpa::R3::Grammar::l0_rule_show {
491 52     52   149 my ($slg, $irlid, $options) = @_;
492 52 50       96 my $verbose = $options->{verbose} or 0;
493 52 100       67 my $diag = $options->{diag} ? 1 : 0;
494 52         61 my $tag = '@' . __FILE__ . ':' . __LINE__;
495 52         52 my $code = <<'END_OF_CODE';
496             local slg, irlid, verbose, diag = ...
497             diag = diag ~= 0 -- convert diag to a boolean
498             return slg:l0_rule_show(irlid, { verbose = verbose, diag = diag })
499             END_OF_CODE
500 52         83 my ($retour) = $slg->call_by_tag($tag, $code, 'iii',
501             $irlid, $verbose, $diag);
502 52         96 return $retour;
503             }
504              
505             sub Marpa::R3::Grammar::productions_show {
506 22     22   10650 my ($slg, $options) = @_;
507 22 100       122 my $verbose = $options->{verbose} or 0;
508 22 100       107 my $diag = $options->{diag} ? 1 : 0;
509 22         72 my $tag = '@' . __FILE__ . ':' . __LINE__;
510 22         53 my $code = <<'END_OF_CODE';
511             local slg, verbose, diag = ...
512             diag = diag ~= 0 -- convert diag to a boolean
513             return slg:xprs_show({ verbose = verbose, diag = diag })
514             END_OF_CODE
515 22         94 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
516             $verbose, $diag);
517 22         191 return $retour;
518             }
519              
520             sub Marpa::R3::Grammar::lmg_rules_show {
521 0     0   0 my ($slg, $subg, $options) = @_;
522 0 0       0 my $verbose = $options->{verbose} or 0;
523 0 0       0 my $diag = $options->{diag} ? 1 : 0;
524 0         0 my $tag = '@' . __FILE__ . ':' . __LINE__;
525 0         0 my $code = <<'END_OF_CODE';
526             local slg, subg, verbose, diag = ...
527             diag = diag ~= 0 -- convert diag to a boolean
528             return slg:lmg_rules_show(subg, { verbose = verbose, diag = diag })
529             END_OF_CODE
530 0         0 my ($retour) = $slg->call_by_tag($tag, $code, 'sii',
531             $subg, $verbose, $diag);
532 0         0 return $retour;
533             }
534              
535             sub Marpa::R3::Grammar::g1_rules_show {
536 11     11   4874 my ($slg, $options) = @_;
537 11 100       59 my $verbose = $options->{verbose} or 0;
538 11 100       56 my $diag = $options->{diag} ? 1 : 0;
539 11         32 my $tag = '@' . __FILE__ . ':' . __LINE__;
540 11         29 my $code = <<'END_OF_CODE';
541             local slg, verbose, diag = ...
542             diag = diag ~= 0 -- convert diag to a boolean
543             return slg:g1_rules_show({ verbose = verbose, diag = diag })
544             END_OF_CODE
545 11         377 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
546             $verbose, $diag);
547 11         76 return $retour;
548             }
549              
550             sub Marpa::R3::Grammar::l0_rules_show {
551 5     5   4115 my ($slg, $options) = @_;
552 5 50       30 my $verbose = $options->{verbose} or 0;
553 5 100       25 my $diag = $options->{diag} ? 1 : 0;
554 5         15 my $tag = '@' . __FILE__ . ':' . __LINE__;
555 5         14 my $code = <<'END_OF_LUA';
556             local slg, verbose, diag = ...
557             diag = diag ~= 0 -- convert diag to a boolean
558             return slg:l0_rules_show({ verbose = verbose, diag = diag })
559             END_OF_LUA
560 5         23 my ($retour) = $slg->call_by_tag($tag, $code, 'ii',
561             $verbose, $diag);
562 5         39 return $retour;
563             }
564              
565             # TODO: Census all uses of Marpa::R3::Grammar::g1_symbol_name
566             # in pod and tests, and make sure that they are appropriate --
567             # that is, that they should not be symbol_name() instead.
568              
569             kwgen(__LINE__, qw(highest_symbol_id highest_symbol_id), '');
570             kwgen(__LINE__, qw(lmg_highest_symbol_id lmg_highest_symbol_id i));
571             kwgen(__LINE__, qw(g1_highest_symbol_id g1_highest_symbol_id), '');
572             kwgen(__LINE__, qw(l0_highest_symbol_id l0_highest_symbol_id), '');
573              
574             kwgen(__LINE__, qw(start_symbol_id start_symbol_id), '');
575             kwgen(__LINE__, qw(lmg_start_symbol_id lmg_start_symbol_id s));
576             kwgen(__LINE__, qw(g1_start_symbol_id g1_start_symbol_id), '');
577             kwgen(__LINE__, qw(l0_start_symbol_id l0_start_symbol_id), '');
578              
579             kwgen(__LINE__, qw(g1_xsymbol_id g1_xsyid i));
580             kwgen(__LINE__, qw(l0_xsymbol_id l0_xsyid i));
581              
582             kwgen(__LINE__, qw(symbol_name symbol_name i));
583             kwgen(__LINE__, qw(lmg_symbol_name lmg_symbol_name si));
584             kwgen(__LINE__, qw(g1_symbol_name g1_symbol_name i));
585             kwgen(__LINE__, qw(l0_symbol_name l0_symbol_name i));
586              
587             kwgen(__LINE__, qw(symbol_display_form symbol_display_form i));
588             kwgen(__LINE__, qw(lmg_symbol_display_form lmg_symbol_display_form si));
589             kwgen(__LINE__, qw(g1_symbol_display_form g1_symbol_display_form i));
590             kwgen(__LINE__, qw(l0_symbol_display_form l0_symbol_display_form i));
591              
592             kwgen(__LINE__, qw(symbol_angled_form symbol_angled_form i));
593             kwgen(__LINE__, qw(lmg_symbol_angled_form lmg_symbol_angled_form si));
594             kwgen(__LINE__, qw(g1_symbol_angled_form g1_symbol_angled_form i));
595             kwgen(__LINE__, qw(l0_symbol_angled_form l0_symbol_angled_form i));
596              
597             kwgen(__LINE__, qw(symbol_dsl_form symbol_dsl_form i));
598             kwgen(__LINE__, qw(lmg_symbol_dsl_form lmg_symbol_dsl_form si));
599             kwgen(__LINE__, qw(g1_symbol_dsl_form g1_symbol_dsl_form i));
600             kwgen(__LINE__, qw(l0_symbol_dsl_form l0_symbol_dsl_form i));
601              
602             kwgen_opt(__LINE__, qw(lmg_symbols_show lmg_symbols_show si), 0, 0);
603             kwgen_opt(__LINE__, qw(g1_symbols_show g1_symbols_show i), 0);
604             kwgen_opt(__LINE__, qw(l0_symbols_show l0_symbols_show i), 0);
605              
606             kwgen(__LINE__, qw(lmg_symbol_by_name lmg_symbol_by_name si));
607             kwgen(__LINE__, qw(g1_symbol_by_name g1_symbol_by_name i));
608             kwgen(__LINE__, qw(l0_symbol_by_name l0_symbol_by_name i));
609              
610             kwgen(__LINE__, qw(g1_symbol_is_accessible g1_symbol_is_accessible i));
611             kwgen(__LINE__, qw(g1_symbol_is_nulling g1_symbol_is_nulling i));
612             kwgen(__LINE__, qw(g1_symbol_is_productive g1_symbol_is_productive i));
613              
614             kwgen(__LINE__, qw(production_dotted_show xpr_dotted_show ii));
615             kwgen(__LINE__, qw(lmg_dotted_rule_show lmg_dotted_rule_show sii));
616             kwgen(__LINE__, qw(g1_dotted_rule_show g1_dotted_rule_show ii));
617             kwgen(__LINE__, qw(l0_dotted_rule_show l0_dotted_rule_show ii));
618              
619             kwgen(__LINE__, qw(production_name xpr_name i));
620              
621             kwgen(__LINE__, qw(lmg_rule_to_production_id lmg_rule_to_xprid si));
622             kwgen(__LINE__, qw(g1_rule_to_production_id g1_rule_to_xprid i));
623             kwgen(__LINE__, qw(l0_rule_to_production_id l0_rule_to_xprid i));
624              
625             kwgen(__LINE__, qw(lmg_rule_to_production_dot lmg_rule_to_xpr_dots si));
626             kwgen(__LINE__, qw(g1_rule_to_production_dot g1_rule_to_xpr_dots i));
627             kwgen(__LINE__, qw(l0_rule_to_production_dot l0_rule_to_xpr_dots i));
628              
629             kwgen(__LINE__, qw(highest_production_id highest_xprid), '');
630             kwgen(__LINE__, qw(lmg_highest_rule_id lmg_highest_rule_id), '');
631             kwgen(__LINE__, qw(g1_highest_rule_id g1_highest_rule_id), '');
632             kwgen(__LINE__, qw(l0_highest_rule_id l0_highest_rule_id), '');
633              
634             kwgen_arr(__LINE__, qw(production_expand xpr_expand i));
635             kwgen_arr(__LINE__, qw(lmg_rule_expand lmg_irl_isyids si));
636             kwgen_arr(__LINE__, qw(g1_rule_expand g1_irl_isyids i));
637             kwgen_arr(__LINE__, qw(l0_rule_expand l0_irl_isyids i));
638              
639             kwgen(__LINE__, qw(production_length xpr_length i));
640              
641             sub Marpa::R3::Grammar::call_by_tag {
642 157369     157369   339161 my ( $slg, $tag, $codestr, $sig, @args ) = @_;
643 157369         247285 my $lua = $slg->[Marpa::R3::Internal_G::L];
644 157369         215253 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
645             # $DB::single = 1 if not defined $lua;
646             # $DB::single = 1 if not defined $regix;
647             # $DB::single = 1 if not defined $tag;
648             # $DB::single = 1 if not defined $codestr;
649             # $DB::single = 1 if not defined $sig;
650             # $DB::single = 1 if grep { not defined $_ } @args;
651 157369         317749 my @results;
652             my $eval_error;
653 157369         0 my $eval_ok;
654             {
655 157369         207680 local $@;
  157369         212304  
656 157369         249446 $eval_ok = eval {
657             # say STDERR "About to call_by_tag($regix, $tag, $codestr, $sig, @args)";;
658 157369         1502106 @results = $lua->call_by_tag($regix, $tag, $codestr, $sig, @args);
659             # say STDERR "Returned from call_by_tag($regix, $tag, $codestr, $sig, @args)";;
660 157369         353261 return 1;
661             };
662 157369         311739 $eval_error = $@;
663             }
664 157369 50       318468 if ( not $eval_ok ) {
665 0         0 Marpa::R3::exception($eval_error);
666             }
667              
668 157369         370643 return @results;
669             }
670              
671             # not to be documented
672             sub Marpa::R3::Grammar::coro_by_tag {
673 1930     1930   6637 my ( $slg, $tag, $args, $codestr ) = @_;
674 1930         4447 my $lua = $slg->[Marpa::R3::Internal_G::L];
675 1930         3895 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
676 1930   50     16882 my $handler = $args->{handlers} // {};
677 1930         5335 my $resume_tag = $tag . '[R]';
678 1930   50     5693 my $signature = $args->{signature} // '';
679 1930   50     5949 my $p_args = $args->{args} // [];
680              
681 1930         5660 my @results;
682             my $eval_error;
683 1930         0 my $eval_ok;
684             {
685 1930         3338 local $@;
  1930         3469  
686 1930         4042 $eval_ok = eval {
687 1930         3958 $lua->call_by_tag( $regix, $tag, $codestr, $signature, @{$p_args} );
  1930         1386247  
688 1930         38595 my $coro_arg;
689 1930         3854 CORO_CALL: while (1) {
690 4324         2864511 my ( $cmd, $yield_data ) =
691             $lua->call_by_tag( $regix, $resume_tag,
692             'local slg, coro_arg = ...; return _M.resume(coro_arg)',
693             's', $coro_arg );
694              
695 4319 100       17571 if (not $cmd) {
696 1925         3550 @results = @{$yield_data};
  1925         5046  
697 1925         7193 return 1;
698             }
699 2394         5894 my $handler = $handler->{$cmd};
700 2394 50       5775 Marpa::R3::exception(qq{No coro handler for "$cmd"})
701             if not $handler;
702 2394   50     5501 $yield_data //= [];
703 2394         3634 my $handler_cmd;
704 2394         3814 ($handler_cmd, $coro_arg) = $handler->(@{$yield_data});
  2394         8016  
705             }
706 0         0 return 1;
707             };
708 1930         5266 $eval_error = $@;
709             }
710 1930 100       5525 if ( not $eval_ok ) {
711 5         32 Marpa::R3::exception($eval_error);
712             }
713 1925         7275 return @results;
714             }
715              
716             sub Marpa::R3::Grammar::symbol_ids_gen {
717 2     2   2025 my ($slg) = @_;
718 2         8 my $next = 1;
719 2         12 my $last = $slg->highest_symbol_id();
720             return sub () {
721 82 100   82   610 return if $next > $last;
722 80         198 my $current;
723 80         215 ($current, $next) = ($next, $next+1);
724 80         204 return $current;
725             }
726 2         24 }
727              
728             sub Marpa::R3::Grammar::lmg_symbol_ids_gen {
729 0     0   0 my ($slg, $subg) = @_;
730 0         0 my $next = 0;
731 0         0 my $last = $slg->lmg_highest_symbol_id($subg);
732             return sub () {
733 0 0   0   0 return if $next > $last;
734 0         0 my $current;
735 0         0 ($current, $next) = ($next, $next+1);
736 0         0 return $current;
737             }
738 0         0 }
739              
740             sub Marpa::R3::Grammar::g1_symbol_ids_gen {
741 6     6   3574 my ($slg) = @_;
742 6         17 my $next = 0;
743 6         29 my $last = $slg->g1_highest_symbol_id();
744             return sub () {
745 65 100   65   392 return if $next > $last;
746 61         102 my $current;
747 61         132 ($current, $next) = ($next, $next+1);
748 61         137 return $current;
749             }
750 6         61 }
751              
752             sub Marpa::R3::Grammar::l0_symbol_ids_gen {
753 2     2   2068 my ($slg) = @_;
754 2         6 my $next = 0;
755 2         10 my $last = $slg->l0_highest_symbol_id();
756             return sub () {
757 68 100   68   438 return if $next > $last;
758 66         113 my $current;
759 66         150 ($current, $next) = ($next, $next+1);
760 66         164 return $current;
761             }
762 2         25 }
763              
764             sub Marpa::R3::Grammar::production_ids_gen {
765 3     3   2458 my ($slg) = @_;
766 3         8 my $next = 1;
767 3         13 my $last = $slg->highest_production_id();
768             return sub () {
769 141 100   141   809 return if $next > $last;
770 138         179 my $current;
771 138         220 ($current, $next) = ($next, $next+1);
772 138         242 return $current;
773             }
774 3         27 }
775              
776             sub Marpa::R3::Grammar::lmg_rule_ids_gen {
777 0     0   0 my ($slg, $subg) = @_;
778 0         0 my $next = 0;
779 0         0 my $last = $slg->lmg_highest_rule_id($subg);
780             return sub () {
781 0 0   0   0 return if $next > $last;
782 0         0 my $current;
783 0         0 ($current, $next) = ($next, $next+1);
784 0         0 return $current;
785             }
786 0         0 }
787              
788             sub Marpa::R3::Grammar::g1_rule_ids_gen {
789 1832     1832   7191 my ($slg) = @_;
790 1832         3205 my $next = 0;
791 1832         5361 my $last = $slg->g1_highest_rule_id();
792             return sub () {
793 50597 100   50597   104142 return if $next > $last;
794 49133         64375 my $current;
795 49133         82449 ($current, $next) = ($next, $next+1);
796 49133         105441 return $current;
797             }
798 1832         14059 }
799              
800             sub Marpa::R3::Grammar::l0_rule_ids_gen {
801 4     4   2645 my ($slg) = @_;
802 4         7 my $next = 0;
803 4         15 my $last = $slg->l0_highest_rule_id();
804             return sub () {
805 108 100   108   431 return if $next > $last;
806 104         105 my $current;
807 104         136 ($current, $next) = ($next, $next+1);
808 104         139 return $current;
809             }
810 4         31 }
811              
812             # not to be documented
813             sub Marpa::R3::Grammar::nrls_show {
814 7     7   326 my ($slg) = @_;
815 7         38 my ($result) =
816             $slg->call_by_tag(
817             ('@' . __FILE__ . ':' . __LINE__),
818             <<'END_OF_LUA', '' );
819             local grammar = ...
820             local g1g = grammar.g1
821             local nrl_count = g1g:_nrl_count()
822             local pieces = {}
823             for nrl_id = 0, nrl_count - 1 do
824             pieces[#pieces+1] = g1g:brief_nrl(nrl_id)
825             end
826             pieces[#pieces+1] = ''
827             return table.concat(pieces, '\n')
828             END_OF_LUA
829 7         44 return $result;
830             }
831              
832             # not to be documented
833             sub Marpa::R3::Grammar::nsys_show {
834 4     4   13 my ($slg) = @_;
835 4         19 my ($result) =
836             $slg->call_by_tag(
837             ('@' . __FILE__ . ':' . __LINE__),
838             <<'END_OF_LUA', '' );
839             local grammar = ...
840             local g1g = grammar.g1
841             local nsy_count = g1g:_nsy_count()
842             local pieces = {}
843             for nsy_id = 0, nsy_count - 1 do
844             pieces[#pieces+1] = g1g:nsy_show(nsy_id)
845             end
846             return table.concat(pieces)
847             END_OF_LUA
848 4         28 return $result;
849             }
850              
851             # not to be documented
852             sub Marpa::R3::Grammar::ahms_show {
853 13     13   4340 my ( $slg, $options ) = @_;
854 13   100     115 $options //= {};
855 13 100       188 my $verbose = $options->{verbose} or 0;
856              
857 13         70 my ($text) = $slg->call_by_tag(
858             ('@' . __FILE__ . ':' . __LINE__),
859             <<'END_OF_LUA', 'i', $verbose );
860             local grammar, verbose = ...
861             local g1g = grammar.g1
862             return g1g:ahms_show({verbose = verbose})
863             END_OF_LUA
864              
865 13         96 return $text;
866              
867             }
868              
869             # not to be documented
870             sub Marpa::R3::Grammar::dotted_nrl_show {
871 490     490   856 my ( $slg, $nrl_id, $dot_position ) = @_;
872 490         1032 my ($result) =
873             $slg->call_by_tag(
874             ('@' . __FILE__ . ':' . __LINE__),
875             <<'END_OF_LUA', 'ii', $nrl_id, $dot_position );
876             local grammar, nrl_id, dot_position = ...
877             local g1g = grammar.g1
878             return g1g:_dotted_nrl_show(nrl_id, dot_position)
879             END_OF_LUA
880 490         1522 return $result;
881             }
882              
883             # not to be documented
884             sub Marpa::R3::Grammar::briefer_ahm {
885 609     609   921 my ( $slg, $item_id ) = @_;
886              
887 609         1175 my ($text) = $slg->call_by_tag(
888             ('@' . __FILE__ . ':' . __LINE__),
889             <<'END_OF_LUA', 'i', $item_id );
890             local grammar, item_id = ...
891             local g1g = grammar.g1
892             local irl_id = g1g:_ahm_nrl(item_id)
893             local dot_position = g1g:_ahm_position(item_id)
894             if (dot_position < 0 ) then
895             return string.format("R%d$", irl_id)
896             end
897             return string.format("R%d:%d", irl_id, dot_position)
898             END_OF_LUA
899              
900 609         1302 return $text;
901              
902             }
903              
904             # not to be documented
905             sub Marpa::R3::Grammar::brief_nrl {
906 0     0   0 my ( $slg, $nrl_id ) = @_;
907 0         0 my ($text) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
908             <<'END_OF_LUA', 'i', $nrl_id );
909             local grammar, nrl_id = ...
910             local g1g = grammar.g1
911             return g1g:brief_nrl(nrl_id)
912             END_OF_LUA
913              
914 0         0 return $text;
915             }
916              
917             # not to be documented
918             sub Marpa::R3::Grammar::regix {
919 1     1   7342 my ( $slg ) = @_;
920 1         4 my $regix = $slg->[Marpa::R3::Internal_G::REGIX];
921 1         3 return $regix;
922             }
923              
924             sub registrations_find {
925 366     366   1140 my ($slg) = @_;
926 366         1054 my $trace_file_handle =
927             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
928 366   50     2271 my $trace_actions =
929             $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] // 0;
930              
931 366         955 my @closure_by_irlid = ();
932 366         860 my @semantics_by_irlid = ();
933 366         821 my @blessing_by_irlid = ();
934              
935 366         1602 my ( $rule_resolutions, $lexeme_resolutions ) = resolve_grammar($slg);
936              
937             # Set the arrays, and perform various checks on the resolutions
938             # we received
939             {
940 365         962 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
  365         1321  
941             my ( $new_resolution, $closure, $semantics, $blessing ) =
942 11869         16429 @{ $rule_resolutions->[$irlid] };
  11869         31943  
943 11869         34319 my ($lhs_id) =
944             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
945             <<'END_OF_LUA', 'i>*', $irlid );
946             local grammar, irlid = ...
947             local g1g = grammar.g1
948             return g1g:rule_lhs(irlid)
949             END_OF_LUA
950              
951             REFINE_SEMANTICS: {
952              
953 11869 100 66     19911 if (
  11869         46342  
954             '[' eq substr $semantics,
955             0, 1 and ']' eq substr $semantics,
956             -1, 1
957             )
958             {
959             # Normalize array semantics
960 10456         118711 $semantics =~ s/ //gxms;
961 10456         21072 last REFINE_SEMANTICS;
962             } ## end if ( '[' eq substr $semantics, 0, 1 and ']' eq ...)
963              
964             state $allowed_semantics = {
965 1413         2534 map { ; ( $_, 1 ) } qw(::array ::undef ::first ::!default),
  495         1681  
966             q{}
967             };
968 1413 50       4427 last REFINE_SEMANTICS if $allowed_semantics->{$semantics};
969             last REFINE_SEMANTICS
970 0 0       0 if $semantics =~ m/ \A rhs \d+ \z /xms;
971              
972 0         0 Marpa::R3::exception(
973             q{Unknown semantics for rule },
974             $slg->g1_rule_show($irlid),
975             "\n",
976             qq{ Semantics were specified as "$semantics"\n}
977             );
978              
979             } ## end REFINE_SEMANTICS:
980              
981 11869         24585 $semantics_by_irlid[$irlid] = $semantics;
982 11869         19871 $blessing_by_irlid[$irlid] = $blessing;
983 11869         19766 $closure_by_irlid[$irlid] = $closure;
984              
985             CHECK_BLESSING: {
986 11869 100       15936 last CHECK_BLESSING if $blessing eq '::undef';
  11869         26630  
987 10426 50       18138 if ($closure) {
988 0         0 my $ref_type = Scalar::Util::reftype $closure;
989 0 0       0 if ( $ref_type eq 'SCALAR' ) {
990              
991             # The constant's dump might be long so I repeat the error message
992 0         0 Marpa::R3::exception(
993             qq{Fatal error: Attempt to bless a rule that resolves to a scalar constant\n},
994             qq{ Scalar constant is },
995             Data::Dumper::Dumper($closure),
996             qq{ Blessing is "$blessing"\n},
997             q{ Rule is: },
998             $slg->g1_rule_show($irlid),
999             "\n",
1000             qq{ Cannot bless rule when it resolves to a scalar constant},
1001             "\n",
1002             );
1003             } ## end if ( $ref_type eq 'SCALAR' )
1004 0         0 last CHECK_BLESSING;
1005             } ## end if ($closure)
1006 10426 100       18695 last CHECK_BLESSING if $semantics eq '::array';
1007 10356 50       33639 last CHECK_BLESSING if ( substr $semantics, 0, 1 ) eq '[';
1008 0         0 Marpa::R3::exception(
1009             qq{Cannot bless rule when the semantics are "$semantics"},
1010             q{ Rule is: },
1011             $slg->g1_rule_show($irlid),
1012             "\n",
1013             qq{ Blessing is "$blessing"\n},
1014             qq{ Semantics are "$semantics"\n}
1015             );
1016             } ## end CHECK_BLESSING:
1017              
1018             }
1019              
1020             } ## end CHECK_FOR_WHATEVER_CONFLICT
1021              
1022             # A LHS can be nullable via more than one rule,
1023             # and that means more than one semantics might be specified for
1024             # the nullable symbol. This logic deals with that.
1025 365         1156 my @nullable_rule_ids_by_lhs = ();
1026 365         1303 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1027              
1028 11869         29085 my ( $lhs_id, $rule_is_nullable ) =
1029             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1030             <<'END_OF_LUA', 'i>*', $irlid );
1031             local grammar, irlid = ...
1032             local g1g = grammar.g1
1033             return g1g:rule_lhs(irlid), g1g:rule_is_nullable(irlid)
1034             END_OF_LUA
1035              
1036 11869 100       32373 push @{ $nullable_rule_ids_by_lhs[$lhs_id] }, $irlid
  545         2485  
1037             if $rule_is_nullable;
1038             }
1039              
1040 365         893 my @null_symbol_closures;
1041             LHS:
1042 365         1570 for ( my $lhs_id = 0 ; $lhs_id <= $#nullable_rule_ids_by_lhs ; $lhs_id++ ) {
1043 7899         11141 my $irlids = $nullable_rule_ids_by_lhs[$lhs_id];
1044 7899         9693 my $resolution_rule;
1045              
1046             # No nullable rules for this LHS? No problem.
1047 7899 100       17989 next LHS if not defined $irlids;
1048 539         959 my $rule_count = scalar @{$irlids};
  539         1084  
1049              
1050             # I am not sure if this test is necessary
1051 539 50       1432 next LHS if $rule_count <= 0;
1052              
1053             # Just one nullable rule? Then that's our semantics.
1054 539 100       1426 if ( $rule_count == 1 ) {
1055 533         1054 $resolution_rule = $irlids->[0];
1056             my ( $resolution_name, $closure ) =
1057 533         923 @{ $rule_resolutions->[$resolution_rule] };
  533         1556  
1058 533 50       1420 if ($trace_actions) {
1059 0         0 my $lhs_name = $slg->g1_symbol_display_form($lhs_id);
1060 0 0       0 say {$trace_file_handle}
  0         0  
1061             qq{Nulled symbol "$lhs_name" },
1062             qq{ resolved to "$resolution_name" from rule },
1063             $slg->g1_rule_show($resolution_rule)
1064             or Marpa::R3::exception('print to trace handle failed');
1065             } ## end if ($trace_actions)
1066 533         1821 $null_symbol_closures[$lhs_id] = $resolution_rule;
1067 533         1666 next LHS;
1068             } ## end if ( $rule_count == 1 )
1069              
1070             # More than one rule? Are any empty?
1071             # If so, use the semantics of the empty rule
1072 6         28 my ($empty_rules) =
1073             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1074             <<'END_OF_LUA', 'i>*', $irlids );
1075             local grammar, irlids = ...
1076             local g1g = grammar.g1
1077             local empty_rules = {}
1078             for ix = 1, #irlids do
1079             local irlid = irlids[ix]
1080             local rule_length = g1g:rule_length(irlid)
1081             if rule_length and rule_length == 0 then
1082             empty_rules[#empty_rules+1] = irlid
1083             end
1084             end
1085             return empty_rules
1086             END_OF_LUA
1087              
1088 6 100       17 if ( scalar @{$empty_rules} ) {
  6         33  
1089 5         10 $resolution_rule = $empty_rules->[0];
1090             my ( $resolution_name, $closure ) =
1091 5         8 @{ $rule_resolutions->[$resolution_rule] };
  5         14  
1092 5 50       20 if ($trace_actions) {
1093 0         0 my $lhs_name = $slg->g1_symbol_display_form($lhs_id);
1094 0 0       0 say {$trace_file_handle}
  0         0  
1095             qq{Nulled symbol "$lhs_name" },
1096             qq{ resolved to "$resolution_name" from rule },
1097             $slg->g1_rule_show($resolution_rule)
1098             or Marpa::R3::exception('print to trace handle failed');
1099             } ## end if ($trace_actions)
1100 5         11 $null_symbol_closures[$lhs_id] = $resolution_rule;
1101 5         17 next LHS;
1102             }
1103              
1104             # Multiple rules, none of them empty.
1105             my ( $first_resolution, @other_resolutions ) =
1106 1         3 map { $rule_resolutions->[$_] } @{$irlids};
  2         8  
  1         4  
1107              
1108             # Do they have more than one semantics?
1109             # If so, just call it an error and let the user sort it out.
1110             my ( $first_closure_name, undef, $first_semantics, $first_blessing ) =
1111 1         4 @{$first_resolution};
  1         5  
1112 1         4 OTHER_RESOLUTION: for my $other_resolution (@other_resolutions) {
1113             my ( $other_closure_name, undef, $other_semantics, $other_blessing )
1114 1         3 = @{$other_resolution};
  1         4  
1115              
1116 1 50 33     15 if ( $first_closure_name ne $other_closure_name
      33        
1117             or $first_semantics ne $other_semantics
1118             or $first_blessing ne $other_blessing )
1119             {
1120 0         0 Marpa::R3::exception(
1121             'When nulled, symbol ',
1122             $slg->g1_symbol_display_form($lhs_id),
1123             qq{ can have more than one semantics\n},
1124             qq{ Marpa needs there to be only one semantics\n},
1125             qq{ The rules involved are:\n},
1126             g1_show_rule_list( $slg, $irlids )
1127             );
1128             } ## end if ( $first_closure_name ne $other_closure_name or ...)
1129             } ## end OTHER_RESOLUTION: for my $other_resolution (@other_resolutions)
1130              
1131             # Multiple rules, but they all have one semantics.
1132             # So (obviously) use that semantics
1133 1         3 $resolution_rule = $irlids->[0];
1134             my ( $resolution_name, $closure ) =
1135 1         3 @{ $rule_resolutions->[$resolution_rule] };
  1         4  
1136 1 50       6 if ($trace_actions) {
1137 0         0 my $lhs_name = $slg->g1_symbol_display_form($lhs_id);
1138 0 0       0 say {$trace_file_handle}
  0         0  
1139             qq{Nulled symbol "$lhs_name" },
1140             qq{ resolved to "$resolution_name" from rule },
1141             $slg->g1_rule_show($resolution_rule)
1142             or Marpa::R3::exception('print to trace handle failed');
1143             } ## end if ($trace_actions)
1144 1         5 $null_symbol_closures[$lhs_id] = $resolution_rule;
1145              
1146             } ## end LHS: for ( my $lhs_id = 0; $lhs_id <= $#nullable_rule_ids_by_lhs...)
1147              
1148             # Do consistency checks
1149              
1150             # Set the object values
1151 365         1526 my $null_values = $slg->[Marpa::R3::Internal_G::NULL_VALUES] =
1152             \@null_symbol_closures;
1153              
1154 365         964 my @semantics_by_lexeme_id = ();
1155 365         855 my @blessing_by_lexeme_id = ();
1156              
1157             # Check the lexeme semantics
1158             {
1159 365         733 my ($highest_symbol_id) =
  365         1626  
1160             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1161             <<'END_OF_LUA', '>*' );
1162             local grammar = ...
1163             local g1g = grammar.g1
1164             return g1g:highest_symbol_id()
1165             END_OF_LUA
1166              
1167 365         1702 LEXEME: for my $lexeme_id ( 0 .. $highest_symbol_id ) {
1168              
1169             my ( $semantics, $blessing ) =
1170 14090         18582 @{ $lexeme_resolutions->[$lexeme_id] };
  14090         30125  
1171 14090 50       27338 $blessing = '::undef' if not defined $blessing;
1172             CHECK_SEMANTICS: {
1173 14090 50       18359 if ( not $semantics ) {
  14090         23273  
1174 0         0 $semantics = '::!default';
1175 0         0 last CHECK_SEMANTICS;
1176             }
1177 14090 100       28509 if ( ( substr $semantics, 0, 1 ) eq '[' ) {
1178 7597         75020 $semantics =~ s/ //gxms;
1179 7597         13935 last CHECK_SEMANTICS;
1180             }
1181             state $allowed_semantics =
1182 6493         8619 { map { ; ( $_, 1 ) } qw(::array ::undef ::!default ) };
  297         977  
1183              
1184 6493 50       12920 if ( not $allowed_semantics->{$semantics} ) {
1185 0         0 Marpa::R3::exception(
1186             q{Unknown semantics for lexeme },
1187             $slg->g1_symbol_display_form($lexeme_id),
1188             "\n",
1189             qq{ Semantics were specified as "$semantics"\n}
1190             );
1191             } ## end if ( not $allowed_semantics->{$semantics} )
1192              
1193             } ## end CHECK_SEMANTICS:
1194 14090         24678 $semantics_by_lexeme_id[$lexeme_id] = $semantics;
1195 14090         26375 $blessing_by_lexeme_id[$lexeme_id] = $blessing;
1196              
1197             }
1198              
1199             }
1200              
1201             # state $op_lua = Marpa::R3::Thin::op('lua');
1202 365         1774 my ($op_lua) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1203             <<'END_OF_LUA', '' );
1204             return _M.defines.MARPA_OP_LUA
1205             END_OF_LUA
1206              
1207 365         1576 my ($op_debug_key) = op_fn_key_by_name( $slg, "debug" );
1208 365         1219 my ($op_noop_key) = op_fn_key_by_name( $slg, "noop" );
1209 365         1156 my ($op_bail_key) = op_fn_key_by_name( $slg, "bail" );
1210 365         1120 my ($op_bless_key) = op_fn_key_by_name( $slg, "bless" );
1211 365         1119 my ($op_callback_key) = op_fn_key_by_name( $slg, "callback" );
1212 365         1190 my ($result_is_undef_key) = op_fn_key_by_name( $slg, 'result_is_undef' );
1213 365         1157 my ($result_is_constant_key) =
1214             op_fn_key_by_name( $slg, 'result_is_constant' );
1215 365         1110 my ($result_is_token_value_key) =
1216             op_fn_key_by_name( $slg, "result_is_token_value" );
1217 365         1147 my ($result_is_n_of_rhs_key) =
1218             op_fn_key_by_name( $slg, "result_is_n_of_rhs" );
1219 365         1144 my ($result_is_n_of_sequence_key) =
1220             op_fn_key_by_name( $slg, "result_is_n_of_sequence" );
1221 365         1150 my ($result_is_array_key) = op_fn_key_by_name( $slg, "result_is_array" );
1222 365         1204 my ($op_push_constant_key) = op_fn_key_by_name( $slg, 'push_constant' );
1223 365         1142 my ($op_push_undef_key) = op_fn_key_by_name( $slg, 'push_undef' );
1224 365         1193 my ($op_push_one_key) = op_fn_key_by_name( $slg, 'push_one' );
1225 365         1113 my ($op_push_values_key) = op_fn_key_by_name( $slg, 'push_values' );
1226 365         1088 my ($op_push_g1_start_key) = op_fn_key_by_name( $slg, 'push_g1_start' );
1227 365         1138 my ($op_push_g1_length_key) = op_fn_key_by_name( $slg, 'push_g1_length' );
1228 365         1130 my ($op_push_start_key) = op_fn_key_by_name( $slg, 'push_start' );
1229 365         1091 my ($op_push_length_key) = op_fn_key_by_name( $slg, 'push_length' );
1230              
1231 365         805 my @nulling_symbol_by_semantic_rule;
1232 365         791 NULLING_SYMBOL: for my $nulling_symbol ( 0 .. $#{$null_values} ) {
  365         1915  
1233 7899         10941 my $semantic_rule = $null_values->[$nulling_symbol];
1234 7899 100       14892 next NULLING_SYMBOL if not defined $semantic_rule;
1235 539         1399 $nulling_symbol_by_semantic_rule[$semantic_rule] = $nulling_symbol;
1236             } ## end NULLING_SYMBOL: for my $nulling_symbol ( 0 .. $#{$null_values} )
1237              
1238 365         1052 my @work_list = ();
1239 365         1370 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1240              
1241 11869         18676 my $semantics = $semantics_by_irlid[$irlid];
1242 11869         19739 my $blessing = $blessing_by_irlid[$irlid];
1243              
1244 11869 100       21019 $semantics = '[name,values]' if $semantics eq '::!default';
1245 11869 100       19946 $semantics = '[values]' if $semantics eq '::array';
1246 11869 100       19982 $semantics = '::rhs0' if $semantics eq '::first';
1247              
1248 11869         34336 push @work_list, [ $irlid, undef, $semantics, $blessing ];
1249             }
1250              
1251 365         1617 my ($highest_symbol_id) =
1252             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1253             <<'END_OF_LUA', '' );
1254             local grammar = ...
1255             return grammar.g1:highest_symbol_id()
1256             END_OF_LUA
1257              
1258 365         1489 LEXEME: for my $lexeme_id ( 0 .. $highest_symbol_id ) {
1259              
1260 14090         21869 my $semantics = $semantics_by_lexeme_id[$lexeme_id];
1261 14090         20414 my $blessing = $blessing_by_lexeme_id[$lexeme_id];
1262              
1263             next LEXEME
1264 14090 100 100     34140 if $semantics eq '::!default' and $blessing eq '::undef';
1265 12468 100       21397 $semantics = '::value' if $semantics eq '::!default';
1266 12468 50       20536 $semantics = '[value]' if $semantics eq '::array';
1267              
1268 12468         30714 push @work_list, [ undef, $lexeme_id, $semantics, $blessing ];
1269             }
1270              
1271             # Registering operations is postponed to this point, because
1272             # the valuator must exist for this to happen. In the future,
1273             # it may be best to have a separate semantics object.
1274 365         1018 my @nulling_closures = ();
1275 365         845 my @registrations = ();
1276              
1277 365         1020 WORK_ITEM: for my $work_item (@work_list) {
1278 24337         34961 my ( $irlid, $lexeme_id, $semantics, $blessing ) = @{$work_item};
  24337         54330  
1279              
1280 24337         38419 my ( $closure, $rule_length,
1281             $is_sequence_rule,
1282             $is_discard_sequence_rule,
1283             $nulling_symbol_id );
1284 24337 100       43822 if ( defined $irlid ) {
1285 11869         18426 $nulling_symbol_id = $nulling_symbol_by_semantic_rule[$irlid];
1286 11869         17888 $closure = $closure_by_irlid[$irlid];
1287              
1288 11869         32377 ( $rule_length, $is_sequence_rule,
1289             $is_discard_sequence_rule ) =
1290             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1291             <<'END_OF_LUA', 'i', $irlid );
1292             local slg, irlid = ...
1293             local g1g = slg.g1
1294             local is_sequence_rule = g1g:sequence_min(irlid) and 1 or 0
1295             local irl = slg.g1.irls[irlid]
1296             local xpr = irl.xpr
1297             local is_discard_sequence = false
1298             if xpr and xpr.discard_separation and is_sequence_rule then
1299             is_discard_sequence = true
1300             end
1301             return g1g:rule_length(irlid), is_sequence_rule, is_discard_sequence
1302             END_OF_LUA
1303              
1304             } ## end if ( defined $irlid )
1305              
1306             # Determine the "fate" of the array of child values
1307 24337         39815 my @array_fate = ();
1308             ARRAY_FATE: {
1309 24337 100 100     33533 if ( defined $closure and ref $closure eq 'CODE' ) {
  24337         49032  
1310 345         787 push @array_fate, $op_lua, $op_callback_key, $op_bail_key;
1311 345         849 last ARRAY_FATE;
1312              
1313             }
1314              
1315 23992 100       54786 if ( ( substr $semantics, 0, 1 ) eq '[' ) {
1316 18582         34398 push @array_fate, $op_lua, $result_is_array_key, $op_bail_key;
1317 18582         29660 last ARRAY_FATE;
1318             }
1319             } ## end ARRAY_FATE:
1320              
1321 24337         33942 my @ops = ();
1322              
1323             SET_OPS: {
1324              
1325 24337 100       31723 if ( $semantics eq '::undef' ) {
  24337         44604  
1326 31         44 @ops = ( $op_lua, $result_is_undef_key, $op_bail_key );
1327 31         41 last SET_OPS;
1328             }
1329              
1330             CHECK_TYPE: {
1331 24306 100       30738 last CHECK_TYPE if not defined $irlid;
  24306         44883  
1332 11838         18614 my $thingy_ref = $closure_by_irlid[$irlid];
1333 11838 100       24159 last CHECK_TYPE if not defined $thingy_ref;
1334 345         1189 my $ref_type = Scalar::Util::reftype $thingy_ref;
1335 345 50       968 if ( $ref_type eq q{} ) {
1336 0         0 my $rule_desc = $slg->g1_rule_show($irlid);
1337 0         0 Marpa::R3::exception(
1338             qq{An action resolved to a scalar.\n},
1339             qq{ This is not allowed.\n},
1340             qq{ A constant action must be a reference.\n},
1341             qq{ Rule was $rule_desc\n}
1342             );
1343             } ## end if ( $ref_type eq q{} )
1344              
1345 345 50       885 if ( $ref_type eq 'CODE' ) {
1346              
1347             # Set the nulling closure if this is the nulling symbol of a rule
1348 345 100 66     1194 $nulling_closures[$nulling_symbol_id] = $thingy_ref
1349             if defined $nulling_symbol_id
1350             and defined $irlid;
1351 345         784 last CHECK_TYPE;
1352             } ## end if ( $ref_type eq 'CODE' )
1353              
1354 0         0 my $rule_desc = $slg->g1_rule_show($irlid);
1355 0         0 Marpa::R3::exception(
1356             qq{Constant action is not of an allowed type.\n},
1357             qq{ It was of type reference to $ref_type.\n},
1358             qq{ Rule was $rule_desc\n}
1359             );
1360             }
1361              
1362             # After this point, any closure will be a ref to 'CODE'
1363              
1364 24306 100 100     62040 if ( defined $lexeme_id and $semantics eq '::value' ) {
1365 4871         8279 @ops = ( $op_lua, $result_is_token_value_key, $op_bail_key );
1366 4871         6978 last SET_OPS;
1367             }
1368              
1369             PROCESS_SINGLETON_RESULT: {
1370 19435 100       26034 last PROCESS_SINGLETON_RESULT if not defined $irlid;
  19435         35029  
1371              
1372 11838         15361 my $singleton;
1373 11838 100       28212 if ( $semantics =~ m/\A [:][:] rhs (\d+) \z/xms ) {
1374 508         2029 $singleton = $1 + 0;
1375             }
1376              
1377 11838 100       23810 last PROCESS_SINGLETON_RESULT if not defined $singleton;
1378              
1379 508         997 my $singleton_element = $singleton;
1380 508 50       1383 if ($is_discard_sequence_rule) {
1381 0         0 @ops = (
1382             $op_lua, $result_is_n_of_sequence_key,
1383             $singleton_element
1384             );
1385 0         0 last SET_OPS;
1386             }
1387 508 50       1515 if ($is_sequence_rule) {
1388 0         0 @ops =
1389             ( $op_lua, $result_is_n_of_rhs_key, $singleton_element );
1390 0         0 last SET_OPS;
1391             }
1392              
1393 508         2065 my ($mask) = $slg->call_by_tag(
1394             ( '@' . __FILE__ . ':' . __LINE__ ),
1395             <<'END_OF_LUA', 'i>0', $irlid );
1396             local slg, irlid = ...
1397             return slg.g1.irls[irlid].mask
1398             END_OF_LUA
1399              
1400             my @elements =
1401 508         1825 grep { $mask->[$_] } 0 .. ( $rule_length - 1 );
  514         1821  
1402 508 50       1679 if ( not scalar @elements ) {
1403 0         0 my $original_semantics = $semantics_by_irlid[$irlid];
1404 0         0 Marpa::R3::exception(
1405             q{Impossible semantics for empty rule: },
1406             $slg->g1_rule_show($irlid),
1407             "\n",
1408             qq{ Semantics were specified as "$original_semantics"\n}
1409             );
1410             } ## end if ( not scalar @elements )
1411 508         1202 $singleton_element = $elements[$singleton];
1412              
1413 508 50       1548 if ( not defined $singleton_element ) {
1414 0         0 my $original_semantics = $semantics_by_irlid[$irlid];
1415 0         0 Marpa::R3::exception(
1416             q{Impossible semantics for rule: },
1417             $slg->g1_rule_show($irlid),
1418             "\n",
1419             qq{ Semantics were specified as "$original_semantics"\n}
1420             );
1421             } ## end if ( not defined $singleton_element )
1422 508         1287 @ops = ( $op_lua, $result_is_n_of_rhs_key, $singleton_element );
1423 508         1541 last SET_OPS;
1424             } ## end PROCESS_SINGLETON_RESULT:
1425              
1426 18927 50       37629 if ( not @array_fate ) {
1427 0         0 @ops = ( $op_lua, $result_is_undef_key, $op_bail_key );
1428 0         0 last SET_OPS;
1429             }
1430              
1431             # if here, @array_fate is non-empty
1432              
1433 18927         29812 my @bless_ops = ();
1434 18927 100       35932 if ( $blessing ne '::undef' ) {
1435 17903         45717 push @bless_ops, $op_lua, $op_bless_key, \[$irlid, $lexeme_id, $blessing];
1436             }
1437              
1438 18927 50       43482 Marpa::R3::exception(qq{Unknown semantics: "$semantics"})
1439             if ( substr $semantics, 0, 1 ) ne '[';
1440              
1441 18927         27551 my @push_ops = ();
1442 18927         33811 my $array_descriptor = substr $semantics, 1, -1;
1443 18927         154470 $array_descriptor =~ s/^\s*|\s*$//g;
1444             RESULT_DESCRIPTOR:
1445 18927         86707 for my $result_descriptor ( split /[,]\s*/xms, $array_descriptor ) {
1446 55167         251479 $result_descriptor =~ s/^\s*|\s*$//g;
1447 55167 100       118773 if ( $result_descriptor eq 'g1start' ) {
1448 70         160 push @push_ops, $op_lua, $op_push_g1_start_key,
1449             $op_bail_key;
1450 70         147 next RESULT_DESCRIPTOR;
1451             }
1452 55097 100       94427 if ( $result_descriptor eq 'g1length' ) {
1453 70         142 push @push_ops, $op_lua, $op_push_g1_length_key,
1454             $op_bail_key;
1455 70         127 next RESULT_DESCRIPTOR;
1456             }
1457 55027 100       96957 if ( $result_descriptor eq 'start' ) {
1458 17782         33606 push @push_ops, $op_lua, $op_push_start_key, $op_bail_key;
1459 17782         30692 next RESULT_DESCRIPTOR;
1460             }
1461 37245 100       63701 if ( $result_descriptor eq 'length' ) {
1462 17782         28457 push @push_ops, $op_lua, $op_push_length_key, $op_bail_key;
1463 17782         28736 next RESULT_DESCRIPTOR;
1464             }
1465              
1466 19463 100       34365 if ( $result_descriptor eq 'lhs' ) {
1467 8 100       16 if ( defined $irlid ) {
1468              
1469 3         10 my ($lhs_id) = $slg->call_by_tag(
1470             ( '@' . __FILE__ . ':' . __LINE__ ),
1471             <<'END_OF_LUA', 'i>*', $irlid );
1472             local grammar, irlid = ...
1473             local g1g = grammar.g1
1474             return g1g:rule_lhs(irlid)
1475             END_OF_LUA
1476 3         7 push @push_ops, $op_lua, $op_push_constant_key,
1477             \$lhs_id;
1478 3         7 next RESULT_DESCRIPTOR;
1479             }
1480 5 50       8 if ( defined $lexeme_id ) {
1481 5         8 push @push_ops, $op_lua, $op_push_constant_key,
1482             \$lexeme_id;
1483 5         9 next RESULT_DESCRIPTOR;
1484             }
1485 0         0 push @push_ops, $op_lua, $op_push_undef_key, $op_bail_key;
1486 0         0 next RESULT_DESCRIPTOR;
1487             } ## end if ( $result_descriptor eq 'lhs' )
1488              
1489 19455 100       34606 if ( $result_descriptor eq 'name' ) {
1490 505 100       1763 if ( defined $irlid ) {
1491 435         1335 my $production_id =
1492             $slg->g1_rule_to_production_id($irlid);
1493 435         1306 my $name = $slg->production_name($production_id);
1494 435         1496 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1495 435         1140 next RESULT_DESCRIPTOR;
1496             }
1497 70 50       148 if ( defined $lexeme_id ) {
1498 70         194 my $name = $slg->g1_symbol_name($lexeme_id);
1499 70         149 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1500 70         178 next RESULT_DESCRIPTOR;
1501             }
1502 0 0       0 if ( defined $nulling_symbol_id ) {
1503 0         0 my $name = $slg->g1_symbol_name($nulling_symbol_id);
1504 0         0 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1505 0         0 next RESULT_DESCRIPTOR;
1506             }
1507 0         0 push @push_ops, $op_lua, $op_push_undef_key, $op_bail_key;
1508 0         0 next RESULT_DESCRIPTOR;
1509             } ## end if ( $result_descriptor eq 'name' )
1510              
1511 18950 100       34241 if ( $result_descriptor eq 'symbol' ) {
1512 16 100       35 if ( defined $irlid ) {
1513 6         18 my ($name) = $slg->call_by_tag(
1514             ( '@' . __FILE__ . ':' . __LINE__ ),
1515             <<'END_OF_LUA', 'i>*', $irlid );
1516             local grammar, irlid = ...
1517             local g1g = grammar.g1
1518             local lhs_id = g1g:rule_lhs(irlid)
1519             return g1g:symbol_name(lhs_id)
1520             END_OF_LUA
1521 6         14 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1522 6         14 next RESULT_DESCRIPTOR;
1523             } ## end if ( defined $irlid )
1524 10 50       24 if ( defined $lexeme_id ) {
1525 10         29 my $name = $slg->g1_symbol_name($lexeme_id);
1526 10         19 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1527 10         23 next RESULT_DESCRIPTOR;
1528             }
1529 0 0       0 if ( defined $nulling_symbol_id ) {
1530 0         0 my $name = $slg->g1_symbol_name($nulling_symbol_id);
1531 0         0 push @push_ops, $op_lua, $op_push_constant_key, \$name;
1532 0         0 next RESULT_DESCRIPTOR;
1533             }
1534 0         0 push @push_ops, $op_lua, $op_push_undef_key, $op_bail_key;
1535 0         0 next RESULT_DESCRIPTOR;
1536             } ## end if ( $result_descriptor eq 'symbol' )
1537              
1538 18934 100       32873 if ( $result_descriptor eq 'rule' ) {
1539 8 100       14 if ( defined $irlid ) {
1540 3         6 push @push_ops, $op_lua, $op_push_constant_key, \$irlid;
1541 3         5 next RESULT_DESCRIPTOR;
1542             }
1543 5         6 push @push_ops, $op_lua, $op_push_undef_key, $op_bail_key;
1544 5         9 next RESULT_DESCRIPTOR;
1545             } ## end if ( $result_descriptor eq 'rule' )
1546 18926 50 66     51152 if ( $result_descriptor eq 'values'
1547             or $result_descriptor eq 'value' )
1548             {
1549 18926 100       34164 if ( defined $lexeme_id ) {
1550 7597         12986 push @push_ops, $op_lua, $op_push_values_key, 1;
1551 7597         13608 next RESULT_DESCRIPTOR;
1552             }
1553 11329 100       19973 if ($is_sequence_rule) {
1554 676 100       1998 push @push_ops, $op_lua, $op_push_values_key,
1555             ( $is_discard_sequence_rule ? 2 : 1 );
1556 676         1519 next RESULT_DESCRIPTOR;
1557             } ## end if ($is_sequence_rule)
1558              
1559 10653         31887 my ($mask) = $slg->call_by_tag(
1560             ( '@' . __FILE__ . ':' . __LINE__ ),
1561             <<'END_OF_LUA', 'i>0', $irlid );
1562             local slg, irlid = ...
1563             return slg.g1.irls[irlid].mask
1564             END_OF_LUA
1565              
1566 10653 100       24939 if ( $rule_length > 0 ) {
1567             push @push_ops, map {
1568 10473 100       24203 $mask->[$_]
  19427         50425  
1569             ? ( $op_lua, $op_push_one_key, $_ )
1570             : ()
1571             } 0 .. $rule_length - 1;
1572             }
1573 10653         29561 next RESULT_DESCRIPTOR;
1574             } ## end if ( $result_descriptor eq 'values' or ...)
1575             Marpa::R3::exception(
1576 0         0 qq{Unknown result descriptor: "$result_descriptor"\n},
1577             qq{ The full semantics were "$semantics"}
1578             );
1579             } ## end RESULT_DESCRIPTOR: for my $result_descriptor ( split /[,]\s*/xms, ...)
1580 18927         63475 @ops = ( @push_ops, @bless_ops, @array_fate );
1581              
1582             } ## end SET_OPS:
1583              
1584 24337 100       48702 if ( defined $irlid ) {
1585 11869         38162 push @registrations, [ 'rule', $irlid, @ops ];
1586             }
1587              
1588 24337 100       45418 if ( defined $nulling_symbol_id ) {
1589              
1590 539         1671 push @registrations, [ 'nulling', $nulling_symbol_id, @ops ];
1591             } ## end if ( defined $nulling_symbol_id )
1592              
1593 24337 100       54526 if ( defined $lexeme_id ) {
1594 12468         51056 push @registrations, [ 'token', $lexeme_id, @ops ];
1595             }
1596              
1597             } ## end WORK_ITEM: for my $work_item (@work_list)
1598              
1599             SLR_NULLING_GRAMMAR_HACK: {
1600              
1601             # A hack for nulling SLR grammars --
1602             # the nulling semantics of the start symbol should
1603             # be those of the symbol on the
1604             # RHS of the start rule --
1605             # so copy them.
1606              
1607 365         925 my $start_symbol_id = $slg->g1_symbol_by_name('[:start:]');
  365         1800  
1608              
1609 365         1680 my ($symbol_is_nullable) =
1610             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1611             <<'END_OF_LUA', 'i>*', $start_symbol_id );
1612             local grammar, irlid = ...
1613             local g1g = grammar.g1
1614             return (g1g:symbol_is_nullable(irlid) and 1 or 0)
1615             END_OF_LUA
1616              
1617 365 50       1394 last SLR_NULLING_GRAMMAR_HACK if not $symbol_is_nullable;
1618              
1619 365         784 my $start_rhs_symbol_id;
1620 365         1405 RULE: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1621 1573         4016 my ( $lhs, $rhs0 ) = $slg->g1_rule_expand($irlid);
1622 1573 100       4657 if ( $start_symbol_id == $lhs ) {
1623 365         783 $start_rhs_symbol_id = $rhs0;
1624 365         974 last RULE;
1625             }
1626             }
1627              
1628 365         1094 REGISTRATION: for my $registration (@registrations) {
1629 23841         30444 my ( $type, $nulling_symbol_id ) = @{$registration};
  23841         42174  
1630 23841 100       48414 if ( $nulling_symbol_id == $start_rhs_symbol_id ) {
1631 313         697 my ( undef, undef, @ops ) = @{$registration};
  313         1183  
1632 313         1452 push @registrations, [ 'nulling', $start_symbol_id, @ops ];
1633 313         982 $nulling_closures[$start_symbol_id] =
1634             $nulling_closures[$start_rhs_symbol_id];
1635 313         1951 last REGISTRATION;
1636             } ## end if ( $nulling_symbol_id == $start_rhs_symbol_id )
1637             } ## end REGISTRATION: for my $registration (@registrations)
1638             } ## end SLR_NULLING_GRAMMAR_HACK:
1639              
1640 365         1175 $slg->[Marpa::R3::Internal_G::CLOSURE_BY_SYMBOL_ID] =
1641             \@nulling_closures;
1642 365         1253 $slg->[Marpa::R3::Internal_G::CLOSURE_BY_RULE_ID] =
1643             \@closure_by_irlid;
1644              
1645 365         25847 return \@registrations;
1646              
1647             }
1648              
1649             sub resolve_grammar {
1650              
1651 366     366   1056 my ($slg) = @_;
1652              
1653 366   50     2212 my $trace_actions =
1654             $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] // 0;
1655 366         938 my $trace_file_handle =
1656             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
1657              
1658 366         810 my $resolve_error;
1659              
1660 366         1932 my $default_action_resolution =
1661             resolve_action( $slg, undef, \$resolve_error );
1662 366 50 0     1476 Marpa::R3::exception( "Could not resolve default action\n",
1663             q{ }, ( $resolve_error // 'Failed to resolve action' ) )
1664             if not $default_action_resolution;
1665              
1666 366         980 my $rule_resolutions = [];
1667              
1668 366         1913 RULE_ID: for (my $iter = $slg->g1_rule_ids_gen(); defined ( my $irlid = $iter->());) {
1669              
1670 11870         22851 my $rule_resolution = resolve_rule_by_id( $slg, $irlid );
1671 11869   66     24210 $rule_resolution //= $default_action_resolution;
1672              
1673 11869 50       22150 if ( not $rule_resolution ) {
1674 0         0 my $rule_desc = $slg->g1_rule_show($irlid);
1675              
1676 0         0 my ($action) =
1677             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1678             <<'END_OF_LUA', 'is>*', $irlid );
1679             local slg, irl_id, rule_desc = ...
1680             local action = slg.g1.irls[irl_id].action
1681             local message = string.format(
1682             "Could not resolve action\n Rule was %s\n",
1683             rule_desc)
1684             if action then
1685             message = message ..
1686             string.format(" Action was specified as %q\n", action)
1687             end
1688             error(message)
1689             END_OF_LUA
1690              
1691             } ## end if ( not $rule_resolution )
1692              
1693             DETERMINE_BLESSING: {
1694              
1695 11869         16237 my $blessing = rule_blessing_find( $slg, $irlid );
  11869         21686  
1696 11869         19051 my ( $closure_name, $closure, $semantics ) = @{$rule_resolution};
  11869         24511  
1697              
1698 11869 100       26852 if ( $blessing ne '::undef' ) {
1699 10426 50       20856 $semantics = '::array' if $semantics eq '::!default';
1700             CHECK_SEMANTICS: {
1701 10426 100       14314 last CHECK_SEMANTICS if $semantics eq '::array';
  10426         18863  
1702             last CHECK_SEMANTICS
1703 10356 50       25749 if ( substr $semantics, 0, 1 ) eq '[';
1704 0         0 Marpa::R3::exception(
1705             qq{Attempt to bless, but improper semantics: "$semantics"\n},
1706             qq{ Blessing: "$blessing"\n},
1707             ' Rule: ',
1708             $slg->g1_rule_show($irlid)
1709             );
1710             } ## end CHECK_SEMANTICS:
1711             } ## end if ( $blessing ne '::undef' )
1712              
1713             $rule_resolution =
1714 11869         37138 [ $closure_name, $closure, $semantics, $blessing ];
1715             } ## end DETERMINE_BLESSING:
1716              
1717 11869         33510 $rule_resolutions->[$irlid] = $rule_resolution;
1718              
1719             }
1720              
1721 365 50       1515 if ( $trace_actions >= 2 ) {
1722              
1723 0         0 my ($highest_irlid) =
1724             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1725             <<'END_OF_LUA', '>*' );
1726             local grammar = ...
1727             local g1g = grammar.g1
1728             return g1g:highest_rule_id()
1729             END_OF_LUA
1730              
1731 0         0 RULE: for my $rule_id ( 0 .. $highest_irlid ) {
1732             my ( $resolution_name, $closure ) =
1733 0         0 @{ $rule_resolutions->[$rule_id] };
  0         0  
1734 0 0       0 say {$trace_file_handle} 'Rule ',
  0         0  
1735             $slg->g1_rule_show($rule_id),
1736             qq{ resolves to "$resolution_name"}
1737             or Marpa::R3::exception('print to trace handle failed');
1738             }
1739             }
1740              
1741 365         1006 my @lexeme_resolutions = ();
1742              
1743 365         1491 my ($highest_symbol_id) =
1744             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1745             <<'END_OF_LUA', '>*' );
1746             local grammar = ...
1747             local g1g = grammar.g1
1748             return g1g:highest_symbol_id()
1749             END_OF_LUA
1750              
1751 365         1698 SYMBOL: for my $lexeme_id ( 0 .. $highest_symbol_id ) {
1752              
1753 14090         27495 my $semantics = lexeme_semantics_find( $slg, $lexeme_id );
1754 14090 50       28452 if ( not defined $semantics ) {
1755 0         0 my $message =
1756             "Could not determine lexeme's semantics\n"
1757             . q{ Lexeme was }
1758             . $slg->g1_symbol_display_form($lexeme_id) . "\n";
1759 0         0 Marpa::R3::exception($message);
1760             } ## end if ( not defined $semantics )
1761 14090         25455 my $blessing = lexeme_blessing_find( $slg, $lexeme_id );
1762 14090 50       28487 if ( not defined $blessing ) {
1763 0         0 my $message =
1764             "Could not determine lexeme's blessing\n"
1765             . q{ Lexeme was }
1766             . $slg->g1_symbol_display_form($lexeme_id) . "\n";
1767 0         0 Marpa::R3::exception($message);
1768             } ## end if ( not defined $blessing )
1769 14090         41220 $lexeme_resolutions[$lexeme_id] = [ $semantics, $blessing ];
1770              
1771             }
1772              
1773 365         3349 return ( $rule_resolutions, \@lexeme_resolutions );
1774             }
1775              
1776             # Given the grammar and an action name, resolve it to a closure,
1777             # or return undef
1778             sub resolve_action {
1779 11861     11861   22963 my ( $slg, $closure_name, $p_error ) = @_;
1780 11861         19868 my $trace_file_handle =
1781             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
1782 11861         17304 my $trace_actions = $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS];
1783              
1784             # A reserved closure name;
1785 11861 100       23477 return [ q{}, undef, '::!default' ] if not defined $closure_name;
1786              
1787 11495 50       22960 if ( $closure_name eq q{} ) {
1788 0 0       0 ${$p_error} = q{The action string cannot be the empty string}
  0         0  
1789             if defined $p_error;
1790 0         0 return;
1791             }
1792              
1793 11495 100       21061 return [ q{}, \undef, $closure_name ] if $closure_name eq '::undef';
1794 11464 100 100     45188 if ( substr( $closure_name, 0, 2 ) eq q{::}
1795             or substr( $closure_name, 0, 1 ) eq '[' )
1796             {
1797 11118         32750 return [ q{}, undef, $closure_name ];
1798             }
1799              
1800 346         781 my $fully_qualified_name;
1801 346 100       1913 if ( $closure_name =~ /([:][:])|[']/xms ) {
1802 211         440 $fully_qualified_name = $closure_name;
1803             }
1804              
1805 346 100       890 if ( not $fully_qualified_name ) {
1806 135         315 my $resolve_package =
1807             $slg->[Marpa::R3::Internal_G::SEMANTICS_PACKAGE];
1808 135 50       388 if ( not defined $resolve_package ) {
1809 0         0 ${$p_error} = Marpa::R3::Internal::X->new(
  0         0  
1810             {
1811             message =>
1812             qq{Could not fully qualify "$closure_name": no semantics package},
1813             name => 'NO RESOLVE PACKAGE'
1814             }
1815             );
1816 0         0 return;
1817             } ## end if ( not defined $resolve_package )
1818 135         438 $fully_qualified_name = $resolve_package . q{::} . $closure_name;
1819             } ## end if ( not $fully_qualified_name )
1820              
1821 346         663 my $closure;
1822             my $type;
1823             TYPE: {
1824 101     101   1296 no strict 'refs';
  101         283  
  101         6073  
  346         713  
1825 346         559 $closure = *{$fully_qualified_name}{'CODE'};
  346         1497  
1826 101     101   805 use strict;
  101         251  
  101         5003  
1827 346 100       1204 if ( defined $closure ) {
1828 345         1092 $type = 'CODE';
1829 345         1053 last TYPE;
1830             }
1831 101     101   728 no strict 'refs';
  101         266  
  101         4482  
1832 1         4 $closure = *{$fully_qualified_name}{'SCALAR'};
  1         6  
1833 101     101   718 use strict;
  101         327  
  101         17125  
1834              
1835             # Currently $closure is always defined, but this
1836             # behavior is said to be subject to change in perlref
1837 1 50 33     7 if ( defined $closure and defined ${$closure} ) {
  1         6  
1838 0         0 $type = 'SCALAR';
1839 0         0 Marpa::R3::exception(
1840             "$closure_name resolves to SCALAR, which is not yet implemented"
1841             );
1842 0         0 last TYPE;
1843             }
1844              
1845 1         4 $closure = undef;
1846             } ## end TYPE:
1847              
1848 346 100       918 if ( defined $closure ) {
1849 345 50       1083 if ($trace_actions) {
1850 0 0       0 print {$trace_file_handle}
  0         0  
1851             qq{Successful resolution of action "$closure_name" as $type },
1852             'to ', $fully_qualified_name, "\n"
1853             or Marpa::R3::exception('Could not print to trace file');
1854             } ## end if ($trace_actions)
1855 345         1193 return [ $fully_qualified_name, $closure, '::array' ];
1856             } ## end if ( defined $closure )
1857              
1858 1 50 33     7 if ( $trace_actions or defined $p_error ) {
1859 1         4 for my $slot (qw(ARRAY HASH IO FORMAT)) {
1860 101     101   814 no strict 'refs';
  101         269  
  101         122765  
1861 4 50       8 if ( defined *{$fully_qualified_name}{$slot} ) {
  4         17  
1862 0         0 my $error =
1863             qq{Failed resolution of action "$closure_name" to $fully_qualified_name\n}
1864             . qq{ $fully_qualified_name is present as a $slot, but a $slot is not an acceptable resolution\n};
1865 0 0       0 if ($trace_actions) {
1866 0 0       0 print {$trace_file_handle} $error
  0         0  
1867             or Marpa::R3::exception('Could not print to trace file');
1868             }
1869 0 0       0 ${$p_error} = $error if defined $p_error;
  0         0  
1870 0         0 return;
1871             } ## end if ( defined *{$fully_qualified_name}{$slot} )
1872             } ## end for my $slot (qw(ARRAY HASH IO FORMAT))
1873             } ## end if ( $trace_actions or defined $p_error )
1874              
1875             {
1876 1         3 my $error =
  1         6  
1877             qq{Failed resolution of action "$closure_name" to $fully_qualified_name\n};
1878 1 50       6 ${$p_error} = $error if defined $p_error;
  1         3  
1879 1 50       6 if ($trace_actions) {
1880 0 0       0 print {$trace_file_handle} $error
  0         0  
1881             or Marpa::R3::exception('Could not print to trace file');
1882             }
1883             }
1884 1         5 return;
1885              
1886             }
1887              
1888             sub resolve_rule_by_id {
1889 11870     11870   20691 my ( $slg, $irlid ) = @_;
1890              
1891 11870         31537 my ($action_name) =
1892             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1893             <<'END_OF_LUA', 'i>*', $irlid );
1894             local slg, irl_id = ...
1895             return slg.g1.irls[irl_id].action
1896             END_OF_LUA
1897              
1898 11870         20017 my $resolve_error;
1899 11870 100       23601 return if not defined $action_name;
1900 11495         24444 my $resolution = resolve_action( $slg, $action_name, \$resolve_error );
1901              
1902 11495 100       25671 if ( not $resolution ) {
1903 1         6 my $rule_desc = $slg->g1_rule_show($irlid);
1904 1   50     13 Marpa::R3::exception(
1905             "Could not resolve rule action named '$action_name'\n",
1906             " Rule was $rule_desc\n",
1907             q{ },
1908             ( $resolve_error // 'Failed to resolve action' )
1909             );
1910             } ## end if ( not $resolution )
1911 11494         20385 return $resolution;
1912             } ## end sub resolve_rule_by_id
1913              
1914             # Find the blessing for a rule.
1915             sub rule_blessing_find {
1916 11869     11869   20993 my ( $slg, $irlid ) = @_;
1917 11869         30500 my ($blessing) =
1918             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1919             <<'END_OF_LUA', 'i', $irlid);
1920             local slg, irlid = ...
1921             local irl = slg.g1.irls[irlid]
1922             local blessing = '::undef'
1923             local xpr = irl.xpr
1924             if xpr then
1925             blessing = xpr.bless or '::undef'
1926             end
1927             return blessing
1928             END_OF_LUA
1929 11869         25505 return $blessing;
1930             }
1931              
1932             # Find the semantics for a lexeme.
1933             sub lexeme_semantics_find {
1934 14090     14090   24156 my ( $slg, $lexeme_id ) = @_;
1935              
1936 14090         33875 my ($semantics) =
1937             $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1938             <<'END_OF_LUA', 'i>*', $lexeme_id);
1939             local slg, isyid = ...
1940             local xsy = slg.g1.xsys[isyid]
1941             if not xsy then return '::!default' end
1942             local semantics = xsy.lexeme_semantics
1943             return semantics or '::!default'
1944             END_OF_LUA
1945              
1946 14090         28954 return $semantics;
1947             }
1948              
1949             # Find the blessing for a lexeme.
1950             sub lexeme_blessing_find {
1951 14090     14090   24024 my ( $slg, $lexeme_id ) = @_;
1952              
1953 14090         32926 my ($result) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1954             <<'END_OF_LUA', 'i', $lexeme_id );
1955             local slg, isyid = ...
1956             local xsy = slg.g1.xsys[isyid]
1957             if not xsy then return '::undef' end
1958             local blessing = xsy.blessing
1959             return blessing or '::undef'
1960             END_OF_LUA
1961              
1962 14090         28722 return $result;
1963             }
1964              
1965             sub op_fn_key_by_name {
1966 6935     6935   13010 my ( $slg, $name ) = @_;
1967 6935         16103 my ($key) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1968             <<'END_OF_LUA', 's', $name );
1969             local recce, name = ...
1970             return _M.get_op_fn_key_by_name(name)
1971             END_OF_LUA
1972              
1973 6935         14642 return $key;
1974             }
1975              
1976             sub op_fn_name_by_key {
1977 0     0   0 my ( $slg, $key ) = @_;
1978 0         0 my ($name) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1979             <<'END_OF_LUA', 'i', $key );
1980             local recce, key = ...
1981             return _M.get_op_fn_name_by_key(key)
1982             END_OF_LUA
1983              
1984 0         0 return $name;
1985             }
1986              
1987             sub registrations_set {
1988 365     365   1290 my ( $slg, $registrations ) = @_;
1989 365         1000 my $trace_file_handle =
1990             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
1991 365   50     2222 my $trace_actions =
1992             $slg->[Marpa::R3::Internal_G::TRACE_ACTIONS] // 0;
1993              
1994 365         875 REGISTRATION: for my $registration ( @{$registrations} ) {
  365         1151  
1995 25189         37408 my ( $type, $id, @raw_ops ) = @{$registration};
  25189         65977  
1996 25189         40161 my @ops = ();
1997             PRINT_TRACES: {
1998 25189 50       33748 last PRINT_TRACES if $trace_actions <= 2;
  25189         51471  
1999 0 0       0 if ( $type eq 'nulling' ) {
2000 0 0       0 say {$trace_file_handle}
  0         0  
2001             "Registering semantics for nulling symbol: ",
2002             $slg->g1_symbol_display_form($id),
2003             "\n", ' Semantics are ', $slg->show_semantics(@raw_ops)
2004             or Marpa::R3::exception('Cannot say to trace file handle');
2005 0         0 last PRINT_TRACES;
2006             } ## end if ( $type eq 'nulling' )
2007 0 0       0 if ( $type eq 'rule' ) {
2008 0 0       0 say {$trace_file_handle}
  0         0  
2009             "Registering semantics for $type: ",
2010             $slg->g1_rule_show($id),
2011             ' Semantics are ', $slg->show_semantics(@raw_ops)
2012             or Marpa::R3::exception('Cannot say to trace file handle');
2013 0         0 last PRINT_TRACES;
2014             }
2015 0 0       0 if ( $type eq 'token' ) {
2016 0 0       0 say {$trace_file_handle}
  0         0  
2017             "Registering semantics for $type: ",
2018             $slg->g1_symbol_display_form($id),
2019             "\n", ' Semantics are ', $slg->show_semantics(@raw_ops)
2020             or Marpa::R3::exception('Cannot say to trace file handle');
2021 0         0 last PRINT_TRACES;
2022             }
2023 0 0       0 say {$trace_file_handle} "Registration has unknown type: $type"
  0         0  
2024             or Marpa::R3::exception('Cannot say to trace file handle');
2025             } ## end PRINT_TRACES:
2026              
2027 25189         40990 OP: for my $raw_op (@raw_ops) {
2028 307989 100       502786 if ( ref $raw_op ) {
2029              
2030 19004         31614 my $constants = $slg->[Marpa::R3::Internal_G::CONSTANTS];
2031 19004         25018 my $next_ix = scalar @{$constants};
  19004         28910  
2032 19004         29446 push @ops, $next_ix;
2033             $slg->[Marpa::R3::Internal_G::CONSTANTS]->[$next_ix]
2034 19004         24449 = ${$raw_op};
  19004         38561  
2035 19004         37604 next OP;
2036             }
2037 288985         418811 push @ops, $raw_op;
2038             } ## end OP: for my $raw_op (@raw_ops)
2039              
2040 25189         74007 my ($constant_ix) = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
2041             << 'END_OF_LUA', 'sii', $type, $id, \@ops );
2042             local grammar, type, id, ops = ...
2043             if type == 'token' then
2044             grammar.token_semantics[id] = ops
2045             elseif type == 'nulling' then
2046             grammar.nulling_semantics[id] = ops
2047             elseif type == 'rule' then
2048             grammar.rule_semantics[id] = ops
2049             end
2050             END_OF_LUA
2051              
2052 25189         71630 next REGISTRATION;
2053              
2054             # Marpa::R3::exception(
2055             # 'Registration: with unknown type: ',
2056             # Data::Dumper::Dumper($registration)
2057             # );
2058              
2059             } ## end REGISTRATION: for my $registration ( @{ $recce->[...]})
2060             }
2061              
2062             1;
2063              
2064             # vim: expandtab shiftwidth=4: