Исходный файл 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; :}
;