package parserp; import java.awt.*; import java.awt.image.*; import java.util.*; public class parser { String err = new String("No error. "); Vector code = null; double curr_x = 0; stack st = null; boolean is_err = false; Vector pb = null; String eq = null; int index = 0; Vector fns = null; Vector consts = null; public parser(String eqn) { err = new String("No error. "); is_err = false; code = new Vector(); pb = new Vector(); eq = new String(eqn); index = 0; fns = new Vector(); fns.addElement(new fn_sin()); fns.addElement(new fn_cos()); fns.addElement(new fn_tan()); fns.addElement(new fn_asin()); fns.addElement(new fn_acos()); fns.addElement(new fn_atan()); fns.addElement(new fn_ln()); fns.addElement(new fn_log()); fns.addElement(new fn_exp()); fns.addElement(new fn_abs()); fns.addElement(new fn_int()); fns.addElement(new fn_sqr()); fns.addElement(new fn_sqrt()); consts = new Vector(); consts.addElement(new op_pushv(Math.PI, "PI")); consts.addElement(new op_pushv(Math.E, "E")); //parse_paren(); parse_add(); if (!is_err) { instruction ins = get_token(); if (ins != null) //set_err("Was expecting end of line, got " + ins.name + " instead."); set_err("Invalid input function. "); } if (is_err) code = null; pb = null; } public String last_err() { return err; } public double[] eval(double x0, double xn, int nx) { if (code == null) return null; double y[] = new double[nx]; double dx = (xn - x0) / (nx - 1); st = new stack(1000); for (int i = 0; i < nx; i ++) { double x; if (i == 0) x = x0; else if (i == nx - 1) x = xn; else x = x0 + i * dx; st.reset(); y[i] = eval(x); } st = null; return y; } public double[] eval(double x[]) { if (code == null) return null; double y[] = new double[x.length]; st = new stack(1000); for (int i = 0; i < x.length; i ++) { st.reset(); y[i] = eval(x[i]); } st = null; return y; } public double eval(double x) { double result = 0; if (code != null) { int flag = 0; if (st == null) { st = new stack(1000); flag = 1; } curr_x = x; for (int i = 0; i < code.size(); i ++) { instruction inst = (instruction) code.elementAt(i); inst.eval(this, st); } result = st.pop(); if (flag == 1) st = null; } return result; } // ************************************* instruction get_token() { if (pb.size() > 0) { instruction ins = (instruction) pb.elementAt(pb.size() - 1); pb.removeElementAt(pb.size() - 1); return ins; } // skip whitespace if (index >= eq.length()) return null; char c = Character.toUpperCase(eq.charAt(index ++)); while (Character.isSpace(c)) { if (index >= eq.length()) return null; c = Character.toUpperCase(eq.charAt(index ++)); } // look for operator if (c == '+') return new op_add(); if (c == '-') return new op_sub(); if (c == '*') return new op_mul(); if (c == '/') return new op_div(); if (c == '^') return new op_pow(); if (c == '(') return new op_paren1(); if (c == ')') return new op_paren2(); // look for x if (c == 'X') return new op_pushx(); // look for number boolean do_pushback = true; if (Character.isDigit(c) || c == '-' || c == '.') { String s = ""; // minus if (c == '-') { s = s + c; if (index >= eq.length()) return new instruction(s); c = Character.toUpperCase(eq.charAt(index ++)); } // integer while (Character.isDigit(c)) { s = s + c; if (index >= eq.length()) { do_pushback = false; break; } c = Character.toUpperCase(eq.charAt(index ++)); } // decimal if (c == '.') { s = s + c; if (index >= eq.length()) do_pushback = false; else { c = Character.toUpperCase(eq.charAt(index ++)); while (Character.isDigit(c)) { s = s + c; if (index >= eq.length()) { do_pushback = false; break; } c = Character.toUpperCase(eq.charAt(index ++)); } // exponent if (c == 'E') { s = s + c; if (index >= eq.length()) return new instruction(s); c = Character.toUpperCase(eq.charAt(index ++)); if (c == '+' || c == '-') { s = s + c; if (index >= eq.length()) return new instruction(s); c = Character.toUpperCase(eq.charAt(index ++)); } while (Character.isDigit(c)) { s = s + c; if (index >= eq.length()) { do_pushback = false; break; } c = Character.toUpperCase(eq.charAt(index ++)); } } } } // get number if (s.equals("-")) return new instruction(s); double v = 0; try { v = Double.valueOf(s).doubleValue(); } catch (NumberFormatException e) { return new instruction(s); } // pushback if (do_pushback) index --; // return value return new op_pushv(v); } // look for function or constant if (Character.isLetter(c)) { String s = ""; while (Character.isLetter(c)) { s = s + c; if (index >= eq.length()) { do_pushback = false; break; } c = Character.toUpperCase(eq.charAt(index ++)); } if (do_pushback) index --; instruction fn = find_fn(s); if (fn != null) return fn; instruction con = find_const(s); if (con != null) return con; return new instruction(s); } // return unknown token return new instruction(new Character(c).toString()); } void pushback(instruction ins) { pb.addElement(ins); } void set_err(String s) { err = new String(s); is_err = true; } instruction find_fn(String s) { if (fns == null) return null; for (int i = 0; i < fns.size(); i ++) { instruction fn = (instruction) fns.elementAt(i); if (fn.name.equals(s)) return fn; } return null; } instruction find_const(String s) { if (consts == null) return null; for (int i = 0; i < consts.size(); i ++) { instruction con = (instruction) consts.elementAt(i); if (con.name.equals(s)) return con; } return null; } // ************************************* void parse_paren() { instruction ins = get_token(); if (ins == null) { //set_err("Unexpected end of line."); set_err("Invalid input function. "); } else if (ins instanceof op_paren1) { parse_add(); if (is_err) return; ins = get_token(); if (ins == null) { //set_err("Unexpected end of line."); set_err("Invalid input function. "); return; } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! problem with paren as first token ? // e.g. (3)+1 if (ins instanceof op_paren2) return; //set_err("Was expecting ), got " + ins.name + " instead."); set_err("Invalid input function. "); } else { pushback(ins); parse_add(); } } void parse_add() { parse_mul(); if (is_err) return; instruction ins = get_token(); if (ins == null) { //set_err("Unexpected end of line."); return; } else if (ins instanceof op_add || ins instanceof op_sub) { while (ins instanceof op_add || ins instanceof op_sub) { parse_mul(); if (is_err) return; code.addElement(ins); ins = get_token(); if (ins == null) { return; } } //set_err("Was expecting end of line, got " + ins.name + " instead."); pushback(ins); } else { //set_err("Was expecting + or -, got " + ins.name + " instead."); pushback(ins); } } void parse_mul() { parse_pow(); if (is_err) return; instruction ins = get_token(); if (ins == null) { return; } else if (ins instanceof op_mul || ins instanceof op_div) { while (ins instanceof op_mul || ins instanceof op_div) { parse_pow(); if (is_err) return; code.addElement(ins); ins = get_token(); if (ins == null) { return; } } pushback(ins); } else { pushback(ins); } } void parse_pow() { parse_neg(); if (is_err) return; instruction ins = get_token(); if (ins == null) { return; } else if (ins instanceof op_pow) { while (ins instanceof op_pow) { parse_neg(); if (is_err) return; code.addElement(ins); ins = get_token(); if (ins == null) { return; } } pushback(ins); } else { pushback(ins); } } void parse_neg() { instruction ins = get_token(); if (ins == null) { //set_err("Unexpected end of line."); set_err("Invalid input function. "); } else if (ins instanceof op_sub) { parse_fn(); if (is_err) return; code.addElement(new op_neg()); } else { pushback(ins); parse_fn(); } } void parse_fn() { instruction ins = get_token(); if (ins == null) { //set_err("Unexpected end of line."); set_err("Invalid input function. "); return; } else if (ins instanceof function) { instruction ins2 = ins; ins = get_token(); if (ins == null) { //set_err("Unexpected end of line."); set_err("Invalid input function. "); return; } if (ins instanceof op_paren1) { pushback(ins); parse_paren(); if (is_err) return; code.addElement(ins2); return; } else { //set_err("Was expecting (, got " + ins.name + " instead."); set_err("Invalid input function. "); return; } } else { pushback(ins); parse_push(); } } void parse_push() { instruction ins = get_token(); if (ins == null) { //set_err("Unexpected end of line."); set_err("Invalid input function. "); } else if ((ins instanceof op_pushv) || (ins instanceof op_pushx)) { code.addElement(ins); } else if (ins instanceof op_paren1) { pushback(ins); parse_paren(); } else { //set_err("Was expecting a number, x, or (, got " + ins.name + " instead."); set_err("Invalid input function. "); } } } // ************************************* class instruction { String name = null; instruction() { name = new String(""); } instruction(String s) { name = new String(s); } void eval(parser p, stack s) { } } class op_pushv extends instruction { double val = 0; op_pushv(double v) { val = v; name = new Double(v).toString(); } op_pushv(double v, String n) { val = v; name = new String(n); } void eval(parser p, stack s) { s.push(val); } } class op_pushx extends instruction { op_pushx(){name = new String("x");} void eval(parser p, stack s) { s.push(p.curr_x); } } class op_add extends instruction { op_add(){name = new String("+");} void eval(parser p, stack s) { double x1 = s.pop(); double x2 = s.pop(); s.push(x1 + x2); } } class op_sub extends instruction { op_sub(){name = new String("-");} void eval(parser p, stack s) { double x1 = s.pop(); double x2 = s.pop(); s.push(x2 - x1); } } class op_mul extends instruction { op_mul(){name = new String("*");} void eval(parser p, stack s) { double x1 = s.pop(); double x2 = s.pop(); s.push(x1 * x2); } } class op_div extends instruction { op_div(){name = new String("/");} void eval(parser p, stack s) { double x1 = s.pop(); double x2 = s.pop(); s.push(x2 / x1); } } class op_neg extends instruction { op_neg(){name = new String("-");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(- x1); } } class op_pow extends instruction { op_pow(){name = new String("^");} void eval(parser p, stack s) { double x1 = s.pop(); double x2 = s.pop(); s.push(Math.pow(x2, x1)); } } class op_paren1 extends instruction { op_paren1(){name = new String("(");} void eval(parser p, stack s){} } class op_paren2 extends instruction { op_paren2(){name = new String(")");} void eval(parser p, stack s){} } // ************************************* class function extends instruction { function(){name = new String("fn()");} void eval(parser p, stack s){} } class fn_sin extends function { fn_sin(){name = new String("SIN");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.sin(x1)); } } class fn_cos extends function { fn_cos(){name = new String("COS");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.cos(x1)); } } class fn_tan extends function { fn_tan(){name = new String("TAN");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.tan(x1)); } } class fn_asin extends function { fn_asin(){name = new String("ASIN");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.asin(x1)); } } class fn_acos extends function { fn_acos(){name = new String("ACOS");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.acos(x1)); } } class fn_atan extends function { fn_atan(){name = new String("ATAN");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.atan(x1)); } } class fn_exp extends function { fn_exp(){name = new String("EXP");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.exp(x1)); } } class fn_ln extends function { fn_ln(){name = new String("LN");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.log(x1)); } } class fn_log extends function { fn_log(){name = new String("LOG");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.log(x1) / Math.log(10.0)); } } class fn_abs extends function { fn_abs(){name = new String("ABS");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.abs(x1)); } } class fn_int extends function { fn_int(){name = new String("INT");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.floor(x1)); } } class fn_sqr extends function { fn_sqr(){name = new String("SQR");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(x1 * x1); } } class fn_sqrt extends function { fn_sqrt(){name = new String("SQRT");} void eval(parser p, stack s) { double x1 = s.pop(); s.push(Math.sqrt(x1)); } } // ************************************* class stack { double[] x = null; int sp = -1; stack(int n) { x = new double[n]; sp = -1; } void push(double y) { x[++ sp] = y; } double pop() { double result = 0; if (sp > -1) result = x[sp]; sp --; if (sp < -1) sp = -1; return result; } void reset() { sp = -1; } }