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