#!perl
# Marpa::R3 is Copyright (C) 2017, Jeffrey Kegler.
#
# This module is free software; you can redistribute it and/or modify it
# under the same terms as Perl 5.10.1. For more details, see the full text
# of the licenses in the directory LICENSES.
#
# This program is distributed in the hope that it will be
# useful, but it is provided "as is" and without any express
# or implied warranties. For details, see the full text of
# of the licenses in the directory LICENSES.
use 5.010001;
use strict;
# The Wall Series: a sequence of numbers generated by an especially
# ambiguous section of Perl syntax, relaxed to ignore precedence
# and lvalue restricitons.
# This produces numbers in the series A052952 in the literature.
# It's a kind of ragtime Fibonacci series. My proof that the
# parse counts generated by this grammar and A052952 are identical
use POSIX qw(setlocale LC_ALL);
POSIX::setlocale(LC_ALL, "C");
use Test::More tests => 12;
use lib 'inc';
# The inefficiency (at least some of it) is deliberate.
# Passing up a duples of [ string, value ] and then
# assembling a final string at the top would be better
# than assembling the string then taking it
# apart at each step. But I wanted to test having
# a start symbol that appears repeatedly on the RHS.
## no critic (Subroutines::RequireArgUnpacking)
sub My_Actions::minus {
my (undef, $values) = @_;
my ( $right_string, $right_value ) = ( $values->[2] =~ /^(.*)==(.*)$/xms );
my ( $left_string, $left_value ) = ( $values->[0] =~ /^(.*)==(.*)$/xms );
my $value = $left_value - $right_value;
return '(' . $left_string . q{-} . $right_string . ')==' . $value;
} ## end sub minus
sub My_Actions::postfix_decr {
my (undef, $values) = @_;
my ( $string, $value ) = ( $values->[0] =~ /^(.*)==(.*)$/xms );
return '(' . $string . q{--} . ')==' . $value--;
}
sub My_Actions::prefix_decr {
my (undef, $values) = @_;
my ( $string, $value ) = ( $values->[2] =~ /^(.*)==(.*)$/xms );
return '(' . q{--} . $string . ')==' . --$value;
}
sub My_Actions::negation {
my (undef, $values) = @_;
my ( $string, $value ) = ( $values->[1] =~ /^(.*)==(.*)$/xms );
return '(' . q{-} . $string . ')==' . -$value;
}
sub My_Actions::number {
my (undef, $values) = @_;
return $values->[0] . q{==} . $values->[0];
}
sub My_Actions::default_action {
my (undef, $values) = @_;
my $v_count = scalar @_;
return q{} if $v_count <= 0;
return $values->[0] if $v_count == 1;
return '(' . join( q{;}, @{$values} ) . ')';
} ## end sub default_action
## use critic
my $g = Marpa::R3::Scanless::G->new(
{
semantics_package => 'My_Actions',
source => \(<<'END_OF_SOURCE'),
:start ::= E
:default ::= action => default_action
E ::=
E Minus E action => minus
| E Minus Minus action => postfix_decr
| Minus Minus E action => prefix_decr
| Minus E action => negation
| Number action => number
Number ~ [0-9]
Minus ~ '-'
END_OF_SOURCE
}
);
my @expected = qw(0 1 1 3 4 8 12 21 33 55 88 144 232 );
for my $n ( 1 .. 12 ) {
# Set max_parses just in case there's an infinite loop.
# This is for debugging, after all
my $recce = Marpa::R3::Scanless::R->new(
{ grammar => $g,
max_parses => 300
}
);
$recce->read( \'6-', 0, 1 );
$recce->resume( 1, 1 ) for 1 .. $n;
$recce->resume( 0, 1 );
my $parse_count = 0;
while ( $recce->value() ) { $parse_count++; }
Marpa::R3::Test::is( $expected[$n], $parse_count,
"Wall Series Number $n" );
} ## end for my $n ( 1 .. 12 )
1; # In case used as "do" file
# vim: expandtab shiftwidth=4: