|
@@ -0,0 +1,556 @@
|
|
|
+package xbc.formula.engine.exp.parser;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashSet;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+import xbc.formula.engine.exp.datatype.XbcExpExpKind;
|
|
|
+import xbc.formula.engine.exp.datatype.XbcExpExpOpKind;
|
|
|
+import xbc.formula.engine.exp.datatype.XbcExpExpTree;
|
|
|
+import xbc.formula.engine.exp.datatype.XbcExpExpVarKind;
|
|
|
+import xbc.formula.engine.exp.datatype.XbcExpToken;
|
|
|
+import xbc.formula.engine.exp.exception.XbcExpParseException;
|
|
|
+import xbc.formula.engine.exp.scanner.XbcExpScanner;
|
|
|
+import xbc.formula.engine.exp.vo.XbcExpDrawnInfoVo;
|
|
|
+import xbc.formula.engine.exp.vo.XbcExpIntervalVo;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 语法分析,最总得到表达式树
|
|
|
+ *
|
|
|
+ * @author leichangchun
|
|
|
+ */
|
|
|
+public class XbcExpParser {
|
|
|
+
|
|
|
+ private String expStr;
|
|
|
+
|
|
|
+ private XbcExpScanner es;
|
|
|
+
|
|
|
+ private int token;
|
|
|
+
|
|
|
+ private Set<String> paramSet;
|
|
|
+
|
|
|
+ private boolean mkDiv;
|
|
|
+
|
|
|
+ public XbcExpParser(String expStr) {
|
|
|
+ this(expStr, false);
|
|
|
+ }
|
|
|
+ public XbcExpParser(String expStr, boolean mkDiv) {
|
|
|
+ this.expStr = expStr;
|
|
|
+ this.mkDiv = mkDiv;
|
|
|
+ paramSet = new HashSet<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public Set<String> getParamSet() {
|
|
|
+ return paramSet;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<XbcExpDrawnInfoVo> getDrawnInfoVos() {
|
|
|
+ if(es == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return es.getDrawnInfoVos();
|
|
|
+ }
|
|
|
+
|
|
|
+ public XbcExpExpTree parse() {
|
|
|
+ es = new XbcExpScanner(expStr, mkDiv);
|
|
|
+ XbcExpExpTree exp = null;
|
|
|
+ token = es.readToken();
|
|
|
+ //while(token != XbcExpToken.EOF_TT) {
|
|
|
+ switch(token) {
|
|
|
+ case XbcExpToken.EXPNAME_TT: // variable-name
|
|
|
+ case XbcExpToken.INT_TT: // integer
|
|
|
+ case XbcExpToken.DBL_TT: // double
|
|
|
+ case XbcExpToken.STR_TT: // string
|
|
|
+ case XbcExpToken.LPRN_TT: // (
|
|
|
+ case XbcExpToken.SELFMNS_TT: // --
|
|
|
+ case XbcExpToken.SELFPLS_TT: // ++
|
|
|
+ case XbcExpToken.PLS_TT: // +
|
|
|
+ case XbcExpToken.MNS_TT: // -
|
|
|
+ case XbcExpToken.BNOT_TT: // ~
|
|
|
+ case XbcExpToken.NOT_TT: // !
|
|
|
+ exp = readExpTree();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new XbcExpParseException("未知的符号: " + XbcExpToken.getTokenName(token) + ", 公式: " + expStr);
|
|
|
+ }
|
|
|
+ token = es.readToken();
|
|
|
+ if(token != XbcExpToken.EOF_TT) {
|
|
|
+ throw new XbcExpParseException("多余的符号: " + XbcExpToken.getTokenName(token) + ", 公式: " + expStr);
|
|
|
+ }
|
|
|
+ //}
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void match(int expectedToken) {
|
|
|
+ if(expectedToken != token) {
|
|
|
+ throw new XbcExpParseException("希望符号【" + XbcExpToken.getTokenName(expectedToken) + "】, 实际符号【" + XbcExpToken.getTokenName(token) + "】。" + " 公式: " + expStr);
|
|
|
+ }
|
|
|
+ token = es.readToken();
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readExpTree() {
|
|
|
+ XbcExpExpTree exp = readAsnExp();
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int translateAsnEt(int t) {
|
|
|
+ switch(t) {
|
|
|
+ case XbcExpToken.MODASN_TT:
|
|
|
+ return XbcExpExpOpKind.MODASN_OK;
|
|
|
+ case XbcExpToken.BANDASN_TT:
|
|
|
+ return XbcExpExpOpKind.BANDASN_OK;
|
|
|
+ case XbcExpToken.MPTASN_TT:
|
|
|
+ return XbcExpExpOpKind.MPTASN_OK;
|
|
|
+ case XbcExpToken.DIVASN_TT:
|
|
|
+ return XbcExpExpOpKind.DIVASN_OK;
|
|
|
+ case XbcExpToken.BXORASN_TT:
|
|
|
+ return XbcExpExpOpKind.BXORASN_OK;
|
|
|
+ case XbcExpToken.BORASN_TT:
|
|
|
+ return XbcExpExpOpKind.BORASN_OK;
|
|
|
+ case XbcExpToken.PLSASN_TT:
|
|
|
+ return XbcExpExpOpKind.PLSASN_OK;
|
|
|
+ case XbcExpToken.S2LASN_TT:
|
|
|
+ return XbcExpExpOpKind.S2LASN_OK;
|
|
|
+ case XbcExpToken.ASN_TT:
|
|
|
+ return XbcExpExpOpKind.ASN_OK;
|
|
|
+ case XbcExpToken.MNSASN_TT:
|
|
|
+ return XbcExpExpOpKind.MNSASN_OK;
|
|
|
+ case XbcExpToken.S2RASN_TT:
|
|
|
+ return XbcExpExpOpKind.S2RASN_OK;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ // 最基础的表达式
|
|
|
+ private XbcExpExpTree readAsnExp() {
|
|
|
+ XbcExpExpTree exp = readCndExp();
|
|
|
+ int op = translateAsnEt(token);
|
|
|
+ if(op > 0) {
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(op);
|
|
|
+ match(token);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readAsnExp();
|
|
|
+ exp = exp1;
|
|
|
+ }
|
|
|
+ // 读取层差表达式
|
|
|
+ if(token == XbcExpToken.LSQB_TT) {
|
|
|
+ XbcExpExpTree itvExp = readItvExp(exp);
|
|
|
+ exp = itvExp;
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readItvExp(XbcExpExpTree lchild) {
|
|
|
+ match(XbcExpToken.LSQB_TT);
|
|
|
+ XbcExpExpTree exp = new XbcExpExpTree(XbcExpExpOpKind.ITV_OK);
|
|
|
+ exp.lchild = lchild;
|
|
|
+ List<XbcExpIntervalVo> itvs = new ArrayList<>();
|
|
|
+ exp.itvs = itvs;
|
|
|
+ while(true) { // 读取区间列表
|
|
|
+ XbcExpIntervalVo itv = new XbcExpIntervalVo();
|
|
|
+ itvs.add(itv);
|
|
|
+ if(token == XbcExpToken.CLN_TT) {
|
|
|
+ if(exp.rchild != null) {
|
|
|
+ throw new XbcExpParseException("层差表达式里面,只能设置一个默认值。 公式: " + expStr);
|
|
|
+ }
|
|
|
+ match(token);
|
|
|
+ exp.rchild = readAsnExp();
|
|
|
+ match(XbcExpToken.CMM_TT);
|
|
|
+ }
|
|
|
+ if(token == XbcExpToken.LT_TT || token == XbcExpToken.LEQ_TT || token == XbcExpToken.GT_TT || token == XbcExpToken.GEQ_TT) {
|
|
|
+ itv.token = token;
|
|
|
+ match(token);
|
|
|
+ itv.startExp = readAsnExp();
|
|
|
+ } else {
|
|
|
+ if(token == XbcExpToken.LPRN_TT) { // ( 开区间
|
|
|
+ itv.startType = XbcExpIntervalVo.OPEN_INTERVAL;
|
|
|
+ } else if(token == XbcExpToken.LBKT_TT) { // [ 闭区间
|
|
|
+ itv.startType = XbcExpIntervalVo.CLOSE_INTERVAL;
|
|
|
+ } else { // , 无起点区间
|
|
|
+ throw new XbcExpParseException("希望符号【" + XbcExpToken.getTokenName(XbcExpToken.LPRN_TT) + "】或【" +
|
|
|
+ XbcExpToken.getTokenName(XbcExpToken.LBKT_TT) + "】, 实际符号【" + XbcExpToken.getTokenName(token) + "】。" + " 公式: " + expStr);
|
|
|
+ }
|
|
|
+ match(token);
|
|
|
+ if(token == XbcExpToken.CMM_TT) {
|
|
|
+ itv.startExp = null;
|
|
|
+ } else {
|
|
|
+ itv.startExp = readAsnExp();
|
|
|
+ }
|
|
|
+ match(XbcExpToken.CMM_TT);
|
|
|
+ if(token == XbcExpToken.RPRN_TT || token == XbcExpToken.RBKT_TT) {
|
|
|
+ if(itv.startExp == null) {
|
|
|
+ throw new XbcExpParseException("层差表达式的区间,不能起点和终点都为空。 公式: " + expStr);
|
|
|
+ }
|
|
|
+ itv.endExp = null;
|
|
|
+ } else {
|
|
|
+ itv.endExp = readAsnExp();
|
|
|
+ }
|
|
|
+ if(token == XbcExpToken.RPRN_TT) {
|
|
|
+ itv.endType = XbcExpIntervalVo.OPEN_INTERVAL;
|
|
|
+ } else if(token == XbcExpToken.RBKT_TT) {
|
|
|
+ itv.endType = XbcExpIntervalVo.CLOSE_INTERVAL;
|
|
|
+ } else {
|
|
|
+ throw new XbcExpParseException("希望符号【" + XbcExpToken.getTokenName(XbcExpToken.RPRN_TT) + "】或【" +
|
|
|
+ XbcExpToken.getTokenName(XbcExpToken.RBKT_TT) + "】, 实际符号【" + XbcExpToken.getTokenName(token) + "】。" + " 公式: " + expStr);
|
|
|
+ }
|
|
|
+ match(token);
|
|
|
+ }
|
|
|
+ match(XbcExpToken.CLN_TT);
|
|
|
+ itv.valueExp = readAsnExp();
|
|
|
+ if(token == XbcExpToken.RSQB_TT) {
|
|
|
+ match(token);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(token == XbcExpToken.CMM_TT) {
|
|
|
+ match(token);
|
|
|
+ } else {
|
|
|
+ throw new XbcExpParseException("希望符号【" + XbcExpToken.getTokenName(XbcExpToken.RSQB_TT) + "】或【" +
|
|
|
+ XbcExpToken.getTokenName(XbcExpToken.CMM_TT) + "】, 实际符号【" + XbcExpToken.getTokenName(token) + "】。" + " 公式: " + expStr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readCndExp() {
|
|
|
+ XbcExpExpTree exp = readOrExp();
|
|
|
+ if(token == XbcExpToken.QRY_TT) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(XbcExpExpOpKind.QRY_OK);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = new XbcExpExpTree(XbcExpExpOpKind.NULL_OK);
|
|
|
+ exp = exp1;
|
|
|
+ exp1 = exp1.rchild;
|
|
|
+ exp1.lchild = readAsnExp();
|
|
|
+ match(XbcExpToken.CLN_TT);
|
|
|
+ exp1.rchild = readAsnExp();
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readOrExp() {
|
|
|
+ XbcExpExpTree exp = readAndExp();
|
|
|
+ while(token == XbcExpToken.OR_TT) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(XbcExpExpOpKind.OR_OK);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readAndExp();
|
|
|
+ exp = exp1;
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readAndExp() {
|
|
|
+ XbcExpExpTree exp = readBorExp();
|
|
|
+ while(token == XbcExpToken.AND_TT) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(XbcExpExpOpKind.AND_OK);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readBorExp();
|
|
|
+ exp = exp1;
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readBorExp() {
|
|
|
+ XbcExpExpTree exp = readBxorExp();
|
|
|
+ while(token == XbcExpToken.BOR_TT) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(XbcExpExpOpKind.BOR_OK);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readBxorExp();
|
|
|
+ exp = exp1;
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readBxorExp() {
|
|
|
+ XbcExpExpTree exp = readBandExp();
|
|
|
+ while(token == XbcExpToken.BXOR_TT) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(XbcExpExpOpKind.BXOR_OK);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readBandExp();
|
|
|
+ exp = exp1;
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readBandExp() {
|
|
|
+ XbcExpExpTree exp = readEquExp();
|
|
|
+ while(token == XbcExpToken.BAND_TT) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(XbcExpExpOpKind.BAND_OK);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readEquExp();
|
|
|
+ exp = exp1;
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int translateEquEt(int t) {
|
|
|
+ switch(t) {
|
|
|
+ case XbcExpToken.EQ_TT:
|
|
|
+ return XbcExpExpOpKind.EQ_OK;
|
|
|
+ case XbcExpToken.NEQ_TT:
|
|
|
+ return XbcExpExpOpKind.NEQ_OK;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readEquExp() {
|
|
|
+ XbcExpExpTree exp = readRelExp();
|
|
|
+ int op = translateEquEt(token);
|
|
|
+ while(op > 0) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(op);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readRelExp();
|
|
|
+ exp = exp1;
|
|
|
+ op = translateEquEt(token);
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int translateRelEt(int t) {
|
|
|
+ switch(t) {
|
|
|
+ case XbcExpToken.LT_TT:
|
|
|
+ return XbcExpExpOpKind.LT_OK;
|
|
|
+ case XbcExpToken.LEQ_TT:
|
|
|
+ return XbcExpExpOpKind.LEQ_OK;
|
|
|
+ case XbcExpToken.GT_TT:
|
|
|
+ return XbcExpExpOpKind.GT_OK;
|
|
|
+ case XbcExpToken.GEQ_TT:
|
|
|
+ return XbcExpExpOpKind.GEQ_OK;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readRelExp() {
|
|
|
+ XbcExpExpTree exp = readShiftExp();
|
|
|
+ int op = translateRelEt(token);
|
|
|
+ while(op > 0) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(op);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readShiftExp();
|
|
|
+ exp = exp1;
|
|
|
+ op = translateRelEt(token);
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int translateShiftEt(int t) {
|
|
|
+ switch(t) {
|
|
|
+ case XbcExpToken.S2L_TT:
|
|
|
+ return XbcExpExpOpKind.S2L_OK;
|
|
|
+ case XbcExpToken.S2R_TT:
|
|
|
+ return XbcExpExpOpKind.S2R_OK;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readShiftExp() {
|
|
|
+ XbcExpExpTree exp = readAddExp();
|
|
|
+ int op = translateShiftEt(token);
|
|
|
+ while(op > 0) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(op);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readAddExp();
|
|
|
+ exp = exp1;
|
|
|
+ op = translateShiftEt(token);
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int translateAddEt(int t) {
|
|
|
+ switch(t) {
|
|
|
+ case XbcExpToken.PLS_TT:
|
|
|
+ return XbcExpExpOpKind.PLS_OK;
|
|
|
+ case XbcExpToken.MNS_TT:
|
|
|
+ return XbcExpExpOpKind.MNS_OK;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readAddExp() {
|
|
|
+ XbcExpExpTree exp = readMulExp();
|
|
|
+ int op = translateAddEt(token);
|
|
|
+ while(op > 0) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(op);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readMulExp();
|
|
|
+ exp = exp1;
|
|
|
+ op = translateAddEt(token);
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int translateMulEt(int t) {
|
|
|
+ switch(t) {
|
|
|
+ case XbcExpToken.MPT_TT:
|
|
|
+ return XbcExpExpOpKind.MPT_OK;
|
|
|
+ case XbcExpToken.DIV_TT:
|
|
|
+ return XbcExpExpOpKind.DIV_OK;
|
|
|
+ case XbcExpToken.MOD_TT:
|
|
|
+ return XbcExpExpOpKind.MOD_OK;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readMulExp() {
|
|
|
+ XbcExpExpTree exp = readCastExp();
|
|
|
+ int op = translateMulEt(token);
|
|
|
+ while(op > 0) {
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(op);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.rchild = readCastExp();
|
|
|
+ exp = exp1;
|
|
|
+ op = translateMulEt(token);
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readCastExp() {
|
|
|
+ XbcExpExpTree exp = null;
|
|
|
+ switch(token) {
|
|
|
+ case XbcExpToken.SELFPLS_TT:
|
|
|
+ match(token);
|
|
|
+ exp = new XbcExpExpTree(XbcExpExpOpKind.PREINC_OK);
|
|
|
+ exp.lchild = readCastExp();
|
|
|
+ break;
|
|
|
+ case XbcExpToken.SELFMNS_TT:
|
|
|
+ match(token);
|
|
|
+ exp = new XbcExpExpTree(XbcExpExpOpKind.PREDEC_OK);
|
|
|
+ exp.lchild = readCastExp();
|
|
|
+ break;
|
|
|
+ case XbcExpToken.MNS_TT:
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = readCastExp();
|
|
|
+ if(exp1.ek == XbcExpExpKind.CST_EK || (exp1.ok != XbcExpExpVarKind.INT_VK && exp1.ok != XbcExpExpVarKind.DBL_VK)) {
|
|
|
+ exp = new XbcExpExpTree(XbcExpExpOpKind.MNS_OK);
|
|
|
+ exp.lchild = XbcExpExpTree.newConstIntExptree("0", expStr);
|
|
|
+ exp.rchild = exp1;
|
|
|
+ } else {
|
|
|
+ if(exp1.ok == XbcExpExpVarKind.INT_VK) {
|
|
|
+ exp1.value = 0 - (int)exp1.value;
|
|
|
+ } else {
|
|
|
+ exp1.value = 0.0 - (double)exp1.value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case XbcExpToken.PLS_TT:
|
|
|
+ match(token);
|
|
|
+ exp = readCastExp();
|
|
|
+ break;
|
|
|
+ case XbcExpToken.BNOT_TT:
|
|
|
+ match(token);
|
|
|
+ exp = new XbcExpExpTree(XbcExpExpOpKind.BNOT_OK);
|
|
|
+ exp.lchild = readCastExp();
|
|
|
+ break;
|
|
|
+ case XbcExpToken.NOT_TT:
|
|
|
+ match(token);
|
|
|
+ exp = new XbcExpExpTree(XbcExpExpOpKind.NOT_OK);
|
|
|
+ exp.lchild = readCastExp();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ exp = readPfExp();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isPfEt(int t) {
|
|
|
+ switch(t) {
|
|
|
+ case XbcExpToken.LPRN_TT:
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void readFuncPlist(XbcExpExpTree exp, String fname) {
|
|
|
+ while(token != XbcExpToken.RPRN_TT) {
|
|
|
+ XbcExpExpTree pexp = readAsnExp();
|
|
|
+ exp.params.add(pexp);
|
|
|
+ if(token == XbcExpToken.CMM_TT) {
|
|
|
+ match(token);
|
|
|
+ if(token == XbcExpToken.RPRN_TT) {
|
|
|
+ throw new XbcExpParseException("解析函数【" + fname + "】的参数时出错。" + " 公式: " + expStr);
|
|
|
+ }
|
|
|
+ } else if(token != XbcExpToken.RPRN_TT) {
|
|
|
+ throw new XbcExpParseException("解析函数【" + fname + "】的参数时出错。" + " 公式: " + expStr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ match(XbcExpToken.RPRN_TT);
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readPfExp() {
|
|
|
+ XbcExpExpTree exp = readFactExp();
|
|
|
+ if(exp == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if(exp.ek == XbcExpExpKind.CST_EK && exp.ok != XbcExpExpVarKind.STR_VK) {
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+ while(isPfEt(token)) {
|
|
|
+ switch(token) {
|
|
|
+ case XbcExpToken.LPRN_TT:
|
|
|
+ match(token);
|
|
|
+ XbcExpExpTree exp1 = new XbcExpExpTree(XbcExpExpOpKind.FUNC_OK);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp1.params = new ArrayList<>();
|
|
|
+ paramSet.remove((String)exp.value);
|
|
|
+ es.setFunctionDiv((String)exp.value);
|
|
|
+ readFuncPlist(exp1, (String)exp.value);
|
|
|
+ exp = exp1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(token == XbcExpToken.SELFMNS_TT || token == XbcExpToken.SELFPLS_TT) {
|
|
|
+ XbcExpExpTree exp1 = null;
|
|
|
+ if(token == XbcExpToken.SELFMNS_TT) {
|
|
|
+ exp1 = new XbcExpExpTree(XbcExpExpOpKind.AFTDEC_OK);
|
|
|
+ } else {
|
|
|
+ exp1 = new XbcExpExpTree(XbcExpExpOpKind.AFTINC_OK);
|
|
|
+ }
|
|
|
+ match(token);
|
|
|
+ exp1.lchild = exp;
|
|
|
+ exp = exp1;
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private XbcExpExpTree readFactExp() {
|
|
|
+ XbcExpExpTree exp = null;
|
|
|
+ switch(token) {
|
|
|
+ case XbcExpToken.EXPNAME_TT:
|
|
|
+ String tokenContent = es.getTokenContent();
|
|
|
+ exp = XbcExpExpTree.newIdExptree(tokenContent);
|
|
|
+ paramSet.add(tokenContent);
|
|
|
+ match(token);
|
|
|
+ break;
|
|
|
+ case XbcExpToken.INT_TT:
|
|
|
+ exp = XbcExpExpTree.newConstIntExptree(es.getTokenContent(), expStr);
|
|
|
+ match(token);
|
|
|
+ break;
|
|
|
+ case XbcExpToken.DBL_TT:
|
|
|
+ exp = XbcExpExpTree.newConstDblExptree(es.getTokenContent(), expStr);
|
|
|
+ match(token);
|
|
|
+ break;
|
|
|
+ case XbcExpToken.STR_TT:
|
|
|
+ exp = XbcExpExpTree.newConstStrExptree(es.getTokenContent());
|
|
|
+ match(token);
|
|
|
+ break;
|
|
|
+ case XbcExpToken.LPRN_TT:
|
|
|
+ match(token);
|
|
|
+ exp = readExpTree();
|
|
|
+ match(XbcExpToken.RPRN_TT);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new XbcExpParseException("读取表达式出错: " + es.getTokenContent() + ", 公式: " + expStr);
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+}
|