Исходный файл CUPCalc.cup (все изменения выделены):
// JavaCup specification for a simple expression evaluator
import java_cup.runtime.*; import java.io.*;
parser code {: public String parsingLine = null; int scanPos = 0;
public void setParsingLine(String s) { parsingLine = s; scanPos = 0; }
void initScanner() { scanPos = 0; }
// Simple scanner Symbol next_token() { // Skip a space while ( scanPos < parsingLine.length() && Character.isWhitespace(parsingLine.charAt(scanPos)) ) { scanPos++; } if (scanPos == parsingLine.length()) { scanPos++; return new Symbol(sym.EOL); // End of line } else if (scanPos > parsingLine.length()) { return new Symbol(sym.EOF); }
char curChar = parsingLine.charAt(scanPos); if (Character.isDigit(curChar)) { // Extract a number String number = "" + curChar; scanPos++; while ( scanPos < parsingLine.length() && Character.isDigit(parsingLine.charAt(scanPos)) ) { number += parsingLine.charAt(scanPos); scanPos++; }
if ( scanPos < parsingLine.length() && parsingLine.charAt(scanPos) == '.' ) { number += '.'; scanPos++; //Part after a decimal point while ( scanPos < parsingLine.length() && Character.isDigit(parsingLine.charAt(scanPos)) ) { number += parsingLine.charAt(scanPos); scanPos++; } } Double val = null; try { val = new Double(number); } catch (NumberFormatException e) { System.err.println("" + e); } return new Symbol(sym.NUMBER, val); } else if (curChar == '+') { scanPos++; return new Symbol(sym.PLUS); } else if (curChar == '-') { scanPos++; return new Symbol(sym.MINUS); } else if (curChar == '*') { scanPos++; return new Symbol(sym.TIMES); } else if (curChar == '/') { scanPos++; return new Symbol(sym.DIVIDE); } else if (curChar == '(') { scanPos++; return new Symbol(sym.LPAREN); } else if (curChar == ')') { scanPos++; return new Symbol(sym.RPAREN); } else { System.err.println("Error token"); scanPos++; return new Symbol(sym.ERROR); } }
public static void main(String args[]) { String line; BufferedReader reader = new BufferedReader( new InputStreamReader(System.in) );
parser parser_obj = new parser();
while (true) { System.out.println( "Input an expression to evaluate (empty for end):" ); try { line = reader.readLine(); } catch (IOException e) { System.err.println("Read error: " + e); break; }
if (line.equals("")) break;
parser_obj.setParsingLine(line); try {
// Parse a line Symbol s = parser_obj.parse(); if (s != null && s.value != null) { System.out.println("= " + (Double)s.value); } else { System.out.println("Error expression"); }
} catch (Exception e) { System.err.println("" + e); }
} }
:};
/* Preliminaries to set up and use the scanner. */ init with {: initScanner(); :};
scan with {: return next_token(); :};
/* Terminals (tokens returned by the scanner). */ terminal PLUS, MINUS, TIMES, DIVIDE; terminal UMINUS, LPAREN, RPAREN; terminal EOL, ERROR; terminal Double NUMBER;
/* Non terminals */ // //----------------------------------------------------- non terminal String expression; non terminal String expr; //----------------------------------------------------- //
/* Precedences */ precedence left PLUS, MINUS; precedence left TIMES, DIVIDE; precedence left UMINUS, LPAREN;
start with expression;
/* The grammar */ expression ::= expr:e EOL {: RESULT = e; :} ;
expr ::= // //--------------------------------------------------------------- expr:e1 PLUS expr:e2 {: RESULT = new String(e1 + ", " + e2 + ", " + "+"); :} |
expr:e1 MINUS expr:e2 {: RESULT = new String(e1 + ", " + e2 + ", " + "-"); :} |
expr:e1 TIMES expr:e2 {: RESULT = new String(e1 + ", " + e2 + ", " + "*"); :} |
expr:e1 DIVIDE expr:e2 {: RESULT = new String(e1 + ", " + e2 + ", " + "/"); :} |
NUMBER:n {: RESULT = new String("" + n); :} |
MINUS expr:e {: RESULT = new String(e + ", " + "--"); :} %prec UMINUS | //------------------------------------------------------------------- //
LPAREN expr:e RPAREN {: RESULT = e; :} ;