Changed grammar to support boolean and and or.

This commit is contained in:
Anthony J. Thibault 2015-12-15 10:35:35 -08:00
parent 2b0ed55077
commit 22756d168b
3 changed files with 39 additions and 43 deletions

View file

@ -78,7 +78,15 @@ AnimExpression::Token AnimExpression::consumeIdentifier(const QString& str, QStr
} }
int pos = (int)(begin - str.begin()); int pos = (int)(begin - str.begin());
int len = (int)(iter - begin); int len = (int)(iter - begin);
return Token(QStringRef(const_cast<const QString*>(&str), pos, len));
QStringRef stringRef(const_cast<const QString*>(&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. // 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'
Expr' + Term Expr' Expr' '||' Term Expr'
| Term Expr'
| ε | ε
Term Factor Term' Term Factor Term'
Term' * Term' Term' '&&' Term'
| / Term'
| ε | ε
Factor INT Factor INT
| BOOL
| FLOAT | FLOAT
| IDENTIFIER | IDENTIFIER
| (Expr) | '(' Expr ')'
*/ */
// Expr → Term Expr'
bool AnimExpression::parseExpr(const QString& str, QString::const_iterator& iter) { bool AnimExpression::parseExpr(const QString& str, QString::const_iterator& iter) {
if (!parseTerm(str, iter)) { if (!parseTerm(str, iter)) {
return false; return false;
@ -221,9 +229,10 @@ bool AnimExpression::parseExpr(const QString& str, QString::const_iterator& iter
return true; return true;
} }
// Expr' → '||' Term Expr' | ε
bool AnimExpression::parseExprPrime(const QString& str, QString::const_iterator& iter) { bool AnimExpression::parseExprPrime(const QString& str, QString::const_iterator& iter) {
auto token = consumeToken(str, iter); auto token = consumeToken(str, iter);
if (token.type == Token::Plus) { if (token.type == Token::Or) {
if (!parseTerm(str, iter)) { if (!parseTerm(str, iter)) {
unconsumeToken(token); unconsumeToken(token);
return false; return false;
@ -232,18 +241,7 @@ bool AnimExpression::parseExprPrime(const QString& str, QString::const_iterator&
unconsumeToken(token); unconsumeToken(token);
return false; return false;
} }
_opCodes.push_back(OpCode {OpCode::Add}); _opCodes.push_back(OpCode {OpCode::Or});
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});
return true; return true;
} else { } else {
unconsumeToken(token); 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) { bool AnimExpression::parseTerm(const QString& str, QString::const_iterator& iter) {
if (!parseFactor(str, iter)) { if (!parseFactor(str, iter)) {
return false; return false;
@ -261,9 +260,10 @@ bool AnimExpression::parseTerm(const QString& str, QString::const_iterator& iter
return true; return true;
} }
// Term' → '&&' Term' | ε
bool AnimExpression::parseTermPrime(const QString& str, QString::const_iterator& iter) { bool AnimExpression::parseTermPrime(const QString& str, QString::const_iterator& iter) {
auto token = consumeToken(str, iter); auto token = consumeToken(str, iter);
if (token.type == Token::Multiply) { if (token.type == Token::And) {
if (!parseTerm(str, iter)) { if (!parseTerm(str, iter)) {
unconsumeToken(token); unconsumeToken(token);
return false; return false;
@ -272,18 +272,7 @@ bool AnimExpression::parseTermPrime(const QString& str, QString::const_iterator&
unconsumeToken(token); unconsumeToken(token);
return false; return false;
} }
_opCodes.push_back(OpCode {OpCode::Multiply}); _opCodes.push_back(OpCode {OpCode::And});
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});
return true; return true;
} else { } else {
unconsumeToken(token); 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) { bool AnimExpression::parseFactor(const QString& str, QString::const_iterator& iter) {
auto token = consumeToken(str, iter); auto token = consumeToken(str, iter);
if (token.type == Token::Int) { if (token.type == Token::Int) {
_opCodes.push_back(OpCode {token.intVal}); _opCodes.push_back(OpCode {token.intVal});
return true; return true;
} else if (token.type == Token::Bool) {
_opCodes.push_back(OpCode {(bool)token.intVal});
return true;
} else if (token.type == Token::Float) { } else if (token.type == Token::Float) {
_opCodes.push_back(OpCode {token.floatVal}); _opCodes.push_back(OpCode {token.floatVal});
return true; return true;
@ -351,7 +344,7 @@ AnimExpression::OpCode AnimExpression::evaluate(const AnimVariantMap& map) const
case OpCode::UnaryMinus: evalUnaryMinus(map, stack); break; case OpCode::UnaryMinus: evalUnaryMinus(map, stack); break;
} }
} }
return stack.top(); return coerseToValue(map, stack.top());
} }
#define POP_BOOL(NAME) \ #define POP_BOOL(NAME) \
@ -602,8 +595,7 @@ AnimExpression::OpCode AnimExpression::coerseToValue(const AnimVariantMap& map,
const AnimVariant& var = map.get(opCode.strVal); const AnimVariant& var = map.get(opCode.strVal);
switch (var.getType()) { switch (var.getType()) {
case AnimVariant::Type::Bool: case AnimVariant::Type::Bool:
qCWarning(animation) << "AnimExpression: type missmatch, expected a number not a bool"; return OpCode((bool)var.getBool());
return OpCode(0);
break; break;
case AnimVariant::Type::Int: case AnimVariant::Type::Int:
return OpCode(var.getInt()); return OpCode(var.getInt());
@ -631,6 +623,7 @@ AnimExpression::OpCode AnimExpression::coerseToValue(const AnimVariantMap& map,
} }
} }
#ifndef NDEBUG
void AnimExpression::dumpOpCodes() const { void AnimExpression::dumpOpCodes() const {
QString tmp; QString tmp;
for (auto& op : _opCodes) { for (auto& op : _opCodes) {
@ -660,3 +653,4 @@ void AnimExpression::dumpOpCodes() const {
qCDebug(animation).nospace().noquote() << "opCodes =" << tmp; qCDebug(animation).nospace().noquote() << "opCodes =" << tmp;
qCDebug(animation).resetFormat(); qCDebug(animation).resetFormat();
} }
#endif

View file

@ -27,6 +27,7 @@ protected:
enum Type { enum Type {
End = 0, End = 0,
Identifier, Identifier,
Bool,
Int, Int,
Float, Float,
And, And,
@ -50,8 +51,9 @@ protected:
}; };
Token(Type type) : type {type} {} Token(Type type) : type {type} {}
Token(const QStringRef& strRef) : type {Type::Identifier}, strVal {strRef.toString()} {} Token(const QStringRef& strRef) : type {Type::Identifier}, strVal {strRef.toString()} {}
Token(int val) : type {Type::Int}, intVal {val} {} explicit Token(int val) : type {Type::Int}, intVal {val} {}
Token(float val) : type {Type::Float}, floatVal {val} {} explicit Token(bool val) : type {Type::Bool}, intVal {val} {}
explicit Token(float val) : type {Type::Float}, floatVal {val} {}
Type type {End}; Type type {End};
QString strVal; QString strVal;
int intVal {0}; int intVal {0};
@ -81,11 +83,11 @@ protected:
UnaryMinus UnaryMinus
}; };
OpCode(Type type) : type {type} {} OpCode(Type type) : type {type} {}
OpCode(const QStringRef& strRef) : type {Type::Identifier}, strVal {strRef.toString()} {} explicit OpCode(const QStringRef& strRef) : type {Type::Identifier}, strVal {strRef.toString()} {}
OpCode(const QString& str) : type {Type::Identifier}, strVal {str} {} explicit OpCode(const QString& str) : type {Type::Identifier}, strVal {str} {}
OpCode(int val) : type {Type::Int}, intVal {val} {} explicit OpCode(int val) : type {Type::Int}, intVal {val} {}
OpCode(bool val) : type {Type::Bool}, intVal {(int)val} {} explicit OpCode(bool val) : type {Type::Bool}, intVal {(int)val} {}
OpCode(float val) : type {Type::Float}, floatVal {val} {} explicit OpCode(float val) : type {Type::Float}, floatVal {val} {}
bool coerceBool(const AnimVariantMap& map) const { bool coerceBool(const AnimVariantMap& map) const {
if (type == Int || type == Bool) { if (type == Int || type == Bool) {

View file

@ -274,7 +274,7 @@ struct ByteData {
QTextStream & operator << (QTextStream& stream, const ByteData & wrapper) { QTextStream & operator << (QTextStream& stream, const ByteData & wrapper) {
// Print bytes as hex // Print bytes as hex
stream << QByteArray::fromRawData(wrapper.data, wrapper.length).toHex(); stream << QByteArray::fromRawData(wrapper.data, (int)wrapper.length).toHex();
return stream; return stream;
} }