From 22756d168b25af08f004d5b7b8de24dd59134db4 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 15 Dec 2015 10:35:35 -0800 Subject: [PATCH] Changed grammar to support boolean and and or. --- libraries/animation/src/AnimExpression.cpp | 64 ++++++++++------------ libraries/animation/src/AnimExpression.h | 16 +++--- tests/QTestExtensions.h | 2 +- 3 files changed, 39 insertions(+), 43 deletions(-) diff --git a/libraries/animation/src/AnimExpression.cpp b/libraries/animation/src/AnimExpression.cpp index b76aaff3f9..5fc1bc9b4f 100644 --- a/libraries/animation/src/AnimExpression.cpp +++ b/libraries/animation/src/AnimExpression.cpp @@ -78,7 +78,15 @@ AnimExpression::Token AnimExpression::consumeIdentifier(const QString& str, QStr } int pos = (int)(begin - str.begin()); int len = (int)(iter - begin); - return Token(QStringRef(const_cast(&str), pos, len)); + + QStringRef stringRef(const_cast(&str), pos, len); + if (stringRef == "true") { + return Token(true); + } else if (stringRef == "false") { + return Token(false); + } else { + return Token(stringRef); + } } // TODO: not very efficient or accruate, but it's close enough for now. @@ -198,19 +206,19 @@ AnimExpression::Token AnimExpression::consumeNot(const QString& str, QString::co /* Expr → Term Expr' -Expr' → + Term Expr' - | – Term Expr' +Expr' → '||' Term Expr' | ε Term → Factor Term' -Term' → * Term' - | / Term' +Term' → '&&' Term' | ε Factor → INT + | BOOL | FLOAT | IDENTIFIER - | (Expr) + | '(' Expr ')' */ +// Expr → Term Expr' bool AnimExpression::parseExpr(const QString& str, QString::const_iterator& iter) { if (!parseTerm(str, iter)) { return false; @@ -221,9 +229,10 @@ bool AnimExpression::parseExpr(const QString& str, QString::const_iterator& iter return true; } +// Expr' → '||' Term Expr' | ε bool AnimExpression::parseExprPrime(const QString& str, QString::const_iterator& iter) { auto token = consumeToken(str, iter); - if (token.type == Token::Plus) { + if (token.type == Token::Or) { if (!parseTerm(str, iter)) { unconsumeToken(token); return false; @@ -232,18 +241,7 @@ bool AnimExpression::parseExprPrime(const QString& str, QString::const_iterator& unconsumeToken(token); return false; } - _opCodes.push_back(OpCode {OpCode::Add}); - return true; - } else if (token.type == Token::Minus) { - if (!parseTerm(str, iter)) { - unconsumeToken(token); - return false; - } - if (!parseExprPrime(str, iter)) { - unconsumeToken(token); - return false; - } - _opCodes.push_back(OpCode {OpCode::Subtract}); + _opCodes.push_back(OpCode {OpCode::Or}); return true; } else { unconsumeToken(token); @@ -251,6 +249,7 @@ bool AnimExpression::parseExprPrime(const QString& str, QString::const_iterator& } } +// Term → Factor Term' bool AnimExpression::parseTerm(const QString& str, QString::const_iterator& iter) { if (!parseFactor(str, iter)) { return false; @@ -261,9 +260,10 @@ bool AnimExpression::parseTerm(const QString& str, QString::const_iterator& iter return true; } +// Term' → '&&' Term' | ε bool AnimExpression::parseTermPrime(const QString& str, QString::const_iterator& iter) { auto token = consumeToken(str, iter); - if (token.type == Token::Multiply) { + if (token.type == Token::And) { if (!parseTerm(str, iter)) { unconsumeToken(token); return false; @@ -272,18 +272,7 @@ bool AnimExpression::parseTermPrime(const QString& str, QString::const_iterator& unconsumeToken(token); return false; } - _opCodes.push_back(OpCode {OpCode::Multiply}); - return true; - } else if (token.type == Token::Divide) { - if (!parseTerm(str, iter)) { - unconsumeToken(token); - return false; - } - if (!parseTermPrime(str, iter)) { - unconsumeToken(token); - return false; - } - _opCodes.push_back(OpCode {OpCode::Divide}); + _opCodes.push_back(OpCode {OpCode::And}); return true; } else { unconsumeToken(token); @@ -291,11 +280,15 @@ bool AnimExpression::parseTermPrime(const QString& str, QString::const_iterator& } } +// Factor → INT | BOOL | FLOAT | IDENTIFIER | '(' Expr ')' bool AnimExpression::parseFactor(const QString& str, QString::const_iterator& iter) { auto token = consumeToken(str, iter); if (token.type == Token::Int) { _opCodes.push_back(OpCode {token.intVal}); return true; + } else if (token.type == Token::Bool) { + _opCodes.push_back(OpCode {(bool)token.intVal}); + return true; } else if (token.type == Token::Float) { _opCodes.push_back(OpCode {token.floatVal}); return true; @@ -351,7 +344,7 @@ AnimExpression::OpCode AnimExpression::evaluate(const AnimVariantMap& map) const case OpCode::UnaryMinus: evalUnaryMinus(map, stack); break; } } - return stack.top(); + return coerseToValue(map, stack.top()); } #define POP_BOOL(NAME) \ @@ -602,8 +595,7 @@ AnimExpression::OpCode AnimExpression::coerseToValue(const AnimVariantMap& map, const AnimVariant& var = map.get(opCode.strVal); switch (var.getType()) { case AnimVariant::Type::Bool: - qCWarning(animation) << "AnimExpression: type missmatch, expected a number not a bool"; - return OpCode(0); + return OpCode((bool)var.getBool()); break; case AnimVariant::Type::Int: return OpCode(var.getInt()); @@ -631,6 +623,7 @@ AnimExpression::OpCode AnimExpression::coerseToValue(const AnimVariantMap& map, } } +#ifndef NDEBUG void AnimExpression::dumpOpCodes() const { QString tmp; for (auto& op : _opCodes) { @@ -660,3 +653,4 @@ void AnimExpression::dumpOpCodes() const { qCDebug(animation).nospace().noquote() << "opCodes =" << tmp; qCDebug(animation).resetFormat(); } +#endif diff --git a/libraries/animation/src/AnimExpression.h b/libraries/animation/src/AnimExpression.h index 6e204483d5..8a1961b326 100644 --- a/libraries/animation/src/AnimExpression.h +++ b/libraries/animation/src/AnimExpression.h @@ -27,6 +27,7 @@ protected: enum Type { End = 0, Identifier, + Bool, Int, Float, And, @@ -50,8 +51,9 @@ protected: }; Token(Type type) : type {type} {} Token(const QStringRef& strRef) : type {Type::Identifier}, strVal {strRef.toString()} {} - Token(int val) : type {Type::Int}, intVal {val} {} - Token(float val) : type {Type::Float}, floatVal {val} {} + explicit Token(int val) : type {Type::Int}, intVal {val} {} + explicit Token(bool val) : type {Type::Bool}, intVal {val} {} + explicit Token(float val) : type {Type::Float}, floatVal {val} {} Type type {End}; QString strVal; int intVal {0}; @@ -81,11 +83,11 @@ protected: UnaryMinus }; OpCode(Type type) : type {type} {} - OpCode(const QStringRef& strRef) : type {Type::Identifier}, strVal {strRef.toString()} {} - OpCode(const QString& str) : type {Type::Identifier}, strVal {str} {} - OpCode(int val) : type {Type::Int}, intVal {val} {} - OpCode(bool val) : type {Type::Bool}, intVal {(int)val} {} - OpCode(float val) : type {Type::Float}, floatVal {val} {} + explicit OpCode(const QStringRef& strRef) : type {Type::Identifier}, strVal {strRef.toString()} {} + explicit OpCode(const QString& str) : type {Type::Identifier}, strVal {str} {} + explicit OpCode(int val) : type {Type::Int}, intVal {val} {} + explicit OpCode(bool val) : type {Type::Bool}, intVal {(int)val} {} + explicit OpCode(float val) : type {Type::Float}, floatVal {val} {} bool coerceBool(const AnimVariantMap& map) const { if (type == Int || type == Bool) { diff --git a/tests/QTestExtensions.h b/tests/QTestExtensions.h index 16e51b41ee..b7b9795a9a 100644 --- a/tests/QTestExtensions.h +++ b/tests/QTestExtensions.h @@ -274,7 +274,7 @@ struct ByteData { QTextStream & operator << (QTextStream& stream, const ByteData & wrapper) { // Print bytes as hex - stream << QByteArray::fromRawData(wrapper.data, wrapper.length).toHex(); + stream << QByteArray::fromRawData(wrapper.data, (int)wrapper.length).toHex(); return stream; }