comparison generator/typeparser.cpp @ 1:e78566595089

initial import
author mandel
date Mon, 11 May 2009 16:01:50 +0000
parents
children
comparison
equal deleted inserted replaced
0:36fb74dc547d 1:e78566595089
1 /****************************************************************************
2 **
3 ** Copyright (C) 1992-2008 Nokia. All rights reserved.
4 **
5 ** This file is part of Qt Jambi.
6 **
7 ** * Commercial Usage
8 * Licensees holding valid Qt Commercial licenses may use this file in
9 * accordance with the Qt Commercial License Agreement provided with the
10 * Software or, alternatively, in accordance with the terms contained in
11 * a written agreement between you and Nokia.
12 *
13 *
14 * GNU General Public License Usage
15 * Alternatively, this file may be used under the terms of the GNU
16 * General Public License versions 2.0 or 3.0 as published by the Free
17 * Software Foundation and appearing in the file LICENSE.GPL included in
18 * the packaging of this file. Please review the following information
19 * to ensure GNU General Public Licensing requirements will be met:
20 * http://www.fsf.org/licensing/licenses/info/GPLv2.html and
21 * http://www.gnu.org/copyleft/gpl.html. In addition, as a special
22 * exception, Nokia gives you certain additional rights. These rights
23 * are described in the Nokia Qt GPL Exception version 1.2, included in
24 * the file GPL_EXCEPTION.txt in this package.
25 *
26 * Qt for Windows(R) Licensees
27 * As a special exception, Nokia, as the sole copyright holder for Qt
28 * Designer, grants users of the Qt/Eclipse Integration plug-in the
29 * right for the Qt/Eclipse Integration to link to functionality
30 * provided by Qt Designer and its related libraries.
31 *
32 *
33 * If you are unsure which license is appropriate for your use, please
34 * contact the sales department at qt-sales@nokia.com.
35
36 **
37 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
38 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
39 **
40 ****************************************************************************/
41
42 #include "typeparser.h"
43
44 #include <qdebug.h>
45 #include <QStack>
46
47 class Scanner
48 {
49 public:
50 enum Token {
51 StarToken,
52 AmpersandToken,
53 LessThanToken,
54 ColonToken,
55 CommaToken,
56 OpenParenToken,
57 CloseParenToken,
58 SquareBegin,
59 SquareEnd,
60 GreaterThanToken,
61
62 ConstToken,
63 Identifier,
64 NoToken
65 };
66
67 Scanner(const QString &s)
68 : m_pos(0), m_length(s.length()), m_chars(s.constData())
69 {
70 }
71
72 Token nextToken();
73 QString identifier() const;
74
75 private:
76 int m_pos;
77 int m_length;
78 int m_token_start;
79 const QChar *m_chars;
80 };
81
82 QString Scanner::identifier() const
83 {
84 return QString(m_chars + m_token_start, m_pos - m_token_start);
85 }
86
87 Scanner::Token Scanner::nextToken()
88 {
89 Token tok = NoToken;
90
91 // remove whitespace
92 while (m_pos < m_length && m_chars[m_pos] == ' ') {
93 ++m_pos;
94 }
95
96 m_token_start = m_pos;
97
98 while (m_pos < m_length) {
99
100 const QChar &c = m_chars[m_pos];
101
102 if (tok == NoToken) {
103 switch (c.toLatin1()) {
104 case '*': tok = StarToken; break;
105 case '&': tok = AmpersandToken; break;
106 case '<': tok = LessThanToken; break;
107 case '>': tok = GreaterThanToken; break;
108 case ',': tok = CommaToken; break;
109 case '(': tok = OpenParenToken; break;
110 case ')': tok = CloseParenToken; break;
111 case '[': tok = SquareBegin; break;
112 case ']' : tok = SquareEnd; break;
113 case ':':
114 tok = ColonToken;
115 Q_ASSERT(m_pos + 1 < m_length);
116 ++m_pos;
117 break;
118 default:
119 if (c.isLetterOrNumber() || c == '_')
120 tok = Identifier;
121 else
122 qFatal("Unrecognized character in lexer: %c", c.toLatin1());
123 break;
124 }
125 }
126
127 if (tok <= GreaterThanToken) {
128 ++m_pos;
129 break;
130 }
131
132 if (tok == Identifier) {
133 if (c.isLetterOrNumber() || c == '_')
134 ++m_pos;
135 else
136 break;
137 }
138 }
139
140 if (tok == Identifier && m_pos - m_token_start == 5) {
141 if (m_chars[m_token_start] == 'c'
142 && m_chars[m_token_start + 1] == 'o'
143 && m_chars[m_token_start + 2] == 'n'
144 && m_chars[m_token_start + 3] == 's'
145 && m_chars[m_token_start + 4] == 't')
146 tok = ConstToken;
147 }
148
149 return tok;
150
151 }
152
153 TypeParser::Info TypeParser::parse(const QString &str)
154 {
155 Scanner scanner(str);
156
157 Info info;
158 QStack<Info *> stack;
159 stack.push(&info);
160
161 bool colon_prefix = false;
162 bool in_array = false;
163 QString array;
164
165 Scanner::Token tok = scanner.nextToken();
166 while (tok != Scanner::NoToken) {
167
168 // switch (tok) {
169 // case Scanner::StarToken: printf(" - *\n"); break;
170 // case Scanner::AmpersandToken: printf(" - &\n"); break;
171 // case Scanner::LessThanToken: printf(" - <\n"); break;
172 // case Scanner::GreaterThanToken: printf(" - >\n"); break;
173 // case Scanner::ColonToken: printf(" - ::\n"); break;
174 // case Scanner::CommaToken: printf(" - ,\n"); break;
175 // case Scanner::ConstToken: printf(" - const\n"); break;
176 // case Scanner::SquareBegin: printf(" - [\n"); break;
177 // case Scanner::SquareEnd: printf(" - ]\n"); break;
178 // case Scanner::Identifier: printf(" - '%s'\n", qPrintable(scanner.identifier())); break;
179 // default:
180 // break;
181 // }
182
183 switch (tok) {
184
185 case Scanner::StarToken:
186 ++stack.top()->indirections;
187 break;
188
189 case Scanner::AmpersandToken:
190 stack.top()->is_reference = true;
191 break;
192
193 case Scanner::LessThanToken:
194 stack.top()->template_instantiations << Info();
195 stack.push(&stack.top()->template_instantiations.last());
196 break;
197
198 case Scanner::CommaToken:
199 stack.pop();
200 stack.top()->template_instantiations << Info();
201 stack.push(&stack.top()->template_instantiations.last());
202 break;
203
204 case Scanner::GreaterThanToken:
205 stack.pop();
206 break;
207
208 case Scanner::ColonToken:
209 colon_prefix = true;
210 break;
211
212 case Scanner::ConstToken:
213 stack.top()->is_constant = true;
214 break;
215
216 case Scanner::OpenParenToken: // function pointers not supported
217 case Scanner::CloseParenToken:
218 {
219 Info i;
220 i.is_busted = true;
221 return i;
222 }
223
224
225 case Scanner::Identifier:
226 if (in_array) {
227 array = scanner.identifier();
228 } else if (colon_prefix || stack.top()->qualified_name.isEmpty()) {
229 stack.top()->qualified_name << scanner.identifier();
230 colon_prefix = false;
231 } else {
232 stack.top()->qualified_name.last().append(" " + scanner.identifier());
233 }
234 break;
235
236 case Scanner::SquareBegin:
237 in_array = true;
238 break;
239
240 case Scanner::SquareEnd:
241 in_array = false;
242 stack.top()->arrays += array;
243 break;
244
245
246 default:
247 break;
248 }
249
250 tok = scanner.nextToken();
251 }
252
253 return info;
254 }
255
256 QString TypeParser::Info::instantiationName() const
257 {
258 QString s(qualified_name.join("::"));
259 if (!template_instantiations.isEmpty()) {
260 s += '<';
261 for (int i=0; i<template_instantiations.size(); ++i) {
262 if (i != 0)
263 s += ",";
264 s += template_instantiations.at(i).toString();
265 }
266 s += '>';
267 }
268
269 return s;
270 }
271
272 QString TypeParser::Info::toString() const
273 {
274 QString s;
275
276 if (is_constant) s += "const ";
277 s += instantiationName();
278 for (int i=0; i<arrays.size(); ++i)
279 s += "[" + arrays.at(i) + "]";
280 s += QString(indirections, '*');
281 if (is_reference) s += '&';
282
283 return s;
284 }