DExpression { protected void parse() throws DException { int iPos; Stack<TokenBase> functionStack = new Stack<TokenBase>(); Stack<TokenBase> operatorStack = new Stack<TokenBase>(); Stack<TokenBase> operandStack = new Stack<TokenBase>(); TokenBase newToken; TokenBase popToken; boolean safe; GetTokenResult actToken; GetTokenResult nextToken; int actTokenType; int lastTokenType; if (parsed) { if (error != null) throw error; return; } varCache.clear(); root = null; lastTokenType = TK_NULL; actToken = new GetTokenResult(); actToken.end = 1; nextToken = new GetTokenResult(); do { iPos = actToken.end; if (nextToken.type != TK_NULL) { actToken.value = nextToken.value; actToken.type = nextToken.type; actToken.begin = nextToken.begin; actToken.end = nextToken.end; nextToken.reset(); } else { getToken(this.exp, iPos, actToken); } if (actToken.type != TK_NULL) { actTokenType = actToken.type; if (! checkTokenOrder(lastTokenType, actTokenType)) { switch (lastTokenType) { case TK_VAL: case TK_PCL: throw new ExpectedEndOfStatement(actToken.begin); case TK_UOP: case TK_OP: case TK_POP: case TK_COM: case TK_NULL: throw new MissingOperand(actToken.begin); default: throw new ExpectedEndOfStatement(actToken.begin); } } switch (actTokenType) { case TK_VAL: newToken = TokenValue.InitToken(TokenValue.ParseRawValue(actToken.value), actToken.begin); operandStack.add(newToken); break; case TK_UOP: case TK_OP: newToken = TokenOperator.InitToken(actToken.value, actToken.begin); if (newToken instanceof UnaryOperator && ( lastTokenType == TK_UOP || lastTokenType == TK_OP || lastTokenType == TK_COM || lastTokenType == TK_POP || lastTokenType == TK_NULL )) { ((UnaryOperator) newToken).setUnary(true); } while (! operatorStack.isEmpty() && (popToken = operatorStack.peek()) instanceof TokenOperator) { if ((!newToken.isRightAssociative() && newToken.getPriority() == popToken.getPriority()) || newToken.getPriority() < popToken.getPriority()) { operatorStack.pop(); addNode(operandStack, popToken); } else { break; } } operatorStack.push(newToken); break; case TK_POP: operatorStack.push(new TokenPar(actToken.begin)); break; case TK_PCL: safe = false; while (! operatorStack.isEmpty()) { popToken = operatorStack.pop(); if (popToken instanceof TokenPar) { if (! operatorStack.isEmpty() && (popToken = operatorStack.peek()) instanceof TokenFunction) { if (lastTokenType != TK_POP) { popToken.setNextChild(null); } if (popToken.nextChildNum() <= popToken.getChildNumber()) { throw new ExpectedParameter(actToken.begin); } addNode(operandStack, operatorStack.pop()); functionStack.pop(); } safe = true; break; } addNode(operandStack, popToken); } if (! safe) { throw new UnbalancedBracket(actToken.begin); } break; case TK_COM: safe = false; while (! operatorStack.isEmpty()) { popToken = operatorStack.peek(); if (popToken instanceof TokenPar) { safe = true; break; } addNode(operandStack, operatorStack.pop()); } if (! safe || functionStack.isEmpty()) { throw new ExpectedEndOfStatement(actToken.begin); } popToken = functionStack.peek(); if (popToken.nextChildNum() + 1 > popToken.getMaxChildNumber()) { throw new UnexpectedParameter(actToken.begin); } popToken.setNextChild(null); break; default: getToken(this.exp, actToken.end, nextToken); if (nextToken.type == TK_POP) { newToken = TokenFunction.InitToken(actToken.value, actToken.begin); if (newToken == null) { throw new UnknownFunction(actToken.value, actToken.begin, actToken.end); } operatorStack.add(newToken); functionStack.add(newToken); } else { newToken = TokenValue.InitToken(actToken.value, actToken.begin); varCache.put(actToken.value, new DVariable()); operandStack.add(newToken); } } lastTokenType=actToken.type; } } while (actToken.type!=TK_NULL ); while (! operatorStack.isEmpty()) { if (operatorStack.peek() instanceof TokenPar) { throw new UnbalancedBracket(exp.length()+1); } addNode(operandStack, operatorStack.pop()); } if (operandStack.isEmpty()) { throw new NothingToEvaluate(); } root = operandStack.pop(); if (varCache.size() > 0) { varKeys = varCache.keySet().toArray(EMPTY_VAR_KEYS); } else { varKeys = EMPTY_VAR_KEYS; } parsed = true; } DExpression();  DExpression(String exp); void setExpression(String exp); String getExpression(); void setContext(DContext context); DContext getContext(); DResult getResult(); long getMaxResult(); long getMinResult(); String[] getRequiredVariables();  }
@Test public void testParse() { System.out.println(""); System.out.println("testParse"); DContext dCtx = new DContext(); testResult(" expup(rand(0,5)) + 4 ", dCtx, 4, 9); testResult("expup(rand(0,5)) + expup(rand(0,5))", dCtx, 0, 10); testResult("1d8 + 1d8 + 1d8 + 1d8 + 1d8", dCtx, 5, 40); }