/** * Parse a subexpression and replace it with its result. */ void Calculator::parseSubexpression(QStringList & expressionParts) { int operatorLine = 0; int prioLine = 0; int priority = 0; int parenthesisPos = 0; int functionLine = 0; for(parenthesisPos = 0; parenthesisPos < expressionParts.size(); parenthesisPos++) if((expressionParts[parenthesisPos]== "(") || (expressionParts[parenthesisPos]=="-(")) parseParenthesis(expressionParts, parenthesisPos); else if(expressionParts[parenthesisPos]== ")"){ throw ExExpressionError(tr("Parenthesis syntax error.")); } if(expressionParts.size() < 2) //evaluation is complete, we had a (Expression) return; //now we have all function arguments directly behind the function name if(!(isNumber(expressionParts.last()) || isVariable(expressionParts.last()))) throw ExExpressionError(tr("Last term of expression must be a number.")); //evaluate function values from right to left for(functionLine = expressionParts.size() - 1; functionLine > -1; functionLine--) if(isFunction(expressionParts[functionLine])) evaluateFunction(expressionParts, functionLine); while(operatorLine < expressionParts.size() &&! isOperator(expressionParts[operatorLine])) operatorLine ++; if(operatorLine >= expressionParts.size() - 1) //no operator, invalid expression or nothing to be done throw ExExpressionError(tr("Missing operator.")); //we found an operator, now search for the first operator with highest priority prioLine = operatorLine; priority = operatorPriority(expressionParts[operatorLine]); while( prioLine < expressionParts.size() - 1 ) { prioLine ++; if(operatorPriority(expressionParts[prioLine]) > priority) { operatorLine = prioLine; priority = operatorPriority(expressionParts[prioLine]); } } //Now lets calculate if(operatorLine < 1) //we have a leading operator { if(expressionParts[operatorLine] == "-" | expressionParts[operatorLine] == "+") //we have a sign { if(expressionParts[operatorLine] == "-") expressionParts[0] = expressionParts[0] + expressionParts[1]; //make a negative number expressionParts.removeAt(1); //and delete the sign from list return; } else throw ExExpressionError(tr("No operator allowed in first position.")); } calculateSubExpression(expressionParts, operatorLine); }
Expression* parseEntitySuffixes(TokenStream* tokens, FileContext* fileContext) { bool hasPrefix = false; bool hasSuffix = false; Token prefixToken; Token suffixToken; string next = tokens->safePeekValue(); if (next == "++" || next == "--") { prefixToken = tokens->pop(); hasPrefix = true; } Expression* expression = parseParenthesis(tokens, fileContext); next = tokens->safePeekValue(); while (next == "." || next == "[" || next == "(") { if (next == ".") { Token dotToken = tokens->pop(); Token fieldNameToken = tokens->pop(); fieldNameToken.assertValidIdentifier(); return new DotField(expression, dotToken, fieldNameToken, fileContext); } else if (next == "[") { Token openBracket = tokens->pop(); vector<Expression*> indices = vector<Expression*>(); bool nextAllowed = true; while (!tokens->popIfPresent("]")) { if (tokens->popIfPresent(":")) { nextAllowed = true; indices.push_back(NULL); } else { Expression* index = parseExpression(tokens, fileContext); nextAllowed = tokens->popIfPresent(":"); indices.push_back(index); } } if (nextAllowed) { indices.push_back(NULL); } if (indices.size() > 3) { throw new ParserException(openBracket, "Too many expressions in this slice expression."); } if (indices.size() == 1) { if (indices.at(0) == NULL) { throw new ParserException(openBracket, "Need an index expression here."); } expression = new BracketIndex(expression, openBracket, indices.at(0), fileContext); } else if (indices.size() == 2) { expression = new BracketSlice( expression, openBracket, indices.at(0), indices.at(1), NULL, fileContext); } else { expression = new BracketSlice( expression, openBracket, indices.at(0), indices.at(1), indices.at(2), fileContext); } } else if (next == "(") { vector<Expression*> args = vector<Expression*>(); Token openParen = tokens->popExpected("("); while (!tokens->popIfPresent(")")) { if (args.size() > 0) { tokens->popExpected(","); } Expression* arg = parseExpression(tokens, fileContext); args.push_back(arg); } expression = new FunctionInvocation(expression, openParen, args, fileContext); next = tokens->safePeekValue(); } next = tokens->safePeekValue(); } if (next == "++" || next == "--") { suffixToken = tokens->pop(); hasSuffix = true; } if (hasPrefix && hasSuffix) { throw new ParserException(suffixToken, "Expression has both suffix and prefix"); } if (hasPrefix) { expression = new InlineIncrement(prefixToken, expression, prefixToken, true, fileContext); } if (hasSuffix) { expression = new InlineIncrement( expression->firstToken, expression, suffixToken, false, fileContext); } return expression; }