AnimExpression::Token AnimExpression::consumeNumber(const QString& str, QString::const_iterator& iter) const { assert(iter != str.end()); assert(iter->isDigit()); auto begin = iter; while (iter->isDigit() && iter != str.end()) { ++iter; } // parse whole integer part int pos = (int)(begin - str.begin()); int len = (int)(iter - begin); QString sub = QStringRef(const_cast<const QString*>(&str), pos, len).toString(); int whole = sub.toInt(); // parse optional fractional part if (iter->unicode() == '.') { iter++; auto begin = iter; while (iter->isDigit() && iter != str.end()) { ++iter; } int pos = (int)(begin - str.begin()); int len = (int)(iter - begin); QString sub = QStringRef(const_cast<const QString*>(&str), pos, len).toString(); int fraction = sub.toInt(); return Token(computeFloat(whole, fraction)); } else { return Token(whole); } }
QDate fromYYYYMMDD (const QString& yyyymmdd) { if (yyyymmdd.length() != YYYYMMDD_FORMAT.length()) throw "Invalid input. Provide date as yyyyMMdd (e.g. June 2, 2016 = '20160602')"; for (QString::const_iterator chr (yyyymmdd.begin()); chr != yyyymmdd.end(); chr++) { if (!chr->isDigit()) throw "Non digit character in input string."; } const QDate result = QDate::fromString(yyyymmdd, YYYYMMDD_FORMAT); if (!result.isValid()) throw "Invalid date input"; return result; }
static ParseResult ParseDecimalPart(ParseResult const& begin, QString::const_iterator end) { Amount multiplier ("0.1"); //exactly 1 tenth Amount decrement ("0.1"); //exactly 1 tenth Amount a = ResultAmount(begin); QString::const_iterator iter; for (iter = ResultIter(begin); iter != end; iter++) { if (iter->isDigit()) { a += Amount(iter->digitValue())*multiplier; multiplier *= decrement; } else { throw std::runtime_error("Invalid currency string"); } } return ParseResult(a,iter); }
AnimExpression::Token AnimExpression::consumeIdentifier(const QString& str, QString::const_iterator& iter) const { assert(iter != str.end()); assert(iter->isLetter()); auto begin = iter; while ((iter->isLetter() || iter->isDigit()) && iter != str.end()) { ++iter; } int pos = (int)(begin - str.begin()); int len = (int)(iter - begin); 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); } }
static ParseResult ParseWholePart(QString::const_iterator begin, QString::const_iterator end) { Amount a (0); QString::const_iterator iter; for (iter = begin; iter != end; iter++) { if (iter->isDigit()) { a *= Amount(10); //scale up a = a + Amount(iter->digitValue()); //add } else if (*iter == QLocale().groupSeparator()) { //eat it } else if (*iter == QLocale().decimalPoint()) { iter++; //skip the decimal point return ParseResult(a, iter); } else { throw std::runtime_error("Invalid currency string"); } } return ParseResult(a,iter); }
AnimExpression::Token AnimExpression::consumeToken(const QString& str, QString::const_iterator& iter) const { if (!_tokenStack.empty()) { Token top = _tokenStack.top(); _tokenStack.pop(); return top; } else { while (iter != str.end()) { if (iter->isSpace()) { ++iter; } else if (iter->isLetter()) { return consumeIdentifier(str, iter); } else if (iter->isDigit()) { return consumeNumber(str, iter); } else { switch (iter->unicode()) { case '&': return consumeAnd(str, iter); case '|': return consumeOr(str, iter); case '>': return consumeGreaterThan(str, iter); case '<': return consumeLessThan(str, iter); case '(': ++iter; return Token(Token::LeftParen); case ')': ++iter; return Token(Token::RightParen); case '!': return consumeNot(str, iter); case '-': ++iter; return Token(Token::Minus); case '+': ++iter; return Token(Token::Plus); case '*': ++iter; return Token(Token::Multiply); case '/': ++iter; return Token(Token::Divide); case '%': ++iter; return Token(Token::Modulus); case ',': ++iter; return Token(Token::Comma); default: qCCritical(animation) << "AnimExpression: unexpected char" << *iter << "at index " << (int)(iter - str.begin()); return Token(Token::Error); } } } return Token(Token::End); } }