#!/usr/bin/perl
# Copyright 2014 Jeffrey Kegler
# This file is part of Marpa::R3. Marpa::R3 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::R3 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::R3. If not, see
# http://www.gnu.org/licenses/.
use 5.010;
use strict;
use warnings;
use Fatal qw(open close);
use Test::More tests => 8;
use lib 'inc';
use Marpa::R3::Test;
use Marpa::R3;
my $grammar = Marpa::R3::Grammar->new(
{ start => 'Expression',
actions => 'My_Actions',
default_action => 'first_arg',
rules => [
{ lhs => 'Expression', rhs => [qw/Term/] },
{ lhs => 'Term', rhs => [qw/Factor/] },
{ lhs => 'Factor', rhs => [qw/Number/] },
{ lhs => 'Term', rhs => [qw/Term Add Term/], action => 'do_add' },
{ lhs => 'Factor',
rhs => [qw/Factor Multiply Factor/],
action => 'do_multiply'
},
],
}
);
$grammar->precompute();
my $recce = Marpa::R3::Recognizer->new( { grammar => $grammar } );
my @tokens = (
[ 'Number', 42 ],
[ 'Multiply', q{*} ],
[ 'Number', 1 ],
[ 'Add', q{+} ],
[ 'Number', 7 ],
);
for my $token_and_value (@tokens) {
$recce->read( @{$token_and_value} );
}
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;
}
sub My_Actions::first_arg { shift; return shift; }
my $value_ref = $recce->value();
my $value = $value_ref ? ${$value_ref} : 'No Parse';
Marpa::R3::Test::is( 49, $value, 'Implementation Example Value 1' );
$recce->reset_evaluation();
my $show_symbols_output = $grammar->show_symbols();
Marpa::R3::Test::is( $show_symbols_output,
<<'END_SYMBOLS', 'Implementation Example Symbols' );
0: Expression
1: Term
2: Factor
3: Number, terminal
4: Add, terminal
5: Multiply, terminal
END_SYMBOLS
my $show_rules_output = $grammar->show_rules();
Marpa::R3::Test::is( $show_rules_output,
<<'END_RULES', 'Implementation Example Rules' );
0: Expression -> Term
1: Term -> Factor
2: Factor -> Number
3: Term -> Term Add Term
4: Factor -> Factor Multiply Factor
END_RULES
my $show_ahms_output = $grammar->show_ahms();
Marpa::R3::Test::is( $show_ahms_output,
<<'END_AHM', 'Implementation Example AHMs' );
AHM 0: postdot = "Term"
Expression ::= . Term
AHM 1: completion
Expression ::= Term .
AHM 2: postdot = "Factor"
Term ::= . Factor
AHM 3: completion
Term ::= Factor .
AHM 4: postdot = "Number"
Factor ::= . Number
AHM 5: completion
Factor ::= Number .
AHM 6: postdot = "Term"
Term ::= . Term Add Term
AHM 7: postdot = "Add"
Term ::= Term . Add Term
AHM 8: postdot = "Term"
Term ::= Term Add . Term
AHM 9: completion
Term ::= Term Add Term .
AHM 10: postdot = "Factor"
Factor ::= . Factor Multiply Factor
AHM 11: postdot = "Multiply"
Factor ::= Factor . Multiply Factor
AHM 12: postdot = "Factor"
Factor ::= Factor Multiply . Factor
AHM 13: completion
Factor ::= Factor Multiply Factor .
AHM 14: postdot = "Expression"
Expression['] ::= . Expression
AHM 15: completion
Expression['] ::= Expression .
END_AHM
my $show_earley_sets_output = $recce->show_earley_sets();
my $expected_earley_sets = <<'END_EARLEY_SETS';
Last Completed: 5; Furthest: 5
Earley Set 0
ahm14: R5:0@0-0
R5:0: Expression['] ::= . Expression
ahm0: R0:0@0-0
R0:0: Expression ::= . Term
ahm2: R1:0@0-0
R1:0: Term ::= . Factor
ahm6: R3:0@0-0
R3:0: Term ::= . Term Add Term
ahm4: R2:0@0-0
R2:0: Factor ::= . Number
ahm10: R4:0@0-0
R4:0: Factor ::= . Factor Multiply Factor
Earley Set 1
ahm5: R2$@0-1
R2$: Factor ::= Number .
[c=R2:0@0-0; s=Number; t=\42]
ahm11: R4:1@0-1
R4:1: Factor ::= Factor . Multiply Factor
[p=R4:0@0-0; c=R2$@0-1]
ahm3: R1$@0-1
R1$: Term ::= Factor .
[p=R1:0@0-0; c=R2$@0-1]
ahm7: R3:1@0-1
R3:1: Term ::= Term . Add Term
[p=R3:0@0-0; c=R1$@0-1]
ahm1: R0$@0-1
R0$: Expression ::= Term .
[p=R0:0@0-0; c=R1$@0-1]
ahm15: R5$@0-1
R5$: Expression['] ::= Expression .
[p=R5:0@0-0; c=R0$@0-1]
Earley Set 2
ahm12: R4:2@0-2
R4:2: Factor ::= Factor Multiply . Factor
[c=R4:1@0-1; s=Multiply; t=\'*']
ahm4: R2:0@2-2
R2:0: Factor ::= . Number
ahm10: R4:0@2-2
R4:0: Factor ::= . Factor Multiply Factor
Earley Set 3
ahm5: R2$@2-3
R2$: Factor ::= Number .
[c=R2:0@2-2; s=Number; t=\1]
ahm11: R4:1@2-3
R4:1: Factor ::= Factor . Multiply Factor
[p=R4:0@2-2; c=R2$@2-3]
ahm13: R4$@0-3
R4$: Factor ::= Factor Multiply Factor .
[p=R4:2@0-2; c=R2$@2-3]
ahm11: R4:1@0-3
R4:1: Factor ::= Factor . Multiply Factor
[p=R4:0@0-0; c=R4$@0-3]
ahm3: R1$@0-3
R1$: Term ::= Factor .
[p=R1:0@0-0; c=R4$@0-3]
ahm7: R3:1@0-3
R3:1: Term ::= Term . Add Term
[p=R3:0@0-0; c=R1$@0-3]
ahm1: R0$@0-3
R0$: Expression ::= Term .
[p=R0:0@0-0; c=R1$@0-3]
ahm15: R5$@0-3
R5$: Expression['] ::= Expression .
[p=R5:0@0-0; c=R0$@0-3]
Earley Set 4
ahm8: R3:2@0-4
R3:2: Term ::= Term Add . Term
[c=R3:1@0-3; s=Add; t=\'+']
ahm2: R1:0@4-4
R1:0: Term ::= . Factor
ahm4: R2:0@4-4
R2:0: Factor ::= . Number
ahm6: R3:0@4-4
R3:0: Term ::= . Term Add Term
ahm10: R4:0@4-4
R4:0: Factor ::= . Factor Multiply Factor
Earley Set 5
ahm5: R2$@4-5
R2$: Factor ::= Number .
[c=R2:0@4-4; s=Number; t=\7]
ahm11: R4:1@4-5
R4:1: Factor ::= Factor . Multiply Factor
[p=R4:0@4-4; c=R2$@4-5]
ahm3: R1$@4-5
R1$: Term ::= Factor .
[p=R1:0@4-4; c=R2$@4-5]
ahm7: R3:1@4-5
R3:1: Term ::= Term . Add Term
[p=R3:0@4-4; c=R1$@4-5]
ahm9: R3$@0-5
R3$: Term ::= Term Add Term .
[p=R3:2@0-4; c=R1$@4-5]
ahm7: R3:1@0-5
R3:1: Term ::= Term . Add Term
[p=R3:0@0-0; c=R3$@0-5]
ahm1: R0$@0-5
R0$: Expression ::= Term .
[p=R0:0@0-0; c=R3$@0-5]
ahm15: R5$@0-5
R5$: Expression['] ::= Expression .
[p=R5:0@0-0; c=R0$@0-5]
END_EARLEY_SETS
Marpa::R3::Test::is( $show_earley_sets_output, $expected_earley_sets,
'Implementation Example Earley Sets' );
my $trace_output;
open my $trace_fh, q{>}, \$trace_output;
$recce->set( { trace_fh => $trace_fh, trace_values => 2 } );
$value_ref = $recce->value();
$recce->set( { trace_fh => \*STDOUT, trace_values => 0 } );
close $trace_fh;
$value = $value_ref ? ${$value_ref} : 'No Parse';
Marpa::R3::Test::is( 49, $value, 'Implementation Example Value 2' );
my $expected_trace_output = <<'END_TRACE_OUTPUT';
Setting trace_values option
Pushed value from R2:1@0-1S3@0: Number = \42
Popping 1 values to evaluate R2:1@0-1S3@0, rule: 2: Factor -> Number
Calculated and pushed value: 42
Pushed value from R4:2@0-2S5@1: Multiply = \'*'
Pushed value from R2:1@2-3S3@2: Number = \1
Popping 1 values to evaluate R2:1@2-3S3@2, rule: 2: Factor -> Number
Calculated and pushed value: 1
Popping 3 values to evaluate R4:3@0-3C2@2, rule: 4: Factor -> Factor Multiply Factor
Calculated and pushed value: 42
Popping 1 values to evaluate R1:1@0-3C4@0, rule: 1: Term -> Factor
Calculated and pushed value: 42
Pushed value from R3:2@0-4S4@3: Add = \'+'
Pushed value from R2:1@4-5S3@4: Number = \7
Popping 1 values to evaluate R2:1@4-5S3@4, rule: 2: Factor -> Number
Calculated and pushed value: 7
Popping 1 values to evaluate R1:1@4-5C2@4, rule: 1: Term -> Factor
Calculated and pushed value: 7
Popping 3 values to evaluate R3:3@0-5C1@4, rule: 3: Term -> Term Add Term
Calculated and pushed value: 49
Popping 1 values to evaluate R0:1@0-5C3@0, rule: 0: Expression -> Term
Calculated and pushed value: 49
New Virtual Rule: R5:1@0-5C0@0, rule: 5: Expression['] -> Expression
Real symbol count is 1
END_TRACE_OUTPUT
Marpa::R3::Test::is( $trace_output, $expected_trace_output,
'Implementation Example Trace Output' );
$recce->reset_evaluation();
$value_ref = $recce->value();
$value = $value_ref ? ${$value_ref} : 'No Parse';
Marpa::R3::Test::is( 49, $value, 'Implementation Example Value 3' );
1; # In case used as "do" file
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4: