import java.util.HashMap; import java.util.Map; import java.util.Stack; import java.util.StringTokenizer; import java.util.regex.Pattern; public class BasicInterpreter { private static enum Operation { ADD("+"){double operate(double x, double y) { return x+y; }}, SUBTRACT("-"){double operate(double x, double y) { return x-y; }}, DIVIDE("/"){double operate(double x, double y) { return x/y; }}, MULTPLY("*"){double operate(double x, double y) { return x*y; }}; String name; private Operation(String name) { this.name = name; } abstract double operate (double x, double y); public static Operation parseString(String str) { for(Operation o : Operation.values()) { if(str.equals(o.name)) return o; } return null; } } private Map symbolTable; public BasicInterpreter() { symbolTable = new HashMap(); } public void parseLine(String line) { String[] tokens = line.split(" "); for(String s:tokens) System.out.println(s); //debug if(tokens[0].equals("let")) { // assignment code here String name = tokens[1]; String expr = line.split("=")[1]; symbolTable.put(name, evaluate(expr.substring(1,expr.length()))); System.out.println("OK"); } else if (tokens[0].equals("print")) { String expr = line.replaceFirst("print ", ""); System.out.println(evaluate(expr)); // print code here } else { System.err.println("Error: Unknown command '" + tokens[0] + "'"); } } private double evaluate(String expr) { System.out.println("expr = " + expr); String[] tokens = expr.split(" "); Pattern ops = Pattern.compile("[\\+\\-\\*\\/\\^]"); String expression = ""; for(int i = 0 ; i < tokens.length ; i++) { System.out.println("tokens[" + i + "] is \"" + tokens[i] + "\"");//debug if(!Character.isDigit(tokens[i].charAt(0)) && !ops.matcher(tokens[i]).matches()) { tokens[i] = ""+symbolTable.get(tokens[i]); } } String finalExpr = ""; for(String s:tokens) finalExpr += s + " "; finalExpr = finalExpr.substring(0,finalExpr.length()-1); // strip trailing space return new StackCalculator().evaluate(finalExpr); } /** * * @author Brad Lindemann * */ private static class StackCalculator { public double evaluate(String prob) { int par1=0; int par2=0; for(int i = 0 ; i< prob.length() ; i++) { if(prob.charAt(i) == '('){ par1 = i; for (int j = prob.length() -1 ; j > par1 ; j--) { if(prob.charAt(j) == ')') { par2 = j; break; } } break; } } if(par1 > par2) throw new Error("Unclosed Parenthesis?"); if(par1 != par2) prob = prob.substring(0,par1) + evaluate(prob.substring(par1+1,par2)) + prob.substring(par2+1,prob.length()); split(prob.replaceAll(" ", "")); return solveStack(); } private void split(String stat) { Stack temp = new Stack(); if(stat.length() < 2) { temp.push(stat); } else { int pos = 0; for(int i = 0 ; i < stat.length() ; i++) { if(!Character.isDigit(stat.charAt(i))) { temp.push(stat.substring(pos, i)); temp.push(""+stat.charAt(i)); pos = i+1; } } temp.push(stat.substring(pos,stat.length())); } while(!temp.isEmpty()) { if(Character.isDigit(temp.peek().charAt(0))) { numbers.push(temp.pop()); } else { operators.push(temp.pop()); } } } private double solveStack() { int level = 0; Stack tempNum = new Stack(), tempOp = new Stack(); while(level < priority.length) { while(!operators.isEmpty()) { if(tempOp.push(operators.pop()).equals(""+priority[level])) { tempNum.push(numbers.pop()); switch(tempOp.pop().charAt(0)) { case '^': tempNum.push(""+Math.pow(Double.parseDouble(tempNum.pop()), Double.parseDouble(numbers.pop()))); break; case '*': tempNum.push(""+Double.parseDouble(tempNum.pop()) * Double.parseDouble(numbers.pop())); break; case '/': tempNum.push(""+Double.parseDouble(tempNum.pop()) / Double.parseDouble(numbers.pop())); break; case '-': tempNum.push(""+(Double.parseDouble(tempNum.pop()) - Double.parseDouble(numbers.pop()))); break; case '+': tempNum.push(""+(Double.parseDouble(tempNum.pop()) + Double.parseDouble(numbers.pop()))); break; default: throw new Error("Invalid operator"); } while(!tempNum.isEmpty()) { numbers.push(tempNum.pop()); } while(!tempOp.isEmpty()) { operators.push(tempOp.pop()); } }else { tempNum.push(numbers.pop()); } } while(!tempNum.isEmpty()) numbers.push(tempNum.pop()); while(!tempOp.isEmpty()) operators.push(tempOp.pop()); level++; } return Double.parseDouble(numbers.pop()); } private Stack numbers = new Stack(); private Stack operators = new Stack(); public static final char[] priority = {'^','*','/','+','-'}; } }