You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeedu/kalzium/src/parser.cpp

218 lines
4.2 KiB

/***************************************************************************
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 <ctype.h>
#include <kdebug.h>
#include "parser.h"
Parser::Parser()
{
start(TQString());
}
Parser::Parser(const TQString& _str)
{
start(_str);
}
Parser::~Parser()
{
}
void
Parser::start(const TQString& _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).latin1();
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()
{
if (m_index == -1)
return -1;
// If end of string, then reset the parser.
if (m_index == (int) m_str.length()) {
m_index = -1;
m_nextChar = -1;
}
else
m_nextChar = m_str.at(++m_index).latin1();
// Take care of null-terminated strings.
if (m_nextChar == 0) {
m_index = -1;
m_nextChar = -1;
}
//kdDebug() << "Parser::getNextChar(): char = " << m_nextChar << endl;
return m_nextChar;
}
int
Parser::skipWhitespace()
{
while (TQChar(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;
}