by Moridin8
20. April 2007 20:36
The Interpreter Pattern
namespace ooppatterns
{
using System;
using System.Collections.Generic;
internal class Program
{
private static void Main( string[] args )
{
string expression = "8 ++ 1 4 + N 200 * +";
PostFixParser PFP = new PostFixParser( expression );
Console.WriteLine( "'{0}' equals {1}", expression, PFP.Evaluate() );
Console.ReadLine();
}
}
interface IExpression
{
void Parse( Stack<double> s );
}
class PostFixParser
{
private List<IExpression> tokenList = new List<IExpression>();
public PostFixParser( string s )
{
foreach ( string token in s.Split( ' ' ) )
switch ( token )
{
case "AND":
case "&&":
this.tokenList.Add( new LAnd() );
break;
case "!":
this.tokenList.Add( new LNot() );
break;
case "N":
this.tokenList.Add( new Neg() );
break;
case "OR":
case "||":
this.tokenList.Add( new LOr() );
break;
case "&":
this.tokenList.Add( new BAnd() );
break;
case "~":
this.tokenList.Add( new BNot() );
break;
case "|":
this.tokenList.Add( new BOr() );
break;
case "<>":
case "!=":
this.tokenList.Add( new NotEquals() );
break;
case "==":
this.tokenList.Add( new Equals() );
break;
case ">":
this.tokenList.Add( new GreaterThan() );
break;
case "<":
this.tokenList.Add( new LessThan() );
break;
case ">=":
this.tokenList.Add( new GreaterOrEqualThan() );
break;
case "<=":
this.tokenList.Add( new LessOrEqualThan() );
break;
case "+":
this.tokenList.Add( new Plus() );
break;
case "++":
this.tokenList.Add( new Inc() );
break;
case "-":
this.tokenList.Add( new Minus() );
break;
case "--":
this.tokenList.Add( new Dec() );
break;
case "*":
this.tokenList.Add( new Multiply() );
break;
case "/":
this.tokenList.Add( new Divide() );
break;
case "%":
this.tokenList.Add( new Modulus() );
break;
case "^":
this.tokenList.Add( new Power() );
break;
default:
this.tokenList.Add( new Number( double.Parse( token ) ) );
break;
}
}
public double Evaluate()
{
Stack<double> evalStack = new Stack<double>();
foreach ( IExpression e in this.tokenList )
e.Parse( evalStack );
return evalStack.Pop();
}
}
// Mathmatical operators
class Number : IExpression
{
private double number;
public Number( double number )
{
this.number = number;
}
public void Parse( Stack<double> s )
{
s.Push( number );
}
}
class Plus : IExpression
{
public void Parse( Stack<double> s )
{
s.Push( s.Pop() + s.Pop() );
}
}
class Inc : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( ++tmp );
}
}
class Dec : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( --tmp );
}
}
class Minus : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() - tmp );
}
}
class Multiply : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() * tmp );
}
}
class Divide : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() / tmp );
}
}
class Modulus : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() % tmp );
}
}
class Power : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( Convert.ToInt32( Math.Pow( s.Pop(), tmp ) ) );
}
}
// Equality operators
class Equals : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() == tmp ? -1 : 0 );
}
}
class NotEquals : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() == tmp ? 0 : -1 );
}
}
class GreaterThan : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() > tmp ? -1 : 0 );
}
}
class LessThan : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() < tmp ? 0 : -1 );
}
}
class GreaterOrEqualThan : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() >= tmp ? -1 : 0 );
}
}
class LessOrEqualThan : IExpression
{
public void Parse( Stack<double> s )
{
double tmp = s.Pop();
s.Push( s.Pop() <= tmp ? 0 : -1 );
}
}
// Logical operators
class LAnd : IExpression
{
public void Parse( Stack<double> s )
{
double LHS = s.Pop();
double RHS = s.Pop();
if ( LHS < -1 || RHS < -1 || LHS > 0 || RHS > 0 )
throw new InvalidOperationException();
if ( LHS == RHS )
s.Push( -1 );
else
s.Push( 0 );
}
}
class LOr : IExpression
{
public void Parse( Stack<double> s )
{
double LHS = s.Pop();
double RHS = s.Pop();
if ( LHS < -1 || RHS < -1 || LHS > 0 || RHS > 0 )
throw new InvalidOperationException();
if ( LHS == -1 || RHS == -1 )
s.Push( -1 );
else
s.Push( 0 );
}
}
class Neg : IExpression
{
public void Parse( Stack<double> s )
{
double LHS = s.Pop();
s.Push( -LHS );
}
}
class LNot : IExpression
{
public void Parse( Stack<double> s )
{
double LHS = s.Pop();
if ( LHS < -1 || LHS > 0 )
throw new InvalidOperationException();
if ( LHS == -1 )
s.Push( 0 );
else
s.Push( -1 );
}
}
// Bitwise operators
class BAnd : IExpression
{
public void Parse( Stack<double> s )
{
double LHS = s.Pop();
double RHS = s.Pop();
s.Push( Convert.ToInt32(LHS) & Convert.ToInt32(RHS) );
}
}
class BOr : IExpression
{
public void Parse( Stack<double> s )
{
double LHS = s.Pop();
double RHS = s.Pop();
s.Push( Convert.ToInt32(LHS) | Convert.ToInt32(RHS) );
}
}
class BNot : IExpression
{
public void Parse( Stack<double> s )
{
double LHS = s.Pop();
s.Push( ~Convert.ToInt32(LHS) );
}
}
}