summaryrefslogtreecommitdiffstats
path: root/Aufgabe6/RPN/lib
diff options
context:
space:
mode:
Diffstat (limited to 'Aufgabe6/RPN/lib')
-rw-r--r--Aufgabe6/RPN/lib/RPN.pm364
1 files changed, 361 insertions, 3 deletions
diff --git a/Aufgabe6/RPN/lib/RPN.pm b/Aufgabe6/RPN/lib/RPN.pm
index 92f6f50..693ca51 100644
--- a/Aufgabe6/RPN/lib/RPN.pm
+++ b/Aufgabe6/RPN/lib/RPN.pm
@@ -2,6 +2,7 @@ package RPN;
use strict;
use warnings;
+use Math::Trig;
require Exporter;
@@ -25,10 +26,367 @@ our $VERSION = '1.0';
# Preloaded methods go here.
+my %operations = (
+ "POP" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ pop @$stackRef;
+ }
+ ),
+ "DUP" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, @$stackRef[-1]);
+ }
+ ),
+ "PI" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 0)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, 4.0*atan2(1.0,1.0));
+ }
+ ),
+ "++" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ @$stackRef[-1]++;
+ }
+ ),
+ "--" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ @$stackRef[-1]--;
+ }
+ ),
+ "ABS" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, abs pop (@$stackRef));
+ }
+ ),
+ "COS" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, cos pop (@$stackRef));
+ }
+ ),
+ "EXP" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, exp pop (@$stackRef));
+ }
+ ),
+ "INT" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, int pop (@$stackRef));
+ }
+ ),
+ "LOG" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, log pop (@$stackRef));
+ }
+ ),
+ "ROUND" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, sprintf ("%.0f", pop (@$stackRef)));
+ }
+ ),
+ "SIN" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, sin pop (@$stackRef));
+ }
+ ),
+ "SQRT" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, sqrt pop (@$stackRef));
+ }
+ ),
+ "TAN" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 1)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, tan pop (@$stackRef));
+ }
+ ),
+ "%" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ my $var2 = pop (@$stackRef);
+ my $var1 = pop (@$stackRef);
+
+ push (@$stackRef, $var1 % $var2);
+ }
+ ),
+ "*" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ my $var2 = pop (@$stackRef);
+ my $var1 = pop (@$stackRef);
+
+ push (@$stackRef, $var1 * $var2);
+ }
+ ),
+ "+" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ my $var2 = pop (@$stackRef);
+ my $var1 = pop (@$stackRef);
+
+ push (@$stackRef, $var1 + $var2);
+ }
+ ),
+ "-" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ my $var2 = pop (@$stackRef);
+ my $var1 = pop (@$stackRef);
+
+ push (@$stackRef, $var1 - $var2);
+ }
+ ),
+ "/" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ my $var2 = pop (@$stackRef);
+ my $var1 = pop (@$stackRef);
+
+ push (@$stackRef, $var1 / $var2);
+ }
+ ),
+ "ATAN2" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ my $var2 = pop (@$stackRef);
+ my $var1 = pop (@$stackRef);
+
+ push (@$stackRef, atan2 $var1, $var2);
+ }
+ ),
+ "EXCH" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ push (@$stackRef, (pop (@$stackRef), pop (@$stackRef)));
+ }
+ ),
+ "MAX" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ my $var2 = pop (@$stackRef);
+ my $var1 = pop (@$stackRef);
+
+ push (@$stackRef, $var1 > $var2 ? $var1 : $var2);
+ }
+ ),
+ "MIN" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ my $var2 = pop (@$stackRef);
+ my $var1 = pop (@$stackRef);
+
+ push (@$stackRef, $var1 < $var2 ? $var1 : $var2);
+ }
+ ),
+ "POW" => (
+ sub {
+ my ($stackRef) = @_;
+
+ if (scalar @{$stackRef} < 2)
+ {
+ return undef;
+ }
+
+ my $var2 = pop (@$stackRef);
+ my $var1 = pop (@$stackRef);
+
+ push (@$stackRef, $var1 ** $var2);
+ }
+ )
+);
+
sub rpn {
- my ( $par1 ) = @_;
- print "Modul RPN Funktion 'rpn'\n";
- return $par1;
+ my ( $RpnString ) = @_;
+
+ # Check if RPN String is supplied.
+ if(!defined $RpnString)
+ {
+ printf STDERR "RpnString needs to be supplied.\n";
+ return undef;
+ }
+
+ # RPN value stack
+ my @stack;
+
+ for my $operand (split /\s+/, $RpnString)
+ {
+ if (defined $operations{$operand})
+ {
+ if(!defined($operations{$operand}->(\@stack)))
+ {
+ return undef;
+ }
+ }
+ else
+ {
+ if ($operand =~ /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/)
+ {
+ push (@stack, $operand);
+ }
+ else
+ {
+ print STDERR "RpnString contains a value that is not numeric or an operand.\n";
+ return undef;
+ }
+ }
+ }
+
+ if (scalar @stack != 1)
+ {
+ print STDERR "After calculation there is not one value on stack.\n";
+ return undef;
+ }
+
+ return $stack[0];
}
1;