1
|
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 }
|