~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to tools/porting/src/rpplexer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2004-2005 Trolltech AS. All rights reserved.
 
4
** Copyright (C) 2001-2004 Roberto Raggi
 
5
**
 
6
** This file is part of the porting application of the Qt Toolkit.
 
7
**
 
8
** This file may be distributed under the terms of the Q Public License
 
9
** as defined by Trolltech AS of Norway and appearing in the file
 
10
** LICENSE.QPL included in the packaging of this file.
 
11
**
 
12
** This file may be distributed and/or modified under the terms of the
 
13
** GNU General Public License version 2 as published by the Free Software
 
14
** Foundation and appearing in the file LICENSE.GPL included in the
 
15
** packaging of this file.
 
16
**
 
17
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
18
**   information about Qt Commercial License Agreements.
 
19
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
20
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
21
**
 
22
** Contact info@trolltech.com if any conditions of this licensing are
 
23
** not clear to you.
 
24
**
 
25
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
26
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
27
**
 
28
****************************************************************************/
 
29
#include "rpplexer.h"
 
30
#include <iostream>
 
31
#include <locale>
 
32
#include <QChar>
 
33
 
 
34
using namespace std;
 
35
using namespace TokenEngine;
 
36
 
 
37
namespace Rpp {
 
38
RppLexer::RppLexer()
 
39
{
 
40
    setupScanTable();
 
41
}
 
42
 
 
43
void RppLexer::setupScanTable()
 
44
{
 
45
    memset(s_attr_table, 0, 256);
 
46
 
 
47
    for (int i=0; i<128; ++i) {
 
48
        switch (i) {
 
49
        case ':':
 
50
        case '*':
 
51
        case '%':
 
52
        case '^':
 
53
        case '=':
 
54
        case '!':
 
55
        case '&':
 
56
        case '|':
 
57
        case '+':
 
58
        case '<':
 
59
        case '>':
 
60
        case '-':
 
61
        case '.':
 
62
            s_scan_table[i] = &RppLexer::scanOperator;
 
63
            break;
 
64
 
 
65
        case '\r':
 
66
                case '\n':
 
67
            s_scan_table[i] = &RppLexer::scanNewline;
 
68
            break;
 
69
 
 
70
        case '\'':
 
71
            s_scan_table[i] = &RppLexer::scanCharLiteral;
 
72
            break;
 
73
 
 
74
        case '"':
 
75
            s_scan_table[i] = &RppLexer::scanStringLiteral;
 
76
            break;
 
77
        case '#':
 
78
            s_scan_table[i] = &RppLexer::scanPreprocessor;
 
79
            break;
 
80
 
 
81
        case '/':
 
82
            s_scan_table[i] = &RppLexer::scanComment;
 
83
            break;
 
84
 
 
85
        default:
 
86
            if (isspace(i)) {
 
87
                s_scan_table[i] = &RppLexer::scanWhiteSpaces;
 
88
                s_attr_table[i] |= A_Whitespace;
 
89
            } else if (isalpha(i) || i == '_') {
 
90
                s_scan_table[i] = &RppLexer::scanKeyword;
 
91
                s_attr_table[i] |= A_Alpha;
 
92
            } else if (isdigit(i)) {
 
93
                s_scan_table[i] = &RppLexer::scanNumberLiteral;
 
94
                s_attr_table[i] |= A_Digit;
 
95
            } else
 
96
                s_scan_table[i] = &RppLexer::scanChar;
 
97
        }
 
98
    }
 
99
 
 
100
    s_scan_table[128] = &RppLexer::scanUnicodeChar;
 
101
}
 
102
 
 
103
QVector<Type> RppLexer::lex(const TokenContainer &tokenContainer)
 
104
{
 
105
    QVector<Type> tokenTypes;
 
106
    const int numTokens = tokenContainer.count();
 
107
    tokenTypes.reserve(numTokens);
 
108
    QByteArray text = tokenContainer.fullText();
 
109
    m_buffer = text.constData();
 
110
    for(int t=0; t<numTokens; ++t) {
 
111
        TokenEngine::Token token = tokenContainer.token(t);
 
112
        tokenTypes.append(indentify(token.start, token.length));
 
113
    }
 
114
    return tokenTypes;
 
115
}
 
116
 
 
117
Type RppLexer::indentify(int pos, int length)
 
118
{
 
119
    Q_ASSERT(length > 0);
 
120
    m_ptr = pos;
 
121
    m_len = length;
 
122
    int kind = 0;
 
123
    const unsigned char ch = m_buffer[pos];
 
124
    (this->*s_scan_table[ch < 128 ? ch : 128])(&kind);
 
125
    return (Type)kind;
 
126
}
 
127
 
 
128
void RppLexer::scanChar(int *kind)
 
129
{
 
130
    *kind = m_buffer[m_ptr];
 
131
}
 
132
 
 
133
void RppLexer::scanWhiteSpaces(int *kind)
 
134
{
 
135
    *kind = Token_whitespaces;
 
136
 
 
137
    while (unsigned char ch = m_buffer[m_ptr]) {
 
138
        if (s_attr_table[ch] & A_Whitespace)
 
139
            ++m_ptr;
 
140
        else
 
141
            break;
 
142
    }
 
143
}
 
144
 
 
145
void RppLexer::scanNewline(int *kind)
 
146
{
 
147
    *kind = '\n';
 
148
}
 
149
 
 
150
void RppLexer::scanUnicodeChar(int *kind)
 
151
{
 
152
    *kind = m_buffer[m_ptr];
 
153
}
 
154
 
 
155
void RppLexer::scanCharLiteral(int *kind)
 
156
{
 
157
    *kind = Token_char_literal;
 
158
}
 
159
 
 
160
void RppLexer::scanStringLiteral(int *kind)
 
161
{
 
162
    *kind = Token_string_literal;
 
163
}
 
164
 
 
165
void RppLexer::scanIdentifier(int *kind)
 
166
{
 
167
    *kind = Token_identifier;
 
168
}
 
169
 
 
170
void RppLexer::scanNumberLiteral(int *kind)
 
171
{
 
172
    *kind = Token_number_literal;
 
173
}
 
174
 
 
175
void RppLexer::scanPreprocessor(int *kind)
 
176
{
 
177
    *kind = Token_preproc;
 
178
}
 
179
 
 
180
void RppLexer::scanComment(int *kind)
 
181
{
 
182
    switch(m_buffer[m_ptr + 1]) {
 
183
    case '/':
 
184
        *kind = Token_line_comment;
 
185
        break;
 
186
    case '*':
 
187
        *kind = Token_multiline_comment;
 
188
        break;
 
189
    default:
 
190
        scanOperator(kind);
 
191
    }
 
192
}
 
193
 
 
194
void RppLexer::scanOperator(int *kind)
 
195
{
 
196
    switch (m_buffer[m_ptr]) {
 
197
    case ':':
 
198
        if (m_buffer[m_ptr+1] == ':') {
 
199
            *kind = Token_scope;
 
200
            return;
 
201
        }
 
202
        break;
 
203
 
 
204
    case '*':
 
205
    case '/':
 
206
    case '%':
 
207
    case '^':
 
208
        if (m_buffer[m_ptr+1] == '=') {
 
209
            *kind = Token_assign;
 
210
            return;
 
211
        }
 
212
        break;
 
213
 
 
214
    case '=':
 
215
       if (m_buffer[m_ptr+1] == '=') {
 
216
            *kind = Token_eq;
 
217
            return;
 
218
        }
 
219
        break;
 
220
    case '!':
 
221
       if (m_buffer[m_ptr+1] == '=') {
 
222
            *kind = Token_not_eq;
 
223
            return;
 
224
        }
 
225
        break;
 
226
 
 
227
    case '&':
 
228
        if (m_buffer[m_ptr+1] == '&') {
 
229
            *kind = Token_and;
 
230
            return;
 
231
        } else if (m_buffer[m_ptr+1] == '=') {
 
232
            *kind = Token_assign;
 
233
            return;
 
234
        }
 
235
        break;
 
236
 
 
237
    case '|':
 
238
        if (m_buffer[m_ptr+1] == '|' ) {
 
239
            *kind = Token_or;
 
240
            return;
 
241
        } else if (m_buffer[m_ptr+1] == '=') {
 
242
            *kind = Token_assign;
 
243
            return;
 
244
        }
 
245
        break;
 
246
 
 
247
    case '+':
 
248
        if (m_buffer[m_ptr+1] == '+' ) {
 
249
            *kind = Token_incr;
 
250
            return;
 
251
        } else if (m_buffer[m_ptr+1] == '=') {
 
252
            *kind = Token_assign;
 
253
            return;
 
254
        }
 
255
        break;
 
256
 
 
257
    case '<':
 
258
        if (m_buffer[m_ptr+1] == '<') {
 
259
            if (m_buffer[m_ptr+2] == '=') {
 
260
                *kind = Token_assign;
 
261
                return;
 
262
            }
 
263
            *kind = Token_left_shift;
 
264
            return;
 
265
        } else if (m_buffer[m_ptr+1] == '=') {
 
266
            *kind = Token_leq;
 
267
            return;
 
268
        }
 
269
        break;
 
270
 
 
271
    case '>':
 
272
        if (m_buffer[m_ptr+1] == '>') {
 
273
            if (m_buffer[m_ptr+2] == '=') {
 
274
                *kind = Token_assign;
 
275
                return;
 
276
            }
 
277
            *kind = Token_right_shift;
 
278
            return;
 
279
        } else if (m_buffer[m_ptr+1] == '=') {
 
280
            *kind = Token_geq;
 
281
            return;
 
282
        }
 
283
        break;
 
284
 
 
285
    case '-':
 
286
        if (m_buffer[m_ptr+1] == '>') {
 
287
            if (m_buffer[m_ptr+2] == '*') {
 
288
                *kind = Token_ptrmem;
 
289
                return;
 
290
            }
 
291
            *kind = Token_arrow;
 
292
            return;
 
293
        } else if (m_buffer[m_ptr+1] == '-') {
 
294
            *kind = Token_decr;
 
295
            return;
 
296
        } else if (m_buffer[m_ptr+1] == '=') {
 
297
            *kind = Token_assign;
 
298
            return;
 
299
        }
 
300
        break;
 
301
 
 
302
    case '.':
 
303
        if (m_buffer[m_ptr+1] == '.' && m_buffer[m_ptr+2] == '.') {
 
304
            *kind = Token_ellipsis;
 
305
            return;
 
306
        } else if (m_buffer[m_ptr+1] == '*') {
 
307
            *kind = Token_ptrmem;
 
308
            return;
 
309
        }
 
310
        break;
 
311
 
 
312
    }
 
313
 
 
314
    *kind = m_buffer[m_ptr++];
 
315
}
 
316
 
 
317
bool RppLexer::match(char *buf, int len)
 
318
{
 
319
    if (m_len != len)
 
320
        return false;
 
321
    for (int i = 0; i < len; ++i) {
 
322
        if(m_buffer[m_ptr + i] != buf[i])
 
323
            return false;
 
324
    }
 
325
    return true;
 
326
}
 
327
 
 
328
void RppLexer::scanKeyword(int *kind)
 
329
{
 
330
    if(match("if", 2))
 
331
        *kind = Token_directive_if;
 
332
    else if(match("elif", 4))
 
333
        *kind = Token_directive_elif;
 
334
    else if(match("else", 4))
 
335
        *kind = Token_directive_else;
 
336
    else if(match("line", 4))
 
337
        *kind = Token_directive_line;
 
338
    else if(match("else", 4))
 
339
        *kind = Token_directive_else;
 
340
    else if(match("line", 4))
 
341
        *kind = Token_directive_line;
 
342
    else if(match("endif", 5))
 
343
        *kind = Token_directive_endif;
 
344
    else if(match("ifdef", 5))
 
345
        *kind = Token_directive_ifdef;
 
346
    else if(match("error", 5))
 
347
        *kind = Token_directive_error;
 
348
    else if(match("undef", 5))
 
349
        *kind = Token_directive_undef;
 
350
    else if(match("pragma", 6))
 
351
        *kind = Token_directive_pragma;
 
352
    else if(match("ifndef", 6))
 
353
        *kind = Token_directive_ifndef;
 
354
    else if(match("define", 6))
 
355
        *kind = Token_directive_define;
 
356
    else if(match("include", 7))
 
357
        *kind = Token_directive_include;
 
358
    else if(match("defined", 7))
 
359
        *kind = Token_defined;
 
360
    else
 
361
        *kind = Token_identifier;
 
362
}
 
363
 
 
364
} //namespace Rpp