options { LOOKAHEAD=1; } PARSER_BEGIN(TParser) import edu.jsu.leathrum.mathlets.shared.*; import java.text.ParsePosition; public class TParser { static TreeBuilder argTree = new TreeBuilder(); public final static int PLUS = '+'; public final static int MINUS = '-'; public final static int MULT = '*'; public final static int DIV = '/'; public final static int POW = '^'; public final static int NEG = '!'; public final static int PI = 'p'; public final static int E = 'e'; public final static int VARXH = 'h'; public final static int VARX = 'x'; public final static int VARY = 'y'; public final static int VARZ = 'z'; public final static int VARU = 'u'; public final static int VARV = 'v'; public final static int VARR = '1'; public final static int VARS = '2'; public final static int VART = '3'; public final static int ABS = '|'; public final static int SQRT = '%'; public final static int SIN = 's'; public final static int COS = 'c'; public final static int TAN = 't'; public final static int SEC = 'q'; public final static int CSC = 'w'; public final static int COT = 'b'; public final static int LN = 'l'; public final static int LOG = 'g'; public final static int EXP = '@'; public final static int ASIN = 'S'; public final static int ACOS = 'C'; public final static int ATAN = 'T'; public final static int ASEC = 'Q'; public final static int MIN = 'n'; public final static int MAX = 'm'; public final static int INT = 'i'; public final static int DBL = 'd'; public final static int FACT = 'f'; public final static int ERROR = 'X'; public final static int DERIV = 'D'; public Node getTree() { try{ try { if (one_line() != 1) { argTree.addNodeByType(new Integer(TParser.ERROR)); } } catch (ParseException z) { argTree.addNodeByType(new Integer(TParser.ERROR)); } } catch (TokenMgrError e) { argTree.addNodeByType(new Integer(TParser.ERROR)); } return (Node) argTree.getTop(); } } PARSER_END(TParser) SKIP : { " " | "\r" | "\t" } TOKEN : { < EOL: "\n" > } TOKEN : /* OPERATORS */ { < PLUSt: "+" > | < MINUSt: "-" > | < MULTIPLY: "*" > | < DIVIDE: "/" > | < EXPt: "^" > | < FACTt: "!" > | < ANDt: "&" > | < ORt: "|" > | < LESSt: "<" > | < GRTt: ">" > | < EQt: "=" > } TOKEN : /* numeric constants */ { < CONSTANT: | ( ["e","E"] ([ "-","+"])? )? > | < #FLOAT: | ( [".",","] )? | [".",","] > | < #INTEGER: ( )+ > | < #DIGIT: ["0" - "9"] > } TOKEN : /* Function names */ { < ID: ( )+ ( | )* > | < #LETTER: ["a"-"z", "A"-"Z"] > } int one_line() : {} { sum() { return 1; } | { return 0; } | { return -1; } } void sum() : {Token x; boolean q = false;} { [ {q=true;} ] term() {if (q) {argTree.addNodeByType(new Integer(TParser.NEG)); q=false;} } ( ( x = | x = ) term() { if ( x.kind == PLUSt ) argTree.addNodeByType(new Integer(TParser.PLUS)); else argTree.addNodeByType(new Integer(TParser.MINUS)); } )* } void term() : {Token x;} { ( LOOKAHEAD(2) numconst() exp() {argTree.addNodeByType(new Integer(TParser.MULT));} | exp() ) ( ( x = | x = ) exp() { if ( x.kind == MULTIPLY ) argTree.addNodeByType(new Integer(TParser.MULT)); else argTree.addNodeByType(new Integer(TParser.DIV)); } )* } void exp() : { } { element() ( element() { argTree.addNodeByType(new Integer(TParser.POW)); } )* } void element() : {} { LOOKAHEAD(2) function() | LOOKAHEAD(2) deriv() | numconst() | idconst() | "(" sum() ")" } void deriv() : {String funcname;} { {funcname = token.image;} "[" sum() "]" { if (funcname.equalsIgnoreCase("D")) { argTree.addNodeByType(new Integer(TParser.VARXH)); argTree.addNodeByType(new Integer(TParser.DERIV)); } else if (funcname.equalsIgnoreCase("Dx")) { argTree.addNodeByType(new Integer(TParser.VARX)); argTree.addNodeByType(new Integer(TParser.DERIV)); } else if (funcname.equalsIgnoreCase("Dy")) { argTree.addNodeByType(new Integer(TParser.VARY)); argTree.addNodeByType(new Integer(TParser.DERIV)); } else if (funcname.equalsIgnoreCase("Dz")) { argTree.addNodeByType(new Integer(TParser.VARZ)); argTree.addNodeByType(new Integer(TParser.DERIV)); } else if (funcname.equalsIgnoreCase("Du")) { argTree.addNodeByType(new Integer(TParser.VARU)); argTree.addNodeByType(new Integer(TParser.DERIV)); } else if (funcname.equalsIgnoreCase("Dv")) { argTree.addNodeByType(new Integer(TParser.VARV)); argTree.addNodeByType(new Integer(TParser.DERIV)); } else if (funcname.equalsIgnoreCase("Dr")) { argTree.addNodeByType(new Integer(TParser.VARR)); argTree.addNodeByType(new Integer(TParser.DERIV)); } else if (funcname.equalsIgnoreCase("Ds")) { argTree.addNodeByType(new Integer(TParser.VARS)); argTree.addNodeByType(new Integer(TParser.DERIV)); } else if (funcname.equalsIgnoreCase("Dt")) { argTree.addNodeByType(new Integer(TParser.VART)); argTree.addNodeByType(new Integer(TParser.DERIV)); } else argTree.addNodeByType(new Integer(TParser.ERROR)); } } void numconst() : {} { { try { argTree.addNodeByType(AMathlet.getNumberFormat().parse(token.image, new ParsePosition(0))); } catch (NumberFormatException ee) { argTree.addNodeByType(new Double(Double.NaN)); } argTree.addNodeByType(new Integer(TParser.DBL)); } } void idconst() : { String idname;} { { idname = token.image; if (idname.equalsIgnoreCase("pi")) { argTree.addNodeByType(new Integer(TParser.PI)); } else if (idname.equalsIgnoreCase("e")) { argTree.addNodeByType(new Integer(TParser.E)); } else if (idname.equalsIgnoreCase("x")) { argTree.addNodeByType(new Integer(TParser.VARX)); } else if (idname.equalsIgnoreCase("y")) { argTree.addNodeByType(new Integer(TParser.VARY)); } else if (idname.equalsIgnoreCase("z")) { argTree.addNodeByType(new Integer(TParser.VARZ)); } else if (idname.equalsIgnoreCase("u")) { argTree.addNodeByType(new Integer(TParser.VARU)); } else if (idname.equalsIgnoreCase("v")) { argTree.addNodeByType(new Integer(TParser.VARV)); } else if (idname.equalsIgnoreCase("r")) { argTree.addNodeByType(new Integer(TParser.VARR)); } else if (idname.equalsIgnoreCase("s")) { argTree.addNodeByType(new Integer(TParser.VARS)); } else if (idname.equalsIgnoreCase("t")) { argTree.addNodeByType(new Integer(TParser.VART)); } else argTree.addNodeByType(new Integer(TParser.ERROR)); } } void function() : { String funcname; double args = 0; } { {funcname = token.image;} "(" [ sum() {args++;} ( "," sum() {args++;})* ] ")" { double a, b; if (funcname.equalsIgnoreCase("abs")) { if (args != 1) { System.err.println("Too many arguments to abs()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.ABS)); } else if (funcname.equalsIgnoreCase("sqrt")) { if (args != 1) { System.err.println("Too many arguments to sqrt()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.SQRT)); } else if (funcname.equalsIgnoreCase("sin")) { if (args != 1) { System.err.println("Too many arguments to sin()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.SIN)); } else if (funcname.equalsIgnoreCase("cos")) { if (args != 1) { System.err.println("Too many arguments to cos()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.COS)); } else if (funcname.equalsIgnoreCase("tan")) { if (args != 1) { System.err.println("Too many arguments to tan()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.TAN)); } else if (funcname.equalsIgnoreCase("sec")) { if (args != 1) { System.err.println("Too many arguments to sec()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.SEC)); } else if (funcname.equalsIgnoreCase("csc")) { if (args != 1) { System.err.println("Too many arguments to csc()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.CSC)); } else if (funcname.equalsIgnoreCase("cot")) { if (args != 1) { System.err.println("Too many arguments to cot()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.COT)); } else if (funcname.equalsIgnoreCase("ln")) { if (args != 1) { System.err.println("Too many arguments to ln()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.LN)); } else if (funcname.equalsIgnoreCase("log")) { if (args != 1) { System.err.println("Too many arguments to log()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.LOG)); } else if (funcname.equalsIgnoreCase("exp")) { if (args != 1) { System.err.println("Too many arguments to exp()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.EXP)); } else if (funcname.equalsIgnoreCase("asin") || funcname.equalsIgnoreCase("arcsin")) { if (args != 1) { System.err.println("Too many arguments to arcsin()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.ASIN)); } else if (funcname.equalsIgnoreCase("acos") || funcname.equalsIgnoreCase("arccos")) { if (args != 1) { System.err.println("Too many arguments to arccos()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.ACOS)); } else if (funcname.equalsIgnoreCase("atan") || funcname.equalsIgnoreCase("arctan")) { if (args != 1) { System.err.println("Too many arguments to arctan()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.ATAN)); } else if (funcname.equalsIgnoreCase("asec") || funcname.equalsIgnoreCase("arcsec")) { if (args != 1) { System.err.println("Too many arguments to arcsec()"); throw new ParseException(); } argTree.addNodeByType(new Integer(TParser.ASEC)); } else { argTree.addNodeByType(new Integer(TParser.ERROR)); } } }