/*************************************************************************** copyright : (C) 2005 by Inge Wallin email : inge@lysator.liu.se ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "parser.h" #include #include Parser::Parser() { start(QString()); } Parser::Parser(const QString& _str) { start(_str); } Parser::~Parser() { } void Parser::start(const QString& _str) { m_str = _str; if (_str.isNull()) { m_index = -1; m_nextChar = -1; m_nextToken = -1; } else { m_index = 0; m_nextChar = m_str.at(0).toLatin1(); getNextToken(); } } // ---------------------------------------------------------------- // Skip whitespace, and try to parse the following characters as an int. // // Return true if successful. bool Parser::parseInt(int *_result) { int sign = 1; skipWhitespace(); if (m_nextChar == '-') { sign = -1; getNextChar(); } if (!isdigit(m_nextChar)) return false; int result = 0; while (isdigit(m_nextChar)) { result = result * 10 + (m_nextChar - '0'); getNextChar(); } *_result = sign * result; return true; } // Skip whitespace, and try to parse the following characters as a // simple float of the type -?[0-9]+'.'?[0-9]* // // Return true if successful. bool Parser::parseSimpleFloat(double *_result) { double sign = 1.0; skipWhitespace(); if (m_nextChar == '-') { sign = -1.0; getNextChar(); } if (!isdigit(m_nextChar)) return false; double result = 0.0; // The integer. while (isdigit(m_nextChar)) { result = result * 10.0 + (double) (m_nextChar - '0'); getNextChar(); } *_result = result; if (m_nextChar != '.' || !isdigit(getNextChar())) { *_result = sign * result; return true; } double decimal = 0.1; while (isdigit(m_nextChar)) { result += decimal * (double) (m_nextChar - '0'); decimal /= 10.0; getNextChar(); } *_result = sign * result; return true; } // ---------------------------------------------------------------- // protected methods int Parser::getNextChar() { // kDebug() << "Parser::getNextChar(): char = " << m_nextChar; // kDebug() << "m_str.size() " << m_str.size() << " with m_str: " << m_str << " and m_index: " << m_index; m_index++; if (m_index == -1) return -1; // If end of string, then reset the parser. if (m_index == m_str.size()) { m_index = -1; m_nextChar = -1; } else m_nextChar = m_str.at(m_index).toLatin1(); // Take care of null-terminated strings. if (m_nextChar == 0) { m_index = -1; m_nextChar = -1; } return m_nextChar; } int Parser::skipWhitespace() { while (QChar(m_nextChar).isSpace()) getNextChar(); return m_nextChar; } // Get the next token. This corresponds to the lexical analyzer of a // standard parser, e.g as generated by lex. // // This basic parser supports integers and simple // floats. Reimplement this method to extend it. int Parser::getNextToken() { int saveIndex = m_index; skipWhitespace(); if (isdigit(nextChar())) { // At this point we know that there is a valid number in the // string. The only question now, is whether it is an int or a // float. parseInt(&m_intVal); skipWhitespace(); if (nextChar() == '.') { m_index = saveIndex; // No need to check since we already know it is correct. (void) parseSimpleFloat(&m_floatVal); m_nextToken = FLOAT_TOKEN; } else m_nextToken = INT_TOKEN; } else if (nextChar() != -1) { // Any character. m_nextToken = nextChar(); getNextChar(); } else // End of string. m_nextToken = -1; return m_nextToken; }