Beispiel #1
0
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();
	}
}
Beispiel #2
0
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;
}
Beispiel #3
0
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();
	}
}
Beispiel #4
0
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++;
	}
}
Beispiel #5
0
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++;
	}
}
Beispiel #6
0
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);
}
Beispiel #7
0
// 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());
	}

}