站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Java 专题一个简单的表达式解析器

一个简单的表达式解析器

摘要: 一个简单的表达式解析器

</td> </tr> <tr> <td width="506" height="35" valign="top" class="ArticleTeitle"> 一个简单的表达式解析器,这个解析器可以计算仅由数字、运算符和括号组成的表达式的值。
下面是演示这个解析器的代码:
import java.io.*;

class PDemo {
public static void main(String args[])
throws IOException
{
String expr;

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Parser p = new Parser();

System.out.println("Enter an empty expression to stop.");

for(;;) {
System.out.print("Enter expression: ");
expr = br.readLine(); //从命令行输入表达式
if(expr.equals("")) break;
try {
System.out.println("Result: " + p.evaluate(expr)); //计算表达式的值并输出
System.out.println();
} catch (ParserException exc) {
System.out.println(exc);
}
}
}
}

运行结果:

C:\java>java PDemo
Enter an empty expression to stop.
Enter expression: 3+7*9
Result: 66.0

Enter expression: (2+3)-7*9
Result: -58.0

Enter expression:

C:\java>
附解析器源码:
/*
不能处理变量的递归下降的表达式解析器
*/

// 处理错误的异常类
class ParserException extends Exception {
String errStr; // describes the error

public ParserException(String str) {
errStr = str;
}

public String toString() {
return errStr;
}
}

class Parser {
// 标识符的类型
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; //被零除

// 这个标识符表示表达式结束
final String EOE = "\0";

private String exp; // 字符串表达式
private int expIdx; // 标识符当前索引
private String token; // 标识符
private int tokType; // 标识符的类型

// 计算表达式的值并返回结果.
public double evaluate(String expstr) throws ParserException
{
double result;
exp = expstr;
expIdx = 0;

getToken();
if(token.equals(EOE))
handleErr(NOEXP); // no expression present

// Parse and evaluate the expression.
result = evalExp2();

if(!token.equals(EOE)) // last token must be EOE
handleErr(SYNTAX);

return result;
}

// Add or subtract two terms.
private double evalExp2() throws ParserException
{
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;
}

// Multiply or divide two factors.
private double evalExp3() throws ParserException
{
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;
}

// Process an exponent.
private double evalExp4() throws ParserException
{
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;
}

// Evaluate a unary + or -.
private double evalExp5() throws ParserException
{
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 ParserException
{
double result;

if(token.equals("(")) {
getToken();
result = evalExp2();
if(!token.equals(")"))
handleErr(UNBALPARENS);
getToken();
}
else result = atom();

return result;
}

// Get the value of a number.
private double atom() throws ParserException
{
double result = 0.0;

switch(tokType) {
case NUMBER:
try {
result = Double.parseDouble(token);
} catch (NumberFormatException exc) {
handleErr(SYNTAX);
}
getToken();
break;
default:
handleErr(SYNTAX);
break;
}
return result;
}

// Handle an error.
private void handleErr(int error) throws ParserException
{
String[] err = {
"Syntax Error",
"Unbalanced Parentheses",
"No Expression Present",
"Division by Zero"
};

throw new ParserException(err[error]);
}

// Obtain the next token.
private 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;
}

} </td> <td width="198" valign="top" class="ArticleTeitle">
</td> </tr> <tr> <td height="25" colspan="2" valign="top" class="ArticleTeitle">


↑返回目录
前一篇: HTML标记过滤
后一篇: 收邮件的演示程序