📄 zformulaparser.java
字号:
/*
* Copyright 2002 EZCell , Inc. All rights reserved.
* Version 1.0.
* Author W.John
*/
package ezcell;
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
/**
* DOCUMENT ME!
*
* @version 1.00
* @author W.John
*/
public class ZFormulaParser {
public static final int ERROR_FORMEVAL = 1;
protected String expression = null;
protected Vector _RPNExpression = new Vector();
protected Vector _tokenExpression = new Vector();
protected Stack tokenStack = new Stack();
protected int _error = 0;
protected Hashtable params = new Hashtable();
protected ZCalculator calculator;
protected Function[] _functions = {
new Function() {
public String getName() {
return "sum";
}
public double calculate(Stack stack) throws Exception {
Object value = stack.pop();
if (value instanceof Double) {
return ((Double) value).doubleValue();
} else if (value instanceof _Cells) {
return ((_Cells) value).sum();
}
return 0.0f;
}
}
,
new Function() {
public String getName() {
return "sin";
}
public double calculate(Stack stack) throws Exception {
double d1 = ((Double) stack.pop()).doubleValue();
return Math.sin(d1);
}
}
,
new Function() {
public String getName() {
return "~";
}
public double calculate(Stack stack) throws Exception {
double d1 = ((Double) stack.pop()).doubleValue();
return -d1;
}
}
,
new Function() {
public String getName() {
return "*";
}
public double calculate(Stack stack) throws Exception {
double d1 = ((Double) stack.pop()).doubleValue();
double d2 = ((Double) stack.pop()).doubleValue();
return d1 * d2;
}
}
,
new Function() {
public String getName() {
return "/";
}
public double calculate(Stack stack) throws Exception {
double d1 = ((Double) stack.pop()).doubleValue();
double d2 = ((Double) stack.pop()).doubleValue();
return d2 / d1;
}
}
,
new Function() {
public String getName() {
return "^";
}
public double calculate(Stack stack) throws Exception {
double d1 = ((Double) stack.pop()).doubleValue();
double d2 = ((Double) stack.pop()).doubleValue();
return Math.pow(d1, d2);
}
}
,
new Function() {
public String getName() {
return "+";
}
public double calculate(Stack stack) throws Exception {
double d1 = ((Double) stack.pop()).doubleValue();
double d2 = ((Double) stack.pop()).doubleValue();
return d1 + d2;
}
}
,
new Function() {
public String getName() {
return "-";
}
public double calculate(Stack stack) throws Exception {
double d1 = ((Double) stack.pop()).doubleValue();
double d2 = ((Double) stack.pop()).doubleValue();
return d2 - d1;
}
}
};
/**
*
*/
public ZFormulaParser(ZCalculator calculator) {
this.calculator = calculator;
}
/**
*/
public void dumpRPN() {
for (int i = 0; i < _RPNExpression.size(); i++) {
RPNField rf = (RPNField) _RPNExpression.elementAt(i);
System.out.println("#" + i + "=" + rf._strValue);
}
}
/**
* @todo implement
*/
public void dumpToken() {
}
/**
*
* @param expression
*
* @return
*/
public double eval(String expression) throws Exception{
this.expression = expression;
_RPNExpression.clear();
_tokenExpression.clear();
tokenStack.clear();
params.clear();
tokenize();
convertToRPN();
return parse();
}
/**
*
*/
/**
* @todo it would be faster if we have Double instead of double in the RPNField
*/
public double parse() throws Exception{
Stack stack = new Stack();
for (int i = 0; i < _RPNExpression.size(); i++) {
RPNField rf = (RPNField) _RPNExpression.elementAt(i);
if (RPNField.TOK_NUMBER == rf._type) {
stack.push(new Double(rf._doubleValue));
} else if (RPNField.TOK_PARAMETER == rf._type) {
stack.push(params.get(rf._strValue));
} else if (RPNField.TOK_OPERATOR == rf._type) {
double h = rf._func.calculate(stack);
//System.out.println(h);
stack.push(new Double(h));
}
}
double h = ((Double) stack.pop()).doubleValue();
return h;
}
/**
*/
protected int getFuncNum(Function func) {
if (null == func) {
return -1;
}
for (int i = 0; i < _functions.length; i++) {
if (_functions[i] == func) {
return i;
}
}
return -1;
}
/**
*
*/
protected RPNField getNextMorphem() {
int pos = 0;
String chars = "+-*/^";
RPNField rf = new RPNField();
String value = trimToCellsStringID(expression);
Object obj = toObject(value);
if (obj != null) {
rf._strValue = value;
rf._type = rf.TOK_PARAMETER;
if(expression.length() > value.length())
expression = expression.substring(value.length());
else
expression ="";
params.put(value, obj);
return rf;
}
char c = expression.charAt(pos);
if (Character.isDigit(c)) // numbers
{
while (true) {
pos++;
if (pos >= expression.length()) {
break;
}
if (!Character.isDigit(expression.charAt(pos))) {
break;
}
}
rf._strValue = expression.substring(0, pos);
rf._type = rf.TOK_NUMBER;
rf._doubleValue = Double.parseDouble(rf._strValue);
pos--;
} else if (Character.isLetter(c)) {
while (true) {
pos++;
if (pos >= expression.length()) {
break;
}
if (!Character.isLetter(expression.charAt(pos))) {
break;
}
}
String s = expression.substring(0, pos);
rf._strValue = s;
if (s.equalsIgnoreCase("X") || s.equalsIgnoreCase("Y") || s.equalsIgnoreCase("Z")) {
rf._type = rf.TOK_PARAMETER;
} else {
rf._type = rf.TOK_OPERATOR;
}
pos--;
} else if ('(' == c) {
rf._strValue = "(";
rf._type = rf.TOK_OPEN_BRACKET;
} else if (')' == c) {
rf._strValue = ")";
rf._type = rf.TOK_CLOSE_BRACKET;
} else if (-1 != chars.indexOf(c)) {
rf._strValue = String.valueOf(c);
rf._type = rf.TOK_OPERATOR;
} else {
System.err.println("error - unknown token!");
}
// determine funtion object, if funtion
if (rf._type == rf.TOK_OPERATOR) {
rf._func = determineFunctionForToken(rf._strValue);
}
// System.out.println("token="+rf._strValue);
expression = expression.substring(pos + 1);
return rf;
}
/**
*/
protected void convertToRPN() {
int aktPos;
int ii = _tokenExpression.size();
for (aktPos = 0; aktPos < ii; aktPos++) {
RPNField h = (RPNField) _tokenExpression.elementAt(aktPos);
RPNField hh = null;
if (!tokenStack.empty()) {
hh = (RPNField) tokenStack.peek();
}
;
if (null != h) {
//System.out.println("h="+h._strValue);
}
switch (h._type) {
case RPNField.TOK_OPERATOR:
if (null != hh) {
//System.out.println("hh="+hh._strValue);
}
if (tokenStack.empty()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -