~ubuntu-branches/ubuntu/precise/kalzium/precise

« back to all changes in this revision

Viewing changes to libscience/parser.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Philip Muškovac
  • Date: 2011-07-03 12:28:58 UTC
  • Revision ID: james.westby@ubuntu.com-20110703122858-q1yyxncs89e4w0hs
Tags: upstream-4.6.90+repack
Import upstream version 4.6.90+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
    copyright            : (C) 2005 by Inge Wallin
 
3
    email                : inge@lysator.liu.se
 
4
 ***************************************************************************/
 
5
/***************************************************************************
 
6
 *                                                                         *
 
7
 *   This program is free software; you can redistribute it and/or modify  *
 
8
 *   it under the terms of the GNU General Public License as published by  *
 
9
 *   the Free Software Foundation; either version 2 of the License, or     *
 
10
 *   (at your option) any later version.                                   *
 
11
 *                                                                         *
 
12
 ***************************************************************************/
 
13
 
 
14
#include "parser.h"
 
15
 
 
16
#include <ctype.h>
 
17
 
 
18
#include <kdebug.h>
 
19
 
 
20
 
 
21
Parser::Parser()
 
22
{
 
23
    start(QString());
 
24
}
 
25
 
 
26
 
 
27
Parser::Parser(const QString& _str)
 
28
{
 
29
    start(_str);
 
30
}
 
31
 
 
32
 
 
33
Parser::~Parser()
 
34
{
 
35
}
 
36
 
 
37
 
 
38
void
 
39
Parser::start(const QString& _str)
 
40
{
 
41
    m_str = _str;
 
42
 
 
43
    if (_str.isNull()) {
 
44
        m_index     = -1;
 
45
        m_nextChar  = -1;
 
46
        m_nextToken = -1;
 
47
    }
 
48
    else {
 
49
        m_index     = 0;
 
50
        m_nextChar  = m_str.at(0).toLatin1();
 
51
        getNextToken();
 
52
    }
 
53
}
 
54
 
 
55
 
 
56
// ----------------------------------------------------------------
 
57
 
 
58
 
 
59
// Skip whitespace, and try to parse the following characters as an int.
 
60
//
 
61
// Return true if successful.  
 
62
 
 
63
bool
 
64
Parser::parseInt(int *_result)
 
65
{
 
66
    int  sign = 1;
 
67
 
 
68
    skipWhitespace();
 
69
 
 
70
    if (m_nextChar == '-') {
 
71
        sign = -1;
 
72
        getNextChar();
 
73
    }
 
74
 
 
75
    if (!isdigit(m_nextChar))
 
76
        return false;
 
77
 
 
78
    int  result = 0;
 
79
    while (isdigit(m_nextChar)) {
 
80
        result = result * 10 + (m_nextChar - '0');
 
81
        getNextChar();
 
82
    }
 
83
 
 
84
    *_result = sign * result;
 
85
    return true;
 
86
}
 
87
 
 
88
 
 
89
// Skip whitespace, and try to parse the following characters as a
 
90
// simple float of the type -?[0-9]+'.'?[0-9]*
 
91
//
 
92
// Return true if successful.  
 
93
 
 
94
bool
 
95
Parser::parseSimpleFloat(double *_result)
 
96
{
 
97
    double  sign = 1.0;
 
98
 
 
99
    skipWhitespace();
 
100
    if (m_nextChar == '-') {
 
101
        sign = -1.0;
 
102
        getNextChar();
 
103
    }
 
104
 
 
105
    if (!isdigit(m_nextChar))
 
106
        return false;
 
107
 
 
108
    double  result = 0.0;
 
109
 
 
110
    // The integer.
 
111
    while (isdigit(m_nextChar)) {
 
112
        result = result * 10.0 + (double) (m_nextChar - '0');
 
113
        getNextChar();
 
114
    }
 
115
    *_result = result;
 
116
 
 
117
    if (m_nextChar != '.' || !isdigit(getNextChar())) {
 
118
        *_result = sign * result;
 
119
        return true;
 
120
    }
 
121
        
 
122
    double  decimal = 0.1;
 
123
    while (isdigit(m_nextChar)) {
 
124
        result += decimal * (double) (m_nextChar - '0');
 
125
        decimal /= 10.0;
 
126
        getNextChar();
 
127
    }
 
128
 
 
129
    *_result = sign * result;
 
130
    return true;
 
131
}
 
132
 
 
133
 
 
134
// ----------------------------------------------------------------
 
135
//                           protected methods
 
136
 
 
137
 
 
138
int
 
139
Parser::getNextChar()
 
140
{
 
141
//      kDebug() << "Parser::getNextChar(): char = " << m_nextChar;
 
142
//      kDebug() << "m_str.size() " << m_str.size()  << " with m_str: " << m_str  << " and m_index: " << m_index;
 
143
        
 
144
        m_index++;
 
145
        
 
146
        if (m_index == -1)
 
147
                return -1;
 
148
 
 
149
        // If end of string, then reset the parser.
 
150
        if (m_index == m_str.size()) {
 
151
                m_index    = -1;
 
152
                m_nextChar = -1;
 
153
        }
 
154
        else 
 
155
                m_nextChar = m_str.at(m_index).toLatin1();
 
156
 
 
157
        // Take care of null-terminated strings.
 
158
        if (m_nextChar == 0) {
 
159
                m_index    = -1;
 
160
                m_nextChar = -1;
 
161
        }
 
162
 
 
163
        return m_nextChar;
 
164
}
 
165
 
 
166
 
 
167
int
 
168
Parser::skipWhitespace()
 
169
{
 
170
    while (QChar(m_nextChar).isSpace())
 
171
        getNextChar();
 
172
 
 
173
    return m_nextChar;
 
174
}
 
175
 
 
176
 
 
177
// Get the next token.  This corresponds to the lexical analyzer of a
 
178
// standard parser, e.g as generated by lex.
 
179
//
 
180
// This basic parser supports integers and simple
 
181
// floats.  Reimplement this method to extend it.
 
182
 
 
183
int
 
184
Parser::getNextToken()
 
185
{
 
186
    int  saveIndex = m_index;
 
187
 
 
188
    skipWhitespace();
 
189
    if (isdigit(nextChar())) {
 
190
        // At this point we know that there is a valid number in the
 
191
        // string.  The only question now, is whether it is an int or a
 
192
        // float.
 
193
 
 
194
        parseInt(&m_intVal);
 
195
 
 
196
        skipWhitespace();
 
197
        if (nextChar() == '.') {
 
198
            m_index = saveIndex;
 
199
 
 
200
            // No need to check since we already know it is correct.
 
201
            (void) parseSimpleFloat(&m_floatVal);
 
202
            m_nextToken = FLOAT_TOKEN;
 
203
        }
 
204
        else
 
205
            m_nextToken = INT_TOKEN;
 
206
    }
 
207
 
 
208
    else if (nextChar() != -1) {
 
209
        // Any character.
 
210
        m_nextToken = nextChar();
 
211
        getNextChar();
 
212
    }
 
213
 
 
214
    else
 
215
        // End of string.
 
216
        m_nextToken = -1;
 
217
 
 
218
    return m_nextToken;
 
219
}