##################################################################
# Modul fuer einen Funktionsparser
# Letzte Aenderung: 06.01.2012
##################################################################
use POSIX qw /floor ceil/;
use Math::Trig;
use strict;
use warnings;

use Data::Dumper;
my $hilfsstring = "";

sub tokenizer {
	my ($text) = @_;
	my ( $token, $vorzeichen );
	my @listevontokens;
	$vorzeichen = 1;
	$text =~ s/ //g;
	$text = lc($text);
	while ( $text ne "" ) {
		if (   ( $text =~ /^([-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?)/ )
			&& ( $vorzeichen == 1 ) )
		{

			# Zahlen mit Vorzeichen
			$token      = $1;
			$vorzeichen = 0;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "Term",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		elsif (( $text =~ /^([0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?)/ )
			&& ( $vorzeichen == 0 ) )
		{

			# Zahlen ohne Vorzeichen
			$token      = $1;
			$vorzeichen = 0;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "Term",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		elsif ( $text =~ /^([-])/ ) {

			# Operatoren
			$token      = $1;
			$vorzeichen = 1;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "minus",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		elsif ( $text =~ /^([+])/ ) {

			# Operatoren
			$token      = $1;
			$vorzeichen = 1;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "plus",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		elsif ( $text =~ /^([*])/ ) {

			# Operatoren
			$token      = $1;
			$vorzeichen = 1;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "mal",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		elsif ( $text =~ /^([:\/])/ ) {

			# Operatoren
			$token      = $1;
			$vorzeichen = 1;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "geteilt",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		elsif ( $text =~
/^(sin|cos|tan|acos|asin|log|ln|ceiling|floor|truncate|round|sqrt|abs|fact|exp)/
		  )
		{

			# Funktionen
			$token      = $1;
			$vorzeichen = 1;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "Funktion",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}

		elsif ( $text =~ /^(\()/ ) {

			# oeffnende Klammer
			$token      = $1;
			$vorzeichen = 1;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "(",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		elsif ( $text =~ /^(\))/ ) {

			# schliessende Klammer
			$token      = $1;
			$vorzeichen = 0;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => ")",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		elsif ( $text =~ /^(\^)/ ) {

			# Hochzeichen
			$token      = $1;
			$vorzeichen = 1;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "hoch",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		elsif ( $text =~ /^([a-z][0-9a-z]*)/ ) {

			# Variable
			$token      = $1;
			$vorzeichen = 0;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "Term",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}
		else {

			# Rest
			$token      = $text;
			$vorzeichen = 1;
			push @listevontokens,
			  {
				'Inhalt' => $token,
				'Typ'    => "Rest",
				'Baum'   => {
					'knoten' => $token,
					'links'  => undef,
					'rechts' => undef
				}
			  };
		}

		#print "Token " . $token . "\n";
		$text = substr $text, length $token;
	}
	return @listevontokens;
}

my $ausgabe = 0;

sub ausgabeliste {
	my @liste        = @_;
	my $listenlaenge = scalar @liste;
	my $i;
	if ( $ausgabe == 1 ) {
		printf("%%'");
		for ( $i = 0 ; $i < $listenlaenge ; $i++ ) {
			printf( "%s", $liste[$i]{'Inhalt'} );
			printf("  ") if ( $i < $listenlaenge - 1 );
		}
		print "'\n";
	}
}

sub regelwerk {
	my (@liste) = @_;
	my ( @klammerterm, $i, $j, $gefunden, $klammerauf, $klammerzu,
		$klammertiefe );

	do {
		$gefunden = 0;
		if ( !$gefunden ) {

			$klammerzu = $klammerauf = $klammertiefe = 0;

# Klammern:
# Wenn eine oeffnende Klammer gefunden wurde, dann wird der Zaehler klammertiefe erhoeht,
# bei einer schliessenden Klammer erniedrigt.
# Bei korrekter Klammerung ist der Zaehler am Ende 0
# und es wird die regelwerk-Funktion auf den Inhalt der Klammer angewendet.

			for ( $i = 0 ; $i < scalar @liste ; $i++ ) {

				if ( $liste[$i]{'Typ'} eq "(" ) {
					if ( ( $klammertiefe == 0 ) ) {
						$klammerauf = $i;
					}
					$klammertiefe++;
				}
				if ( $liste[$i]{'Typ'} eq ")" ) {
					$klammertiefe--;
					if ( $klammertiefe == 0 ) {
						$klammerzu = $i;
					}
				}

			}
			## Fehler wenn klammertiefe != 0 muss noch bearbeitet werden

			if ( $klammerauf != $klammerzu ) {

				@klammerterm = ();
				for ( $j = $klammerauf + 1 ; $j <= $klammerzu - 1 ; $j++ ) {
					push @klammerterm,
					  {
						'Inhalt' => $liste[$j]{'Inhalt'},
						'Typ'    => $liste[$j]{'Typ'},
						'Baum'   => {
							'knoten' => $liste[$j]{'Baum'}{'knoten'},
							'links'  => undef,
							'rechts' => undef
						}
					  };
				}

				splice( @liste, $klammerauf, $klammerzu - $klammerauf + 1,
					regelwerk(@klammerterm) );
				$gefunden = 1;

			}

		}
		if ( !$gefunden ) {

			# Potenzieren
			for ( $i = 0 ; $i < scalar @liste - 2 ; $i++ ) {

				if (   ( $liste[$i]{'Typ'} eq "Term" )
					&& ( $liste[ $i + 1 ]{'Typ'} eq "hoch" )
					&& ( $liste[ $i + 2 ]{'Typ'} eq "Term" )
					&& ( !$gefunden ) )
				{

					splice(
						@liste, $i, 3,
						{
							'Inhalt' => "("
							  . $liste[$i]{'Inhalt'}
							  . $liste[ $i + 1 ]{'Inhalt'}
							  . $liste[ $i + 2 ]{'Inhalt'} . ")",
							'Typ'  => "Term",
							'Baum' => {
								'knoten' => $liste[ $i + 1 ]{'Baum'}{'knoten'},
								'links'  => $liste[$i]{'Baum'},
								'rechts' => $liste[ $i + 2 ]{'Baum'}
							}
						}
					);
					$gefunden = 1;
				}
			}
		}
		if ( !$gefunden ) {

			# Multiplikation und Division
			for ( $i = 0 ; $i < scalar @liste - 2 ; $i++ ) {
				if (
					( $liste[$i]{'Typ'} eq "Term" )
					&& (   ( $liste[ $i + 1 ]{'Typ'} eq "mal" )
						|| ( $liste[ $i + 1 ]{'Typ'} eq "geteilt" ) )
					&& ( $liste[ $i + 2 ]{'Typ'} eq "Term" )
					&& ( !$gefunden )
				  )
				{
					splice(
						@liste, $i, 3,
						{
							'Inhalt' => "("
							  . $liste[$i]{'Inhalt'}
							  . $liste[ $i + 1 ]{'Inhalt'}
							  . $liste[ $i + 2 ]{'Inhalt'} . ")",
							'Typ'  => "Term",
							'Baum' => {
								'knoten' => $liste[ $i + 1 ]{'Baum'}{'knoten'},
								'links'  => $liste[$i]{'Baum'},
								'rechts' => $liste[ $i + 2 ]{'Baum'}
							}
						}
					);
					$gefunden = 1;
				}
			}
		}
		if ( !$gefunden ) {

			# Funktion
			for ( $i = 0 ; $i < scalar @liste - 1 ; $i++ ) {
				if (   ( $liste[$i]{'Typ'} eq "Funktion" )
					&& ( $liste[ $i + 1 ]{'Typ'} eq "Term" )
					&& ( !$gefunden ) )
				{
					if ( $liste[$i]{'Inhalt'} eq "exp" ) {
						splice(
							@liste, $i, 2,
							{
								'Inhalt' => "("
								  . exp(1) . "\^"
								  . $liste[ $i + 1 ]{'Inhalt'} . ")",
								'Typ'  => "Term",
								'Baum' => {
									'knoten' => "^",
									'links'  => {
										'knoten' => exp(1),
										'links'  => undef,
										'rechts' => undef
									},
									'rechts' => $liste[ $i + 1 ]{'Baum'}
								}
							}
						);
					}
					else {
						splice(
							@liste, $i, 2,
							{
								'Inhalt' => "("
								  . $liste[$i]{'Inhalt'}
								  . $liste[ $i + 1 ]{'Inhalt'} . ")",
								'Typ'  => "Term",
								'Baum' => {
									'knoten' => $liste[$i]{'Baum'}{'knoten'},
									'links'  => $liste[ $i + 1 ]{'Baum'},
									'rechts' => undef
								}
							}
						);
					}
					$gefunden = 1;
				}
			}
		}
		if ( !$gefunden ) {

			# Addition und Subtraktion
			for ( $i = 0 ; $i < scalar @liste - 2 ; $i++ ) {
				if (
					( $liste[$i]{'Typ'} eq "Term" )
					&& (   ( $liste[ $i + 1 ]{'Typ'} eq "plus" )
						|| ( $liste[ $i + 1 ]{'Typ'} eq "minus" ) )
					&& ( $liste[ $i + 2 ]{'Typ'} eq "Term" )
					&& ( !$gefunden )
				  )
				{
					splice(
						@liste, $i, 3,
						{
							'Inhalt' => "("
							  . $liste[$i]{'Inhalt'}
							  . $liste[ $i + 1 ]{'Inhalt'}
							  . $liste[ $i + 2 ]{'Inhalt'} . ")",
							'Typ'  => "Term",
							'Baum' => {
								'knoten' => $liste[ $i + 1 ]{'Baum'}{'knoten'},
								'links'  => $liste[$i]{'Baum'},
								'rechts' => $liste[ $i + 2 ]{'Baum'}
							}
						}
					);
					$gefunden = 1;
				}
			}
		}
		if ( !$gefunden ) {

			# Term mit Vorzeichen
			for ( $i = 0 ; $i < scalar @liste - 1 ; $i++ ) {
				if (
					(
						   ( $liste[$i]{'Typ'} eq "plus" )
						|| ( $liste[$i]{'Typ'} eq "minus" )
					)
					&& ( $liste[ $i + 1 ]{'Typ'} eq "Term" )
				  )
				{
					splice(
						@liste, $i, 2,
						{
							'Inhalt' => "(0"
							  . $liste[$i]{'Inhalt'}
							  . $liste[ $i + 1 ]{'Inhalt'} . ")",
							'Typ'  => "Term",
							'Baum' => {
								'knoten' => $liste[$i]{'Baum'}{'knoten'},
								'links'  => {
									'knoten' => 0,
									'links'  => undef,
									'rechts' => undef
								},
								'rechts' => $liste[ $i + 1 ]{'Baum'}
							}
						}
					);
					$gefunden = 1;
				}
			}
		}

	} while ($gefunden);

	#ausgabeliste(@liste);
	return @liste;
}

sub regelwerkupn {
	my @liste = @_;
	my ( @klammerterm, $i, $j, $gefunden, $klammerauf, $klammerzu,
		$klammertiefe );

	do {
		$gefunden = 0;
		if ( !$gefunden ) {

			$klammerzu = $klammerauf = $klammertiefe = 0;

# Klammern:
# Wenn eine oeffnende Klammer gefunden wurde, dann wird der Zaehler klammertiefe erhoeht,
# bei einer schliessenden Klammer erniedrigt.
# Bei korrekter Klammerung ist der Zaehler am Ende 0
# und es wird die regelwerk-Funktion auf den Inhalt der Klammer angewendet.

			for ( $i = 0 ; $i < scalar @liste ; $i++ ) {

				if ( $liste[$i]{'Typ'} eq "(" ) {
					if ( ( $klammertiefe == 0 ) ) {
						$klammerauf = $i;
					}
					$klammertiefe++;
				}
				if ( $liste[$i]{'Typ'} eq ")" ) {
					$klammertiefe--;
					if ( $klammertiefe == 0 ) {
						$klammerzu = $i;
					}
				}

			}
			## Fehler wenn klammertiefe != 0 muss noch bearbeitet werden

			if ( $klammerauf != $klammerzu ) {

				@klammerterm = ();
				for ( $j = $klammerauf + 1 ; $j <= $klammerzu - 1 ; $j++ ) {
					push @klammerterm,
					  {
						'Inhalt' => $liste[$j]{'Inhalt'},
						'Typ'    => $liste[$j]{'Typ'},
						'Baum'   => {
							'knoten' => $liste[$j]{'Baum'}{'knoten'},
							'links'  => undef,
							'rechts' => undef
						}
					  };
				}

				splice(
					@liste, $klammerauf,
					$klammerzu - $klammerauf + 1,
					regelwerkupn(@klammerterm)
				);
				$gefunden = 1;

			}

		}
		if ( !$gefunden ) {

			# Potenzieren
			for ( $i = 0 ; $i < scalar @liste - 2 ; $i++ ) {
				if (   ( $liste[$i]{'Typ'} eq "Term" )
					&& ( $liste[ $i + 1 ]{'Typ'} eq "hoch" )
					&& ( $liste[ $i + 2 ]{'Typ'} eq "Term" ) )
				{

					if ( $liste[ $i + 2 ]{'Inhalt'} == 2 ) {
						splice(
							@liste, $i, 3,
							{
								'Inhalt' => "("
								  . $liste[$i]{'Inhalt'}
								  . $liste[ $i + 1 ]{'Inhalt'}
								  . $liste[ $i + 2 ]{'Inhalt'} . ")",
								'Typ'  => "Term",
								'Baum' => {
									'knoten' => "mul",
									'links'  => $liste[$i]{'Baum'},
									'rechts' => {
										'knoten' => "dup",
										'links'  => undef,
										'rechts' => undef
									},
								}
							}
						);
					}
					else {

						splice(
							@liste, $i, 3,
							{
								'Inhalt' => "("
								  . $liste[$i]{'Inhalt'}
								  . $liste[ $i + 1 ]{'Inhalt'}
								  . $liste[ $i + 2 ]{'Inhalt'} . ")",
								'Typ'  => "Term",
								'Baum' => {
									'knoten' =>
									  $liste[ $i + 1 ]{'Baum'}{'knoten'},
									'links'  => $liste[$i]{'Baum'},
									'rechts' => $liste[ $i + 2 ]{'Baum'}
								}
							}
						);
					}
					$gefunden = 1;

					ausgabeliste(@liste);
				}
			}
		}
		if ( !$gefunden ) {

			# Multiplikation und Division
			for ( $i = 0 ; $i < scalar @liste - 2 ; $i++ ) {
				if (
					( $liste[$i]{'Typ'} eq "Term" )
					&& (   ( $liste[ $i + 1 ]{'Typ'} eq "mal" )
						|| ( $liste[ $i + 1 ]{'Typ'} eq "geteilt" ) )
					&& ( $liste[ $i + 2 ]{'Typ'} eq "Term" )
				  )
				{
					splice(
						@liste, $i, 3,
						{
							'Inhalt' => "("
							  . $liste[$i]{'Inhalt'}
							  . $liste[ $i + 1 ]{'Inhalt'}
							  . $liste[ $i + 2 ]{'Inhalt'} . ")",
							'Typ'  => "Term",
							'Baum' => {
								'knoten' => $liste[ $i + 1 ]{'Baum'}{'knoten'},
								'links'  => $liste[$i]{'Baum'},
								'rechts' => $liste[ $i + 2 ]{'Baum'}
							}
						}
					);
					$gefunden = 1;

					ausgabeliste(@liste);
				}
			}
		}
		if ( !$gefunden ) {

			# Funktion
			for ( $i = 0 ; $i < scalar @liste - 1 ; $i++ ) {
				if (   ( $liste[$i]{'Typ'} eq "Funktion" )
					&& ( $liste[ $i + 1 ]{'Typ'} eq "Term" ) )
				{
					if ( $liste[$i]{'Inhalt'} eq "exp" ) {
						splice(
							@liste, $i, 2,
							{
								'Inhalt' => "("
								  . exp(1) . "\^"
								  . $liste[ $i + 1 ]{'Inhalt'} . ")",
								'Typ'  => "Term",
								'Baum' => {
									'knoten' => "^",
									'links'  => {
										'knoten' => exp(1),
										'links'  => undef,
										'rechts' => undef
									},
									'rechts' => $liste[ $i + 1 ]{'Baum'}
								}
							}
						);
					}
					else {
						splice(
							@liste, $i, 2,
							{
								'Inhalt' => "("
								  . $liste[$i]{'Inhalt'}
								  . $liste[ $i + 1 ]{'Inhalt'} . ")",
								'Typ'  => "Term",
								'Baum' => {
									'knoten' => $liste[$i]{'Baum'}{'knoten'},
									'links'  => $liste[ $i + 1 ]{'Baum'},
									'rechts' => undef
								}
							}
						);
					}
					$gefunden = 1;

					ausgabeliste(@liste);
				}
			}
		}
		if ( !$gefunden ) {

			# Addition und Subtraktion
			for ( $i = 0 ; $i < scalar @liste - 2 ; $i++ ) {
				if (   ( $liste[$i]{'Typ'} eq "Term" )
					&& ( ( $liste[ $i + 1 ]{'Typ'} eq "plus" ) )
					&& ( $liste[ $i + 2 ]{'Typ'} eq "Term" ) )
				{
					splice(
						@liste, $i, 3,
						{
							'Inhalt' => "("
							  . $liste[$i]{'Inhalt'}
							  . $liste[ $i + 1 ]{'Inhalt'}
							  . $liste[ $i + 2 ]{'Inhalt'} . ")",
							'Typ'  => "Term",
							'Baum' => {
								'knoten' => $liste[ $i + 1 ]{'Baum'}{'knoten'},
								'links'  => $liste[$i]{'Baum'},
								'rechts' => $liste[ $i + 2 ]{'Baum'}
							}
						}
					);
					$gefunden = 1;

					ausgabeliste(@liste);
				}
			}
		}

		if ( !$gefunden ) {

			# Addition und Subtraktion
			for ( $i = 0 ; $i < scalar @liste - 2 ; $i++ ) {
				if (   ( $liste[$i]{'Typ'} eq "Term" )
					&& ( ( $liste[ $i + 1 ]{'Typ'} eq "minus" ) )
					&& ( $liste[ $i + 2 ]{'Typ'} eq "Term" ) )
				{
					splice(
						@liste, $i, 3,
						{
							'Inhalt' => "("
							  . $liste[$i]{'Inhalt'}
							  . $liste[ $i + 1 ]{'Inhalt'}
							  . $liste[ $i + 2 ]{'Inhalt'} . ")",
							'Typ'  => "Term",
							'Baum' => {
								'knoten' => "minus",
								'links'  => $liste[$i]{'Baum'},
								'rechts' => $liste[ $i + 2 ]{'Baum'}
							}
						}
					);
					$gefunden = 1;

					ausgabeliste(@liste);
				}
			}
		}

		if ( !$gefunden ) {

			# Term mit Vorzeichen
			for ( $i = 0 ; $i < scalar @liste - 1 ; $i++ ) {
				if (
					(
						   ( $liste[$i]{'Typ'} eq "plus" )
						|| ( $liste[$i]{'Typ'} eq "minus" )
					)
					&& ( $liste[ $i + 1 ]{'Typ'} eq "Term" )
				  )
				{
					splice(
						@liste, $i, 2,
						{
							'Inhalt' => "(0"
							  . $liste[$i]{'Inhalt'}
							  . $liste[ $i + 1 ]{'Inhalt'} . ")",
							'Typ'  => "Term",
							'Baum' => {
								'knoten' => "neg",
								'links'  => undef,
								'rechts' => $liste[ $i + 1 ]{'Baum'}
							}
						}
					);
					$gefunden = 1;

					ausgabeliste(@liste);
				}
			}
		}
	} while ($gefunden);

	ausgabeliste(@liste);
	return @liste;
}

sub rechenbaum_ausrechnen {
	my $baum      = shift;
	my $variablen = shift;

	#print $$baum{'knoten'} . "\n";
	if ( $$baum{'knoten'} eq "*" ) {
		return rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) *
		  rechenbaum_ausrechnen( $$baum{'rechts'}, $variablen );
	}
	elsif ( $$baum{'knoten'} eq ":" ) {
		return rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) /
		  rechenbaum_ausrechnen( $$baum{'rechts'}, $variablen );
	}
	elsif ( $$baum{'knoten'} eq "/" ) {
		return rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) /
		  rechenbaum_ausrechnen( $$baum{'rechts'}, $variablen );
	}
	elsif ( $$baum{'knoten'} eq "+" ) {

		return rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) +
		  rechenbaum_ausrechnen( $$baum{'rechts'}, $variablen );
	}
	elsif ( $$baum{'knoten'} eq "^" ) {

		return rechenbaum_ausrechnen( $$baum{'links'}, $variablen )
		  **rechenbaum_ausrechnen( $$baum{'rechts'}, $variablen );
	}

	elsif ( $$baum{'knoten'} eq "-" ) {
		return rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) -
		  rechenbaum_ausrechnen( $$baum{'rechts'}, $variablen );
	}
	elsif ( defined $$variablen{ $$baum{'knoten'} } ) {
		return $$variablen{ $$baum{'knoten'} };
	}
	elsif ( $$baum{'knoten'} eq "sin" ) {
		return sin( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "cos" ) {
		return cos( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "tan" ) {
		return tan( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "asin" ) {
		return arcsin( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "acos" ) {
		return acos( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "log" ) {
		return log( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "ceiling" ) {
		return aufrunden( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ),
			1 );
	}
	elsif ( $$baum{'knoten'} eq "floor" ) {
		return abrunden( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ),
			1 );
	}
	elsif ( $$baum{'knoten'} eq "truncate" ) {

		if ( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) < 0 ) {
			return aufrunden(
				rechenbaum_ausrechnen( $$baum{'links'}, $variablen ), 1 );
		}
		else {
			return abrunden(
				rechenbaum_ausrechnen( $$baum{'links'}, $variablen ), 1 );
		}

	}
	elsif ( $$baum{'knoten'} eq "round" ) {
		return round( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "sqrt" ) {
		return sqrt( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "abs" ) {
		return abs( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "fact" ) {
		return fact( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	elsif ( $$baum{'knoten'} eq "exp" ) {
		return exp( rechenbaum_ausrechnen( $$baum{'links'}, $variablen ) );
	}
	else {

		# ACHTUNG: Keine Fehlerbehandlung!!!
		return $$baum{'knoten'};
	}

}

sub polnisch {
	my $ref = shift;
	$hilfsstring = $$ref{'knoten'} . " " . " " . $hilfsstring;

	# suche rechts (rekursiv)
	if ( defined( $$ref{'rechts'} ) ) { polnisch( $$ref{'rechts'} ); }

	# suche links (rekursiv)
	if ( defined( $$ref{'links'} ) ) { polnisch( $$ref{'links'} ); }

	# Ausgabe des Knotens
	return $hilfsstring;
}

sub upn {
	my $funktionsausdruck = shift;
	my @ergebnis          = regelwerkupn( tokenizer($funktionsausdruck) );
	my $funktion;
	$funktion = polnisch( $ergebnis[0]{'Baum'} );
	$funktion =~ s/\*/mul/g;
	$funktion =~ s/\+/add/g;
	$funktion =~ s/minus/sub/g;
	$funktion =~ s/\//div/g;
	$funktion =~ s/\:/div/g;
	$funktion =~ s/\^/exp/g;
	$funktion =~ s/pi/3.14159/g;

	if ( scalar @ergebnis != 1 ) {
		printf("Fehler \n");
		ausgabeliste(@ergebnis);
	}
	else {
		$hilfsstring = "";
		return $funktion;

	}
}

sub dreidimensional {
	my ( $funktion, $variable ) = @_;

	my $gefunden;
	$gefunden = 0;

	if   ( $funktion =~ /$variable/ ) { return 1; }
	else                              { return 0; }

}

1;
