bool Number::operator==(Number arg) { Number::Type type = arg.property("Type").toInt() ? Number::intType : Number::doubleType; QVariant val = arg.property("Number"); if (mType == Number::intType && type == Number::intType) { return mNumber.toInt() == val.toInt(); } else if (mType == Number::intType && type == Number::doubleType) { return mNumber.toInt() == val.toDouble(); } else if (mType == Number::doubleType && type == Number::intType) { return mNumber.toDouble() == val.toInt(); } else { return mNumber.toDouble() == val.toDouble(); } }
Number BlockParser::applyFunction(const QString &variable, Number value) { Number result; double argument = value.property("Number").toDouble(); if (variable == "cos") result = Number(cos(argument), Number::doubleType); else if (variable == "sin") result = Number(sin(argument), Number::doubleType); else if (variable == "ln") result = Number(log(argument), Number::doubleType); else if (variable == "exp") result = Number(exp(argument), Number::doubleType); else if (variable == "sgn") result = Number((argument >= 0 ? 1 : -1), Number::intType); else if (variable == "acos") result = Number(acos(argument), Number::doubleType); else if (variable == "asin") result = Number(asin(argument), Number::doubleType); else if (variable == "atan") result = Number(atan(argument), Number::doubleType); else if (variable == "sqrt") result = Number(sqrt(argument), Number::doubleType); else if (variable == "abs") result = Number(fabs(argument), Number::doubleType); return result; }
void Number::operator/=(Number div) { Number::Type type = div.property("Type").toInt() ? Number::intType : Number::doubleType; QVariant val = div.property("Number"); if (mType == type) { switch (type) { case Number::intType: mNumber = mNumber.toInt() / val.toInt(); break; case Number::doubleType: mNumber = mNumber.toDouble() / val.toDouble(); break; } } else { mType = Number::doubleType; mNumber = mNumber.toDouble() / val.toDouble(); } }
void BlockParser::parseCommand(QString stream, int& pos) { int typesMismatchIndex = pos; QString variable = parseIdentifier(stream, pos); if (mReservedVariables.contains(variable)) { hasParseErrors = true; mErrorReporter->addError(QObject::tr("Using reserved variables %1").arg(variable), mCurrentId); return; } skip(stream, pos); if (hasParseErrors || checkForEndOfStream(stream, pos)) { return; } if (!mVariables.contains(variable)) { error(unknownIdentifier, QString::number(typesMismatchIndex + 1), "", variable); } if (isAssignment(stream.at(pos))) { pos++; Number n = parseExpression(stream, pos); if (!hasParseErrors) { Number::Type t1 = mVariables[variable].property("Type").toInt() ? Number::intType : Number::doubleType; Number::Type t2 = n.property("Type").toInt() ? Number::intType : Number::doubleType; if (t1==t2) { mVariables[variable] = n; } else { if (t1 == Number::intType) { mVariables[variable].setProperty("Number", n.property("Number").toInt()); error(typesMismatch, QString::number(typesMismatchIndex + 1), "\'int\'", "\'double\'"); } else { mVariables[variable].setProperty("Number", n.property("Number").toDouble()); } } } } else { error(unexpectedSymbol, QString::number(pos+1), "=", QString(stream.at(pos))); return; } if (!hasParseErrors && checkForColon(stream, pos)) { pos++; } }
void ExpressionsParser::parseCommand(QString const &stream, int &pos) { int typesMismatchIndex = pos; QString variable = parseIdentifier(stream, pos); skip(stream, pos); if (hasErrors() || isEndOfStream(stream, pos)) { return; } checkForVariable(variable, typesMismatchIndex); if (checkForUsingReservedVariables(variable)) return; if (isAssignment(stream.at(pos))) { pos++; Number n = parseExpression(stream, pos); if (!hasErrors()) { bool const containsVariable = mVariables.keys().contains(variable); Number::Type const t1 = containsVariable ? (mVariables[variable].property("Type").toInt() ? Number::intType : Number::doubleType) : Number::intType; Number::Type const t2 = n.property("Type").toInt() ? Number::intType : Number::doubleType; if (!containsVariable || t1 == t2) { mVariables[variable] = n; } else { if (t1 == Number::intType) { mVariables[variable].setProperty("Number", n.property("Number").toInt()); error(typesMismatch, QString::number(typesMismatchIndex + 1), "\'int\'", "\'double\'"); } else { mVariables[variable].setProperty("Number", n.property("Number").toDouble()); } } } } else { error(unexpectedSymbol, QString::number(pos+1), "=", QString(stream.at(pos))); return; } if (!hasErrors() && checkForColon(stream, pos)) { pos++; } }
TEST_F(BlockParserTest, parseProcessTest) { QString const stream = "var int a, b; double c; a=5; b=3; c=a+b;"; int pos = 0; mParser->parseProcess(stream, pos, Id::rootId()); QMap<QString, Number>* variables = mParser->getVariables(); QStringList variableNames = variables->keys(); ASSERT_EQ(variableNames.size(), 3); ASSERT_TRUE(variableNames.contains("a")); ASSERT_TRUE(variableNames.contains("b")); ASSERT_TRUE(variableNames.contains("c")); Number a = variables->value("a"); Number b = variables->value("b"); Number c = variables->value("c"); EXPECT_EQ(a.property("Number").toInt(), 5); EXPECT_EQ(b.property("Number").toInt(), 3); EXPECT_EQ(c.property("Number").toDouble(), 8); }
// TODO: refactor this! void RuleParser::parsePropertyChange(QString const &stream, int &pos, QHash<Id, Id> const &mMatch) { QString const name = parseElemName(stream, pos); if (hasErrors()) { return; } QString const prop = parseElemProperty(stream, pos); if (hasErrors()) { return; } pos++; skip(stream, pos); if (!checkForEqual(stream, pos)) { return; } pos++; skip(stream, pos); if (stream.mid(pos, 5) == "cond(") { pos += 5; skip(stream, pos); QString const condName = parseElemName(stream, pos); if (hasErrors()) { return; } QString const condProperty = parseElemProperty(stream, pos); if (hasErrors()) { return; } checkForClosingBracketAndColon(stream, pos); Id const condId = elementByName(condName, mMatch); if (condId == Id::rootId()) { error(unknownElementName); return; } int position = 0; bool value = parseCondition(property(condId, condProperty).toString(), position, condId); Id const id = elementByName(name, mMatch); if (id == Id::rootId()) { error(unknownElementName); return; } setProperty(id, prop, QString(value ? "true" : "false")); mCurrentId = mRuleId; return; } if (stream.at(pos).toLatin1() == '"') { pos++; QString const value = stream.mid(pos, stream.indexOf("\"", pos) - pos); pos += value.length(); if (stream.at(pos).toLatin1() != '"') { error(unexpectedSymbol, QString::number(pos) , "\"", QString(stream.at(pos).toLatin1())); return; } Id const id = elementByName(name, mMatch); if (id == Id::rootId()) { error(unknownElementName); return; } setProperty(id, prop, value); pos++; skip(stream, pos); if (!checkForColon(stream, pos)) { return; } pos++; return; } if (checkForLogicalConst(stream, pos)) { int len = 0; QString value = ""; if (stream.mid(pos, 4) == "true") { len = 4; value = "true"; } if (stream.mid(pos, 5) == "false") { len = 5; value = "false"; } QChar c = stream.at(pos + len).toLatin1(); if (!isDigit(c) && !isLetter(c)) { pos += len; skip(stream, pos); if (!checkForColon(stream, pos)) { return; } pos++; Id const id = elementByName(name, mMatch); if (id == Id::rootId()) { error(unknownElementName); return; } setProperty(id, prop, value); return; } } if (stream.mid(pos, 4) == "null") { pos += 4; skip(stream, pos); if (!checkForColon(stream, pos)) { return; } pos++; Id const elem = elementByName(name, mMatch); if (elem == Id::rootId()) { error(unknownElementName); return; } setProperty(elem, prop, QVariant(property(elem, prop).type())); return; } if ((stream.indexOf("=", pos) > pos && stream.indexOf("=", pos) < stream.indexOf(";", pos)) || (stream.indexOf("<", pos) > pos && stream.indexOf("<", pos) < stream.indexOf(";", pos)) || (stream.indexOf(">", pos) > pos && stream.indexOf(">", pos) < stream.indexOf(";", pos))) { bool result = parseConditionHelper(stream, pos); if (hasErrors()) { return; } skip(stream, pos); if (!checkForColon(stream, pos)) { return; } pos++; Id const id = elementByName(name, mMatch); if (id == Id::rootId()) { error(unknownElementName); return; } setProperty(id, prop, QString(result ? "true" : "false")); } else { Number result = parseExpression(stream, pos); if (hasErrors()) { return; } skip(stream, pos); if (!checkForColon(stream, pos)) { return; } pos++; Id const id = elementByName(name, mMatch); if (id == Id::rootId()) { error(unknownElementName); return; } setProperty(id, prop, result.property("Number").toString()); } }