Interpreter in Java

Interpreter in Java

Why read if you can watch?

Watch Interpreter's video tutorial
read full article

Interpreter aside

"The pattern doesn't address parsing." "When the grammer is very complex, other techniques (such as a parser) are more appropriate."

public class InterpreterDemo {
public static boolean precedence( char a, char b ) {
String high = "*/", low = "+-";
if (a == '(') return false; // if (a == '(' && b == ')') return false;
if (a == ')' && b == '(') { System.out.println( ")-(" ); return false; }
if (b == '(') return false;
if (b == ')') return true;
if (high.indexOf( a ) > -1 && low.indexOf( b ) > -1) return true;
if (high.indexOf( a ) > -1 && high.indexOf( b ) > -1) return true;
if (low.indexOf( a ) > -1 && low.indexOf( b ) > -1) return true;
return false;
}
public static String convertToPostfix( String in ) {
StkChar opstk = new StkChar();
StringBuffer out = new StringBuffer();
String opers = "+-*/()";
char topsym = '+';
boolean empty;

for (int i = 0; i < in.length(); i++)
if (opers.indexOf( in.charAt(i) ) == -1)
out.append( in.charAt(i) );
else {
while ( ! (empty = opstk.isEmpty())
&& precedence( topsym = opstk.pop(), in.charAt(i) ))
out.append( topsym );
if ( ! empty) opstk.push( topsym );
if (empty || in.charAt(i) != ')') opstk.push( in.charAt(i) );
else topsym = opstk.pop();
}
while ( ! opstk.isEmpty()) out.append( opstk.pop() );
return out.toString();
}
public static int evaluate( String in ) {
StkInt stack = new StkInt();
String opers = "+-*/";
for (int a, b, i=0; i < in.length(); i++)
if (opers.indexOf( in.charAt(i) ) == -1)
stack.push( in.charAt(i)-48 );
else {
b = stack.pop(); a = stack.pop();
if (in.charAt(i) == '+') a = a + b;
else if (in.charAt(i) == '-') a = a - b;
else if (in.charAt(i) == '*') a = a * b;
else if (in.charAt(i) == '/') a = a / b;
stack.push( a );
}
return stack.pop();
}
public static void main( String[] args ) {
System.out.print( args[0] );
String postfix = convertToPostfix( args[0] );
System.out.print( " -- " + postfix );
System.out.println( " -- " + evaluate( postfix ) );
}

class StkChar {
private char[] arr = new char[9];
private int sp = -1;
void push( char ch ) { if ( ! isFull()) arr[++sp] = ch; }
char pop() { if (isEmpty()) return '\0'; return arr[sp--]; }
boolean isFull() { return sp == arr.length-1; }
boolean isEmpty() { return sp == -1; }
}

class StkInt {
private int[] arr = new int[9];
private int sp = -1;
void push( int ch ) { if ( ! isFull()) arr[++sp] = ch; }
int pop() { if (isEmpty()) return 0; return arr[sp--]; }
boolean isFull() { return sp == arr.length-1; }
boolean isEmpty() { return sp == -1; }
}}

2+3*4-5+6 -- 234*+5-6+ -- 15 (2+3)*4-5+6 -- 23+4*5-6+ -- 21 2+3*(4-5)+6 -- 2345-*+6+ -- 5 2+3*((4-5)+6) -- 2345-6+*+ -- 17 (3-(4*(5+6))/(7-8))*9/4 -- 3456+*78-/-9*4/ -- 105