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