Provided by: libmarpa-r2-perl_12.000000-1_amd64 bug

NAME

       Marpa::R2::Tutorial2 - Marpa Tutorial 2

Synopsis

           use Marpa::R2;

           my $dsl = <<'END_OF_DSL';
           :default ::= action => [name,values]
           lexeme default = latm => 1
           Calculator ::= Expression action => ::first

           Factor ::= Number action => ::first
           Term ::=
               Term '*' Factor action => do_multiply
               | Factor action => ::first
           Expression ::=
               Expression '+' Term action => do_add
               | Term action => ::first
           Number ~ digits
           digits ~ [\d]+
           :discard ~ whitespace
           whitespace ~ [\s]+
           END_OF_DSL

           my $grammar = Marpa::R2::Scanless::G->new( { source => \$dsl } );
           my $recce = Marpa::R2::Scanless::R->new(
               { grammar => $grammar, semantics_package => 'My_Actions' } );
           my $input = '42 * 1 + 7';
           my $length_read = $recce->read( \$input );

           die "Read ended after $length_read of ", length $input, " characters"
               if $length_read != length $input;

           if ( my $ambiguous_status = $recce->ambiguous() ) {
               chomp $ambiguous_status;
               die "Parse is ambiguous\n", $ambiguous_status;
           }

           my $value_ref = $recce->value;
           my $value = ${$value_ref};

           sub My_Actions::do_add {
               my ( undef, $t1, undef, $t2 ) = @_;
               return $t1 + $t2;
           }

           sub My_Actions::do_multiply {
               my ( undef, $t1, undef, $t2 ) = @_;
               return $t1 * $t2;
           }

Description

   Overview
       This document contains a second tutorial of the Scanless interface (SLIF), which demonstrates a lower
       level of method calls.  These lower level calls allow access to more of Marpa's features.  For example,
       users will need to use the lower level calls

       •   to use SLIF parse events;

       •   to examine the values of multiple  parses of an ambiguous parse;

       •   and to get finer control of the response to Marpa errors.

       This  uses the same extremely simple calculator as the tutorial in the landing page.  Most of the code is
       exactly the same in fact, and we will skip it.  Here is what is new:

   Marpa::R2::Scanless::R::new
           my $recce = Marpa::R2::Scanless::R->new(
               { grammar => $grammar, semantics_package => 'My_Actions' } );

       "Marpa::R2::Scanless::R::new" creates a new SLIF recognizer.  Its arguments are references to  hashes  of
       named  arguments.   In  this example the first named argument is the required argument: ""grammar"".  The
       value of the "grammar" named argument must be a Marpa::R2 SLIF grammar.

       The second argument is optional, but  you  will  use  it  frequently.   The  ""semantics_package""  named
       argument  tells  Marpa in which Perl package to look for the closures implementing the semantics for this
       grammar.

   Marpa::R2::Scanless::R::read
           my $input = '42 * 1 + 7';
           my $length_read = $recce->read( \$input );

       To parse a string, we use the Marpa::R2::Scanless::R::read() method.  In its simplest form, as here,  the
       Marpa::R2::Scanless::R::read()  method  takes  a reference to a string containing the input stream as its
       argument.

   Checking for a premature end
           die "Read ended after $length_read of ", length $input, " characters"
               if $length_read != length $input;

       Most premature endings occur when a parse is exhausted.  A parse is "exhausted" when there is no possible
       way for it to continue on to success.   Premature  parse  exhaustion  is  thrown  as  a  failure  by  the
       Marpa::R2::Scanless::R::read() method, and it is not necessary to check for it explicitly.

       There  are other premature endings that are not necessarily failures, and which therefore are not thrown.
       These are Marpa's SLIF parse events.  SLIF parse events  are  an  advanced  feature,  and  are  described
       elsewhere.   In this example, any premature ending caused by the triggering of a SLIF parse event will be
       caused by stray parse events -- unexpected parse events due to a mistake in writing the DSL.

       Programming a stray parse event is a programming mistake that you are not likely  to  make,  so  arguably
       this check is not really necessary.  There are no SLIF parse events, stray or otherwise, in this example.
       But this check is included for completeness, and as an example of a cautious programming style.

   Checking for an ambiguous parse
           if ( my $ambiguous_status = $recce->ambiguous() ) {
               chomp $ambiguous_status;
               die "Parse is ambiguous\n", $ambiguous_status;
           }

       Much  more  likely  than  stray  SLIF  parse events are ambiguous parses -- parses where the input can be
       parsed in two or more ways.  Ambiguous parses are not necessarily a problem -- some applications may  not
       care about them.  Other applications, as an advanced technique, actually exploit ambiguity,

       Beginners  should  regard  an  ambiguous  parse  as a sign of trouble.  The existence of ambiguous parses
       should be tolerated only if you understand the kind of ambiguity that exists in your grammar, and only if
       you know that ambiguities of that kind will not cause trouble.  The  above  code  uses  the  recognizer's
       ambigous()  method to spot ambiguous parses.  The ambigous() method returns the empty string if there was
       exactly one parse.  If there was no parse, the ambigous() method returns a string stating that.  If there
       were two or more parses, the ambigous() method returns a string describing the ambiguity.

   Marpa::R2::Scanless::R::value
           my $value_ref = $recce->value;
           my $value = ${$value_ref};

       The Marpa::R2::Scanless::R::value() method returns a reference to the parse result's value, if there  was
       a  parse  result.   If  there was no parse result, Marpa::R2::Scanless::R::value() returns "undef".  This
       code does not check for the case where there is no parse result, because we already performed that  check
       along with the check for ambiguity.

       The  value  of  the  parse  is exactly the same, and computed in exactly the same way, as in the previous
       tutorial.

Copyright and License

         Copyright 2022 Jeffrey Kegler
         This file is part of Marpa::R2.  Marpa::R2 is free software: you can
         redistribute it and/or modify it under the terms of the GNU Lesser
         General Public License as published by the Free Software Foundation,
         either version 3 of the License, or (at your option) any later version.

         Marpa::R2 is distributed in the hope that it will be useful,
         but WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         Lesser General Public License for more details.

         You should have received a copy of the GNU Lesser
         General Public License along with Marpa::R2.  If not, see
         http://www.gnu.org/licenses/.

perl v5.40.1                                       2025-06-25                          Marpa::R2::Tutorial2(3pm)