int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc) { char ch; if (!m_io->isOpen()) { qCritical() << "JSonScanner::yylex - io device is not open"; return -1; } yylloc->step(); do { bool ret; if (m_io->atEnd()) { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::END"; return yy::json_parser::token::END; } else ret = m_io->getChar(&ch); if (!ret) { qCritical() << "JSonScanner::yylex - error reading from io device"; return -1; } qjsonDebug() << "JSonScanner::yylex - got |" << ch << "|"; yylloc->columns(); if (ch == '\n' || ch == '\r') yylloc->lines(); } while (m_quotmarkClosed && (isspace(ch) != 0)); if (m_quotmarkClosed && ((ch == 't') || (ch == 'T') || (ch == 'n') || (ch == 'N'))) { // check true & null value const QByteArray buf = m_io->peek(3).toLower(); if (buf.length() == 3) { if (buf == "rue") { m_io->read (3); yylloc->columns(3); qjsonDebug() << "JSonScanner::yylex - TRUE_VAL"; return yy::json_parser::token::TRUE_VAL; } else if (buf == "ull") { m_io->read (3); yylloc->columns(3); qjsonDebug() << "JSonScanner::yylex - NULL_VAL"; return yy::json_parser::token::NULL_VAL; } } } else if (m_quotmarkClosed && ((ch == 'f') || (ch == 'F'))) { // check false value const QByteArray buf = m_io->peek(4).toLower(); if (buf.length() == 4) { if (buf == "alse") { m_io->read (4); yylloc->columns(4); qjsonDebug() << "JSonScanner::yylex - FALSE_VAL"; return yy::json_parser::token::FALSE_VAL; } } } else if (m_quotmarkClosed && ((ch == 'e') || (ch == 'E'))) { QByteArray ret(1, ch); const QByteArray buf = m_io->peek(1); if (!buf.isEmpty()) { if ((buf[0] == '+' ) || (buf[0] == '-' )) { ret += m_io->read (1); yylloc->columns(); } } *yylval = QVariant(QString::fromUtf8(ret)); return yy::json_parser::token::E; } if (ch != '"' && !m_quotmarkClosed) { // we're inside a " " block QByteArray raw; raw += ch; char prevCh = ch; bool escape_on = (ch == '\\') ? true : false; while ( true ) { char nextCh; qint64 ret = m_io->peek(&nextCh, 1); if (ret != 1) { if (m_io->atEnd()) return yy::json_parser::token::END; else return -1; } else if ( !escape_on && nextCh == '\"' ) { bool ok; if(raw.left(15) == "@base64-b8An45:"){ ok = true; *yylval = QByteArray::fromBase64(raw.mid(15)); } else { const QString str = unescape( raw, &ok ); *yylval = ok ? str : QString(); } return ok ? yy::json_parser::token::STRING : -1; } #if 0 if ( prevCh == '\\' && nextCh != '"' && nextCh != '\\' && nextCh != '/' && nextCh != 'b' && nextCh != 'f' && nextCh != 'n' && nextCh != 'r' && nextCh != 't' && nextCh != 'u') { qjsonDebug() << "Just read" << nextCh; qjsonDebug() << "JSonScanner::yylex - error decoding escaped sequence"; return -1; } #endif m_io->read(1); // consume raw += nextCh; prevCh = nextCh; if (escape_on) escape_on = false; else escape_on = (prevCh == '\\') ? true : false; #if 0 if (nextCh == '\\') { char buf; if (m_io->getChar (&buf)) { yylloc->columns(); if (((buf != '"') && (buf != '\\') && (buf != '/') && (buf != 'b') && (buf != 'f') && (buf != 'n') && (buf != 'r') && (buf != 't') && (buf != 'u'))) { qjsonDebug() << "Just read" << buf; qjsonDebug() << "JSonScanner::yylex - error decoding escaped sequence"; return -1; } } else { qCritical() << "JSonScanner::yylex - error decoding escaped sequence : io error"; return -1; } } #endif } } else if (isdigit(ch) != 0 && m_quotmarkClosed) { *yylval = QVariant(QString::fromLatin1(QByteArray(&ch,1))); qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DIGIT"; return yy::json_parser::token::DIGIT; } else if (isalnum(ch) != 0) { *yylval = QVariant(QString(QChar::fromLatin1(ch))); qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::WORD (" << ch << ")"; return yy::json_parser::token::STRING; } else if (ch == ':') { // set yylval qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::COLON"; return yy::json_parser::token::COLON; } else if (ch == '"') { // yy::json_parser::token::QUOTMARK (") // set yylval m_quotmarkCount++; if (m_quotmarkCount %2 == 0) { m_quotmarkClosed = true; m_quotmarkCount = 0; qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::QUOTMARKCLOSE"; return yy::json_parser::token::QUOTMARKCLOSE; } else { m_quotmarkClosed = false; qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::QUOTMARKOPEN"; return yy::json_parser::token::QUOTMARKOPEN; } } else if (ch == ',') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::COMMA"; return yy::json_parser::token::COMMA; } else if (ch == '.') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DOT"; return yy::json_parser::token::DOT; } else if (ch == '-') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::MINUS"; return yy::json_parser::token::MINUS; } else if (ch == '[') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_OPEN"; return yy::json_parser::token::SQUARE_BRACKET_OPEN; } else if (ch == ']') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_CLOSE"; return yy::json_parser::token::SQUARE_BRACKET_CLOSE; } else if (ch == '{') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_OPEN"; return yy::json_parser::token::CURLY_BRACKET_OPEN; } else if (ch == '}') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_CLOSE"; return yy::json_parser::token::CURLY_BRACKET_CLOSE; } //unknown char! //TODO yyerror? qCritical() << "JSonScanner::yylex - unknown char, returning -1"; return -1; }
int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc) { char ch; if (!m_io->isOpen()) { qCritical() << "JSonScanner::yylex - io device is not open"; return -1; } yylloc->step(); do { bool ret; if (m_io->atEnd()) { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::END"; return yy::json_parser::token::END; } else ret = m_io->getChar(&ch); if (!ret) { qCritical() << "JSonScanner::yylex - error reading from io device"; return -1; } qjsonDebug() << "JSonScanner::yylex - got |" << ch << "|"; yylloc->columns(); if (ch == '\n' || ch == '\r') yylloc->lines(); } while (m_quotmarkClosed && (isspace(ch) != 0)); if (m_quotmarkClosed && ((ch == 't') || (ch == 'T'))) { const QByteArray buf = m_io->peek(3).toLower(); if (buf == "rue") { m_io->read (3); yylloc->columns(3); qjsonDebug() << "JSonScanner::yylex - TRUE_VAL"; return yy::json_parser::token::TRUE_VAL; } } else if (m_quotmarkClosed && ((ch == 'n') || (ch == 'N'))) { const QByteArray buf = m_io->peek(3).toLower(); if (buf == "ull") { m_io->read (3); yylloc->columns(3); qjsonDebug() << "JSonScanner::yylex - NULL_VAL"; return yy::json_parser::token::NULL_VAL; } else if (buf.startsWith("an") && m_allowSpecialNumbers) { m_io->read(2); yylloc->columns(2); qjsonDebug() << "JSonScanner::yylex - NAN_VAL"; return yy::json_parser::token::NAN_VAL; } } else if (m_quotmarkClosed && ((ch == 'f') || (ch == 'F'))) { // check false value const QByteArray buf = m_io->peek(4).toLower(); if (buf.length() == 4) { if (buf == "alse") { m_io->read (4); yylloc->columns(4); qjsonDebug() << "JSonScanner::yylex - FALSE_VAL"; return yy::json_parser::token::FALSE_VAL; } } } else if (m_quotmarkClosed && ((ch == 'e') || (ch == 'E'))) { QByteArray ret(1, ch); const QByteArray buf = m_io->peek(1); if (!buf.isEmpty()) { if ((buf[0] == '+' ) || (buf[0] == '-' )) { ret += m_io->read (1); yylloc->columns(); } } *yylval = QVariant(QString::fromUtf8(ret)); return yy::json_parser::token::E; } else if (m_allowSpecialNumbers && m_quotmarkClosed && ((ch == 'I') || (ch == 'i'))) { QByteArray ret(1, ch); const QByteArray buf = m_io->peek(7); if (buf == "nfinity") { m_io->read(7); yylloc->columns(7); qjsonDebug() << "JSonScanner::yylex - INFINITY_VAL"; return yy::json_parser::token::INFINITY_VAL; } } if (ch != '"' && !m_quotmarkClosed) { // we're inside a " " block QByteArray raw; raw += ch; char prevCh = ch; bool escape_on = (ch == '\\') ? true : false; while ( true ) { char nextCh; qint64 ret = m_io->peek(&nextCh, 1); if (ret != 1) { if (m_io->atEnd()) return yy::json_parser::token::END; else return -1; } else if ( !escape_on && nextCh == '\"' ) { bool ok; const QString str = unescape( raw, &ok ); *yylval = ok ? str : QString(); return ok ? yy::json_parser::token::STRING : -1; } #if 0 if ( prevCh == '\\' && nextCh != '"' && nextCh != '\\' && nextCh != '/' && nextCh != 'b' && nextCh != 'f' && nextCh != 'n' && nextCh != 'r' && nextCh != 't' && nextCh != 'u') { qjsonDebug() << "Just read" << nextCh; qjsonDebug() << "JSonScanner::yylex - error decoding escaped sequence"; return -1; } #endif m_io->read(1); // consume raw += nextCh; prevCh = nextCh; if (escape_on) escape_on = false; else escape_on = (prevCh == '\\') ? true : false; #if 0 if (nextCh == '\\') { char buf; if (m_io->getChar (&buf)) { yylloc->columns(); if (((buf != '"') && (buf != '\\') && (buf != '/') && (buf != 'b') && (buf != 'f') && (buf != 'n') && (buf != 'r') && (buf != 't') && (buf != 'u'))) { qjsonDebug() << "Just read" << buf; qjsonDebug() << "JSonScanner::yylex - error decoding escaped sequence"; return -1; } } else { qCritical() << "JSonScanner::yylex - error decoding escaped sequence : io error"; return -1; } } #endif } } else if (isdigit(ch) != 0 && m_quotmarkClosed) { bool ok; QByteArray numArray = QByteArray::fromRawData( &ch, 1 * sizeof(char) ); qulonglong number = numArray.toULongLong(&ok); if (!ok) { //This shouldn't happen qCritical() << "JSonScanner::yylex - error while converting char to ulonglong, returning -1"; return -1; } if (number == 0) { // we have to return immediately otherwise numbers like // 2.04 will be converted to 2.4 *yylval = QVariant(number); qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DIGIT"; return yy::json_parser::token::DIGIT; } char nextCh; qint64 ret = m_io->peek(&nextCh, 1); while (ret == 1 && isdigit(nextCh)) { m_io->read(1); //consume yylloc->columns(1); numArray = QByteArray::fromRawData( &nextCh, 1 * sizeof(char) ); number = number * 10 + numArray.toULongLong(&ok); if (!ok) { //This shouldn't happen qCritical() << "JSonScanner::yylex - error while converting char to ulonglong, returning -1"; return -1; } ret = m_io->peek(&nextCh, 1); } *yylval = QVariant(number); qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DIGIT"; return yy::json_parser::token::DIGIT; } else if (isalnum(ch) != 0) { *yylval = QVariant(QString(QChar::fromLatin1(ch))); qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::WORD (" << ch << ")"; return yy::json_parser::token::STRING; } else if (ch == ':') { // set yylval qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::COLON"; return yy::json_parser::token::COLON; } else if (ch == '"') { // yy::json_parser::token::QUOTMARK (") // set yylval m_quotmarkCount++; if (m_quotmarkCount %2 == 0) { m_quotmarkClosed = true; m_quotmarkCount = 0; qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::QUOTMARKCLOSE"; return yy::json_parser::token::QUOTMARKCLOSE; } else { m_quotmarkClosed = false; qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::QUOTMARKOPEN"; return yy::json_parser::token::QUOTMARKOPEN; } } else if (ch == ',') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::COMMA"; return yy::json_parser::token::COMMA; } else if (ch == '.') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DOT"; return yy::json_parser::token::DOT; } else if (ch == '-') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::MINUS"; return yy::json_parser::token::MINUS; } else if (ch == '[') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_OPEN"; return yy::json_parser::token::SQUARE_BRACKET_OPEN; } else if (ch == ']') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_CLOSE"; return yy::json_parser::token::SQUARE_BRACKET_CLOSE; } else if (ch == '{') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_OPEN"; return yy::json_parser::token::CURLY_BRACKET_OPEN; } else if (ch == '}') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_CLOSE"; return yy::json_parser::token::CURLY_BRACKET_CLOSE; } //unknown char! //TODO yyerror? qCritical() << "JSonScanner::yylex - unknown char, returning -1"; return -1; }