options{ //DEBUG_PARSER = true; DEBUG_TOKEN_MANAGER = true; } PARSER_BEGIN(Calculator) import java.util.HashMap; public class Calculator { private static HashMap variables = new HashMap(); public static void main(String[] args) { Calculator parser = new Calculator(System.in); while (true){ System.out.print("Type your expression: "); try{ Double value = parser.evaluateNextLine(); System.out.println("Returned: " + value); }catch (ParseException e){ // Now we will parse the exception message to render it in our format. if(e.getMessage().split("\n").length > 1){ // The error message is on multiple line -> it had been generated int index = "Encountered: \"".length(); String em = e.getMessage().substring(index); String token = em.substring(1,4); if (token.equals("ILL")){ // Illegal token em = em.substring(7); index = em.indexOf("\"")-1; if (index == 0){ // Special case in which the illegal token would be '"' index = 2; } System.out.println("Illegal token: '"+ em.substring(0 , index) +"'."); }else{ //Other generated error messages index = em.indexOf("\""); if (index == 0){ // Meaning the last token is not but "char" em = em.substring(1); index = em.indexOf("\""); }else{ index--; } System.out.println("Last read token: '"+ em.substring(0 , index)+"', w"+em.substring(em.indexOf("\nW")+2)); } }else{ //Those were error messages created by ourselves, they are one line messages that we can directly print System.out.println(e.getMessage()); } try{ parser.passStatement(); // wiping the tokens of the malformed expression }catch (ParseException ex){ System.out.println(ex.getMessage()); //not suppose to be possible to end up here } } } } } PARSER_END(Calculator) SKIP : { " "|"\t" } TOKEN : { | | | | | | | | | | | // Defined so that I can 'wipe' the half parsed line in case of malformations } double statement() : { Token id; double i = 0.0; } { { System.exit(0); }| i=expression() { return i; }| id= i=expression() { variables.put(id.image,i); //Storing the variable return i; } } double expression() : { Token op = null; double l = 0.0; double r = 0.0; } { l=term() ((op= | op=) r=term() { // folding everything in the l variable if (op != null){ if (op.image.equals("+")) l += r; else l -= r; } } )* { //returning the parsed value return l; } } double term() : { Token op = null; double l = 0.0; double r = 0.0; } { l=factor() ((op=
| op=) r=factor() { // folding everything in the l variable if (op != null){ if (op.image.equals("/")) l /= r; else l *= r; } } )* { //returning the parsed value return l; } } double factor() : { Token t = null; Token id = null; double i = 0.0; } { (t= | id= | (i=expression()) ) { if(id != null){ Object var = variables.get(id.image); if (var != null) i = (double) var; else throw new ParseException("'" + id.image + "' is not yet defined."); }else if(t != null) i = Double.parseDouble(t.image); return i; }| (t= | id= | (i=expression()) ) { if(id != null){ i = (double)variables.get(id.image); }else if(t != null) i = Double.parseDouble(t.image); return i*(-1); } } double evaluateNextLine() : { double result = 0.0; } { (result=statement()) { return result; }| {System.out.println("\nBuffer was closed. Exiting."); System.exit(0);} } void passStatement() : { } { (||||||
|||||)* | //Skip *anything* until the next EOL {System.out.println("\nBuffer was closed. Exiting."); System.exit(0);}| {} }