📄 expcomplier.java
字号:
/*
* Copyright 2006 CSK
* http://www.csksoft.net
*/
package net.csksoft.util.expcomp;
import org.omg.CORBA.*;
import java.util.*;
public class ExpComplier {
private String strExpressionBuf;
private LinkedList<ExpToken> tokenCalBuf;
private String strLastErrInfo;
public ExpComplier()
{
initEnv();
}
public ExpComplier(String Exp)
{
initEnv();
SetExpression(Exp);
}
public String SetExpression(String Exp)
{
String strOld;
strOld = strExpressionBuf;
strExpressionBuf = Exp;
return strOld;
}
public String GetExpression()
{
return strExpressionBuf;
}
public String GetLastError()
{
return strLastErrInfo;
}
public boolean Complie()
{
return TokenizerAndParse();
}
private boolean TokenizerAndParse()
{
tokenCalBuf.clear();
int nPos;
int nLastState;
Stack<Character> stkParser = new Stack<Character>();
Stack<Integer> stkParserNum = new Stack<Integer>();
String tmpStr= new String(strExpressionBuf);
String tmpNumBuffer = "";
tmpStr = "#" + tmpStr + "#";
ExpToken currentToken;
nLastState = 0;
char cLast = 0;
char cCurrent =0 ;
for (nPos=0;nPos<tmpStr.length();nPos++) // DFA RegExp
{
cLast = cCurrent;
cCurrent= tmpStr.charAt(nPos);
switch(getCharType(cCurrent))
{
case 0: // invaild char
strLastErrInfo = "at" + nPos + " bad operation type";
return false;
case 1: // number
switch(nLastState)
{
case 0://start
tmpNumBuffer ="";
break;
case 1://last is number
tmpNumBuffer +=cCurrent;
break;
case 2://last is op
tmpNumBuffer = "";
tmpNumBuffer +=cCurrent;
break;
}
nLastState = 1;
break;
case 2: //operator
switch(nLastState)
{
case 0://start
break;
case 1://last is number
NumberToken tmpNumbetTk =new NumberToken();
try
{
tmpNumbetTk.setValue(Double.parseDouble(tmpNumBuffer));
}
catch(NumberFormatException ec){
strLastErrInfo = "at" + nPos + " Bad Number";
return false;
}
currentToken = (ExpToken)tmpNumbetTk;
tokenCalBuf.add(currentToken);
break;
case 2:
if (cCurrent=='+' || cCurrent=='-')
{
if (cLast!=')')
{
currentToken = (ExpToken)new NumberToken(0);
tokenCalBuf.add(currentToken);
}
}
}
if (cCurrent == '#'){
if (nPos!=0 && nPos!=tmpStr.length()-1)
{
strLastErrInfo = "at" + nPos + " bad operation type";
return false;
}
}
if (!onGetOpToken(stkParser,stkParserNum,nPos,cCurrent,nLastState)) return false;
nLastState = 2;
break;
}
}
if (!stkParser.isEmpty())
{
strLastErrInfo = "at" + nPos + " stack err";
return false;
}
return true;
}
private boolean onGetOpToken(Stack<Character> opstk,Stack<Integer> opNumstk,int currentpos,char cToken,int laststate)
{
char tmpStkToken;
do
{
if (opstk.isEmpty()){
if (cToken=='#'){
opstk.push(new Character(cToken));
opNumstk.push(new Integer(laststate));
return true;
}
else
{
strLastErrInfo = "at" + currentpos + " stack err";
return false;
}
}
tmpStkToken = opstk.peek().charValue();
int currentTokenInfo = opNumstk.peek().intValue();
switch(compareOpLevel(tmpStkToken,cToken))
{
case 0:
opstk.pop();
opNumstk.pop();
return true;
case -1:
opstk.push(new Character(cToken));
opNumstk.push(new Integer(laststate));
return true;
case 1:
opstk.pop();
opNumstk.pop();
ExpToken tOpToken;
switch(tmpStkToken)
{
case '+':
// if (currentTokenInfo==2){
// OpPlus tmpTk = new OpPlus();
// tmpTk.setArgNum(1);
// tOpToken =(ExpToken)tmpTk;
// }else
// {
tOpToken =(ExpToken) new OpPlus();
// }
break;
case '-':
// if (currentTokenInfo==2){
// OpMinus tmpTk = new OpMinus();
// tmpTk.setArgNum(1);
// tOpToken =(ExpToken)tmpTk;
// }else
// {
tOpToken =(ExpToken) new OpMinus();
// }
break;
case '*':
tOpToken =(ExpToken) new OpMul();
break;
case '/':
tOpToken =(ExpToken) new OpDiv();
break;
default:
strLastErrInfo = "at" + currentpos + " bad operation";
return false;
}
tokenCalBuf.add(tOpToken);
break;
case 2:
strLastErrInfo = "at" + currentpos + " bad operation" ;
return false;
}
}while(true);
}
private int compareOpLevel(char tokenA,char tokenB){
int[][] opLevelTable
={
// + - * / ^ ( ) #
{1, 1,-1,-1,-1,-1, 1, 1}, // +
{1, 1,-1,-1,-1,-1, 1, 1}, // -
{1, 1, 1, 1,-1,-1, 1, 1}, // *
{1, 1, 1, 1,-1,-1, 1, 1}, // /
{1, 1, 1, 1, 1,-1, 1, 1}, // ^
{-1,-1,-1,-1,-1,-1, 0, 2}, // (
{1, 1, 1, 1, 1, 2, 1, 1}, // )
{-1,-1,-1,-1,-1,-1, 2, 0} // #
};
return opLevelTable[getOpIndex(tokenA)][getOpIndex(tokenB)];
}
private int getCharType(char c){
String strDigitalTable = "0123456789.";
if (strDigitalTable.indexOf(c)!=-1) return 1;
if (getOpIndex(c)!=-1) return 2;
return 0;
}
private int getOpIndex(char c)
{
String strOperationTable = "+-*/^()#";
return strOperationTable.indexOf(c);
}
public boolean calc(DoubleHolder ans){
Stack<OpObj> stkCalc = new Stack<OpObj>();
if (strLastErrInfo.equals(""))
{
while(!tokenCalBuf.isEmpty())
{
ExpToken CurrentToken = tokenCalBuf.removeFirst();
switch(CurrentToken.getTokenType())
{
case ExpToken.TOKEN_NUMBER_CONST:
stkCalc.push((OpObj)CurrentToken);
break;
case ExpToken.TOKEN_OPERATION:
if (((OperationToken)CurrentToken).Calc(stkCalc) == false)
{
strLastErrInfo = "error when exec op";
return false;
}
}
}
if (stkCalc.isEmpty())
{
ans.value = 0;
}
else
{
ans.value = stkCalc.pop().getValue();
}
if (!stkCalc.isEmpty())
{
strLastErrInfo = "stack err";
return false;
}
return true;
}
return false;
}
private void initEnv()
{
tokenCalBuf = new LinkedList<ExpToken>();
strExpressionBuf = "";
strLastErrInfo = "";
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -