File: sl_wall.t

package info (click to toggle)
libmarpa-r2-perl 12.000000-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,660 kB
  • sloc: perl: 42,628; ansic: 23,387; sh: 4,363; makefile: 157
file content (125 lines) | stat: -rw-r--r-- 3,792 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!perl
# 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/.
#
use 5.010001;
use strict;
use warnings;

# 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
# is at perlmonks.org: http://perlmonks.org/?node_id=649892

use Test::More tests => 12;
use lib 'inc';
use Marpa::R2::Test;
use Marpa::R2;

# 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 {
    shift;
    my ( $right_string, $right_value ) = ( $_[2] =~ /^(.*)==(.*)$/xms );
    my ( $left_string,  $left_value )  = ( $_[0] =~ /^(.*)==(.*)$/xms );
    my $value = $left_value - $right_value;
    return '(' . $left_string . q{-} . $right_string . ')==' . $value;
} ## end sub minus

sub My_Actions::postfix_decr {
    shift;
    my ( $string, $value ) = ( $_[0] =~ /^(.*)==(.*)$/xms );
    return '(' . $string . q{--} . ')==' . $value--;
}

sub My_Actions::prefix_decr {
    shift;
    my ( $string, $value ) = ( $_[2] =~ /^(.*)==(.*)$/xms );
    return '(' . q{--} . $string . ')==' . --$value;
}

sub My_Actions::negation {
    shift;
    my ( $string, $value ) = ( $_[1] =~ /^(.*)==(.*)$/xms );
    return '(' . q{-} . $string . ')==' . -$value;
}

sub My_Actions::number {
    shift;
    return "$_[0]==$_[0]";
}

sub My_Actions::default_action {
    shift;
    my $v_count = scalar @_;
    return q{}   if $v_count <= 0;
    return $_[0] if $v_count == 1;
    return '(' . join( q{;}, @_ ) . ')';
} ## end sub default_action

## use critic

my $g = Marpa::R2::Scanless::G->new(
    {   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::R2::Scanless::R->new(
        {   grammar           => $g,
            semantics_package => 'My_Actions',
            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::R2::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: