📄 parser.java
字号:
/*
* 创建日期 2005-4-4
*
* TODO 要更改此生成的文件的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/
/**
* @author Administrator
*
* TODO 递归下降法解析表达式
* 表达式充许:加,减,乘,除,乘方,括号
*/
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;
//变量的值存储表
private double vars[]=new double[26];
//表达式解析入口
public double evaluate(String expstr) throws ParserException
{
double result;
exp=expstr;
expIdx=0;
getToken();
//没有表达式出错
if(token.equals(EOE))
handleErr(NOEXP);
//执行表达式解析
result=evalExp1();
//表达式没有结束符
if(!token.equals(EOE))
handleErr(SYNTAX);
return result;
}
//处理变量的值
private double evalExp1() throws ParserException
{
double result;
int varIdx;
int ttokType;
String temptoken;
if(tokType==VARIABLE)
{
//保存当前项
temptoken=new String(token);
ttokType=tokType;
//记录变量的下标
varIdx=Character.toUpperCase(token.charAt(0))-'A';
getToken();
if(!token.equals("=")){
putBack();//返回到取本次取等号之前
token = new String(temptoken);
tokType=ttokType;
}
else{
getToken();
result = evalExp2();
vars[varIdx]=result;
return result;
}
}
return evalExp2();
}
/*加,减两个项
*
*/
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;
}
//对两个因数 乘,除,或取余
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;
}
//乘方处理
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;
}
//正负号的处理
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;
}
//括号的处理
private double evalExp6() throws ParserException
{
double result;
if(token.equals("(")){
getToken();
result= evalExp2();
if(!token.equals(")"))
handleErr(UNBALPARENS);
getToken();
}
else
result =atom();
return result;
}
//获取表达式中的数值因数
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;
case VARIABLE:
result=findVar(token);
getToken();
break;
default:
handleErr(SYNTAX);
break;
}
return result;
}
/*
* 获最变量名第一个字符与A的偏移量为下标的数组里的变量值
*/
private double findVar(String vname) throws ParserException
{
if(!Character.isLetter(vname.charAt(0))){
handleErr(SYNTAX);
return 0.0;
}
return vars[Character.toUpperCase(vname.charAt(0))-'A'];
}
/*
* 将表达式的输入字符后退到当前处理之前
*/
private void putBack()
{
if(token==EOE) return;
for(int i=0;i<token.length();i++) expIdx--;
}
//捕捉出错
private void handleErr(int error) throws ParserException
{
String[] err={
"错误0: 非正则表达式错误!",
"错误1: 表达式中括号不匹配!",
"错误2: 没有表达式!",
"错误3: 除零错!"
};
//抛出异常
throw new ParserException(err[error]);
}
//获取表达式的下一项
private void getToken()
{
//将当前项置空
tokType=NONE;
token="";
//检查表达式是否结束
if(expIdx == exp.length()){
token = EOE;
return;
}
//去除空白符
while(expIdx<exp.length() && Character.isWhitespace(exp.charAt(expIdx)))
++expIdx;
//去空白符后,再次检查是否结束
if(expIdx == exp.length()){
token = EOE;
return;
}
//当前项为分隔符
if(isDelim(exp.charAt(expIdx))){
token += exp.charAt(expIdx);
expIdx++;
tokType = DELIMITER;
}//当前项为变量,变量只有第一个字母有意义
else if(Character.isLetter(exp.charAt(expIdx))){
while(!isDelim(exp.charAt(expIdx))){
token += exp.charAt(expIdx);
expIdx++;
if(expIdx>=exp.length()) break;
}
tokType= VARIABLE;
}//当前项为数值
else if(Character.isDigit(exp.charAt(expIdx))){
while(!isDelim(exp.charAt(expIdx))){
token += exp.charAt(expIdx);
expIdx++;
if(expIdx>=exp.length()) break;
}
tokType = NUMBER;
}//结束
else{
token=EOE;
return;
}
}
/**检查是否为分隔符
* @param c
* @return
*/
private boolean isDelim(char c) {
// TODO 自动生成方法存根
if((" +-/*%^=()".indexOf(c) != -1))
return true;
else
return false;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -