bool StelJsonParserInstance::skipAndConsumeChar(char r) { char c; while (getChar(&c)) { switch (c) { case ' ': case '\t': case '\n': case '\r': break; case '/': { if (!getChar(&c)) throw std::runtime_error(qPrintable(QString("Unexpected '/%1' in the JSON content").arg(c))); if (c=='/') skipLine(); else { // We have a problem, we removed a '/'.. This should never happen with properly formatted JSON though throw std::runtime_error(qPrintable(QString("Unexpected '/%1' in the JSON content").arg(c))); } } break; default: if (r==c) return true; ungetChar(c); return false; } } return false; }
bool WikiLexer::matchString ( const QString & string ) { QStack<QChar> stack; bool result = false; QChar buff; for ( int idx = 0; idx < string.length(); ++idx ) { if ( getChar ( &buff ) ) { result = ( buff == string.at ( idx ) ); stack.push ( buff ); m_currentChar = buff; if ( !result ) break; } else break; } while ( !stack.isEmpty() && !result ) ungetChar ( stack.pop() ); if( result ) m_tokenText = string; return result; }
QVariant StelJsonParserInstance::readOther() { QByteArray str; char c; while (getChar(&c)) { if (c==' ' || c==',' || c=='\n' || c=='\r' || c==']' || c=='\t' || c=='}') { ungetChar(c); break; } str+=c; } bool ok; const int i = str.toInt(&ok); if (ok) return i; const double d = str.toDouble(&ok); if (ok) return d; if (str=="true") return QVariant(true); if (str=="false") return QVariant(false); if (str=="null") return QVariant(); QDateTime dt = QDateTime::fromString(str, Qt::ISODate); if (dt.isValid()) return QVariant(dt); throw std::runtime_error(qPrintable(QString("Invalid JSON value: \"")+str+"\"")); }
void Lexer::getString(Token& currentToken) { QString str = "\""; // start with a " cauz it just got lost QChar currentChar = QChar(); // start empty while ( currentChar != '"' && !(currentChar == '\x0a' || currentChar == '\n') && !inputStream->atEnd() ) { currentChar = getChar(); if (currentChar == '\\') // escape sequence { currentChar = getChar(); switch (currentChar) { case 'n': str += '\n'; break; case 't': str += '\t'; break; case 'f': str += '\f'; break; case '"': str += '"'; break; } } else if (currentChar == '\x0a' || currentChar == '\n') // if the user forgot to delimit the string { ungetChar(currentChar); break; } else str += currentChar; } currentToken.type = tokString; currentToken.look = str; kdDebug(0)<<"Lexer::getStringConstant, got STRINGCONSTANT: "<<currentToken.look<<"'"<<endl; }
/** * @brief Read until '{','}','[' or ']' is found. * @param pJson JSON parsing structure * @param pVal Value string where read characters are stored * @param size Maximal size of the value string * @param c_first Last read character * @return Last character, in case it is -1 */ static int readValue(PT_uJson pJson, char *pVal, int size, int c_first) { int c; int n = 0; n++; *pVal++ = c_first; while (1) { c = getChar(pJson); if (c < 0) break; if (c == '{' || c == '}' || c == '[' || c == ']' || c == ',') { ungetChar(pJson, c); break; } n++; if (n < size - 1) *pVal++ = c; } *pVal = '\0'; return c; }
void readEOL(int conn) { int c; while ((c = getChar(conn)) != '\n'); ungetChar(c); }
void StelJsonParserInstance::skipJson() { // There is a weakness in this code -- it will cause any standalone '/' to be absorbed. char c; while (getChar(&c)) { switch (c) { case ' ': case '\t': case '\n': case '\r': break; case '/': { if (!getChar(&c)) return; if (c=='/') skipLine(); else { // We have a problem, we removed a '/'.. This should never happen with properly formatted JSON though throw std::runtime_error(qPrintable(QString("Unexpected '/%1' in the JSON content").arg(c))); } } break; default: ungetChar(c); return; } } }
int Lexer::lexan() { int c; while(1) { c = getChar(); while (c == ' ' || c == '\t') c = getChar(); // Remove spaces if (isDigit(c)) { while(isDigit(c = getChar())) { // DO something } ungetChar(); return NUM; } if (c == '_' || isAlpha(c)) { c = getChar(); while(c == '_' || isAlpha(str[current]) || isDigit(str[current])) { c = getChar(); } ungetChar(); return ID; } switch(c) { case '+': case '-': case '*': case '/': case '%': case '(': case ')': return c; } if (c == NONE) return NONE; cout << endl << c << endl; error(); } }
void Lexer::skipSpaces() { // kdDebug(0)<<"Lexer::skipSpaces(), skipping SPACES."<<endl; QChar currentChar = getChar(); // when the Separator_* groups can be identified in the QChar thing would be easier while ( !inputStream->atEnd() && ( currentChar.isSpace() && !(currentChar == '\x0a' || currentChar == '\n') ) ) { currentChar = getChar(); } ungetChar(currentChar); // unget the tokEOL we likely just found }
bool StelJsonParserInstance::tryReadChar(char c) { char r; if (!getChar(&r)) return false; if (r == c) return true; ungetChar(r); return false; }
int getInt ( int conn) { int num = 0; int c; while (isspace (c = getChar (conn))); while (isdigit (c)) { num = (num * 10) + (c - '0'); c = getChar (conn); } ungetChar (c); return num; }
int Lexer::getWord(QString& word) { // kdDebug(0)<<"Lexer::getWord()"<<endl; QChar currentChar = getChar(); if ( currentChar.isLetter() || currentChar == '[' || currentChar == ']' ) { while ( ( currentChar.isLetterOrNumber() || currentChar == '_' || currentChar == '[' || currentChar == ']' ) && !inputStream->atEnd() ) { word += currentChar; currentChar = getChar(); } kdDebug(0)<<"Lexer::getWord(), got NAME: '"<<word<<"'"<<endl; ungetChar(currentChar); //read one too much return tokUnknown; // returns tokUnknown, actual token is to be determained later in Lexer::setTokenType } else return tokError; }
char * MIFrfile::getWord() { static char Word[LineMax]; char *cptr = Word; int ch; skipWhite(); while ((ch = getChar()) != EOF) { if (isalnum(ch)) *cptr++ = ch; else { ungetChar(ch); break; } } *cptr = '\0'; skipWhite(); return Word; }
char * MIFrfile::getString(long len) { static char String[LineMax]; char *cptr = String; long pos = 0; int ch = 0; if (len > LineMax) cptr = new char[len]; skipWhite(); while ((ch = getChar()) != EOF) { if (ch == '`') // skip opening quote continue; if (ch == '\'') // stop at ending quote break; if (ch == '\\') { // process some backslashs ch = getChar(); if (ch == 'q') ch = '\''; else if (ch == 'Q') ch = '`'; //else if (ch == '\\') // ; // cptr[pos++] = ch; else if (ch != '>') { // leave \\ and \x and \t alone ungetChar(ch); ch = '\\'; } } cptr[pos++] = ch; // keep the rest if (pos > (len - 3)) break; } cptr[pos] = '\0'; return cptr; }
void MIFrfile::skipImport() { int ch; skipLine(); while ((ch = getChar()) != EOF) { switch (ch) { case '&': case '=': skipLine(); break; case '\n': case '\r': case ' ': break; default: ungetChar(ch); return; } } }
int Lexer::getNumber(Value& num, QString& look) { // by reference the value (Value) and look part are set // kdDebug(0)<<"Lexer::getNumber()"<<endl; bool hasPoint = false; QChar currentChar = getChar(); if ( currentChar.isNumber() ) { while ( ( currentChar.isNumber() || (currentChar == '.' && !hasPoint) ) && !inputStream->atEnd() ) { if (currentChar == '.') { hasPoint = true; } look += currentChar; currentChar = getChar(); } ungetChar(currentChar); //read one too much num.setNumber( look.toDouble() ); kdDebug(0)<<"Lexer::getNumber(), got NUMBER: '"<<num.Number()<<"'"<<endl; return tokNumber; } else return tokError; }
Token Lexer::lex() { skipSpaces(); // skips the white space that it quite likely (indentation) infront of the Token Token currentToken; currentToken.type = tokNotSet; // not really needed currentToken.look = ""; currentToken.value = 0; currentToken.start.row = row; currentToken.start.col = col; QChar currentChar = getChar(); if ( inputStream->atEnd() ) { kdDebug(0)<<"Lexer::lex(), got EOF."<<endl; currentToken.type = tokEOF; currentToken.look = "EOF"; ungetChar(currentChar); // unget the currentChar and fix the row/col values return currentToken; } if (currentChar == '#') { while ( !inputStream->atEnd() && !(currentChar == '\x0a' || currentChar == '\n') ) currentChar = getChar(); } // if (currentChar.category() == QChar::Separator_Line) somehow doesnt work if (currentChar == '\x0a' || currentChar == '\n') { currentToken.type = tokEOL; currentToken.look = "EOL"; } else if (currentChar.isLetter() || currentChar == '[' || currentChar == ']') { ungetChar(currentChar); // sets currentToken.look by reference, and set the currentToken.type to tokUnknown currentToken.type = getWord(currentToken.look); setTokenType(currentToken); // gets the actual tokenType } else if ( currentChar.isNumber() ) { ungetChar(currentChar); // set currentToken.value/look by reference, and set the currentToken.type to tokNumber currentToken.type = getNumber(currentToken.value, currentToken.look); } else if (currentChar == '>') { currentChar = getChar(); if (currentChar == '=') { currentToken.type = tokGe; currentToken.look = ">="; } else { ungetChar(currentChar); currentToken.type = tokGt; currentToken.look = ">"; } } else if (currentChar == '<') { currentChar = getChar(); if ( currentChar == '=' ) { currentToken.type = tokLe; currentToken.look = "<="; } else { ungetChar(currentChar); currentToken.type = tokLt; currentToken.look = ">"; } } else if (currentChar == '!') { currentChar = getChar(); if (currentChar == '=') { currentToken.type = tokNe; currentToken.look = "!="; } else { ungetChar(currentChar); currentToken.type = tokNot; currentToken.look = "!"; } } else if (currentChar == '=') { currentChar = getChar(); if (currentChar == '=') { currentToken.type = tokEq; currentToken.look = "=="; } else { ungetChar(currentChar); currentToken.type = tokAssign; currentToken.look = "="; } } else if (currentChar == '(') { currentToken.type = tokBraceOpen; currentToken.look = "("; } else if (currentChar == ')') { currentToken.type = tokBraceClose; currentToken.look = ")"; } else if (currentChar == '+') { currentToken.type = tokPlus; currentToken.look = "+"; } else if (currentChar == '-') { currentToken.type = tokMinus; currentToken.look = "-"; } else if (currentChar == '*') { currentToken.type = tokMul; currentToken.look = "*"; } else if (currentChar == '/') { currentToken.type = tokDev; currentToken.look = "/"; } else if (currentChar == ',') { currentToken.type = tokComma; currentToken.look = ","; } else if (currentChar == '"') { getString(currentToken); } else { currentToken.type = tokUnknown; currentToken.look = currentChar; } currentToken.end.row = row; currentToken.end.col = col; return currentToken; }
int Lexan::getNextToken() { int State = 0; char Char; int Exp = 0, ExpSign = 1; /* Velikost a znamenko exponentu */ double DmsPos = 0.1; /* prave zpracovavany desetinny rad */ while (true) { Char = getChar(); switch (State) { case 0: if (Char == ' ' || Char == '\n' || Char == '\t' || Char == '\r') break; if (Char == ';') return (LEX_SEMICOLON); if (Char == '/') { State = 2; break; } if (Char == '=') { State = 29; break; } if (Char == '*') { State = 25; break; } if (Char == '(') return (LEX_LPA); if (Char == ')') return (LEX_RPA); if (Char == '}') return (LEX_END); if (Char == '{') return (LEX_BEGIN); if (isalpha(Char)) { identifierName = ""; //na zacatku je string nazvu prazdny identifierName += Char; //prvni znak identifikatoru State = 38; break; } if (Char == '0') { intValue = 0; floatValue = 0.0; State = 7; break; } if (isdigit(Char)) //nula je chycana drive { intValue = Char - '0'; floatValue = Char - '0'; State = 11; break; } if (Char == '+') { State = 17; break; } if (Char == '-') { State = 20; break; } if (Char == '%') { State = 27; break; } if (Char == '!') { State = 31; break; } if (Char == '<') { State = 33; break; } if (Char == '>') { State = 35; break; } if (Char == '.') { floatValue = 0.0; DmsPos = 0.1; State = 16; break; } if (Char == EOF) return (LEX_NULL); return (LEX_ERROR); case 2: if (Char == '/') { //jednoradkovy komentar State = 4; break; } if (Char == '=') { //operator /= return (LEX_DIVASSIGN); } if (Char == '*') { State = 5; break; } ungetChar(Char); //operator / return (LEX_DIV); case 4: if (Char == '\n') { State = 0; break; } if (Char == EOF) return (LEX_ERROR); break; //pokud by byl eof uvnitr // komentare zustava ve stavu 4 case 5: if (Char == '*') { State = 6; break; } if(Char == LEX_EOF) return (LEX_ERROR); case 6: if (Char == '/') { //konec komentare State = 0; break; } if (Char != '*') { State = 5; break; } break; //state porad = 6 pri * case 7: if (isodigit(Char)) { State = 8; intValue = Char - '0'; break; } if(Char == 'x' || Char == 'X') { State = 9; break; } if(Char == '.') { State = 12; break; } if (Char == EOF) return (LEX_ERROR); if(isalpha(Char)) return (LEX_ERROR); ungetChar(Char); cout << "intValue = " << intValue << endl; return (LEX_INT); //pokud neni ani okta ani hexa case 8: if (isodigit(Char)) { intValue = (intValue << 3) + (Char - '0'); State = 8; //state bude porad 8 break; } if(isalpha(Char)) return (LEX_ERROR); ungetChar(Char); cout << "intValue = " << intValue << endl; return(LEX_INT); case 9: if(isxdigit(Char)) { Char = (char)toupper(Char); intValue = (Char >= 'A') ? Char - 'A' + 10 : Char - '0'; State = 10; break; } return(LEX_ERROR); case 10: if (isxdigit(Char)) { Char = (char)toupper(Char); intValue = (intValue << 4) + ((Char >= 'A') ? Char - 'A' + 10 : Char - '0'); break; } case 11: if(isdigit(Char)) { intValue = intValue * 10 + Char - '0'; floatValue = floatValue * 10.0 + Char - '0'; break; } if(Char == '.') { State = 12; break; } if(isalpha(Char)) return (LEX_ERROR); ungetChar(Char); // nalezen integer cout << "intValue = " << intValue << endl; return (LEX_INT); case 12: if(isdigit(Char)) { floatValue += DmsPos * (Char - '0'); DmsPos /= 10.0; // pocitat intValue break; } if(Char == 'E' || Char == 'e') { Exp = 0; ExpSign = 1; State = 13; break; } if(isalpha(Char)) return (LEX_ERROR); ungetChar(Char); //desetinne cislo s jednim destinnym mistem cout << "floatValue = " << floatValue << endl; return (LEX_FLOAT); case 13: if(isdigit(Char)) { Exp = Char - 0x30; State = 15; break; } if (Char == '+' || Char == '-') { ExpSign = (Char == '-') ? -1 : 1; State = 14; break; } return (LEX_ERROR); case 14: if(isdigit(Char)) { Exp = Char - 0x30; State = 15; break; } return (LEX_ERROR); case 15: if(isdigit(Char)) { Exp = 10 * Exp + Char - 0x30; //dalsi cifry exponentu break; } ungetChar(Char); floatValue *= pow(10.0, Exp * ExpSign); cout << "floatValue = " << floatValue << endl; return (LEX_FLOAT); case 16: if(isdigit(Char)) { floatValue = 0.1 * (Char - '0'); DmsPos = 0.01; //priste jsou zpracovavany setiny State = 12; break; } case 17: if (Char == '=' || Char == '+') // == { if(Char == '=') { State = 18; ungetChar(Char); break; } if (Char == '+') { State = 19; ungetChar(Char); break; } } else { ungetChar(Char); return (LEX_ADD); } case 18: if(Char == '=') return LEX_ADDASSIGN; else { ungetChar(Char); // jenom = return LEX_ADD; } case 19: if(Char == '+') return (LEX_INCREMENT); else { ungetChar(Char); return (LEX_ADD); } case 20: if(Char == '=' || Char == '-') { if(Char == '=') { State = 22; ungetChar(Char); break; } if(Char == '-') { State = 21; ungetChar(Char); break; } } else { ungetChar(Char); return (LEX_SUB); } case 21: if(Char == '-') return (LEX_DECREMENT); else { ungetChar(Char); return (LEX_SUB); } case 22: if(Char == '=') return (LEX_SUBASSIGN); else { ungetChar(Char); return (LEX_SUB); } case 25: if(Char == '=') return (LEX_MULASSIGN); else { ungetChar(Char); return (LEX_MUL); } case 27: if(Char == '=') return (LEX_MODASSIGN); else { ungetChar(Char); return (LEX_MOD); } case 29: if(Char == '=') return (LEX_ISEQUAL); else { ungetChar(Char); return (LEX_ASSIGN); } case 31: if(Char == '=') return (LEX_ISNEQUAL); else { ungetChar(Char); return (LEX_EXCLAMATION); } case 33: if(Char == '=') return (LEX_LESS_EQU_THAN); else { ungetChar(Char); return (LEX_LESS_THAN); } case 35: if(Char == '=') return (LEX_GREATER_EQU_THAN); else { ungetChar(Char); return (LEX_GREATER_THAN); } case 38: if(isalpha(Char) || isdigit(Char)) { identifierName += Char; break; } else { ungetChar(Char); map<int, string>::iterator i; for (i = keywords.begin(); i != keywords.end(); i++) if (identifierName.compare(i->second) == 0) { cout << "keyword: " << i->second << endl; return (i->first); } //identifikator nebyl nalezen v klicovych slovech cout << "identifier: " << identifierName << endl; return (LEX_IDENT); } default: throw "Lexical ERROR: unknown state"; break; } } }
Token* Tokenizer::getToken() { int startRow = row; int startCol = col; QChar c = getChar(); // get and store the next character from the string // catch the end of the input string if (atEnd) return new Token(Token::EndOfInput, "END", row, col, row, col); int cType = translator->look2type(c); // since we need to know it often we store it // catch spaces if (isSpace(c)) { QString look; do { look += (isTab(c) ? " " : " "); c = getChar(); } while (isSpace(c) && !atEnd); ungetChar(); return new Token(Token::WhiteSpace, look, startRow, startCol, row, col); } // catch EndOfLine's if (isBreak(c)) { return new Token(Token::EndOfLine, "\\n", startRow, startCol, startRow+1, 1); } // catch comments if (cType == Token::Comment) { QString look; do { look += c; c = getChar(); } while (!isBreak(c) && !atEnd); ungetChar(); return new Token(Token::Comment, look, startRow, startCol, row, col); } // catch strings if (cType == Token::StringDelimiter) { QString look = QString(c); do { c = getChar(); look += c; } while (!(translator->look2type(c) == Token::StringDelimiter && look.right(2) != "\\\"") && !isBreak(c) && !atEnd); return new Token(Token::String, look, startRow, startCol, row, col); } // catch variables if (cType == Token::VariablePrefix) { QString look; do { look += c; c = getChar(); } while (isWordChar(c) || c.category() == QChar::Number_DecimalDigit || c == '_'); ungetChar(); return new Token(Token::Variable, look, startRow, startCol, row, col); } // catch words (known commands or function calls) if (isWordChar(c)) { // first char has to be a letter QString look; do { look += c; c = getChar(); } while (isWordChar(c) || c.isDigit() || c == '_'); // next chars ungetChar(); int type = translator->look2type(look); if (type == Token::Unknown) type = Token::FunctionCall; return new Token(type, look, startRow, startCol, row, col); } // catch numbers if (c.isDigit() || cType == Token::DecimalSeparator) { bool hasDot = false; int localType = cType; QString look; do { if (localType == Token::DecimalSeparator) hasDot = true; look += c; c = getChar(); localType = translator->look2type(c); } while (c.isDigit() || (localType == Token::DecimalSeparator && !hasDot)); ungetChar(); // if all we got is a dot then this is not a number, so return an Error token here if (translator->look2type(look) == Token::DecimalSeparator) return new Token(Token::Error, look, startRow, startCol, row, col); return new Token(Token::Number, look, startRow, startCol, row, col); } // catch previously uncatched 'double charactered tokens' (tokens that ar not in letters, like: == != >= <=) { QString look = QString(c).append(getChar()); int type = translator->look2type(look); if (type != Token::Unknown) return new Token(type, look, startRow, startCol, row, col); ungetChar(); } // catch known tokens of a single character (as last...) if (cType != Token::Unknown) return new Token(cType, static_cast<QString>(c), startRow, startCol, row, col); // this does not neglect calls to functions with a name of length one (checked it) return new Token(Token::Error, static_cast<QString>(c), startRow, startCol, row, col); }
// Parse the given input stream QVariant StelJsonParserInstance::parse() { skipJson(); char r; if (!getChar(&r)) return QVariant(); switch (r) { case '{': { // We've got an object (a tuple) QVariantMap map; if (skipAndConsumeChar('}')) return map; for (;;) { if (!skipAndConsumeChar('\"')) { char cc=0; getChar(&cc); throw std::runtime_error(qPrintable(QString("Expected '\"' at beginning of string, found: '%1' (ASCII %2)").arg(cc).arg((int)(cc)))); } const QByteArray& ar = readString(); const QString& key = QString::fromUtf8(ar.constData(), ar.size()); if (!skipAndConsumeChar(':')) throw std::runtime_error(qPrintable(QString("Expected ':' after a member name: ")+key)); skipJson(); map.insert(key, parse()); if (!skipAndConsumeChar(',')) break; } if (!skipAndConsumeChar('}')) throw std::runtime_error("Expected '}' to close an object"); return map; } case '[': { // We've got an array (a vector) QVariantList list; if (skipAndConsumeChar(']')) return list; for (;;) { list.append(parse()); if (!skipAndConsumeChar(',')) break; } if (!skipAndConsumeChar(']')) throw std::runtime_error("Expected ']' to close an array"); return list; } case '\"': { // We've got a string const QByteArray& ar = readString(); return QString::fromUtf8(ar.constData(), ar.size()); } default: { ungetChar(r); return readOther(); } } }
long MIFrfile::getVal() { int ch; long val = 0; int decim = 0; long neg = 1; skipWhite(); while ((ch = getChar()) != EOF) { if (isdigit(ch)) { val = (val * 10) + (ch - '0'); if (decim) decim++; } else if (ch == '-') neg = -1; else if (ch == '.') decim = 1; // decimal point else { ungetChar(ch); break; } } if (decim) decim--; skipWhite(); CurrUnits = SetUnits; switch (ch = getChar()) { case '%': // percent CurrUnits = percent; break; case '"': // inches CurrUnits = inch; break; case 'c': ch = getChar(); if (ch == 'm') CurrUnits = cm; else if (ch == 'c') CurrUnits = cc; else ungetChar(ch); break; case 'm': ch = getChar(); if (ch == 'm') CurrUnits = mm; else ungetChar(ch); break; case 'p': ch = getChar(); if (ch == 'c') CurrUnits = pc; else if (ch == 't') CurrUnits = pt; else ungetChar(ch); break; case 'd': ch = getChar(); if (ch == 'd') CurrUnits = dd; else ungetChar(ch); break; default: ungetChar(ch); break; } switch (CurrUnits) { case inch: while (decim > 5) { val /= 10; decim--; } while (decim < 5) { val *= 10; decim++; } break; case pc: case cc: val *= 12; case pt: case dd: while (decim > 2) { val /= 10; decim--; } while (decim < 2) { val *= 10; decim++; } break; case cm: val *= 10; case mm: while (decim > 3) { val /= 10; decim--; } while (decim < 3) { val *= 10; decim++; } break; default: // handle unitless FDW value as percent case percent: while (decim > 2) { val /= 10; decim--; } while (decim < 2) { val *= 10; decim++; } break; } return val * neg; }
int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken) { bool HasDecimalOrExponent = false; int declen; int str_len; int isDouble = 0; declen = 0; str_len=len; char* str = ppToken->name; if (ch == '.') { HasDecimalOrExponent = true; str[len++] = (char)ch; ch = getChar(); while (ch >= '0' && ch <= '9') { if (len < TPpToken::maxTokenLength) { declen++; if (len > 0 || ch != '0') { str[len] = (char)ch; len++; str_len++; } ch = getChar(); } else { parseContext.error(ppToken->loc, "float literal too long", "", ""); len = 1; str_len = 1; } } } // Exponent: if (ch == 'e' || ch == 'E') { HasDecimalOrExponent = true; if (len >= TPpToken::maxTokenLength) { parseContext.error(ppToken->loc, "float literal too long", "", ""); len = 1; str_len = 1; } else { str[len++] = (char)ch; ch = getChar(); if (ch == '+') { str[len++] = (char)ch; ch = getChar(); } else if (ch == '-') { str[len++] = (char)ch; ch = getChar(); } if (ch >= '0' && ch <= '9') { while (ch >= '0' && ch <= '9') { if (len < TPpToken::maxTokenLength) { str[len++] = (char)ch; ch = getChar(); } else { parseContext.error(ppToken->loc, "float literal too long", "", ""); len = 1; str_len = 1; } } } else { parseContext.error(ppToken->loc, "bad character in float exponent", "", ""); } } } if (len == 0) { ppToken->dval = 0.0; strcpy(str, "0.0"); } else { if (ch == 'l' || ch == 'L') { parseContext.doubleCheck(ppToken->loc, "double floating-point suffix"); if (! HasDecimalOrExponent) parseContext.error(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); int ch2 = getChar(); if (ch2 != 'f' && ch2 != 'F') { ungetChar(); ungetChar(); } else { if (len < TPpToken::maxTokenLength) { str[len++] = (char)ch; str[len++] = (char)ch2; isDouble = 1; } else { parseContext.error(ppToken->loc, "float literal too long", "", ""); len = 1,str_len=1; } } } else if (ch == 'f' || ch == 'F') { parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix"); if (! parseContext.relaxedErrors()) parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix"); if (! HasDecimalOrExponent) parseContext.error(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); if (len < TPpToken::maxTokenLength) str[len++] = (char)ch; else { parseContext.error(ppToken->loc, "float literal too long", "", ""); len = 1,str_len=1; } } else ungetChar(); str[len]='\0'; ppToken->dval = strtod(str, nullptr); } if (isDouble) return CPP_DOUBLECONSTANT; else return CPP_FLOATCONSTANT; }
//************************************************************************* // // The following utility functions are used to skip whitespaces and // parse integers. // //************************************************************************* void readWhiteSpace ( int conn) { int c; while (isspace (c = getChar (conn))); ungetChar (c); }