Исходные файлы CUPCalc.cup, CUPCalc.java и Der.java(новый файл) (все изменения выделены):
CUPCalc.cup
// JavaCup specification for a simple expression evaluator
import java_cup.runtime.*; import java.io.*;
// //----------------------------------------------------------- import Der; //------------------------------------------------------------ //
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++;
}
}
Integer val = null;
try {
val = new Integer(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 == 'x') {
scanPos++; return new Symbol(sym.X);
} 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("= " + (Integer)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 MINUS, PLUS, TIMES; terminal LPAREN, RPAREN; terminal EOL, ERROR; terminal String X; terminal Integer NUMBER; //-------------------------------------------------- //
/* Non terminals */ non terminal String expression; non terminal String expr;
/* Precedences */
// //------------------------------------------------- precedence left PLUS, MINUS; precedence left TIMES; precedence left LPAREN; //------------------------------------------------- //
start with expression;
/* The grammar */
expression ::= expr:e EOL
{: RESULT = e; :}
;
//
//----------------------------------------------------------------------
expr ::= expr:e1 PLUS expr:e2
{:String f1 = Der.function(e1);
String d1 = Der.derivation(e1);
String f2 = Der.function(e2);
String d2 = Der.derivation(e2);
if (f1 != "nf" && f2 != "nf") RESULT = new String("("+f1 + " + " + f2 +")!(" + d1 + " + " + d2+")");
else if (f1 == "nf" && f2 != "nf") RESULT = new String("("+e1 + " + " + f2 + ")!" + d2);
else if (f1 != "nf" && f2 == "nf") RESULT = new String("("+f1 + " + " + e2 + ")!" + d1);
else RESULT = new String(e1 + "+" + e2 + "!0");
:}
|
expr:e1 MINUS expr:e2
{:String f1 = Der.function(e1);
String d1 = Der.derivation(e1);
String f2 = Der.function(e2);
String d2 = Der.derivation(e2);
if (f1 != "nf" && f2 != "nf") RESULT = new String("("+f1 + " - " + f2 +")!(" + d1 + " - " + d2 +")");
else if (f1 == "nf" && f2 != "nf") RESULT = new String("(" + e1 + " - " + f2 + ")!" + d2);
else if (f1 != "nf" && f2 == "nf") RESULT = new String("(" + f1 + " - " + e2 + ")!" + d1);
else RESULT = new String(e1 + "-" + e2 + "!0");
:}
|
expr:e1 TIMES expr:e2
{:
String f1 = Der.function(e1);
String d1 = Der.derivation(e1);
String f2 = Der.function(e2);
String d2 = Der.derivation(e2);
if (f1 != "nf" && f2 != "nf") RESULT = new String(f1 + " * " + f2 +"!(" + d1 + " * " + f2 + " + " + f1 + " * " + d2 + ")");
else if (f1 == "nf" && f2 != "nf") RESULT = new String(e1 + " * " + f2 + "!" + e1 + " * " + d2);
else if (f1 != "nf" && f2 == "nf") RESULT = new String(f1 + " * " + e2 + "!" + d1 + " * " + e2);
else RESULT = new String(e1 + " * " + e2 + "! ");
:}
|
NUMBER:n
{: RESULT = n.toString(); :}
|
X:n
{: RESULT = "x!1"; :}
|
LPAREN expr:e RPAREN
{: RESULT = e; :}
;
//------------------------------------------------------------------------
//
CUPCalc.java
/** * Calculator of ariphmetic expressions * Uses CUP (Java version of YACC) technology */ import java.awt.*; import java.awt.event.*; import java.applet.Applet;
// //----------------------------------------------------------- import Der; //----------------------------------------------------------- //
import java_cup.runtime.*; // CUP runtime environment import parser; // Parser generated by CUP from the file "CUPCalc.cup"
public class CUPCalc extends Applet {
Button evaluateButton;
TextField expression;
TextField result;
// Layout constants
static final int margin = 5;
static final int headlineHeight = 30;
static final int vertSkip = 5;
static final int horSkip = 5;
static final int labelWidth = 80;
static final int textWidth = 300;
static final int buttonWidth = 80;
static final int buttonHeight = 30;
public static void main(String[] args) {
Frame f = new Frame("CUP Calculator");
WindowAdapter wa = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
f.addWindowListener(wa);
f.setFont(new Font("Helvetica", Font.PLAIN, 14));
// Add menu bar
final MenuBar mb = new MenuBar();
f.setMenuBar(mb);
final Menu fileMenu = new Menu("File");
final MenuItem quitItem = new MenuItem("Quit");
fileMenu.add(quitItem);
mb.add(fileMenu);
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// System.out.println("Action " + e);
if (e.getActionCommand().equals("Quit")) {
System.exit(0);
}
}
};
fileMenu.addActionListener(al);
CUPCalc cc = new CUPCalc();
f.add("Center", cc);
// f.pack();
f.setSize(
2*margin + labelWidth + horSkip + textWidth + 10,
2*margin + headlineHeight + 4*buttonHeight + 3*vertSkip + 50
);
cc.init();
cc.start();
f.setVisible(true);
}
public void init() {
setLayout(null);
setFont(new Font("Helvetica", Font.PLAIN, 14));
setBackground(Color.lightGray);
//
//-------------------------------------------------------------
Label headline = new Label("Computing the derivation of algebraic function");
//-------------------------------------------------------------
//
headline.setFont(new Font("TimesRoman", Font.BOLD, 18));
add(headline);
int x = margin;
int y = margin;
headline.setBounds(x, y, 380, 30);
y += headlineHeight + vertSkip;
Label l = new Label("Expression:");
add(l);
l.setBounds(x, y, labelWidth, buttonHeight);
x += labelWidth + horSkip;
expression = new TextField();
add(expression);
expression.setBounds(x, y, textWidth, buttonHeight);
y += buttonHeight + vertSkip;
evaluateButton = new Button("Derivate");
add(evaluateButton);
x += (textWidth - buttonWidth);
evaluateButton.setBounds(x, y, buttonWidth, buttonHeight);
y += buttonHeight + vertSkip;
x = margin;
l = new Label("Result:");
add(l);
l.setBounds(x, y, labelWidth, buttonHeight);
x += labelWidth + horSkip;
result = new TextField();
result.setEditable(false);
add(result);
result.setBounds(x, y, textWidth, buttonHeight);
result.setForeground(Color.blue);
// Add action listener for "Expression" text field
// (for processing of the "Enter" button) and "Evaluate" button
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// System.out.println("Text action " + e);
onEvaluate();
}
};
expression.addActionListener(al);
evaluateButton.addActionListener(al);
// That's all.
}
// Evaluate an expression
void onEvaluate() {
parser parser_obj = new parser();
parser_obj.setParsingLine(expression.getText());
try {
// Parse a line
Symbol s = parser_obj.parse();
//
//-----------------------------------------------------
if (s != null && s.value != null) {
result.setText(Der.derivation("" + s.value));
} else {
result.setText("Syntax error");
}
//-----------------------------------------------------
//
} catch (Exception e) {
//... System.err.println("" + e);
result.setText("Syntax error");
}
}
}
Der.java
public class Der {
static String function(String s) {
int index = s.indexOf("!");
if (index != -1) return s.substring(0, index);
else return("nf");
}
static String derivation(String s) {
int index = s.indexOf("!");
if (index != -1) return s.substring(index + 1, s.length());
else return("nf");
} }