Logo Search packages:      
Sourcecode: kalzium version File versions  Download package

parser.cpp

/***************************************************************************
    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 <ctype.h>

#include <kdebug.h>


00021 Parser::Parser()
{
    start(QString());
}


00027 Parser::Parser(const QString& _str)
{
    start(_str);
}


00033 Parser::~Parser()
{
}


void
00039 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
00139 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
00168 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
00184 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;
}

Generated by  Doxygen 1.6.0   Back to index