Acme-AlgebraicToRPN

 view release on metacpan or  search on metacpan

lib/Acme/AlgebraicToRPN.pm  view on Meta::CPAN

  userFunc - user functions, as array reference

If you had a user function box and fft, you'd need to
specify them like this:

  $al = Acme::AlgebraicToRPN->new(userFunc =>
    [qw(box fft)]);

=cut

sub new {
    my ($class, %opts) = @_;
    my $self = \%opts;
    bless $self, $class;
    $.stack = [];
    $.parser = Math::Symbolic::Parser->new;
    $.Class = $class;
    if (defined $.userFunc) {
        my @uf = @{$.userFunc};
        my %uf;
        map { $uf{$_} = 1 } @uf;
        $.userFunc = \%uf;
        my %x;
        map {
            my $proc = $_;
            $x{$_} = sub {
                my $argumentstring = shift;
                return Math::Symbolic::Constant->new(
                    qq($proc($argumentstring))
                );
            };
        } @uf;
        Math::SymbolicX::ParserExtensionFactory->add_private_functions(
            $.parser,
            %x
        );

lib/Acme/AlgebraicToRPN.pm  view on Meta::CPAN

      the next thing on the stack is the I<number> of arguments,
      and then the arguments themselves. For example, let's say
      you registered your function 'foo' (in constructor)
      and you gave B<rpn> this equation: 4*foo(a,3)

      You'd get back this:
      4 a 3 2 foo multiply

=cut

sub rpn {
    my ($self, $algebraic) = @_;
    $algebraic =~ s/\s+//g;
    # ensure parens match
    my $open  = $algebraic =~ tr/(/(/;
    my $close = $algebraic =~ tr/)/)/;
    return unless $open == $close;
    #my $tree = Math::Symbolic->parse_from_string($algebraic);
    my $tree;
    my $rpn;

lib/Acme/AlgebraicToRPN.pm  view on Meta::CPAN


=head2 B<rpn_as_string>

  $stack = $al->rpn($expr);

Same as B<rpn>, but returns as a comma-separated list. Split on
commas, and you have your stack to be processed.

=cut

sub rpn_as_string {
    my ($self, $algebraic) = @_;
    my @result = ./rpn($algebraic);
    return join(",", @result);
}

sub _Cleanup {
    my ($self) = @_;
    my @Stack;
    map {
        $_ =~ s/^,//;
        if ($_ ne '') {
            my (@c) = split(',', $_);
            if (@c) {
                s/\s//g foreach @c;
                push(@Stack, @c);
            }
            else {
                push(@Stack, $_);
            }
        }
    } @{$.stack};
    return @Stack;
}

sub _Eval {
    my ($self, $expr) = @_;
    return unless defined $expr;
    #print "Evaling $expr\n";
    if ($expr =~ /(.+?),(.+)/) {
        my $L = $1;
        my $R = $2;
        if ($L =~ /^\w+$/ && $R =~ /$RE{balanced}{-parens=>'()'}/) {
            #print "HERE $L\n";
            push(@{$.stack}, $L);
        }

lib/Acme/AlgebraicToRPN.pm  view on Meta::CPAN

  $ok = $al->check(\@stack, @expected);

Checks result of RPN conversion. @stack is what the B<rpn> function
returned, and @expected is what you expected the result to be. This
is kind of a diagnostic routine for testing.

Returns 1 if both @stack and @expected were the same, 0 if not.

=cut

sub check {
    my ($self, $ref, @result) = @_;
    my @shouldbe = @$ref;
    return 0 unless @shouldbe == @result;
    my $same = 1;
    map {
        my $sb = shift(@shouldbe);
        $same = 0 unless $sb eq $_;
    } @result;
    return $same;
}

t/01-test.t  view on Meta::CPAN

test('a^b', qw(a b exponentiate));
test('a^b3', qw(a b3 exponentiate));
test('a^-1', qw(a 1 negate exponentiate));
test('sin(pi/3)*2/log(2,1.3)', qw(pi 3 divide sin 2 multiply 2 1.3 log divide));
test('4*foo(a,3)', qw(4 a 3 2 foo multiply));
test('4*foo(a,3,55)', qw(4 a 3 55 3 foo multiply));
print STDERR "Shouldn't parse due to 'boo' function, which we don't know\n";
ok(!defined($rpn->rpn('4*boo(a,3,55)')));
#print $rpn->rpn_as_string($expr), "\n";

sub test {
    my ($expr, @desired) = @_;
    print STDERR "rpn = $expr... ";
    my @r = $rpn->rpn($expr);
    #print Dumper(\@r);
    my $same = $rpn->check(\@desired, @r);
    print STDERR "Different lengths\n" unless @r == @desired;
    print STDERR $same ? "Ok!\n" : "NOT Ok!\n";
    print STDERR "Got: ", Dumper(\@r) unless $same;
    print STDERR "Expected: ", Dumper(\@desired) unless $same;
    ok($same);



( run in 0.228 second using v1.01-cache-2.11-cpan-4d50c553e7e )