?? 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 + -