File Coverage

blib/lib/Marpa/R3/SLR.pm
Criterion Covered Total %
statement 485 591 82.0
branch 93 156 59.6
condition 28 53 52.8
subroutine 61 72 84.7
pod 0 1 0.0
total 667 873 76.4


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::Recognizer;
13              
14 104     104   2002 use 5.010001;
  104         456  
15 104     104   615 use strict;
  104         234  
  104         2265  
16 104     104   544 use warnings;
  104         211  
  104         3198  
17              
18 104     104   556 use vars qw($VERSION $STRING_VERSION);
  104         209  
  104         8551  
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_R;
26              
27 104     104   692 use Scalar::Util qw(blessed tainted);
  104         208  
  104         6625  
28 104     104   698 use English qw( -no_match_vars );
  104         245  
  104         680  
29              
30             our $PACKAGE = 'Marpa::R3::Recognizer';
31              
32             # Given a scanless
33             # recognizer and a symbol,
34             # return the start earley set
35             # and length
36             # of the last such symbol completed,
37             # undef if there was none.
38             sub Marpa::R3::Recognizer::last_completed {
39 86     86   765 my ( $slr, $symbol_name ) = @_;
40 86         246 my ($start, $length) = $slr->call_by_tag(
41             ('@' . __FILE__ . ':' . __LINE__),
42             <<'END_OF_LUA', 'i', $symbol_name);
43             local slr, xsy_name = ...
44             local xsyid = slr.slg:symbol_by_name(xsy_name)
45             if not xsyid then
46             _M.userX(
47             "last_completed(%q): no symbol with that name",
48             xsy_name)
49             end
50             return slr:last_completed(xsyid)
51             END_OF_LUA
52 86 100       257 return if not defined $start;
53 74         208 return $start, $length;
54             } ## end sub Marpa::R3::Recognizer::last_completed
55              
56             # Given a scanless recognizer and
57             # and two earley sets, return the input string
58             sub Marpa::R3::Recognizer::g1_literal {
59 1635     1635   3958 my ( $slr, $g1_start, $g1_count ) = @_;
60              
61 1635         4234 my ($literal) = $slr->call_by_tag(
62             ('@' . __FILE__ . ':' . __LINE__),
63             <<'END_OF_LUA', 'ii', $g1_start, $g1_count);
64             local slr, g1_start, g1_count = ...
65             return slr:g1_literal(g1_start, g1_count)
66             END_OF_LUA
67              
68 1635         7156 return $literal;
69              
70             } ## end sub Marpa::R3::Recognizer::g1_literal
71              
72             # Substring in terms of locations in the input stream
73             # This is the one users will be most interested in.
74             sub Marpa::R3::Recognizer::literal {
75 98     98   635 my ( $slr, $block_id, $offset, $length ) = @_;
76 98         243 my ($literal) = $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
77             <<'END_OF_LUA', 'iii', $block_id, $offset, $length );
78             local slr, block_id_arg, offset_arg, length_arg = ...
79             local block_id, offset, eoread
80             = slr:block_check_range(block_id_arg, offset_arg, length_arg)
81             if not block_id then
82             -- if block == nil, offset is error message
83             error(offset)
84             end
85             return slr:literal(block_id, offset, eoread-offset)
86             END_OF_LUA
87 98         257 return $literal;
88             }
89              
90             sub Marpa::R3::Internal::meta_recce {
91 291     291 0 835 my ($hash_args) = @_;
92 291         865 state $meta_grammar = Marpa::R3::Internal::meta_grammar();
93 291         1359 $hash_args->{grammar} = $meta_grammar;
94 291         2056 my $self = Marpa::R3::Recognizer->new($hash_args);
95 291         1452 return $self;
96             } ## end sub Marpa::R3::Internal::meta_recce
97              
98             # Set those common args which are at the Perl level.
99             sub perl_common_set {
100 1215     1215   2332 my ( $slr, $flat_args ) = @_;
101 1215 100       3105 if ( my $value = $flat_args->{'trace_file_handle'} ) {
102 10         23 $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE] = $value;
103             }
104 1215         3504 my $trace_file_handle =
105             $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE];
106 1215         2087 delete $flat_args->{'trace_file_handle'};
107 1215         2220 return $flat_args;
108             }
109              
110             sub gen_app_event_handler {
111 6111     6111   11397 my ($slr) = @_;
112 6111         9244 my $event_handlers =
113             $slr->[Marpa::R3::Internal_R::EVENT_HANDLERS];
114             return sub {
115 1333     1333   3625 my ( $event_type, $event_name, @data ) = @_;
116 1333         2341 my $current_event =
117             $slr->[Marpa::R3::Internal_R::CURRENT_EVENT];
118 1333 50       2562 if ($current_event) {
119 0         0 Marpa::R3::exception(
120             qq{Attempt to call one event handler inside another\n},
121             qq{ This is not allowed\n},
122             qq{ The currently active handler is for a "$current_event" event\n},
123             qq{ The attempted handler call is for a "$event_name" event\n}
124             );
125             }
126 1333         2100 my $handler = $event_handlers->{$event_name};
127 1333 100       2565 if ( not $handler ) {
128 725         1037 $handler = $event_handlers->{"'default"};
129             }
130 1333 50       2451 if ( not $handler ) {
131 0         0 Marpa::R3::exception(
132             qq{'No event handler for event "$event_name"\n});
133             }
134 1333 50       3391 if ( ref $handler ne 'CODE' ) {
135 0         0 my $ref_type = ref $handler;
136 0         0 Marpa::R3::exception(
137             qq{Bad event handler for event "$event_name"\n},
138             qq{ Handler is a ref to $ref_type\n},
139             qq{ A handler should be a ref to code\n}
140             );
141             }
142 1333         2281 $slr->[Marpa::R3::Internal_R::CURRENT_EVENT] = $event_name;
143 1333   50     3564 my $retour = $handler->( $slr, $event_name, @data ) // 'ok';
144              
145             RETOUR_CHECK: {
146 1333 100       9172 if ($retour eq 'ok') {
  1333         2705  
147 644 50       1138 if ($event_type eq 'before lexeme') {
148 0         0 Marpa::R3::exception(
149             qq{Bad return from event handler for event "$event_name"\n},
150             qq{ Event type was "$event_type"\n},
151             qq{ Return from handler was "$retour"\n},
152             qq{ A handler of type "$event_type" must return "pause"\n},
153             );
154             }
155 644         1068 last RETOUR_CHECK;
156             }
157 689 50       1481 last RETOUR_CHECK if $retour eq 'pause';
158 0         0 Marpa::R3::exception(
159             qq{Bad return from event handler for event "$event_name"\n},
160             qq{ Event type was "$event_type"\n},
161             qq{ Return from handler was "$retour"\n},
162             qq{ Handler must return "ok" or "pause"\n},
163             );
164             }
165 1333         1864 $slr->[Marpa::R3::Internal_R::CURRENT_EVENT] = undef;
166 1333         3429 return 'ok', $retour;
167 6111         49882 };
168             }
169              
170             sub gen_codepoint_event_handler {
171 3095     3095   6004 my ($slr) = @_;
172 3095         4664 my $slg = $slr->[Marpa::R3::Internal_R::SLG];
173 3095         4760 my $character_class_table =
174             $slg->[Marpa::R3::Internal_G::CHARACTER_CLASS_TABLE];
175              
176             return sub {
177 5541     5541   9303 my ( $codepoint, $trace_terminals ) = @_;
178 5541         17971 my $character = pack( 'U', $codepoint );
179 5541         21587 my $is_graphic = ( $character =~ m/[[:graph:]]+/ );
180              
181 5541         8108 my @symbols;
182 5541         7092 for my $entry ( @{$character_class_table} ) {
  5541         10945  
183              
184 231283         295502 my ( $symbol_id, $re ) = @{$entry};
  231283         349768  
185              
186             # say STDERR "Codepoint %x vs $re\n";
187              
188 231283 100       788744 if ( $character =~ $re ) {
189              
190 26156 100       46965 if ( $trace_terminals >= 2 ) {
191 18         159 my $trace_file_handle =
192             $slr
193             ->[ Marpa::R3::Internal_R::TRACE_FILE_HANDLE ];
194 18         41 my $char_desc = character_describe( $slr, $codepoint );
195 18 50       30 say {$trace_file_handle}
  18         80  
196             qq{Registering character $char_desc as symbol $symbol_id: },
197             $slg->l0_symbol_display_form($symbol_id)
198             or Marpa::R3::exception("Could not say(): $ERRNO");
199             } ## end if ( $trace_terminals >= 2 )
200              
201 26156         47517 push @symbols, $symbol_id;
202              
203             } ## end if ( $character =~ $re )
204             } ## end for my $entry ( @{$character_class_table} )
205              
206 5541         14684 my $coro_arg = { symbols => \@symbols };
207 5541 100       13673 $coro_arg->{is_graphic} = 'true' if $is_graphic;
208 5541         13101 return 'ok', $coro_arg;
209 3095         15896 };
210             }
211              
212             sub Marpa::R3::Recognizer::new {
213 1204     1204   208402 my ( $class, @args ) = @_;
214              
215 1204         2354 my $slr = [];
216 1204         2372 bless $slr, $class;
217              
218             # Set recognizer args to default
219             # Lua equivalent is set below
220              
221 1204         4109 my ( $flat_args, $error_message ) = Marpa::R3::flatten_hash_args( \@args );
222 1204 50       3074 Marpa::R3::exception( sprintf $error_message, '$slr->new' )
223             if not $flat_args;
224 1204         3114 $flat_args = perl_common_set( $slr, $flat_args );
225              
226 1204         2105 my $slg = $flat_args->{grammar};
227 1204 50       2633 Marpa::R3::exception(
228             qq{Marpa::R3::Recognizer::new() called without a "grammar" argument} )
229             if not defined $slg;
230 1204         2320 $slr->[Marpa::R3::Internal_R::SLG] = $slg;
231 1204         2178 delete $flat_args->{grammar};
232              
233 1204   100     4310 my $event_handlers = $flat_args->{event_handlers} // {};
234 1204         2322 $slr->[Marpa::R3::Internal_R::EVENT_HANDLERS] = $event_handlers;
235 1204 50       3114 if ( ref $event_handlers ne 'HASH' ) {
236 0         0 my $ref_type = ref $event_handlers;
237 0         0 Marpa::R3::exception(
238             qq{'event_handlers' named argument to new() is $ref_type\n},
239             " It should be a ref to a hash\n",
240             " whose keys are event names and\n",
241             " whose values are code refs\n"
242             );
243             }
244 1204         1873 delete $flat_args->{event_handlers};
245              
246 1204         2305 my $slg_class = 'Marpa::R3::Grammar';
247 1204 50 33     10462 if ( not blessed $slg or not $slg->isa($slg_class) ) {
248 0         0 my $ref_type = ref $slg;
249 0 0       0 my $desc = $ref_type ? "a ref to $ref_type" : 'not a ref';
250 0         0 Marpa::R3::exception(
251             qq{'grammar' named argument to new() is $desc\n},
252             " It should be a ref to $slg_class\n"
253             );
254             } ## end if ( not blessed $slg or not $slg->isa($slg_class) )
255              
256 1204   66     5699 $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE] //=
257             $slg->[Marpa::R3::Internal_G::TRACE_FILE_HANDLE];
258              
259 1204         2053 my $trace_file_handle =
260             $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE];
261              
262 1204         1889 my $lua = $slg->[Marpa::R3::Internal_G::L];
263 1204         1961 $slr->[Marpa::R3::Internal_R::L] = $lua;
264              
265             my ( $regix ) = $slg->coro_by_tag(
266             ( '@' . __FILE__ . ':' . __LINE__ ),
267             {
268             signature => 's',
269             args => [$flat_args],
270             handlers => {
271             perl_undef => sub {
272 0     0   0 return 'sig', [ 'S', undef ];
273             },
274             trace => sub {
275 8     8   15 my ($msg) = @_;
276 8         13 say {$trace_file_handle} $msg;
  8         29  
277 8         29 return 'ok';
278             },
279 1204         8740 codepoint => gen_codepoint_event_handler($slr),
280             event => gen_app_event_handler($slr),
281             }
282             },
283             <<'END_OF_LUA');
284             local slg, flat_args = ...
285             _M.wrap(function ()
286             local slr = slg:slr_new(flat_args)
287             return 'ok', slr.regix
288             end)
289             END_OF_LUA
290              
291 1204         26392 $slr->[Marpa::R3::Internal_R::REGIX] = $regix;
292              
293             $slr->coro_by_tag(
294             ( '@' . __FILE__ . ':' . __LINE__ ),
295             {
296             signature => 's',
297             args => [$flat_args],
298             handlers => {
299             trace => sub {
300 0     0   0 my ($msg) = @_;
301 0         0 say {$trace_file_handle} $msg;
  0         0  
302 0         0 return 'ok';
303             },
304 1204         7106 event => gen_app_event_handler($slr),
305             }
306             },
307             <<'END_OF_LUA');
308             local slr, flat_args = ...
309             _M.wrap(function ()
310             slr:convert_libmarpa_events()
311             return 'ok'
312             end)
313             END_OF_LUA
314              
315 1204         14113 return $slr;
316             } ## end sub Marpa::R3::Recognizer::new
317              
318             sub Marpa::R3::Recognizer::DESTROY {
319             # say STDERR "In Marpa::R3::Recognizer::DESTROY before test";
320 1197     1197   123436 my $slr = shift;
321 1197         2290 my $lua = $slr->[Marpa::R3::Internal_R::L];
322              
323             # If we are destroying the Perl interpreter, then all the Marpa
324             # objects will be destroyed, including Marpa's Lua interpreter.
325             # We do not need to worry about cleaning up the
326             # recognizer is an orderly manner, because the Lua interpreter
327             # containing the recognizer will be destroyed.
328             # In fact, the Lua interpreter may already have been destroyed,
329             # so this test is necessary to avoid a warning message.
330 1197 50       3066 return if not $lua;
331             # say STDERR "In Marpa::R3::Recognizer::DESTROY after test";
332              
333 1197         2494 my $regix = $slr->[Marpa::R3::Internal_R::REGIX];
334 1197         3769 $slr->call_by_tag(
335             ('@' . __FILE__ . ':' . __LINE__),
336             <<'END_OF_LUA', '');
337             local slr = ...
338             local regix = slr.regix
339             _M.unregister(_M.registry, regix)
340             END_OF_LUA
341             }
342              
343             sub Marpa::R3::Recognizer::set {
344 11     11   5846 my ( $slr, @args ) = @_;
345              
346 11         46 my ($flat_args, $error_message) = Marpa::R3::flatten_hash_args(\@args);
347 11 50       39 Marpa::R3::exception( sprintf $error_message, '$slr->set()' ) if not $flat_args;
348 11         33 $flat_args = perl_common_set($slr, $flat_args);
349 11         30 my $trace_file_handle =
350             $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE];
351              
352             $slr->coro_by_tag(
353             ( '@' . __FILE__ . ':' . __LINE__ ),
354             {
355             signature => 's',
356             args => [ $flat_args ],
357             handlers => {
358             trace => sub {
359 2     2   6 my ($msg) = @_;
360 2         9 say {$trace_file_handle} $msg;
  2         10  
361 2         6 return 'ok';
362             }
363             }
364             },
365 11         229 <<'END_OF_LUA');
366             local slr, flat_args = ...
367             return _M.wrap(function ()
368             slr:common_set(flat_args)
369             end
370             )
371             END_OF_LUA
372 11         76 return;
373             } ## end sub Marpa::R3::Recognizer::set
374              
375             sub Marpa::R3::Recognizer::read {
376 1209     1209   14954 my ( $slr, $p_string, $start_pos, $length ) = @_;
377 1209 50       3203 if ( $slr->[Marpa::R3::Internal_R::CURRENT_EVENT] ) {
378 0         0 Marpa::R3::exception(
379             "$slr->read() called from inside a handler\n",
380             " This is not allowed\n",
381             " The event was ",
382             $slr->[Marpa::R3::Internal_R::CURRENT_EVENT],
383             "\n",
384             );
385             }
386 1209         2065 my $slg = $slr->[Marpa::R3::Internal_R::SLG];
387              
388 1209         3537 my $block_id = $slr->block_new($p_string);
389 1208         4527 $slr->block_set($block_id);
390 1208         3775 $slr->block_move($start_pos, $length);
391 1208         3211 return $slr->block_read();
392             }
393              
394             sub Marpa::R3::Recognizer::resume {
395 549     549   3806 my ( $slr, $start_pos, $length ) = @_;
396 549 50       1270 if ( $slr->[Marpa::R3::Internal_R::CURRENT_EVENT] ) {
397 0         0 Marpa::R3::exception(
398             "$slr->resume() called from inside a handler\n",
399             " This is not allowed\n",
400             " The event was ",
401             $slr->[Marpa::R3::Internal_R::CURRENT_EVENT],
402             "\n",
403             );
404             }
405 549         844 my $trace_file_handle =
406             $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE];
407 549   100     2022 $length //= -1;
408 549         1432 $slr->block_move( $start_pos, $length );
409 549         1147 return $slr->block_read();
410             }
411              
412             sub character_describe {
413 18     18   32 my ($slr, $codepoint) = @_;
414              
415 18         51 my ($desc) = $slr->call_by_tag(
416             ('@' . __FILE__ . ':' . __LINE__),
417             <<'END__OF_LUA', 'i', $codepoint );
418             local slr, codepoint = ...
419             return slr:character_describe(codepoint)
420             END__OF_LUA
421              
422 18         39 return $desc;
423             } ## end sub character_describe
424              
425             # This is a Marpa Grammar method, but is included in this
426             # file because internally it is all about the recognizer.
427             sub Marpa::R3::Grammar::parse {
428 2     2   29 my ( $slg, $input_ref, @more_args ) = @_;
429 2 50 33     18 if ( not defined $input_ref or ref $input_ref ne 'SCALAR' ) {
430 0         0 Marpa::R3::exception(
431             q{$slr->parse(): first argument must be a ref to string});
432             }
433 2         12 my @recce_args = ( { grammar => $slg } );
434 2 50       9 if ( grep { ref $_ ne 'HASH' } @more_args ) {
  0         0  
435 0         0 Marpa::R3::exception(
436             q{$slr->parse(): second and later arguments must be ref to HASH});
437             }
438 2         13 my $slr = Marpa::R3::Recognizer->new( @recce_args, @more_args,
439             );
440 2         7 my $input_length = ${$input_ref};
  2         6  
441 2         10 my $length_read = $slr->read($input_ref);
442 2 50       13 if ( $length_read != length $input_length ) {
443 0         0 die 'read in $slr->parse() ended prematurely', "\n",
444             " The input length is $input_length\n",
445             " The length read is $length_read\n",
446             " The cause may be an event\n",
447             " The $slr->parse() method does not allow parses to trigger events";
448             } ## end if ( $length_read != length $input_length )
449 2         23 my $slv = Marpa::R3::Valuer->new( { recognizer => $slr });
450 2         16 my $ambiguity_level = $slv->ambiguity_level();
451 2 50       10 if ( $ambiguity_level != 1 ) {
452 0         0 my $ambiguous_status = $slv->ambiguous();
453 0         0 Marpa::R3::exception( "Parse of the input is ambiguous\n",
454             $ambiguous_status );
455             }
456              
457 2         11 my $value_ref = $slv->value();
458 2 50       10 Marpa::R3::exception(
459             '$slr->parse() read the input, but there was no parse', "\n" )
460             if not $value_ref;
461              
462 2         13 return $value_ref;
463             } ## end sub Marpa::R3::Grammar::parse
464              
465             # Brief description of block/line/column for
466             # an L0 range
467             sub lc_brief {
468 0     0   0 my ( $slr, $pos, $block ) = @_;
469 0   0     0 my ($result) = $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
470             <<'END_OF_LUA', 'ii', $pos, ($block // -1));
471             local slr, pos, block = ...
472             if block < 0 then block = nil end
473             return slr:lc_brief(block, pos)
474             END_OF_LUA
475 0         0 return $result;
476             }
477              
478             # Brief description of block/line/column for
479             # an L0 range
480             sub lc_range_brief {
481 0     0   0 my ( $slr, $first_block, $first_pos, $last_block, $last_pos ) = @_;
482 0         0 my ($result) = $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
483             <<'END_OF_LUA', 'iiii', $first_block, $first_pos, $last_block, $last_pos );
484             local slr, block1, pos1, block2, pos2 = ...
485             return slr:lc_range_brief(block1, pos1, block2, pos2)
486             END_OF_LUA
487 0         0 return $result;
488              
489             }
490              
491             sub Marpa::R3::Recognizer::progress_show {
492 19     19   2831 my ( $slr, $start_ordinal, $end_ordinal ) = @_;
493 19         79 my ($text) = $slr->call_by_tag(
494             ( '@' . __FILE__ . ':' . __LINE__ ),
495             <<'END_OF_LUA', 'ii', $start_ordinal, $end_ordinal );
496             local slr, start_ordinal_arg, end_ordinal_arg = ...
497             return slr:progress_show(start_ordinal_arg, end_ordinal_arg )
498             END_OF_LUA
499 19         124 return $text;
500             }
501              
502             sub Marpa::R3::Recognizer::progress {
503 19     19   12972 my ( $slr, $ordinal_arg ) = @_;
504 19   100     98 my ($result) = $slr->call_by_tag(
505             ('@' . __FILE__ . ':' . __LINE__),
506             <<'END_OF_LUA', 'i>0', ($ordinal_arg // -1));
507             local slr, ordinal_arg = ...
508             return slr:progress(ordinal_arg)
509             END_OF_LUA
510 19         78 return $result;
511             }
512              
513             sub Marpa::R3::Recognizer::g1_progress_show {
514 0     0   0 my ( $slr, $start_ordinal, $end_ordinal ) = @_;
515 0         0 my ($text) = $slr->call_by_tag(
516             ( '@' . __FILE__ . ':' . __LINE__ ),
517             <<'END_OF_LUA', 'ii', $start_ordinal, $end_ordinal );
518             local slr, start_ordinal_arg, end_ordinal_arg = ...
519             return slr:g1_progress_show(start_ordinal_arg, end_ordinal_arg )
520             END_OF_LUA
521 0         0 return $text;
522             }
523              
524             sub Marpa::R3::Recognizer::g1_progress {
525 21     21   10863 my ( $slr, $ordinal_arg ) = @_;
526 21   50     99 my ($result) = $slr->call_by_tag(
527             ('@' . __FILE__ . ':' . __LINE__),
528             <<'END_OF_LUA', 'i>0', ($ordinal_arg // -1));
529             local slr, ordinal_arg = ...
530             return slr:g1_progress(ordinal_arg)
531             END_OF_LUA
532 21         73 return $result;
533             }
534              
535             sub Marpa::R3::Recognizer::terminals_expected {
536 35     35   907 my ($slr) = @_;
537 35         100 my ($results) = $slr->call_by_tag(
538             ('@' . __FILE__ . ':' . __LINE__),
539             <<'END_OF_LUA', '');
540             local slr = ...
541             local slg = slr.slg
542             local g1g = slg.g1
543             local terminals_expected = slr.g1:terminals_expected()
544             local results = {}
545             for ix = 1, #terminals_expected do
546             local g1_symbol_id = terminals_expected[ix]
547             local xsy = g1g:_xsy(g1_symbol_id)
548             if xsy then
549             results[#results+1] = xsy.name
550             end
551             end
552             return results
553             END_OF_LUA
554              
555 35         113 return $results;
556             }
557              
558             sub Marpa::R3::Recognizer::exhausted {
559 18     18   265 my ($slr) = @_;
560 18         48 my ($is_exhausted) = $slr->call_by_tag(
561             ('@' . __FILE__ . ':' . __LINE__),
562             <<'END_OF_LUA', '');
563             local recce = ...
564             local is_exhausted = recce.g1:is_exhausted()
565             return is_exhausted
566             END_OF_LUA
567 18         40 return $is_exhausted;
568             }
569              
570             # Latest and current G1 location are the same
571             sub Marpa::R3::Recognizer::g1_pos {
572 185     185   7065 my ($slr) = @_;
573 185         536 my ($latest_earley_set) = $slr->call_by_tag(
574             ('@' . __FILE__ . ':' . __LINE__),
575             <<'END_OF_LUA', '');
576             local recce = ...
577             local latest_earley_set = recce:latest_earley_set()
578             return latest_earley_set
579             END_OF_LUA
580 185         552 return $latest_earley_set;
581             }
582              
583             sub Marpa::R3::Recognizer::current_earleme {
584 12     12   6048 my ($slr) = @_;
585 12         39 my ($current_earleme) = $slr->call_by_tag(
586             ('@' . __FILE__ . ':' . __LINE__),
587             <<'END_OF_LUA', '');
588             local recce = ...
589             local current_earleme = recce:current_earleme()
590             return current_earleme
591             END_OF_LUA
592 12         29 return $current_earleme;
593             }
594              
595             sub Marpa::R3::Recognizer::closest_earleme {
596 12     12   5793 my ($slr) = @_;
597 12         39 my ($closest_earleme) = $slr->call_by_tag(
598             ('@' . __FILE__ . ':' . __LINE__),
599             <<'END_OF_LUA', '');
600             local recce = ...
601             local closest_earleme = recce:closest_earleme()
602             return closest_earleme
603             END_OF_LUA
604 12         31 return $closest_earleme;
605             }
606              
607             sub Marpa::R3::Recognizer::furthest_earleme {
608 12     12   6434 my ($slr) = @_;
609 12         39 my ($furthest_earleme) = $slr->call_by_tag(
610             ('@' . __FILE__ . ':' . __LINE__),
611             <<'END_OF_LUA', '');
612             local recce = ...
613             local furthest_earleme = recce:furthest_earleme()
614             return furthest_earleme
615             END_OF_LUA
616 12         27 return $furthest_earleme;
617             }
618              
619             sub Marpa::R3::Recognizer::latest_earleme {
620 11     11   6158 my ($slr) = @_;
621 11         34 my ($latest_earleme) = $slr->call_by_tag(
622             ('@' . __FILE__ . ':' . __LINE__),
623             <<'END_OF_LUA', '');
624             local recce = ...
625             local latest_earleme = recce:latest_earleme()
626             return latest_earleme
627             END_OF_LUA
628 11         27 return $latest_earleme;
629             }
630              
631             sub Marpa::R3::Recognizer::earleme {
632 1     1   6 my ( $slr, $earley_set_id ) = @_;
633 1         3 my ($earleme) = $slr->call_by_tag(
634             ('@' . __FILE__ . ':' . __LINE__),
635             <<'END_OF_LUA', 'i', $earley_set_id);
636             local recce, earley_set_id = ...
637             local earleme = recce:earleme(earley_set_id)
638             return earleme
639             END_OF_LUA
640 1         3 return $earleme;
641             }
642              
643             sub Marpa::R3::Recognizer::lexeme_alternative_literal {
644 84     84   4409 my ( $slr, $symbol_name, $length ) = @_;
645 84   100     337 $length //= 1;
646              
647 84 50       183 Marpa::R3::exception(
648             "slr->alternative_literal(): symbol name is undefined\n",
649             " The symbol name cannot be undefined\n"
650             ) if not defined $symbol_name;
651              
652 84         205 my ($ok) = $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
653             <<'END_OF_LUA', 'si', $symbol_name, $length);
654             local slr, symbol_name, length = ...
655             return slr:lexeme_alternative_literal(symbol_name, length)
656             END_OF_LUA
657 84 50       266 return 1 if $ok;
658 0         0 return;
659             }
660              
661             sub Marpa::R3::Recognizer::lexeme_alternative {
662 137     137   1001 my ( $slr, $symbol_name, $value, $length ) = @_;
663 137   100     548 $length //= 1;
664              
665 137 50       400 if ( Scalar::Util::tainted( $value ) ) {
666 0         0 Marpa::R3::exception(
667             "Problem in Marpa::R3: Attempt to use a tainted token value\n",
668             "Marpa::R3 is insecure for use with tainted data\n"
669             );
670             }
671              
672             Marpa::R3::exception(
673 137 50       283 "slr->alternative(): symbol name is undefined\n",
674             " The symbol name cannot be undefined\n"
675             ) if not defined $symbol_name;
676              
677 137         190 my $ok;
678 137 100       297 if (defined $value) {
679 127         332 ($ok) = $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
680             <<'END_OF_LUA', 'sSi', $symbol_name, $value, $length );
681             local slr, symbol_name, token_sv, length = ...
682             return slr:lexeme_alternative(symbol_name, token_sv, length)
683             END_OF_LUA
684             } else {
685 10         23 ($ok) = $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
686             <<'END_OF_LUA', 'si', $symbol_name, $length );
687             local slr, symbol_name, length = ...
688             return slr:lexeme_alternative_undef(symbol_name, length )
689             END_OF_LUA
690             }
691              
692 135 50       636 return 1 if $ok;
693 0         0 return;
694             }
695              
696             # Returns 0 on unthrown failure, current location on success
697             sub Marpa::R3::Recognizer::lexeme_complete {
698 189     189   4642 my ( $slr, $block, $offset, $length ) = @_;
699 189 50       393 if ( $slr->[Marpa::R3::Internal_R::CURRENT_EVENT] ) {
700 0         0 Marpa::R3::exception(
701             "$slr->lexeme_complete() called from inside a handler\n",
702             " This is not allowed\n",
703             " The event was ",
704             $slr->[Marpa::R3::Internal_R::CURRENT_EVENT],
705             "\n",
706             );
707             }
708              
709 189         260 my $trace_file_handle =
710             $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE];
711              
712             my ($return_value) = $slr->coro_by_tag(
713             ( '@' . __FILE__ . ':' . __LINE__ ),
714             {
715             signature => 'iii',
716             args => [ $block, $offset, $length ],
717             handlers => {
718             trace => sub {
719 0     0   0 my ($msg) = @_;
720 0         0 say {$trace_file_handle} $msg;
  0         0  
721 0         0 return 'ok';
722             },
723 189         1099 codepoint => gen_codepoint_event_handler($slr),
724             event => gen_app_event_handler($slr),
725             }
726             },
727             <<'END_OF_LUA');
728             local slr, block_id_arg, offset_arg, length_arg = ...
729             local block_id, offset, eoread
730             = slr:block_check_range(block_id_arg, offset_arg, length_arg)
731             _M.wrap(function ()
732             local new_offset = slr:lexeme_complete(block_id, offset, eoread-offset)
733             slr:convert_libmarpa_events()
734             return 'ok', new_offset
735             end
736             )
737             END_OF_LUA
738              
739 189         2884 return $return_value;
740              
741             } ## end sub Marpa::R3::Recognizer::lexeme_complete
742              
743             # Returns 0 on unthrown failure, current location on success,
744             # undef if lexeme not accepted.
745             sub Marpa::R3::Recognizer::lexeme_read_literal {
746 116     116   668 my ( $slr, $symbol_name, $block_id, $offset, $length ) = @_;
747 116 50       258 if ( $slr->[Marpa::R3::Internal_R::CURRENT_EVENT] ) {
748 0         0 Marpa::R3::exception(
749             "$slr->lexeme_read_literal() called from inside a handler\n",
750             " This is not allowed\n",
751             " The event was ",
752             $slr->[Marpa::R3::Internal_R::CURRENT_EVENT],
753             "\n",
754             );
755             }
756             my ($ok, $return_value) = $slr->coro_by_tag(
757             ( '@' . __FILE__ . ':' . __LINE__ ),
758             {
759             signature => 'siii',
760             args => [ $symbol_name, $block_id, $offset, $length ],
761             handlers => {
762             trace => sub {
763 0     0   0 my ($msg) = @_;
764 0         0 my $trace_file_handle =
765             $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE];
766 0         0 say {$trace_file_handle} $msg;
  0         0  
767 0         0 return 'ok';
768             },
769 116         667 codepoint => gen_codepoint_event_handler($slr),
770             event => gen_app_event_handler($slr),
771             }
772             },
773             <<'END_OF_LUA');
774             local slr, symbol_name, block_id, offset, length = ...
775             _M.wrap(function ()
776             local offset = slr:lexeme_read_literal(symbol_name, block_id, offset, length )
777             if not offset then return 'ok', 0 end
778             return 'ok', 1, offset
779             end
780             )
781             END_OF_LUA
782              
783 116 50       1460 return if not $ok;
784 116         282 return $return_value;
785             }
786              
787             # Returns 0 on unthrown failure, current location on success,
788             # undef if lexeme not accepted.
789             sub Marpa::R3::Recognizer::lexeme_read_block {
790 243     243   6732 my ( $slr, $symbol_name, $value, $block_id, $offset, $length ) = @_;
791 243 50       523 if ( $slr->[Marpa::R3::Internal_R::CURRENT_EVENT] ) {
792 0         0 Marpa::R3::exception(
793             "$slr->lexeme_read_block() called from inside a handler\n",
794             " This is not allowed\n",
795             " The event was ",
796             $slr->[Marpa::R3::Internal_R::CURRENT_EVENT],
797             "\n",
798             );
799             }
800 243 50       655 if ( Scalar::Util::tainted( $value ) ) {
801 0         0 Marpa::R3::exception(
802             "Problem in Marpa::R3: Attempt to use a tainted token value\n",
803             "Marpa::R3 is insecure for use with tainted data\n"
804             );
805             }
806             my ($ok, $return_value) = $slr->coro_by_tag(
807             ( '@' . __FILE__ . ':' . __LINE__ ),
808             {
809             signature => 'sSiii',
810             args => [ $symbol_name, $value, $block_id, $offset, $length ],
811             handlers => {
812             trace => sub {
813 0     0   0 my ($msg) = @_;
814 0         0 my $trace_file_handle =
815             $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE];
816 0         0 say {$trace_file_handle} $msg;
  0         0  
817 0         0 return 'ok';
818             },
819 243         1326 codepoint => gen_codepoint_event_handler($slr),
820             event => gen_app_event_handler($slr),
821             }
822             },
823             <<'END_OF_LUA');
824             local slr, symbol_name, token_sv, block_id, offset, length = ...
825             _M.wrap(function ()
826             local offset = slr:lexeme_read_block(symbol_name, token_sv, block_id, offset, length )
827             if not offset then return 'ok', 0 end
828             return 'ok', 1, offset
829             end
830             )
831             END_OF_LUA
832              
833 243 50       3230 return if not $ok;
834 243         573 return $return_value;
835             }
836              
837             # Returns 0 on unthrown failure, current location on success,
838             # undef if lexeme not accepted.
839             sub Marpa::R3::Recognizer::lexeme_read_string {
840 36     36   1007 my ( $slr, $symbol_name, $string ) = @_;
841 36 50       86 if ( $slr->[Marpa::R3::Internal_R::CURRENT_EVENT] ) {
842 0         0 Marpa::R3::exception(
843             '$recce->lexeme_read_string() called from inside a handler', "\n",
844             " This is not allowed\n",
845             " The event was ",
846             $slr->[Marpa::R3::Internal_R::CURRENT_EVENT],
847             "\n",
848             );
849             }
850              
851             my ($ok, $return_value) = $slr->coro_by_tag(
852             ( '@' . __FILE__ . ':' . __LINE__ ),
853             {
854             signature => 'ss',
855             args => [ $symbol_name, $string ],
856             handlers => {
857             trace => sub {
858 0     0   0 my ($msg) = @_;
859 0         0 my $trace_file_handle =
860             $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE];
861 0         0 say {$trace_file_handle} $msg;
  0         0  
862 0         0 return 'ok';
863             },
864 36         371 codepoint => gen_codepoint_event_handler($slr),
865             event => gen_app_event_handler($slr),
866             }
867             },
868             <<'END_OF_LUA');
869             local slr, symbol_name, input_string = ...
870             _M.wrap(function ()
871             local offset = slr:lexeme_read_string(symbol_name, input_string )
872             if not offset then return 'ok', 0 end
873             return 'ok', 1, offset
874             end
875             )
876             END_OF_LUA
877              
878 36 100       513 return if not $ok;
879 35         94 return $return_value;
880              
881             }
882              
883             sub Marpa::R3::Recognizer::g1_to_block_first {
884 56     56   965 my ( $slr, $g1_pos ) = @_;
885 56         221 return $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
886             <<'END_OF_LUA', 'i', $g1_pos );
887             local slr, g1_pos = ...
888             g1_pos = math.tointeger(g1_pos)
889             if not g1_pos then
890             _M.userX(
891             "g1_to_block_first(%s): argument must be an integer",
892             g1_pos)
893             end
894             return slr:g1_to_block_first(g1_pos)
895             END_OF_LUA
896             }
897              
898             sub Marpa::R3::Recognizer::g1_to_block_last {
899 51     51   199 my ( $slr, $g1_pos ) = @_;
900 51         155 return $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
901             <<'END_OF_LUA', 'i', $g1_pos );
902             local slr, g1_pos = ...
903             g1_pos = math.tointeger(g1_pos)
904             if not g1_pos then
905             _M.userX(
906             "g1_to_block_last(%s): argument must be an integer",
907             g1_pos)
908             end
909             return slr:g1_to_block_last(g1_pos)
910             END_OF_LUA
911             }
912              
913             # TODO -- Document this method ??
914             sub Marpa::R3::Recognizer::lc_brief {
915 36     36   105 my ( $slr, $first_block, $first_pos, $last_block, $last_pos ) = @_;
916 36         105 my ($desc) = $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
917             <<'END_OF_LUA', 'iiii', $first_block, $first_pos, $last_block, $last_pos );
918             local slr, first_block, first_pos, last_block, last_pos = ...
919             local function usage()
920             error(
921             "usage: $recce->lc_brief(first_block, first_pos, [last_block, last_pos])"
922             )
923             end
924             if not first_block or not first_pos then
925             return usage()
926             end
927             if last_block == nil or last_pos == nil then
928             if last_block ~= nil or last_pos ~= nil then
929             return usage()
930             end
931             last_block = first_block
932             last_pos = first_pos
933             end
934             return slr:lc_range_brief(
935             first_block, first_pos, last_block, last_pos)
936             END_OF_LUA
937 36         157 return $desc;
938             }
939              
940             sub Marpa::R3::Recognizer::line_column {
941 131     131   740 my ( $slr, $block, $pos, ) = @_;
942 131   33     252 $pos //= $slr->pos();
943 131   50     218 $block //= -1;
944              
945 131         294 my ($line_no, $column_no) = $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
946             <<'END_OF_LUA', 'ii', $block, $pos );
947             local slr, block, pos = ...
948             if block <= 0 then block = slr.current_block.index end
949             local _, line_no, column_no = slr:per_pos(block, pos)
950             return line_no, column_no
951             END_OF_LUA
952              
953 131         312 return $line_no, $column_no;
954             } ## end sub Marpa::R3::Recognizer::line_column
955              
956             sub Marpa::R3::Recognizer::block_new {
957 1308     1308   2792 my ( $slr, $p_string ) = @_;
958 1308         2201 my $slg = $slr->[Marpa::R3::Internal_R::SLG];
959              
960             Marpa::R3::exception(
961             q{Attempt to use a tainted input string in $slr->read()},
962             qq{\n Marpa::R3 is insecure for use with tainted data\n}
963 1308 100       1898 ) if Scalar::Util::tainted( ${$p_string} );
  1308         4544  
964              
965 1307 50       4495 if ( ( my $ref_type = ref $p_string ) ne 'SCALAR' ) {
966 0 0       0 my $desc = $ref_type ? "a ref to $ref_type" : 'not a ref';
967 0         0 Marpa::R3::exception(
968             qq{Arg to Marpa::R3::Recognizer::read() is $desc\n},
969             ' It should be a ref to scalar' );
970             } ## end if ( ( my $ref_type = ref $p_string ) ne 'SCALAR' )
971              
972 1307 50       2054 if ( not defined ${$p_string} ) {
  1307         3177  
973 0         0 Marpa::R3::exception(
974             qq{Arg to Marpa::R3::Recognizer::read() is a ref to an undef\n},
975             ' It should be a ref to a defined scalar' );
976             } ## end if ( ( my $ref_type = ref $p_string ) ne 'SCALAR' )
977              
978 1307         2367 my $character_class_table =
979             $slg->[Marpa::R3::Internal_G::CHARACTER_CLASS_TABLE];
980              
981             my ($block_id) = $slr->coro_by_tag(
982             ( '@' . __FILE__ . ':' . __LINE__ ),
983             {
984             signature => 's',
985 1307         2362 args => [ ${$p_string} ],
  1307         3800  
986             handlers => {
987             codepoint => gen_codepoint_event_handler($slr),
988             event => gen_app_event_handler($slr),
989             },
990             },
991             <<'END_OF_LUA');
992             local slr, input_string = ...
993             local new_block_id
994             _M.wrap(function()
995             new_block_id = slr:block_new(input_string)
996             return 'ok', new_block_id
997             end
998             )
999             END_OF_LUA
1000              
1001 1307         18689 return $block_id;
1002             }
1003              
1004             sub Marpa::R3::Recognizer::block_progress {
1005 648     648   29085 my ($slr, $block_id) = @_;
1006 648         992 my ($l0_pos, $l0_end);
1007 648         1610 ($block_id, $l0_pos, $l0_end)
1008             = $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1009             <<'END_OF_LUA', 'i', $block_id );
1010             local slr, block_id_arg = ...
1011             local block_id, erreur = slr:block_check_id(block_id_arg)
1012             if not block_id then
1013             error(erreur)
1014             end
1015             local l0_pos, l0_end
1016             block_id, l0_pos, l0_end = slr:block_progress(block_id)
1017             return block_id, l0_pos, l0_end
1018             END_OF_LUA
1019 648         1640 return $block_id, $l0_pos, $l0_end;
1020             }
1021              
1022             sub Marpa::R3::Recognizer::block_set {
1023 1352     1352   4400 my ($slr, $block_id) = @_;
1024 1352 50       3656 if ( $slr->[Marpa::R3::Internal_R::CURRENT_EVENT] ) {
1025 0         0 Marpa::R3::exception(
1026             "$slr->block_set() called from inside a handler\n",
1027             " This is not allowed\n",
1028             " The event was ",
1029             $slr->[Marpa::R3::Internal_R::CURRENT_EVENT],
1030             "\n",
1031             );
1032             }
1033 1352         4789 $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1034             <<'END_OF_LUA', 'i', $block_id );
1035             local slr, block_id_arg = ...
1036             local block_id, erreur = slr:block_check_id(block_id_arg)
1037             if not block_id then
1038             error(erreur)
1039             end
1040             return slr:block_set(block_id)
1041             END_OF_LUA
1042 1352         2388 return;
1043             }
1044              
1045             # block_id defaults to current block
1046             # block_offset defaults to don't set offset
1047             # length defaults to don't set eoread
1048             sub Marpa::R3::Recognizer::block_move {
1049 2153     2153   6537 my ($slr, $offset, $length) = @_;
1050 2153         6430 $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1051             <<'END_OF_LUA', 'ii', $offset, $length );
1052             local slr, offset_arg, length_arg = ...
1053             local ok, offset, eoread
1054             = slr:block_check_range(nil, offset_arg, length_arg)
1055             if not ok then
1056             -- new_block_offset is error message
1057             error(offset)
1058             end
1059             -- we don't set offset if the arg was nil
1060             local new_offset = offset_arg and offset or nil
1061             -- we don't set eoread if the length arg was nil
1062             local new_eoread = length_arg and eoread or nil
1063             return slr:block_move(new_offset, new_eoread)
1064             END_OF_LUA
1065 2153         4287 return;
1066             }
1067              
1068             sub Marpa::R3::Recognizer::block_read {
1069 1812     1812   4108 my ($slr ) = @_;
1070             my ($offset) = $slr->coro_by_tag(
1071             ( '@' . __FILE__ . ':' . __LINE__ ),
1072             {
1073             signature => '',
1074             args => [],
1075             handlers => {
1076             trace => sub {
1077 314     314   527 my ($msg) = @_;
1078 314         483 my $trace_file_handle =
1079             $slr->[Marpa::R3::Internal_R::TRACE_FILE_HANDLE];
1080 314         411 say {$trace_file_handle} $msg;
  314         871  
1081 314         759 return 'ok';
1082             },
1083 1812         10351 event => gen_app_event_handler($slr),
1084             }
1085             },
1086             <<'END_OF_LUA');
1087             local slr = ...
1088             _M.wrap(function ()
1089             local offset = slr:block_read()
1090             return 'ok', offset
1091             end
1092             )
1093             END_OF_LUA
1094 1803         27004 return $offset;
1095             }
1096              
1097             sub Marpa::R3::Recognizer::input_length {
1098 2     2   1326 my ( $slr, $block_id ) = @_;
1099 2   100     14 my ($length) = $slr->call_by_tag(
1100             ('@' . __FILE__ . ':' . __LINE__),
1101             <<'END_OF_LUA', 'i', ($block_id // -1));
1102             local slr, block_id = ...
1103             local block = block_id > 0 and slr.inputs[block_id] or slr.current_block
1104             return #block
1105             END_OF_LUA
1106              
1107 2         16 return $length;
1108             }
1109              
1110             # no return value documented
1111             sub Marpa::R3::Recognizer::activate {
1112 536     536   1778 my ( $slr, $event_name, $activate ) = @_;
1113 536         772 my $slg = $slr->[Marpa::R3::Internal_R::SLG];
1114              
1115 536         1271 $slr->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1116             <<'END_OF_LUA', 'si', $event_name, $activate);
1117             local slr, event_name, activate = ...
1118             if not activate then
1119             activate = 1
1120             else
1121             activate = activate ~= 0
1122             end
1123             -- print('$slr->activate():', event_name, activate)
1124             return slr:activate_by_event_name(event_name, activate)
1125             END_OF_LUA
1126 536         996 return;
1127             }
1128              
1129             # On success, returns the old priority value.
1130             # Failures are thrown.
1131             sub Marpa::R3::Recognizer::lexeme_priority_set {
1132 12     12   65 my ( $slr, $lexeme_name, $new_priority ) = @_;
1133 12         32 my ($old_priority) = $slr->call_by_tag(
1134             ('@' . __FILE__ . ':' . __LINE__),
1135             <<'END_OF_LUA', 'si>*', $lexeme_name, $new_priority );
1136             local recce, lexeme_name, new_priority = ...
1137             local slg = recce.slg
1138             local g1g = slg.g1
1139             local lexeme_id = g1g.isyid_by_name[lexeme_name]
1140             if not lexeme_id then
1141             _M.userX(
1142             "lexeme_priority_set(): no such symbol as %q",
1143             lexeme_name
1144             )
1145             end
1146             if type(new_priority) ~= 'number' then
1147             _M.userX(
1148             "lexeme_priority_set(): priority is not a number, it is %s",
1149             new_priority
1150             )
1151             end
1152             local g_lexeme_data = slg.g1.isys[lexeme_id]
1153             local r_lexeme_data = recce.g1_isys[lexeme_id]
1154             if not g_lexeme_data.lexeme then
1155             print(inspect(lexeme_data))
1156             _M.userX(
1157             "lexeme_priority_set(): %q is not a lexeme",
1158             lexeme_name
1159             )
1160             end
1161             local old_priority = r_lexeme_data.lexeme_priority
1162             r_lexeme_data.lexeme_priority = new_priority
1163             return old_priority
1164             END_OF_LUA
1165              
1166 12         25 return $old_priority;
1167             }
1168              
1169             # Internal methods, not to be documented
1170              
1171             # not to be documented
1172             sub Marpa::R3::Recognizer::call_by_tag {
1173 8825     8825   29342 my ( $slr, $tag, $codestr, $signature, @args ) = @_;
1174 8825         13537 my $lua = $slr->[Marpa::R3::Internal_R::L];
1175 8825         12539 my $regix = $slr->[Marpa::R3::Internal_R::REGIX];
1176              
1177 8825 50       16594 $DB::single = 1 if not $slr;
1178 8825 50       15002 $DB::single = 1 if not $regix;
1179             # $DB::single = 1 if grep { not defined $_ } @args;
1180 8825         17651 my @results;
1181             my $eval_error;
1182 8825         0 my $eval_ok;
1183             {
1184 8825         11494 local $@;
  8825         11651  
1185 8825         13643 $eval_ok = eval {
1186 8825         283571 @results =
1187             $lua->call_by_tag( $regix, $tag, $codestr, $signature, @args );
1188 8823         20122 return 1;
1189             };
1190 8825         17751 $eval_error = $@;
1191             }
1192 8825 100       18027 if ( not $eval_ok ) {
1193 2         7 Marpa::R3::exception($eval_error);
1194             }
1195 8823         25873 return @results;
1196             }
1197              
1198             # not to be documented
1199             sub Marpa::R3::Recognizer::coro_by_tag {
1200 6116     6116   13963 my ( $slr, $tag, $args, $codestr ) = @_;
1201 6116         9251 my $lua = $slr->[Marpa::R3::Internal_R::L];
1202 6116         8461 my $regix = $slr->[Marpa::R3::Internal_R::REGIX];
1203 6116   50     14900 my $handler = $args->{handlers} // {};
1204 6116         12410 my $resume_tag = $tag . '[R]';
1205 6116   50     12199 my $signature = $args->{signature} // '';
1206 6116   50     11653 my $p_args = $args->{args} // [];
1207              
1208 6116         12587 my @results;
1209             my $eval_error;
1210 6116         0 my $eval_ok;
1211             {
1212 6116         7953 local $@;
  6116         8176  
1213 6116         9821 $eval_ok = eval {
1214 6116         8704 $lua->call_by_tag( $regix, $tag, $codestr, $signature, @{$p_args} );
  6116         100312  
1215 6116         17002 my @resume_args = ('');
1216 6116         8905 my $signature = 's';
1217 6116         8109 CORO_CALL: while (1) {
1218 13306         8337676 my ( $cmd, $yield_data ) =
1219             $lua->call_by_tag( $regix, $resume_tag,
1220             'local slr, resume_arg = ...; return _M.resume(resume_arg)',
1221             $signature, @resume_args ) ;
1222 13297 100       46878 if (not $cmd) {
1223 6107         8701 @results = @{$yield_data};
  6107         13040  
1224 6107         19687 return 1;
1225             }
1226 7190         13933 my $handler = $handler->{$cmd};
1227 7190 50       13443 Marpa::R3::exception(qq{No coro handler for "$cmd"})
1228             if not $handler;
1229 7190   50     12918 $yield_data //= [];
1230 7190         9695 my ($handler_cmd, $new_resume_args) = $handler->(@{$yield_data});
  7190         16287  
1231 7190 50       15451 Marpa::R3::exception(qq{Undefined return command from handler for "$cmd"})
1232             if not defined $handler_cmd;
1233 7190 50       14200 if ($handler_cmd eq 'ok') {
1234 7190         10246 $signature = 's';
1235 7190         18881 @resume_args = ($new_resume_args);
1236 7190 50       14876 if (scalar @resume_args < 1) {
1237 0         0 @resume_args = ('');
1238             }
1239 7190         16201 next CORO_CALL;
1240             }
1241 0 0       0 if ($handler_cmd eq 'sig') {
1242 0         0 @resume_args = @{$new_resume_args};
  0         0  
1243 0         0 $signature = shift @resume_args;
1244 0         0 next CORO_CALL;
1245             }
1246 0         0 Marpa::R3::exception(qq{Bad return command ("$handler_cmd") from handler for "$cmd"})
1247             }
1248 0         0 return 1;
1249             };
1250 6116         13800 $eval_error = $@;
1251             }
1252 6116 100       12701 if ( not $eval_ok ) {
1253             # if it's an object, just die
1254 9 50       37 die $eval_error if ref $eval_error;
1255 9         51 Marpa::R3::exception($eval_error);
1256             }
1257 6107         16111 return @results;
1258             }
1259              
1260             # not to be documented
1261             sub Marpa::R3::Recognizer::earley_set_size {
1262 78     78   319 my ($slr, $set_id) = @_;
1263 78   50     219 my ($size) = $slr->call_by_tag(
1264             ('@' . __FILE__ . ':' . __LINE__),
1265             <<'END_OF_LUA', 'i', ($set_id // -1));
1266             local recce, set_id = ...
1267             local g1r = recce.g1
1268             if set_id < 0 then set_id = g1r:latest_earley_set() end
1269             return g1r:_earley_set_size(set_id)
1270             END_OF_LUA
1271 78         287 return $size;
1272             }
1273              
1274             # not to be documented
1275             sub Marpa::R3::Recognizer::earley_sets_show {
1276 8     8   2949 my ($slr) = @_;
1277              
1278 8         35 my ($last_completed_earleme, $furthest_earleme) = $slr->call_by_tag(
1279             ('@' . __FILE__ . ':' . __LINE__),
1280             <<'END_OF_LUA', '');
1281             local recce = ...
1282             local g1r = recce.g1
1283             return g1r:current_earleme(), g1r:furthest_earleme()
1284             END_OF_LUA
1285              
1286 8         51 my $text = "Last Completed: $last_completed_earleme; "
1287             . "Furthest: $furthest_earleme\n";
1288 8         23 LIST: for ( my $ix = 0;; $ix++ ) {
1289 67         241 my $set_desc =
1290             $slr->Marpa::R3::Recognizer::earley_set_show( $ix );
1291 67 100       185 last LIST if not $set_desc;
1292 59         635 $text .= "Earley Set $ix\n$set_desc";
1293             }
1294 8         92 return $text;
1295             }
1296              
1297             # not to be documented
1298             sub Marpa::R3::Recognizer::earley_set_show {
1299 67     67   149 my ( $slr, $traced_set_id ) = @_;
1300 67         172 my $slg = $slr->[Marpa::R3::Internal_R::SLG];
1301              
1302 67         191 my ($set_data) =
1303             $slr->call_by_tag(
1304             ('@' . __FILE__ . ':' . __LINE__),
1305             <<'END_OF_LUA', 'i>2', $traced_set_id );
1306             local recce, traced_set_id = ...
1307             return recce:g1_earley_set_data(traced_set_id)
1308             END_OF_LUA
1309              
1310 67 100       190 return if not $set_data;
1311 59         93 my %set_data = @{$set_data};
  59         424  
1312              
1313 59         136 my $current_earleme = $set_data{earleme};
1314              
1315 59         93 my @sorted_data = ();
1316              
1317 59         233 EARLEY_ITEM: for ( my $item_id = 0 ; ; $item_id++ ) {
1318              
1319 511         850 my $item_data = $set_data{ $item_id + 1 };
1320 511 100       1000 last EARLEY_ITEM if not defined $item_data;
1321              
1322 452         568 my %item_data = @{$item_data};
  452         1899  
1323              
1324 452         735 my $nrl_id = $item_data{nrl_id};
1325 452         605 my $dot_position = $item_data{dot_position};
1326 452         568 my $ahm_desc;
1327 452 100       850 if ( $dot_position < 0 ) {
1328 177         540 $ahm_desc = sprintf( 'R%d$', $nrl_id );
1329             }
1330             else {
1331 275         836 $ahm_desc = sprintf( 'R%d:%d', $nrl_id, $dot_position );
1332             }
1333 452         689 my $ahm_id_of_yim = $item_data{ahm_id_of_yim};
1334 452         608 my $origin_earleme = $item_data{origin_earleme};
1335              
1336 452         1152 my $text .= sprintf "ahm%d: %s@%d-%d", $ahm_id_of_yim,
1337             $ahm_desc,
1338             $origin_earleme, $current_earleme;
1339              
1340 452         833 my @lines = $text;
1341 452         1433 push @lines,
1342             qq{ }
1343             . $ahm_desc . q{: }
1344             . $slg->dotted_nrl_show( $nrl_id, $dot_position );
1345              
1346 452         895 push @sorted_data, @lines;
1347              
1348             # Token links
1349             {
1350 452         618 my @sort_data = ();
1351 452         578 my @lines = ();
1352 452         739 my $token_links = $item_data{token_links};
1353 452         554 my %token_links = @{$token_links};
  452         793  
1354 452         747 TOKEN_LINK: for ( my $token_link_ix = 0 ; ; $token_link_ix++ ) {
1355 519         924 my $token_link_data = $token_links{ $token_link_ix + 1 };
1356 519 100       1134 last TOKEN_LINK if not $token_link_data;
1357 67         102 my %token_link_data = @{$token_link_data};
  67         281  
1358              
1359 67         119 my $predecessor_ahm = $token_link_data{predecessor_ahm};
1360 67         104 my $origin_earleme = $token_link_data{origin_earleme};
1361 67         96 my $middle_earleme = $token_link_data{middle_earleme};
1362 67         85 my $middle_set_id = $token_link_data{middle_set_id};
1363 67         101 my $token_name = $token_link_data{token_name};
1364 67         95 my $token_id = $token_link_data{token_id};
1365 67         88 my $value_ix = $token_link_data{value_ix};
1366 67         111 my $value = $token_link_data{value};
1367             my $source_predecessor_state =
1368 67         97 $token_link_data{source_predecessor_state};
1369              
1370 67         92 my @pieces = ();
1371 67 50       164 if ( defined $predecessor_ahm ) {
1372 67         188 my $ahm_desc = $slg->briefer_ahm($predecessor_ahm);
1373 67         198 push @pieces,
1374             'c='
1375             . $ahm_desc . q{@}
1376             . $origin_earleme . q{-}
1377             . $middle_earleme;
1378             } ## end if ( defined $predecessor_ahm )
1379              
1380 67         127 push @pieces, 's=' . $token_name;
1381              
1382 67 50       152 if ( not defined $value ) {
1383              
1384             # Value is literal
1385 67         107 my $token_length = $current_earleme - $middle_earleme;
1386 67         174 $value = $slr->g1_literal( $middle_earleme, $token_length );
1387             }
1388 67         361 my $token_dump =
1389             Data::Dumper->new( [ \$value ] )->Terse(1)->Dump;
1390 67         3396 chomp $token_dump;
1391 67         170 push @pieces, "t=$token_dump";
1392 67         183 my $token_link_desc = '[' . ( join '; ', @pieces ) . ']';
1393 67         276 push @sort_data,
1394             [
1395             $middle_set_id, $token_id,
1396             $predecessor_ahm, $token_link_desc
1397             ];
1398             }
1399 67         283 push @sorted_data, map { qq{ } . $_->[-1] } sort {
1400 452 0 0     1115 $a->[0] <=> $b->[0]
  0         0  
1401             || $a->[1] <=> $b->[1]
1402             || $a->[2] <=> $b->[2]
1403             } @sort_data;
1404             }
1405              
1406             # Completion links
1407             {
1408 452         622 my @sort_data = ();
  452         637  
1409 452         570 my @lines = ();
1410 452         681 my $completion_links = $item_data{completion_links};
1411 452         563 my %completion_links = @{$completion_links};
  452         835  
1412             TOKEN_LINK:
1413 452         682 for ( my $completion_link_ix = 0 ; ; $completion_link_ix++ ) {
1414             my $completion_link_data =
1415 689         1071 $completion_links{ $completion_link_ix + 1 };
1416 689 100       1353 last TOKEN_LINK if not $completion_link_data;
1417 237         303 my %completion_link_data = @{$completion_link_data};
  237         688  
1418              
1419             my $predecessor_ahm_id =
1420 237         376 $completion_link_data{predecessor_state};
1421 237         319 my $ahm_id = $completion_link_data{ahm_id};
1422 237         343 my $origin_earleme = $completion_link_data{origin_earleme};
1423 237         305 my $middle_earleme = $completion_link_data{middle_earleme};
1424 237         584 my $ahm_desc = $slg->briefer_ahm($ahm_id);
1425              
1426 237         385 my @pieces = ();
1427 237 50       500 if ( defined $predecessor_ahm_id ) {
1428 237         516 my $predecessor_ahm_desc =
1429             $slg->briefer_ahm($predecessor_ahm_id);
1430 237         647 push @pieces,
1431             'p='
1432             . $predecessor_ahm_desc . '@'
1433             . $origin_earleme . q{-}
1434             . $middle_earleme;
1435             }
1436              
1437 237         469 push @pieces,
1438             'c='
1439             . $ahm_desc . q{@}
1440             . $middle_earleme . q{-}
1441             . $current_earleme;
1442 237         547 my $link_desc = '[' . ( join '; ', @pieces ) . ']';
1443              
1444 237   50     982 push @sort_data,
1445             [
1446             $middle_earleme, $ahm_id,
1447             ( $predecessor_ahm_id // -1 ), $link_desc
1448             ];
1449             }
1450 237         917 push @sorted_data, map { q{ } . $_->[-1] } sort {
1451 452 50 66     862 $a->[0] <=> $b->[0]
  27         172  
1452             || $a->[1] <=> $b->[1]
1453             || $a->[2] <=> $b->[2]
1454             } @sort_data;
1455             }
1456              
1457             # Leo links
1458             {
1459 452         631 my @sort_data = ();
  452         627  
  452         599  
1460 452         580 my @lines = ();
1461 452         642 my $leo_links = $item_data{leo_links};
1462 452         549 my %leo_links = @{$leo_links};
  452         734  
1463             LEO_LINK:
1464 452         635 for ( my $leo_link_ix = 0 ; ; $leo_link_ix++ ) {
1465 460         699 my $leo_link_data = $leo_links{ $leo_link_ix + 1 };
1466 460 100       896 last LEO_LINK if not $leo_link_data;
1467 8         28 my %leo_link_data = @{$leo_link_data};
  8         23  
1468              
1469 8         12 my $middle_earleme = $leo_link_data{middle_earleme};
1470 8         16 my $middle_set_id = $leo_link_data{middle_set_id};
1471             my $leo_transition_symbol =
1472 8         9 $leo_link_data{leo_transition_symbol};
1473 8         13 my $ahm_id = $leo_link_data{ahm_id};
1474 8         31 my $ahm_desc = $slg->briefer_ahm($ahm_id);
1475              
1476 8         13 my @pieces = ();
1477 8         22 push @pieces,
1478             'l=L' . $leo_transition_symbol . q{@} . $middle_earleme;
1479 8         21 push @pieces,
1480             'c='
1481             . $ahm_desc . q{@}
1482             . $middle_earleme . q{-}
1483             . $current_earleme;
1484 8         19 my $link_desc = '[' . ( join '; ', @pieces ) . ']';
1485              
1486 8         29 push @sort_data,
1487             [
1488             $middle_set_id, $ahm_id,
1489             $leo_transition_symbol, $link_desc,
1490             ];
1491             }
1492 8         44 push @sorted_data, map { q{ } . $_->[-1] } sort {
1493 452 0 0     1371 $a->[0] <=> $b->[0]
  0         0  
1494             || $a->[1] <=> $b->[1]
1495             || $a->[2] <=> $b->[2]
1496             } @sort_data;
1497             }
1498             }
1499              
1500             # Leo items
1501             {
1502 59         79 my $leo_data = $set_data{leo};
  59         100  
1503 59         81 my %leo_data = @{$leo_data};
  59         108  
1504 59         102 my @sort_data = ();
1505 59         94 LEO_ITEM: for ( my $leo_item_id = 0 ; ; $leo_item_id++ ) {
1506              
1507 67         119 my $leo_item_data = $leo_data{ $leo_item_id + 1 };
1508 67 100       182 last LEO_ITEM if not defined $leo_item_data;
1509              
1510 8         10 my %leo_item_data = @{$leo_item_data};
  8         31  
1511 8         14 my $postdot_symbol_id = $leo_item_data{postdot_symbol_id};
1512 8         11 my $postdot_symbol_name = $leo_item_data{postdot_symbol_name};
1513 8         15 my $predecessor_symbol_id = $leo_item_data{predecessor_symbol_id};
1514 8         11 my $base_origin_earleme = $leo_item_data{base_origin_earleme};
1515 8         10 my $leo_base_state = $leo_item_data{leo_base_state};
1516 8         16 my $trace_earleme = $leo_item_data{trace_earleme};
1517              
1518             # L2@8 ["Expression"; L2@6; S16@6-8]
1519 8         19 my @link_texts = ( q{"} . $postdot_symbol_name . q{"} );
1520 8 100       20 if ( defined $predecessor_symbol_id ) {
1521 6         20 push @link_texts,
1522             sprintf( 'L%d@%d',
1523             $predecessor_symbol_id, $base_origin_earleme );
1524             }
1525 8         23 push @link_texts,
1526             sprintf( 'S%d@%d-%d',
1527             $leo_base_state, $base_origin_earleme, $trace_earleme );
1528 8         24 my $leo_line = sprintf( 'L%d@%d [%s]',
1529             $postdot_symbol_id, $trace_earleme,
1530             ( join q{; }, @link_texts ) );
1531 8         21 push @sort_data, [ $postdot_symbol_id, $leo_line ];
1532             push @sorted_data,
1533             (
1534             join q{},
1535 8         19 map { $_->[-1] } sort { $a->[0] <=> $b->[0] } @sort_data
  8         36  
  0         0  
1536             );
1537             }
1538             }
1539              
1540 59         1264 return join "\n", @sorted_data, q{};
1541             }
1542              
1543             # not to be documented
1544             sub Marpa::R3::Recognizer::regix {
1545 1     1   7121 my ( $slr ) = @_;
1546 1         3 my $regix = $slr->[Marpa::R3::Internal_R::REGIX];
1547 1         3 return $regix;
1548             }
1549              
1550             # Dump semantics for diagnostics
1551             sub Marpa::R3::Recognizer::show_semantics {
1552 0     0   0 my ( $slg, @ops ) = @_;
1553 0         0 my @op_descs = ();
1554 0         0 my $op_ix = 0;
1555 0         0 OP: while ( $op_ix < scalar @ops ) {
1556 0         0 my $op = $ops[ $op_ix++ ];
1557              
1558 0         0 my $op_name = $slg->call_by_tag( ( '@' . __FILE__ . ':' . __LINE__ ),
1559             <<'END_OF_LUA', 'i', $op );
1560             local grammar, op = ...
1561             return _M.op_names[op]
1562             END_OF_LUA
1563              
1564 0         0 push @op_descs, $op_name;
1565 0 0       0 if ( $op_name eq 'lua' ) {
1566              
1567 0         0 my ($lua_op_name) = op_fn_name_by_key( $slg, $ops[$op_ix] );
1568 0         0 push @op_descs, $lua_op_name;
1569 0         0 $op_ix++;
1570 0 0       0 if ( $lua_op_name eq 'callback' ) {
1571 0         0 push @op_descs, op_fn_name_by_key( $slg, $ops[$op_ix] );
1572             }
1573             else {
1574 0         0 push @op_descs, $ops[$op_ix];
1575             }
1576 0         0 $op_ix++;
1577 0         0 next OP;
1578             }
1579 0 0       0 if ( $op_name eq 'alternative' ) {
1580 0         0 push @op_descs, $ops[$op_ix];
1581 0         0 $op_ix++;
1582 0         0 push @op_descs, $ops[$op_ix];
1583 0         0 $op_ix++;
1584 0         0 next OP;
1585             } ## end if ( $op_name eq 'alternative' )
1586             } ## end OP: while ( $op_ix < scalar @ops )
1587 0         0 return join q{ }, @op_descs;
1588             } ## end sub show_semantics
1589              
1590             # For diagnostics
1591             sub g1_show_rule_list {
1592 0     0   0 my ( $slg, $rule_ids ) = @_;
1593 0         0 my @rules = map { $slg->g1_rule_show($_) } @{$rule_ids};
  0         0  
  0         0  
1594 0         0 return join q{}, map { q{ } . $_ . "\n" } @rules;
  0         0  
1595             }
1596              
1597             sub Marpa::R3::Recognizer::value {
1598 738     738   240559 my ( $slr, $per_parse_arg ) = @_;
1599 738         3624 my $slv = Marpa::R3::Valuer->new( { recognizer => $slr } );
1600 738         2706 my $ambiguity_level = $slv->ambiguity_level();
1601 738 100       2197 return if $ambiguity_level == 0;
1602 718 50       1695 if ( $ambiguity_level != 1 ) {
1603 0         0 my $ambiguous_status = $slv->ambiguous();
1604 0         0 Marpa::R3::exception( "Parse of the input is ambiguous\n",
1605             $ambiguous_status );
1606             }
1607 718         1954 my $value_ref = $slv->value($per_parse_arg);
1608 708 50       1993 Marpa::R3::exception("$slr->value(): No parse\n")
1609             if not $value_ref;
1610 708         2791 return $value_ref;
1611             }
1612              
1613             # INTERNAL OK AFTER HERE _marpa_
1614              
1615             1;
1616              
1617             # vim: expandtab shiftwidth=4: