Marpa::R2::Tutorial2 - Marpa Tutorial 2
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; }
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:
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.
Marpa::R2::Scanless::R::new
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.
semantics_package
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.
Marpa::R2::Scanless::R::read()
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.
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.
ambigous()
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.
Marpa::R2::Scanless::R::value()
undef
The value of the parse is exactly the same, and computed in exactly the same way, as in the previous tutorial.
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/.
To install Marpa::R2, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Marpa::R2
CPAN shell
perl -MCPAN -e shell install Marpa::R2
For more information on module installation, please visit the detailed CPAN module installation guide.