ITPub博客

首页 > 数据库 > 数据库开发技术 > 表达式解析器实例

表达式解析器实例

原创 数据库开发技术 作者:panpa 时间:2005-08-17 17:51:40 0 删除 编辑

今儿程序需要编写一个解析计算用户所给算数表达式的程序,采用多个函数逐级递归解析各层运算符的方法来实现.支持的运算符包括:+ - * / % ^ ( ) ? :

这里共享出来供大家参考

[@more@]

/**
* @author Panpa Pan
*
* Description:该类用于解析数学表达式,并计算获得所需值 支持的运算符包括:+,-,*,/,%,(,),?,:
*/
public class ExpressionParser {
//标识符类型
final int NONE = 0;

final int DELIMITER = 1;

final int VARIABLE = 2;

final int NUMBER = 3;

// 错误常量

final int SYNTAX = 0;

final int UNBALPARENS = 1;

final int NOEXP = 2;

final int DIVBYZERO = 3;

/* EOE标志解析器已达到表达式的结尾 */
final String EOE = "";

private String exp;//表达式变量

private int expIdx;//当前解析表达式的位置

private String token;//当前标识符

private int tokType;//当前标识符类型

public static void main(String[] args) {
String sqlStr = "(20<40)?100*3+34:(20<30)?30*150:20*300";
ExpressionParser parser = new ExpressionParser();
try {
double v = parser.evaluate(sqlStr);
System.out.print(v);
} catch (Exception e) {
e.printStackTrace();
}

}
public String evaluate(String expstr,String resultformat) throws Exception{
return ValueFormat.formatNumber(evaluate(expstr),resultformat);
}

public double evaluate(String expstr) throws Exception {
double result = 0;
if(expstr==null)
handleErr(NOEXP);
exp = expstr;
expIdx = 0;
getToken();
if (token.equals(EOE))
handleErr(NOEXP); // no expression present
result = evalExp1();
if (!token.equals(EOE))
handleErr(SYNTAX);
return result;
}

public void getToken() {
tokType = NONE;
token = "";
// Check for end of expression.
if (expIdx == exp.length()) {
token = EOE;
return;
}
//Skip over white space.
while (expIdx < exp.length()
&& Character.isWhitespace(exp.charAt(expIdx)))
++expIdx;
// Trailing whitespace ends expression.
if (expIdx == exp.length()) {
token = EOE;
return;
}
if (isDelim(exp.charAt(expIdx))) { // is operator
token += exp.charAt(expIdx);
expIdx++;
tokType = DELIMITER;
} else if (Character.isLetter(exp.charAt(expIdx))) { // is variable
while (!isDelim(exp.charAt(expIdx))) {
token += exp.charAt(expIdx);
expIdx++;
if (expIdx >= exp.length())
break;
}
tokType = VARIABLE;
} else if (Character.isDigit(exp.charAt(expIdx))) { // is number
while (!isDelim(exp.charAt(expIdx))) {
token += exp.charAt(expIdx);
expIdx++;
if (expIdx >= exp.length())
break;
}
tokType = NUMBER;
} else { // unknown character terminates expression
token = EOE;
return;
}
}

// Return true if c is a delimiter.
private boolean isDelim(char c) {
if (("+-/*%^=()?:><".indexOf(c) != -1))
return true;
return false;
}

public void handleErr(int errcd) throws Exception {
String[] errs = { "非法表达式", "表达式符号不配对", "空表达式", "除零运算" };
throw new Exception(errs[errcd]);
}

private double evalExp1() throws Exception {
char op;
double result;
double partialResult;
result = evalExp2();
while ((op = token.charAt(0)) == '<' || op == '>' || op== '=') {
getToken();
partialResult = evalExp2();
switch (op) {
case '<':
if(result < partialResult)
result = 1;
else
result = -1;
break;
case '>':
if(result > partialResult)
result = 1;
else
result = -1;
break;
case '=':
if(result == partialResult)
result = 1;
else
result = -1;
break;
}
}
return result;
}

private double evalExp2() throws Exception {
char op;
double result;
double partialResult;
result = evalExp3();
while ((op = token.charAt(0)) == '+' || op == '-') {
getToken();
partialResult = evalExp3();
switch (op) {
case '-':
result = result - partialResult;
break;
case '+':
result = result + partialResult;
break;
}
}
return result;
}

private double evalExp3() throws Exception {
char op;
double result;
double partialResult;
result = evalExp4();
while ((op = token.charAt(0)) == '*' || op == '/' || op == '%') {
getToken();
partialResult = evalExp4();
switch (op) {
case '*':
result = result * partialResult;
break;
case '/':
if (partialResult == 0.0)
handleErr(DIVBYZERO);
result = result / partialResult;
break;
case '%':
if (partialResult == 0.0)
handleErr(DIVBYZERO);
result = result % partialResult;
break;
}
}
return result;
}

private double evalExp4() throws Exception {
double result;
double partialResult;
double ex;
int t;
result = evalExp5();
if (token.equals("^")) {
getToken();
partialResult = evalExp4();
ex = result;
if (partialResult == 0.0) {
result = 1.0;
} else
for (t = (int) partialResult - 1; t > 0; t--)
result = result * ex;
}
return result;
}

private double evalExp5() throws Exception {
double result;
String op;
op = "";
if ((tokType == DELIMITER) && token.equals("+") || token.equals("-")) {
op = token;
getToken();
}
result = evalExp6();
if (op.equals("-"))
result = -result;
return result;
}

// Process a parenthesized expression
private double evalExp6() throws Exception {
double result;
if (token.equals("(")) {
getToken();
result = evalExp1();
if (!token.equals(")"))
handleErr(UNBALPARENS);
getToken();
if(token.equals("?")){
getToken();
if(result>0){ //
result = evalExp1();
if (!token.equals(":"))
handleErr(UNBALPARENS);
token = EOE;
}else{
evalExp1();
if (!token.equals(":"))
handleErr(UNBALPARENS);
getToken();
result = evalExp1();
}
}
} else
result = atom();
return result;
}

// Get the value of a number.
private double atom() throws Exception {
double result = 0.0;
switch (tokType) {
case NUMBER:
try {
result = Double.parseDouble(token);
} catch (NumberFormatException exc) {
handleErr(SYNTAX);
}
getToken();
break;
default:
if(!token.equals(":"))
handleErr(SYNTAX);
break;
}
return result;
}
}

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/67736/viewspace-804669/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    20
  • 访问量
    56017