|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2001-2004 Roberto Raggi |
|
4 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
5 ** All rights reserved. |
|
6 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
7 ** |
|
8 ** This file is part of the qt3to4 porting application of the Qt Toolkit. |
|
9 ** |
|
10 ** $QT_BEGIN_LICENSE:LGPL$ |
|
11 ** No Commercial Usage |
|
12 ** This file contains pre-release code and may not be distributed. |
|
13 ** You may use this file in accordance with the terms and conditions |
|
14 ** contained in the Technology Preview License Agreement accompanying |
|
15 ** this package. |
|
16 ** |
|
17 ** GNU Lesser General Public License Usage |
|
18 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
19 ** General Public License version 2.1 as published by the Free Software |
|
20 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
21 ** packaging of this file. Please review the following information to |
|
22 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
24 ** |
|
25 ** In addition, as a special exception, Nokia gives you certain additional |
|
26 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
28 ** |
|
29 ** If you have questions regarding the use of this file, please contact |
|
30 ** Nokia at qt-info@nokia.com. |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** |
|
39 ** $QT_END_LICENSE$ |
|
40 ** |
|
41 ****************************************************************************/ |
|
42 |
|
43 #include "parser.h" |
|
44 #include "tokens.h" |
|
45 #include "errors.h" |
|
46 |
|
47 #include <QString> |
|
48 #include <QStringList> |
|
49 #include <QDateTime> |
|
50 |
|
51 QT_BEGIN_NAMESPACE |
|
52 |
|
53 #define TT (tokenStream->currentTokenText().data()) |
|
54 |
|
55 #define ADVANCE(tk, descr) \ |
|
56 { \ |
|
57 if (tokenStream->lookAhead() != tk) { \ |
|
58 reportError(QString::fromLatin1("'%1' expected found '%2'").arg(QLatin1String(descr)).arg(QString::fromLatin1((tokenStream->currentTokenText().constData())))); \ |
|
59 return false; \ |
|
60 } \ |
|
61 advance(); \ |
|
62 } |
|
63 |
|
64 #define ADVANCE_NR(tk, descr) \ |
|
65 do { \ |
|
66 if (tokenStream->lookAhead() != tk) { \ |
|
67 reportError(i18n("'%1' expected found '%2'").arg(QLatin1String(descr)).arg(QString::fromLatin1(tokenStream->currentTokenText().constData()))); \ |
|
68 } \ |
|
69 else \ |
|
70 advance(); \ |
|
71 } while (0) |
|
72 |
|
73 #define CHECK(tk, descr) \ |
|
74 do { \ |
|
75 if (tokenStream->lookAhead() != tk) { \ |
|
76 return false; \ |
|
77 } \ |
|
78 advance(); \ |
|
79 } while (0) |
|
80 |
|
81 #define MATCH(tk, descr) \ |
|
82 do { \ |
|
83 if (tokenStream->lookAhead() != tk) { \ |
|
84 reportError(Errors::SyntaxError); \ |
|
85 return false; \ |
|
86 } \ |
|
87 } while (0) |
|
88 |
|
89 #define UPDATE_POS(_node, start, end) \ |
|
90 do { \ |
|
91 (_node)->setPosition(start, end); \ |
|
92 } while (0) |
|
93 |
|
94 #define AST_FROM_TOKEN(node, tk) \ |
|
95 AST *node = CreateNode<AST>(m_pool); \ |
|
96 UPDATE_POS(node, (tk), (tk)+1); |
|
97 |
|
98 #define DUMP_AST(node) \ |
|
99 do { \ |
|
100 fprintf(stderr, "\n=================================================\n"); \ |
|
101 for (int i=node->startToken(); i<node->endToken(); ++i) \ |
|
102 fprintf(stderr, "%s", tokenStream->tokenText(i).constData()); \ |
|
103 fprintf(stderr, "\n=================================================\n"); \ |
|
104 } while (0) |
|
105 |
|
106 #define RXX_NO_ERROR |
|
107 |
|
108 QString i18n(const char *arg) |
|
109 { |
|
110 return QLatin1String(arg); |
|
111 } |
|
112 |
|
113 |
|
114 //@todo remove me |
|
115 enum |
|
116 { |
|
117 OBJC_CLASS, |
|
118 OBJC_PROTOCOL, |
|
119 OBJC_ALIAS |
|
120 }; |
|
121 |
|
122 Parser::Parser() |
|
123 { |
|
124 m_maxProblems = 5; |
|
125 objcp = false; |
|
126 } |
|
127 |
|
128 Parser::~Parser() |
|
129 { |
|
130 } |
|
131 |
|
132 TranslationUnitAST *Parser::parse(TokenStreamAdapter::TokenStream *p_tokenStream, pool *p) |
|
133 { |
|
134 //tokenStream->rewind(0); |
|
135 m_pool = p; |
|
136 tokenStream = p_tokenStream; |
|
137 TranslationUnitAST *ast = 0; |
|
138 parseTranslationUnit(ast); |
|
139 return ast; |
|
140 } |
|
141 |
|
142 /* |
|
143 Parses a part of the translation unit given by tokenStream. When the number |
|
144 of nodes in the AST exeeds targetMaxASTnodes, this function will return as |
|
145 soon as possible. The progress is stored by updating the cursor inside |
|
146 tokenStream. done is set to true if the parser finished parsing the |
|
147 tokenStream, and to false otherwise. |
|
148 */ |
|
149 TranslationUnitAST *Parser::parse(TokenStreamAdapter::TokenStream *p_tokenStream, pool *p, int targetMaxASTNodes, bool &done) |
|
150 { |
|
151 m_pool = p; |
|
152 tokenStream = p_tokenStream; |
|
153 TranslationUnitAST *ast = 0; |
|
154 // we always create one node, so target max nodes cannot be < 2. |
|
155 if (targetMaxASTNodes < 2) |
|
156 targetMaxASTNodes = 2; |
|
157 |
|
158 // Advance past whitespace and comment tokens at the start. |
|
159 while (tokenStream->isHidden(tokenStream->cursor())) { |
|
160 tokenStream->nextToken(); |
|
161 } |
|
162 int start = tokenStream->cursor(); |
|
163 |
|
164 AST::N = 0; |
|
165 m_problems = 0; |
|
166 ast = CreateNode<TranslationUnitAST>(m_pool); |
|
167 while (tokenStream->lookAhead() && AST::N < targetMaxASTNodes) { |
|
168 DeclarationAST *def = 0; |
|
169 int startDecl = tokenStream->cursor(); |
|
170 if (!parseDeclaration(def)) { |
|
171 // error recovery |
|
172 if (startDecl == tokenStream->cursor()) |
|
173 advance(); // skip at least one token |
|
174 skipUntilDeclaration(); |
|
175 } |
|
176 ast->addDeclaration(def); |
|
177 } |
|
178 |
|
179 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
180 |
|
181 done = tokenStream->tokenAtEnd(); |
|
182 return ast; |
|
183 } |
|
184 |
|
185 |
|
186 bool Parser::reportError(const Error& err) |
|
187 { |
|
188 Q_UNUSED(err); |
|
189 #ifndef RXX_NO_ERROR |
|
190 if (m_problems < m_maxProblems) { |
|
191 ++m_problems; |
|
192 int line=0, col=0; |
|
193 QByteArray fileName; |
|
194 tokenStream->getTokenStartPosition(tokenStream->cursor(), &line, &col, &fileName); |
|
195 |
|
196 QString s = tokenStream->currentTokenText(); |
|
197 s = s.left(30).trimmed(); |
|
198 if (s.isEmpty()) |
|
199 s = i18n("<eof>"); |
|
200 |
|
201 if (fileName.isEmpty()) |
|
202 //fileName = m_file->fileName; |
|
203 fileName = "implement me"; |
|
204 |
|
205 // m_driver->addProblem(m_driver->currentFileName(), Problem(err.text.arg(s), line, col)); |
|
206 fprintf(stderr, "%s: error %s at line %d column %d\n", |
|
207 fileName.constData(), |
|
208 err.text.arg(s).toLatin1().constData(), line, col); |
|
209 } |
|
210 #endif // RXX_NO_ERROR |
|
211 return true; |
|
212 } |
|
213 |
|
214 bool Parser::reportError(const QString& msg) |
|
215 { |
|
216 Q_UNUSED(msg); |
|
217 #ifndef RXX_NO_ERROR |
|
218 if (m_problems < m_maxProblems) { |
|
219 ++m_problems; |
|
220 int line=0, col=0; |
|
221 QByteArray fileName; |
|
222 tokenStream->getTokenStartPosition(tokenStream->cursor(), &line, &col, &fileName); |
|
223 |
|
224 if (fileName.isEmpty()) |
|
225 //fileName = m_file->fileName; |
|
226 fileName = "implement me"; |
|
227 |
|
228 // m_driver->addProblem(m_driver->currentFileName(), Problem(msg, line, col)); |
|
229 fprintf(stderr, "%s: error %s at line %d column %d\n", |
|
230 fileName.constData(), |
|
231 msg.toLatin1().constData(), line, col); |
|
232 } |
|
233 #endif // RXX_NO_ERROR |
|
234 return true; |
|
235 } |
|
236 |
|
237 void Parser::syntaxError() |
|
238 { |
|
239 (void) reportError(Errors::SyntaxError); |
|
240 } |
|
241 |
|
242 bool Parser::skipUntil(int token) |
|
243 { |
|
244 while (tokenStream->lookAhead()) { |
|
245 if (tokenStream->lookAhead() == token) |
|
246 return true; |
|
247 |
|
248 advance(); |
|
249 } |
|
250 |
|
251 return false; |
|
252 } |
|
253 |
|
254 bool Parser::skipUntilDeclaration() |
|
255 { |
|
256 while (tokenStream->lookAhead()) { |
|
257 |
|
258 switch(tokenStream->lookAhead()) { |
|
259 case ';': |
|
260 case '~': |
|
261 case Token_scope: |
|
262 case Token_identifier: |
|
263 case Token_operator: |
|
264 case Token_char: |
|
265 case Token_wchar_t: |
|
266 case Token_bool: |
|
267 case Token_short: |
|
268 case Token_int: |
|
269 case Token_long: |
|
270 case Token_signed: |
|
271 case Token_unsigned: |
|
272 case Token_float: |
|
273 case Token_double: |
|
274 case Token_void: |
|
275 case Token_extern: |
|
276 case Token_namespace: |
|
277 case Token_using: |
|
278 case Token_typedef: |
|
279 case Token_asm: |
|
280 case Token_template: |
|
281 case Token_export: |
|
282 |
|
283 case Token_const: // cv |
|
284 case Token_volatile: // cv |
|
285 |
|
286 case Token_public: |
|
287 case Token_protected: |
|
288 case Token_private: |
|
289 case Token_signals: // Qt |
|
290 case Token_slots: // Qt |
|
291 return true; |
|
292 |
|
293 default: |
|
294 advance(); |
|
295 } |
|
296 } |
|
297 |
|
298 return false; |
|
299 } |
|
300 |
|
301 bool Parser::skipUntilStatement() |
|
302 { |
|
303 while (tokenStream->lookAhead()) { |
|
304 switch(tokenStream->lookAhead()) { |
|
305 case ';': |
|
306 case '{': |
|
307 case '}': |
|
308 case Token_const: |
|
309 case Token_volatile: |
|
310 case Token_identifier: |
|
311 case Token_case: |
|
312 case Token_default: |
|
313 case Token_if: |
|
314 case Token_switch: |
|
315 case Token_while: |
|
316 case Token_do: |
|
317 case Token_for: |
|
318 case Token_break: |
|
319 case Token_continue: |
|
320 case Token_return: |
|
321 case Token_goto: |
|
322 case Token_try: |
|
323 case Token_catch: |
|
324 case Token_throw: |
|
325 case Token_char: |
|
326 case Token_wchar_t: |
|
327 case Token_bool: |
|
328 case Token_short: |
|
329 case Token_int: |
|
330 case Token_long: |
|
331 case Token_signed: |
|
332 case Token_unsigned: |
|
333 case Token_float: |
|
334 case Token_double: |
|
335 case Token_void: |
|
336 case Token_class: |
|
337 case Token_struct: |
|
338 case Token_union: |
|
339 case Token_enum: |
|
340 case Token_scope: |
|
341 case Token_template: |
|
342 case Token_using: |
|
343 return true; |
|
344 |
|
345 default: |
|
346 advance(); |
|
347 } |
|
348 } |
|
349 |
|
350 return false; |
|
351 } |
|
352 |
|
353 bool Parser::skip(int l, int r) |
|
354 { |
|
355 int count = 0; |
|
356 while (tokenStream->lookAhead()) { |
|
357 int tk = tokenStream->lookAhead(); |
|
358 |
|
359 if (tk == l) |
|
360 ++count; |
|
361 else if (tk == r) |
|
362 --count; |
|
363 else if (l != '{' && (tk == '{' || tk == '}' || tk == ';')) |
|
364 return false; |
|
365 |
|
366 if (count == 0) |
|
367 return true; |
|
368 |
|
369 advance(); |
|
370 } |
|
371 |
|
372 return false; |
|
373 } |
|
374 |
|
375 bool Parser::skipCommaExpression(AbstractExpressionAST *&node) |
|
376 { |
|
377 #ifndef RXX_NO_PARSE_EXPRESSION |
|
378 return parseCommaExpression(node); |
|
379 #else |
|
380 int start = tokenStream->cursor(); |
|
381 |
|
382 AbstractExpressionAST *expr = 0; |
|
383 if (!skipExpression(expr)) |
|
384 return false; |
|
385 |
|
386 while (tokenStream->lookAhead() == ',') { |
|
387 advance(); |
|
388 |
|
389 if (!skipExpression(expr)) { |
|
390 reportError(i18n("expression expected")); |
|
391 return false; |
|
392 } |
|
393 } |
|
394 |
|
395 AbstractExpressionAST *ast = CreateNode<AbstractExpressionAST>(m_pool); |
|
396 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
397 node = ast; |
|
398 |
|
399 return true; |
|
400 #endif // RXX_NO_PARSE_EXPRESSION |
|
401 } |
|
402 |
|
403 bool Parser::skipExpression(AbstractExpressionAST *&node) |
|
404 { |
|
405 #ifndef RXX_NO_PARSE_EXPRESSION |
|
406 return parseExpression(node); |
|
407 #else |
|
408 int start = tokenStream->cursor(); |
|
409 int count = 0; |
|
410 |
|
411 while (tokenStream->lookAhead()) { |
|
412 int tk = tokenStream->lookAhead(); |
|
413 |
|
414 switch(tk) { |
|
415 case '(': |
|
416 case '[': |
|
417 case '{': |
|
418 ++count; |
|
419 advance(); |
|
420 break; |
|
421 |
|
422 case ']': |
|
423 case ')': |
|
424 case '}': |
|
425 if (count == 0) { |
|
426 AbstractExpressionAST *ast = CreateNode<AbstractExpressionAST>(m_pool); |
|
427 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
428 node = ast; |
|
429 return true; |
|
430 } |
|
431 --count; |
|
432 advance(); |
|
433 break; |
|
434 |
|
435 case Token_struct: |
|
436 case Token_union: |
|
437 case Token_class: { |
|
438 int c = tokenStream->cursor(); |
|
439 TypeSpecifierAST *spec = 0; |
|
440 if (!parseClassSpecifier(spec)) |
|
441 tokenStream->rewind(c + 1); |
|
442 } |
|
443 break; |
|
444 |
|
445 case ',': |
|
446 case ';': |
|
447 case Token_case: |
|
448 case Token_default: |
|
449 case Token_if: |
|
450 case Token_while: |
|
451 case Token_do: |
|
452 case Token_for: |
|
453 case Token_break: |
|
454 case Token_continue: |
|
455 case Token_return: |
|
456 case Token_goto: |
|
457 { |
|
458 if ((tk == ',' || tk == ';') && count > 0) { |
|
459 advance(); |
|
460 break; |
|
461 } |
|
462 |
|
463 AbstractExpressionAST *ast = CreateNode<AbstractExpressionAST>(m_pool); |
|
464 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
465 node = ast; |
|
466 } |
|
467 return true; |
|
468 |
|
469 default: |
|
470 advance(); |
|
471 } |
|
472 } |
|
473 |
|
474 return false; |
|
475 #endif // RXX_NO_PARSE_EXPRESSION |
|
476 } |
|
477 |
|
478 bool Parser::parseName(NameAST *&node, bool parseTemplateId) |
|
479 { |
|
480 AST *winDeclSpec = 0; |
|
481 parseWinDeclSpec(winDeclSpec); |
|
482 |
|
483 int start = tokenStream->cursor(); |
|
484 |
|
485 NameAST *ast = CreateNode<NameAST>(m_pool); |
|
486 |
|
487 if (tokenStream->lookAhead() == Token_scope) { |
|
488 ast->setGlobal(true); |
|
489 advance(); |
|
490 } |
|
491 |
|
492 int idx = tokenStream->cursor(); |
|
493 |
|
494 while (true) { |
|
495 ClassOrNamespaceNameAST *n = 0; |
|
496 if (!parseUnqualifiedName(n)) |
|
497 return false; |
|
498 |
|
499 if (tokenStream->lookAhead() == Token_scope) { |
|
500 advance(); |
|
501 ast->addClassOrNamespaceName(n); |
|
502 if (tokenStream->lookAhead() == Token_template) |
|
503 advance(); /// skip optional template #### @todo CHECK |
|
504 } else if (!parseTemplateId && n) { |
|
505 tokenStream->rewind(n->startToken()); |
|
506 parseUnqualifiedName(n, parseTemplateId); |
|
507 ast->setUnqualifiedName(n); |
|
508 break; |
|
509 } else { |
|
510 ast->setUnqualifiedName(n); |
|
511 break; |
|
512 } |
|
513 } |
|
514 |
|
515 if (idx == tokenStream->cursor()) |
|
516 return false; |
|
517 |
|
518 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
519 node = ast; |
|
520 |
|
521 return true; |
|
522 } |
|
523 |
|
524 bool Parser::parseTranslationUnit(TranslationUnitAST *&node) |
|
525 { |
|
526 QTime t; |
|
527 t.start(); |
|
528 |
|
529 advance(); |
|
530 int start = tokenStream->cursor(); |
|
531 |
|
532 m_problems = 0; |
|
533 TranslationUnitAST *tun = CreateNode<TranslationUnitAST>(m_pool); |
|
534 node = tun; |
|
535 while (tokenStream->lookAhead()) { |
|
536 DeclarationAST *def = 0; |
|
537 int startDecl = tokenStream->cursor(); |
|
538 if (!parseDeclaration(def)) { |
|
539 // error recovery |
|
540 if (startDecl == tokenStream->cursor()) |
|
541 advance(); // skip at least one token |
|
542 skipUntilDeclaration(); |
|
543 } |
|
544 node->addDeclaration(def); |
|
545 } |
|
546 |
|
547 UPDATE_POS(node, start, tokenStream->cursor()); |
|
548 |
|
549 return m_problems == 0; |
|
550 } |
|
551 |
|
552 bool Parser::parseDeclaration(DeclarationAST *&node) |
|
553 { |
|
554 int start = tokenStream->cursor(); |
|
555 |
|
556 switch(tokenStream->lookAhead()) { |
|
557 |
|
558 case ';': |
|
559 advance(); |
|
560 return true; |
|
561 |
|
562 case Token_extern: |
|
563 return parseLinkageSpecification(node); |
|
564 |
|
565 case Token_namespace: |
|
566 return parseNamespace(node); |
|
567 |
|
568 case Token_using: |
|
569 return parseUsing(node); |
|
570 |
|
571 case Token_typedef: |
|
572 return parseTypedef(node); |
|
573 |
|
574 case Token_asm: |
|
575 return parseAsmDefinition(node); |
|
576 |
|
577 case Token_template: |
|
578 case Token_export: |
|
579 return parseTemplateDeclaration(node); |
|
580 |
|
581 default: |
|
582 { |
|
583 // tokenStream->rewind(start); |
|
584 |
|
585 if (objcp && parseObjcDef(node)) |
|
586 return true; |
|
587 |
|
588 tokenStream->rewind(start); |
|
589 |
|
590 AST *storageSpec = 0; |
|
591 parseStorageClassSpecifier(storageSpec); |
|
592 |
|
593 AST *cv = 0; |
|
594 parseCvQualify(cv); |
|
595 |
|
596 TypeSpecifierAST *spec = 0; |
|
597 if (parseEnumSpecifier(spec) || parseClassSpecifier(spec)) { |
|
598 spec->setCvQualify(cv); |
|
599 |
|
600 AST *cv2 = 0; |
|
601 parseCvQualify(cv2); |
|
602 spec->setCv2Qualify(cv2); |
|
603 |
|
604 InitDeclaratorListAST *declarators = 0; |
|
605 parseInitDeclaratorList(declarators); |
|
606 ADVANCE(';', ";"); |
|
607 |
|
608 SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool); |
|
609 ast->setStorageSpecifier(storageSpec); |
|
610 ast->setTypeSpec(spec); |
|
611 ast->setInitDeclaratorList(declarators); |
|
612 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
613 node = ast; |
|
614 |
|
615 return true; |
|
616 } |
|
617 |
|
618 tokenStream->rewind(start); |
|
619 return parseDeclarationInternal(node); |
|
620 } |
|
621 |
|
622 } // end switch |
|
623 } |
|
624 |
|
625 bool Parser::parseLinkageSpecification(DeclarationAST *&node) |
|
626 { |
|
627 int start = tokenStream->cursor(); |
|
628 |
|
629 if (tokenStream->lookAhead() != Token_extern) { |
|
630 return false; |
|
631 } |
|
632 advance(); |
|
633 |
|
634 LinkageSpecificationAST *ast = CreateNode<LinkageSpecificationAST>(m_pool); |
|
635 |
|
636 int startExternType = tokenStream->cursor(); |
|
637 if (tokenStream->lookAhead() == Token_string_literal) { |
|
638 advance(); |
|
639 AST *externType = CreateNode<AST>(m_pool); |
|
640 UPDATE_POS(externType, startExternType, tokenStream->cursor()); |
|
641 |
|
642 ast->setExternType(externType); |
|
643 } |
|
644 |
|
645 if (tokenStream->lookAhead() == '{') { |
|
646 LinkageBodyAST *linkageBody = 0; |
|
647 parseLinkageBody(linkageBody); |
|
648 ast->setLinkageBody(linkageBody); |
|
649 } else { |
|
650 DeclarationAST *decl = 0; |
|
651 if (!parseDeclaration(decl)) { |
|
652 reportError(i18n("Declaration syntax error")); |
|
653 } |
|
654 ast->setDeclaration(decl); |
|
655 } |
|
656 |
|
657 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
658 |
|
659 node = ast; |
|
660 |
|
661 return true; |
|
662 } |
|
663 |
|
664 bool Parser::parseLinkageBody(LinkageBodyAST *&node) |
|
665 { |
|
666 |
|
667 int start = tokenStream->cursor(); |
|
668 |
|
669 if (tokenStream->lookAhead() != '{') { |
|
670 return false; |
|
671 } |
|
672 advance(); |
|
673 |
|
674 LinkageBodyAST *lba = CreateNode<LinkageBodyAST>(m_pool); |
|
675 node = lba; |
|
676 |
|
677 while (tokenStream->lookAhead()) { |
|
678 int tk = tokenStream->lookAhead(); |
|
679 |
|
680 if (tk == '}') |
|
681 break; |
|
682 |
|
683 DeclarationAST *def = 0; |
|
684 int startDecl = tokenStream->cursor(); |
|
685 if (parseDeclaration(def)) { |
|
686 node->addDeclaration(def); |
|
687 } else { |
|
688 // error recovery |
|
689 if (startDecl == tokenStream->cursor()) |
|
690 advance(); // skip at least one token |
|
691 skipUntilDeclaration(); |
|
692 } |
|
693 } |
|
694 |
|
695 if (tokenStream->lookAhead() != '}') { |
|
696 reportError(i18n("} expected")); |
|
697 } else |
|
698 advance(); |
|
699 |
|
700 UPDATE_POS(node, start, tokenStream->cursor()); |
|
701 return true; |
|
702 } |
|
703 |
|
704 bool Parser::parseNamespace(DeclarationAST *&node) |
|
705 { |
|
706 int start = tokenStream->cursor(); |
|
707 |
|
708 if (tokenStream->lookAhead() != Token_namespace) { |
|
709 return false; |
|
710 } |
|
711 advance(); |
|
712 |
|
713 int startNamespaceName = tokenStream->cursor(); |
|
714 if (tokenStream->lookAhead() == Token_identifier) { |
|
715 advance(); |
|
716 } |
|
717 AST *namespaceName = CreateNode<AST>(m_pool); |
|
718 UPDATE_POS(namespaceName, startNamespaceName, tokenStream->cursor()); |
|
719 |
|
720 if (tokenStream->lookAhead() == '=') { |
|
721 // namespace alias |
|
722 advance(); |
|
723 |
|
724 NameAST *name = 0; |
|
725 if (parseName(name)) { |
|
726 ADVANCE(';', ";"); |
|
727 |
|
728 NamespaceAliasAST *ast = CreateNode<NamespaceAliasAST>(m_pool); |
|
729 ast->setNamespaceName(namespaceName); |
|
730 ast->setAliasName(name); |
|
731 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
732 node = ast; |
|
733 return true; |
|
734 } else { |
|
735 reportError(i18n("namespace expected")); |
|
736 return false; |
|
737 } |
|
738 } else if (tokenStream->lookAhead() != '{') { |
|
739 reportError(i18n("{ expected")); |
|
740 return false; |
|
741 } |
|
742 |
|
743 NamespaceAST *ast = CreateNode<NamespaceAST>(m_pool); |
|
744 ast->setNamespaceName(namespaceName); |
|
745 |
|
746 LinkageBodyAST *linkageBody = 0; |
|
747 parseLinkageBody(linkageBody); |
|
748 |
|
749 ast->setLinkageBody(linkageBody); |
|
750 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
751 node = ast; |
|
752 |
|
753 return true; |
|
754 } |
|
755 |
|
756 bool Parser::parseUsing(DeclarationAST *&node) |
|
757 { |
|
758 int start = tokenStream->cursor(); |
|
759 |
|
760 if (tokenStream->lookAhead() != Token_using) { |
|
761 return false; |
|
762 } |
|
763 advance(); |
|
764 |
|
765 if (tokenStream->lookAhead() == Token_namespace) { |
|
766 if (!parseUsingDirective(node)) { |
|
767 return false; |
|
768 } |
|
769 UPDATE_POS(node, start, tokenStream->cursor()); |
|
770 return true; |
|
771 } |
|
772 |
|
773 UsingAST *ast = CreateNode<UsingAST>(m_pool); |
|
774 |
|
775 int startTypeName = tokenStream->cursor(); |
|
776 if (tokenStream->lookAhead() == Token_typename) { |
|
777 advance(); |
|
778 AST *tn = CreateNode<AST>(m_pool); |
|
779 UPDATE_POS(tn, startTypeName, tokenStream->cursor()); |
|
780 ast->setTypeName(tn); |
|
781 } |
|
782 |
|
783 NameAST *name = 0; |
|
784 if (!parseName(name)) |
|
785 return false; |
|
786 |
|
787 ast->setName(name); |
|
788 |
|
789 ADVANCE(';', ";"); |
|
790 |
|
791 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
792 node = ast; |
|
793 |
|
794 return true; |
|
795 } |
|
796 |
|
797 bool Parser::parseUsingDirective(DeclarationAST *&node) |
|
798 { |
|
799 int start = tokenStream->cursor(); |
|
800 |
|
801 if (tokenStream->lookAhead() != Token_namespace) { |
|
802 return false; |
|
803 } |
|
804 advance(); |
|
805 |
|
806 NameAST *name = 0; |
|
807 if (!parseName(name)) { |
|
808 reportError(i18n("Namespace name expected")); |
|
809 return false; |
|
810 } |
|
811 |
|
812 ADVANCE(';', ";"); |
|
813 |
|
814 UsingDirectiveAST *ast = CreateNode<UsingDirectiveAST>(m_pool); |
|
815 ast->setName(name); |
|
816 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
817 node = ast; |
|
818 |
|
819 return true; |
|
820 } |
|
821 |
|
822 |
|
823 bool Parser::parseOperatorFunctionId(AST *&node) |
|
824 { |
|
825 int start = tokenStream->cursor(); |
|
826 |
|
827 if (tokenStream->lookAhead() != Token_operator) { |
|
828 return false; |
|
829 } |
|
830 advance(); |
|
831 |
|
832 AST *op = 0; |
|
833 if (parseOperator(op)) { |
|
834 AST *asn = CreateNode<AST>(m_pool); |
|
835 node = asn; |
|
836 UPDATE_POS(node, start, tokenStream->cursor()); |
|
837 return true; |
|
838 } else { |
|
839 // parse cast operator |
|
840 AST *cv = 0; |
|
841 parseCvQualify(cv); |
|
842 |
|
843 TypeSpecifierAST *spec = 0; |
|
844 if (!parseSimpleTypeSpecifier(spec)) { |
|
845 syntaxError(); |
|
846 return false; |
|
847 } |
|
848 spec->setCvQualify(cv); |
|
849 |
|
850 AST *cv2 = 0; |
|
851 parseCvQualify(cv2); |
|
852 spec->setCv2Qualify(cv2); |
|
853 |
|
854 AST *ptrOp = 0; |
|
855 while (parsePtrOperator(ptrOp)) |
|
856 ; |
|
857 |
|
858 AST *asn = CreateNode<AST>(m_pool); |
|
859 node = asn; |
|
860 UPDATE_POS(node, start, tokenStream->cursor()); |
|
861 return true; |
|
862 } |
|
863 } |
|
864 |
|
865 bool Parser::parseTemplateArgumentList(TemplateArgumentListAST *&node, bool reportError) |
|
866 { |
|
867 int start = tokenStream->cursor(); |
|
868 |
|
869 TemplateArgumentListAST *ast = CreateNode<TemplateArgumentListAST>(m_pool); |
|
870 |
|
871 AST *templArg = 0; |
|
872 if (!parseTemplateArgument(templArg)) |
|
873 return false; |
|
874 ast->addArgument(templArg); |
|
875 |
|
876 while (tokenStream->lookAhead() == ',') { |
|
877 advance(); |
|
878 |
|
879 if (!parseTemplateArgument(templArg)) { |
|
880 if (reportError) { |
|
881 syntaxError(); |
|
882 break; |
|
883 } else |
|
884 return false; |
|
885 } |
|
886 ast->addArgument(templArg); |
|
887 } |
|
888 |
|
889 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
890 node = ast; |
|
891 |
|
892 return true; |
|
893 } |
|
894 |
|
895 bool Parser::parseTypedef(DeclarationAST *&node) |
|
896 { |
|
897 int start = tokenStream->cursor(); |
|
898 |
|
899 if (tokenStream->lookAhead() != Token_typedef) { |
|
900 return false; |
|
901 } |
|
902 advance(); |
|
903 |
|
904 TypeSpecifierAST *spec = 0; |
|
905 if (!parseTypeSpecifierOrClassSpec(spec)) { |
|
906 reportError(i18n("Need a type specifier to declare")); |
|
907 return false; |
|
908 } |
|
909 |
|
910 InitDeclaratorListAST *declarators = 0; |
|
911 if (!parseInitDeclaratorList(declarators)) { |
|
912 //reportError(i18n("Need an identifier to declare")); |
|
913 //return false; |
|
914 } |
|
915 |
|
916 ADVANCE(';', ";"); |
|
917 |
|
918 TypedefAST *ast = CreateNode<TypedefAST>(m_pool); |
|
919 ast->setTypeSpec(spec); |
|
920 ast->setInitDeclaratorList(declarators); |
|
921 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
922 node = ast; |
|
923 |
|
924 return true; |
|
925 } |
|
926 |
|
927 bool Parser::parseAsmDefinition(DeclarationAST *&node) |
|
928 { |
|
929 int start = tokenStream->cursor(); |
|
930 |
|
931 ADVANCE(Token_asm, "asm"); |
|
932 |
|
933 AST *cv = 0; |
|
934 parseCvQualify(cv); |
|
935 |
|
936 skip('(', ')'); |
|
937 advance(); |
|
938 ADVANCE(';', ";"); |
|
939 |
|
940 DeclarationAST *ast = CreateNode<DeclarationAST>(m_pool); |
|
941 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
942 node = ast; |
|
943 |
|
944 return true; |
|
945 } |
|
946 |
|
947 bool Parser::parseTemplateDeclaration(DeclarationAST *&node) |
|
948 { |
|
949 int start = tokenStream->cursor(); |
|
950 |
|
951 AST *exp = 0; |
|
952 |
|
953 int startExport = tokenStream->cursor(); |
|
954 if (tokenStream->lookAhead() == Token_export) { |
|
955 advance(); |
|
956 AST *n = CreateNode<AST>(m_pool); |
|
957 UPDATE_POS(n, startExport, tokenStream->cursor()); |
|
958 exp = n; |
|
959 } |
|
960 |
|
961 if (tokenStream->lookAhead() != Token_template) { |
|
962 return false; |
|
963 } |
|
964 advance(); |
|
965 |
|
966 TemplateParameterListAST *params = 0; |
|
967 if (tokenStream->lookAhead() == '<') { |
|
968 advance(); |
|
969 parseTemplateParameterList(params); |
|
970 |
|
971 ADVANCE('>', ">"); |
|
972 } |
|
973 |
|
974 DeclarationAST *def = 0; |
|
975 if (!parseDeclaration(def)) { |
|
976 reportError(i18n("expected a declaration")); |
|
977 } |
|
978 |
|
979 TemplateDeclarationAST *ast = CreateNode<TemplateDeclarationAST>(m_pool); |
|
980 ast->setExported(exp); |
|
981 ast->setTemplateParameterList(params); |
|
982 ast->setDeclaration(def); |
|
983 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
984 node = ast; |
|
985 |
|
986 return true; |
|
987 } |
|
988 |
|
989 bool Parser::parseOperator(AST *&/*node*/) |
|
990 { |
|
991 QString text(QString::fromLatin1(tokenStream->currentTokenText().constData())); |
|
992 |
|
993 switch(tokenStream->lookAhead()) { |
|
994 case Token_new: |
|
995 case Token_delete: |
|
996 advance(); |
|
997 if (tokenStream->lookAhead() == '[' && tokenStream->lookAhead(1) == ']') { |
|
998 advance(); |
|
999 advance(); |
|
1000 text += QLatin1String("[]"); |
|
1001 } |
|
1002 return true; |
|
1003 |
|
1004 case '+': |
|
1005 case '-': |
|
1006 case '*': |
|
1007 case '/': |
|
1008 case '%': |
|
1009 case '^': |
|
1010 case '&': |
|
1011 case '|': |
|
1012 case '~': |
|
1013 case '!': |
|
1014 case '=': |
|
1015 case '<': |
|
1016 case '>': |
|
1017 case ',': |
|
1018 case Token_assign: |
|
1019 case Token_shift: |
|
1020 case Token_eq: |
|
1021 case Token_not_eq: |
|
1022 case Token_leq: |
|
1023 case Token_geq: |
|
1024 case Token_and: |
|
1025 case Token_or: |
|
1026 case Token_incr: |
|
1027 case Token_decr: |
|
1028 case Token_ptrmem: |
|
1029 case Token_arrow: |
|
1030 advance(); |
|
1031 return true; |
|
1032 |
|
1033 default: |
|
1034 if (tokenStream->lookAhead() == '(' && tokenStream->lookAhead(1) == ')') { |
|
1035 advance(); |
|
1036 advance(); |
|
1037 return true; |
|
1038 } else if (tokenStream->lookAhead() == '[' && tokenStream->lookAhead(1) == ']') { |
|
1039 advance(); |
|
1040 advance(); |
|
1041 return true; |
|
1042 } |
|
1043 } |
|
1044 |
|
1045 return false; |
|
1046 } |
|
1047 |
|
1048 bool Parser::parseCvQualify(AST *&node) |
|
1049 { |
|
1050 int start = tokenStream->cursor(); |
|
1051 |
|
1052 AST *ast = CreateNode<AST>(m_pool); |
|
1053 |
|
1054 int n = 0; |
|
1055 while (tokenStream->lookAhead()) { |
|
1056 int tk = tokenStream->lookAhead(); |
|
1057 if (tk == Token_const || tk == Token_volatile) { |
|
1058 ++n; |
|
1059 int startWord = tokenStream->cursor(); |
|
1060 advance(); |
|
1061 AST *word = CreateNode<AST>(m_pool); |
|
1062 UPDATE_POS(word, startWord, tokenStream->cursor()); |
|
1063 word->setParent(ast); |
|
1064 } else |
|
1065 break; |
|
1066 } |
|
1067 |
|
1068 if (n == 0) |
|
1069 return false; |
|
1070 |
|
1071 |
|
1072 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1073 |
|
1074 node = ast; |
|
1075 return true; |
|
1076 } |
|
1077 |
|
1078 bool Parser::parseSimpleTypeSpecifier(TypeSpecifierAST *&node, bool onlyIntegral) |
|
1079 { |
|
1080 int start = tokenStream->cursor(); |
|
1081 bool isIntegral = false; |
|
1082 bool done = false; |
|
1083 |
|
1084 while (!done) { |
|
1085 switch(tokenStream->lookAhead()) { |
|
1086 case Token_char: |
|
1087 case Token_wchar_t: |
|
1088 case Token_bool: |
|
1089 case Token_short: |
|
1090 case Token_int: |
|
1091 case Token_long: |
|
1092 case Token_signed: |
|
1093 case Token_unsigned: |
|
1094 case Token_float: |
|
1095 case Token_double: |
|
1096 case Token_void: |
|
1097 isIntegral = true; |
|
1098 advance(); |
|
1099 break; |
|
1100 |
|
1101 default: |
|
1102 done = true; |
|
1103 } |
|
1104 } |
|
1105 |
|
1106 TypeSpecifierAST *ast = CreateNode<TypeSpecifierAST>(m_pool); |
|
1107 if (isIntegral) { |
|
1108 ClassOrNamespaceNameAST *cl = CreateNode<ClassOrNamespaceNameAST>(m_pool); |
|
1109 |
|
1110 AST *n = CreateNode<AST>(m_pool); |
|
1111 UPDATE_POS(n, start, tokenStream->cursor()); |
|
1112 cl->setName(n); |
|
1113 UPDATE_POS(cl, start, tokenStream->cursor()); |
|
1114 |
|
1115 NameAST *name = CreateNode<NameAST>(m_pool); |
|
1116 name->setUnqualifiedName(cl); |
|
1117 UPDATE_POS(name, start, tokenStream->cursor()); |
|
1118 ast->setName(name); |
|
1119 } else if (tokenStream->lookAhead() == Token___typeof) { |
|
1120 advance(); |
|
1121 if (tokenStream->lookAhead() == '(') { |
|
1122 advance(); |
|
1123 TypeIdAST *typeId = 0; |
|
1124 parseTypeId(typeId); |
|
1125 ADVANCE(')', ")"); |
|
1126 } else { |
|
1127 AbstractExpressionAST *e = 0; |
|
1128 parseUnaryExpression(e); |
|
1129 } |
|
1130 } else if (onlyIntegral) { |
|
1131 tokenStream->rewind(start); |
|
1132 return false; |
|
1133 } else { |
|
1134 NameAST *name = 0; |
|
1135 if (!parseName(name)) { |
|
1136 tokenStream->rewind(start); |
|
1137 return false; |
|
1138 } |
|
1139 ast->setName(name); |
|
1140 } |
|
1141 |
|
1142 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1143 node = ast; |
|
1144 return true; |
|
1145 } |
|
1146 |
|
1147 bool Parser::parsePtrOperator(AST *&node) |
|
1148 { |
|
1149 int start = tokenStream->cursor(); |
|
1150 int tok = tokenStream->lookAhead(); |
|
1151 AST *memPtr = 0; |
|
1152 |
|
1153 switch (tok) { |
|
1154 case '&': |
|
1155 case '*': |
|
1156 advance(); |
|
1157 break; |
|
1158 |
|
1159 case Token_scope: |
|
1160 case Token_identifier: |
|
1161 if (!parsePtrToMember(memPtr)) { |
|
1162 tokenStream->rewind(start); |
|
1163 return false; |
|
1164 } |
|
1165 break; |
|
1166 |
|
1167 default: |
|
1168 return false; |
|
1169 } |
|
1170 |
|
1171 AST *cv = 0; |
|
1172 parseCvQualify(cv); |
|
1173 |
|
1174 AST *ast = CreateNode<AST>(m_pool); |
|
1175 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1176 node = ast; |
|
1177 |
|
1178 return true; |
|
1179 } |
|
1180 |
|
1181 |
|
1182 bool Parser::parseTemplateArgument(AST *&node) |
|
1183 { |
|
1184 int start = tokenStream->cursor(); |
|
1185 |
|
1186 TypeIdAST *typeId = 0; |
|
1187 if (parseTypeId(typeId)) { |
|
1188 if (tokenStream->lookAhead() == ',' || tokenStream->lookAhead() == '>') { |
|
1189 node = typeId; |
|
1190 return true; |
|
1191 } |
|
1192 } |
|
1193 |
|
1194 tokenStream->rewind(start); |
|
1195 AbstractExpressionAST *expr = 0; |
|
1196 if (!parseLogicalOrExpression(expr, true)) { |
|
1197 return false; |
|
1198 } |
|
1199 node = expr; |
|
1200 |
|
1201 return true; |
|
1202 } |
|
1203 |
|
1204 bool Parser::parseTypeSpecifier(TypeSpecifierAST *&spec) |
|
1205 { |
|
1206 AST *cv = 0; |
|
1207 parseCvQualify(cv); |
|
1208 |
|
1209 if (parseElaboratedTypeSpecifier(spec) || parseSimpleTypeSpecifier(spec)) { |
|
1210 spec->setCvQualify(cv); |
|
1211 |
|
1212 AST *cv2 = 0; |
|
1213 parseCvQualify(cv2); |
|
1214 spec->setCv2Qualify(cv2); |
|
1215 |
|
1216 return true; |
|
1217 } |
|
1218 |
|
1219 return false; |
|
1220 } |
|
1221 |
|
1222 bool Parser::parseDeclarator(DeclaratorAST *&node) |
|
1223 { |
|
1224 int start = tokenStream->cursor(); |
|
1225 |
|
1226 DeclaratorAST *ast = CreateNode<DeclaratorAST>(m_pool); |
|
1227 |
|
1228 DeclaratorAST *decl = 0; |
|
1229 NameAST *declId = 0; |
|
1230 |
|
1231 AST *ptrOp = 0; |
|
1232 while (parsePtrOperator(ptrOp)) { |
|
1233 ast->addPtrOp(ptrOp); |
|
1234 } |
|
1235 |
|
1236 if (tokenStream->lookAhead() == '(') { |
|
1237 advance(); |
|
1238 |
|
1239 if (!parseDeclarator(decl)) { |
|
1240 return false; |
|
1241 } |
|
1242 ast->setSubDeclarator(decl); |
|
1243 |
|
1244 if (tokenStream->lookAhead() != ')') { |
|
1245 return false; |
|
1246 } |
|
1247 advance(); |
|
1248 } else { |
|
1249 if (tokenStream->lookAhead() == ':') { |
|
1250 // unnamed bitfield |
|
1251 } else if (parseDeclaratorId(declId)) { |
|
1252 ast->setDeclaratorId(declId); |
|
1253 } else { |
|
1254 tokenStream->rewind(start); |
|
1255 return false; |
|
1256 } |
|
1257 |
|
1258 if (tokenStream->lookAhead() == ':') { |
|
1259 advance(); |
|
1260 AbstractExpressionAST *expr = 0; |
|
1261 if (!parseConstantExpression(expr)) { |
|
1262 reportError(i18n("Constant expression expected")); |
|
1263 } |
|
1264 goto update_pos; |
|
1265 } |
|
1266 } |
|
1267 |
|
1268 { |
|
1269 bool isVector = false; |
|
1270 |
|
1271 while (tokenStream->lookAhead() == '[') { |
|
1272 int startArray = tokenStream->cursor(); |
|
1273 advance(); |
|
1274 AbstractExpressionAST *expr = 0; |
|
1275 parseCommaExpression(expr); |
|
1276 |
|
1277 ADVANCE(']', "]"); |
|
1278 AST *array = CreateNode<AST>(m_pool); |
|
1279 UPDATE_POS(array, startArray, tokenStream->cursor()); |
|
1280 ast->addArrayDimension(array); |
|
1281 isVector = true; |
|
1282 } |
|
1283 |
|
1284 bool skipParen = false; |
|
1285 if (tokenStream->lookAhead() == Token_identifier |
|
1286 && tokenStream->lookAhead(1) == '(' |
|
1287 && tokenStream->lookAhead(2) == '(') { |
|
1288 advance(); |
|
1289 advance(); |
|
1290 skipParen = true; |
|
1291 } |
|
1292 |
|
1293 int tok = tokenStream->lookAhead(); |
|
1294 if (ast->subDeclarator() && !(isVector || tok == '(' || tok == ',' || tok == ';' || tok == '=')) { |
|
1295 tokenStream->rewind(start); |
|
1296 return false; |
|
1297 } |
|
1298 |
|
1299 int index = tokenStream->cursor(); |
|
1300 if (tokenStream->lookAhead() == '(') { |
|
1301 advance(); |
|
1302 |
|
1303 ParameterDeclarationClauseAST *params = 0; |
|
1304 if (!parseParameterDeclarationClause(params)) { |
|
1305 tokenStream->rewind(index); |
|
1306 goto update_pos; |
|
1307 } |
|
1308 ast->setParameterDeclarationClause(params); |
|
1309 |
|
1310 if (tokenStream->lookAhead() != ')') { |
|
1311 tokenStream->rewind(index); |
|
1312 goto update_pos; |
|
1313 } |
|
1314 |
|
1315 advance(); // skip ')' |
|
1316 |
|
1317 AST *constant = 0; |
|
1318 parseCvQualify(constant); |
|
1319 ast->setConstant(constant); |
|
1320 |
|
1321 AST *except = 0; |
|
1322 if (parseExceptionSpecification(except)) { |
|
1323 ast->setExceptionSpecification(except); |
|
1324 } |
|
1325 } |
|
1326 |
|
1327 if (skipParen) { |
|
1328 if (tokenStream->lookAhead() != ')') { |
|
1329 reportError(i18n("')' expected")); |
|
1330 } else |
|
1331 advance(); |
|
1332 } |
|
1333 } |
|
1334 |
|
1335 update_pos: |
|
1336 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1337 node = ast; |
|
1338 |
|
1339 return true; |
|
1340 } |
|
1341 |
|
1342 bool Parser::parseAbstractDeclarator(DeclaratorAST *&node) |
|
1343 { |
|
1344 int start = tokenStream->cursor(); |
|
1345 |
|
1346 DeclaratorAST *ast = CreateNode<DeclaratorAST>(m_pool); |
|
1347 DeclaratorAST *decl = 0; |
|
1348 |
|
1349 AST *ptrOp = 0; |
|
1350 while (parsePtrOperator(ptrOp)) { |
|
1351 ast->addPtrOp(ptrOp); |
|
1352 } |
|
1353 |
|
1354 int index = tokenStream->cursor(); |
|
1355 if (tokenStream->lookAhead() == '(') { |
|
1356 advance(); |
|
1357 |
|
1358 if (!parseAbstractDeclarator(decl)) { |
|
1359 tokenStream->rewind(index); |
|
1360 goto label1; |
|
1361 } |
|
1362 |
|
1363 ast->setSubDeclarator(decl); |
|
1364 |
|
1365 if (tokenStream->lookAhead() != ')'){ |
|
1366 tokenStream->rewind(start); |
|
1367 return false; |
|
1368 } |
|
1369 advance(); |
|
1370 } else if (tokenStream->lookAhead() == ':') { |
|
1371 advance(); |
|
1372 AbstractExpressionAST *expr = 0; |
|
1373 if (!parseConstantExpression(expr)) { |
|
1374 reportError(i18n("Constant expression expected")); |
|
1375 } |
|
1376 goto update_pos; |
|
1377 } |
|
1378 |
|
1379 label1: |
|
1380 { |
|
1381 bool isVector = false; |
|
1382 |
|
1383 while (tokenStream->lookAhead() == '[') { |
|
1384 int startArray = tokenStream->cursor(); |
|
1385 advance(); |
|
1386 AbstractExpressionAST *expr = 0; |
|
1387 parseCommaExpression(expr); |
|
1388 |
|
1389 ADVANCE(']', "]"); |
|
1390 AST *array = CreateNode<AST>(m_pool); |
|
1391 UPDATE_POS(array, startArray, tokenStream->cursor()); |
|
1392 ast->addArrayDimension(array); |
|
1393 isVector = true; |
|
1394 } |
|
1395 |
|
1396 int tok = tokenStream->lookAhead(); |
|
1397 if (ast->subDeclarator() && !(isVector || tok == '(' || tok == ',' || tok == ';' || tok == '=')) { |
|
1398 tokenStream->rewind(start); |
|
1399 return false; |
|
1400 } |
|
1401 |
|
1402 int index = tokenStream->cursor(); |
|
1403 if (tokenStream->lookAhead() == '(') { |
|
1404 advance(); |
|
1405 |
|
1406 ParameterDeclarationClauseAST *params = 0; |
|
1407 if (!parseParameterDeclarationClause(params)) { |
|
1408 tokenStream->rewind(index); |
|
1409 goto update_pos; |
|
1410 } |
|
1411 ast->setParameterDeclarationClause(params); |
|
1412 |
|
1413 if (tokenStream->lookAhead() != ')') { |
|
1414 tokenStream->rewind(index); |
|
1415 goto update_pos; |
|
1416 } |
|
1417 |
|
1418 advance(); // skip ')' |
|
1419 |
|
1420 AST *constant = 0; |
|
1421 parseCvQualify(constant); |
|
1422 ast->setConstant(constant); |
|
1423 |
|
1424 AST *except = 0; |
|
1425 if (parseExceptionSpecification(except)) { |
|
1426 ast->setExceptionSpecification(except); |
|
1427 } |
|
1428 } |
|
1429 } |
|
1430 |
|
1431 update_pos: |
|
1432 if (tokenStream->cursor() == start) |
|
1433 return false; |
|
1434 |
|
1435 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1436 node = ast; |
|
1437 |
|
1438 return true; |
|
1439 } |
|
1440 |
|
1441 bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node) |
|
1442 { |
|
1443 int start = tokenStream->cursor(); |
|
1444 |
|
1445 if (tokenStream->lookAhead() != Token_enum) { |
|
1446 return false; |
|
1447 } |
|
1448 |
|
1449 advance(); |
|
1450 |
|
1451 NameAST *name = 0; |
|
1452 parseName(name); |
|
1453 |
|
1454 if (tokenStream->lookAhead() != '{') { |
|
1455 tokenStream->rewind(start); |
|
1456 return false; |
|
1457 } |
|
1458 advance(); |
|
1459 |
|
1460 EnumSpecifierAST *ast = CreateNode<EnumSpecifierAST>(m_pool); |
|
1461 ast->setName(name); |
|
1462 |
|
1463 EnumeratorAST *enumerator = 0; |
|
1464 if (parseEnumerator(enumerator)) { |
|
1465 ast->addEnumerator(enumerator); |
|
1466 |
|
1467 while (tokenStream->lookAhead() == ',') { |
|
1468 advance(); |
|
1469 |
|
1470 if (!parseEnumerator(enumerator)) { |
|
1471 //reportError(i18n("Enumerator expected")); |
|
1472 break; |
|
1473 } |
|
1474 |
|
1475 ast->addEnumerator(enumerator); |
|
1476 } |
|
1477 } |
|
1478 |
|
1479 if (tokenStream->lookAhead() != '}') |
|
1480 reportError(i18n("} missing")); |
|
1481 else |
|
1482 advance(); |
|
1483 |
|
1484 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1485 node = ast; |
|
1486 |
|
1487 return true; |
|
1488 } |
|
1489 |
|
1490 bool Parser::parseTemplateParameterList(TemplateParameterListAST *&node) |
|
1491 { |
|
1492 int start = tokenStream->cursor(); |
|
1493 |
|
1494 TemplateParameterListAST *ast = CreateNode<TemplateParameterListAST>(m_pool); |
|
1495 |
|
1496 TemplateParameterAST *param = 0; |
|
1497 if (!parseTemplateParameter(param)) { |
|
1498 return false; |
|
1499 } |
|
1500 ast->addTemplateParameter(param); |
|
1501 |
|
1502 while (tokenStream->lookAhead() == ',') { |
|
1503 advance(); |
|
1504 |
|
1505 if (!parseTemplateParameter(param)) { |
|
1506 syntaxError(); |
|
1507 break; |
|
1508 } else { |
|
1509 ast->addTemplateParameter(param); |
|
1510 } |
|
1511 } |
|
1512 |
|
1513 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1514 node = ast; |
|
1515 |
|
1516 return true; |
|
1517 } |
|
1518 |
|
1519 bool Parser::parseTemplateParameter(TemplateParameterAST *&node) |
|
1520 { |
|
1521 int start = tokenStream->cursor(); |
|
1522 TemplateParameterAST *ast = CreateNode<TemplateParameterAST>(m_pool); |
|
1523 |
|
1524 TypeParameterAST *typeParameter = 0; |
|
1525 ParameterDeclarationAST *param = 0; |
|
1526 |
|
1527 int tk = tokenStream->lookAhead(); |
|
1528 |
|
1529 if ((tk == Token_class || tk == Token_typename || tk == Token_template) && parseTypeParameter(typeParameter)) { |
|
1530 ast->setTypeParameter(typeParameter); |
|
1531 goto ok; |
|
1532 } |
|
1533 |
|
1534 if (!parseParameterDeclaration(param)) |
|
1535 return false; |
|
1536 ast->setTypeValueParameter(param); |
|
1537 |
|
1538 ok: |
|
1539 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1540 node = ast; |
|
1541 |
|
1542 return true; |
|
1543 } |
|
1544 |
|
1545 bool Parser::parseTypeParameter(TypeParameterAST *&node) |
|
1546 { |
|
1547 int start = tokenStream->cursor(); |
|
1548 TypeParameterAST *ast = CreateNode<TypeParameterAST>(m_pool); |
|
1549 |
|
1550 AST_FROM_TOKEN(kind, tokenStream->cursor()); |
|
1551 ast->setKind(kind); |
|
1552 |
|
1553 switch(tokenStream->lookAhead()) { |
|
1554 |
|
1555 case Token_class: |
|
1556 case Token_typename: |
|
1557 { |
|
1558 advance(); // skip class |
|
1559 |
|
1560 // parse optional name |
|
1561 NameAST *name = 0; |
|
1562 if(parseName(name)){ |
|
1563 ast->setName(name); |
|
1564 |
|
1565 if (tokenStream->lookAhead() == '='){ |
|
1566 advance(); |
|
1567 |
|
1568 TypeIdAST *typeId = 0; |
|
1569 if(!parseTypeId(typeId)){ |
|
1570 //syntaxError(); |
|
1571 tokenStream->rewind(start); |
|
1572 return false; |
|
1573 } |
|
1574 ast->setTypeId(typeId); |
|
1575 } else if (!(tokenStream->lookAhead() == ',' || tokenStream->lookAhead() == '>')) { |
|
1576 tokenStream->rewind(start); |
|
1577 return false; |
|
1578 } |
|
1579 } |
|
1580 } |
|
1581 break; |
|
1582 |
|
1583 case Token_template: |
|
1584 { |
|
1585 advance(); // skip template |
|
1586 ADVANCE('<', "<"); |
|
1587 |
|
1588 TemplateParameterListAST *params = 0; |
|
1589 if (!parseTemplateParameterList(params)) { |
|
1590 return false; |
|
1591 } |
|
1592 ast->setTemplateParameterList(params); |
|
1593 |
|
1594 ADVANCE('>', ">"); |
|
1595 |
|
1596 if (tokenStream->lookAhead() == Token_class) |
|
1597 advance(); |
|
1598 |
|
1599 // parse optional name |
|
1600 NameAST *name = 0; |
|
1601 if (parseName(name)) { |
|
1602 ast->setName(name); |
|
1603 if (tokenStream->lookAhead() == '=') { |
|
1604 advance(); |
|
1605 |
|
1606 TypeIdAST *typeId = 0; |
|
1607 if (!parseTypeId(typeId)) { |
|
1608 syntaxError(); |
|
1609 return false; |
|
1610 } |
|
1611 ast->setTypeId(typeId); |
|
1612 } |
|
1613 } |
|
1614 |
|
1615 if (tokenStream->lookAhead() == '=') { |
|
1616 advance(); |
|
1617 |
|
1618 NameAST *templ_name = 0; |
|
1619 parseName(templ_name); |
|
1620 } |
|
1621 } |
|
1622 break; |
|
1623 |
|
1624 default: |
|
1625 return false; |
|
1626 |
|
1627 } // end switch |
|
1628 |
|
1629 |
|
1630 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1631 node = ast; |
|
1632 return true; |
|
1633 } |
|
1634 |
|
1635 bool Parser::parseStorageClassSpecifier(AST *&node) |
|
1636 { |
|
1637 int start = tokenStream->cursor(); |
|
1638 AST *ast = CreateNode<AST>(m_pool); |
|
1639 |
|
1640 while (tokenStream->lookAhead()) { |
|
1641 int tk = tokenStream->lookAhead(); |
|
1642 if (tk == Token_friend || tk == Token_auto || tk == Token_register || tk == Token_static || |
|
1643 tk == Token_extern || tk == Token_mutable) { |
|
1644 int startNode = tokenStream->cursor(); |
|
1645 advance(); |
|
1646 |
|
1647 AST *n = CreateNode<AST>(m_pool); |
|
1648 UPDATE_POS(n, startNode, tokenStream->cursor()); |
|
1649 n->setParent(ast); |
|
1650 } else |
|
1651 break; |
|
1652 } |
|
1653 |
|
1654 if (length(ast->children()) == 0) |
|
1655 return false; |
|
1656 |
|
1657 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1658 node = ast; |
|
1659 return true; |
|
1660 } |
|
1661 |
|
1662 bool Parser::parseFunctionSpecifier(AST *&node) |
|
1663 { |
|
1664 int start = tokenStream->cursor(); |
|
1665 AST *ast = CreateNode<AST>(m_pool); |
|
1666 |
|
1667 while (tokenStream->lookAhead()) { |
|
1668 int tk = tokenStream->lookAhead(); |
|
1669 if (tk == Token_inline || tk == Token_virtual || tk == Token_explicit) { |
|
1670 int startNode = tokenStream->cursor(); |
|
1671 advance(); |
|
1672 |
|
1673 AST *n = CreateNode<AST>(m_pool); |
|
1674 UPDATE_POS(n, startNode, tokenStream->cursor()); |
|
1675 n->setParent(ast); |
|
1676 } else { |
|
1677 break; |
|
1678 } |
|
1679 } |
|
1680 |
|
1681 if (length(ast->children()) == 0) |
|
1682 return false; |
|
1683 |
|
1684 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1685 node = ast; |
|
1686 return true; |
|
1687 } |
|
1688 |
|
1689 bool Parser::parseTypeId(TypeIdAST *&node) |
|
1690 { |
|
1691 /// @todo implement the AST for typeId |
|
1692 int start = tokenStream->cursor(); |
|
1693 |
|
1694 TypeSpecifierAST *spec = 0; |
|
1695 if (!parseTypeSpecifier(spec)) { |
|
1696 tokenStream->rewind(start); |
|
1697 return false; |
|
1698 } |
|
1699 |
|
1700 DeclaratorAST *decl = 0; |
|
1701 parseAbstractDeclarator(decl); |
|
1702 |
|
1703 TypeIdAST *ast = CreateNode<TypeIdAST>(m_pool); |
|
1704 ast->setTypeSpecifier(spec); |
|
1705 ast->setDeclarator(decl); |
|
1706 |
|
1707 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1708 node = ast; |
|
1709 |
|
1710 return true; |
|
1711 } |
|
1712 |
|
1713 bool Parser::parseInitDeclaratorList(InitDeclaratorListAST *&node) |
|
1714 { |
|
1715 int start = tokenStream->cursor(); |
|
1716 |
|
1717 InitDeclaratorListAST *ast = CreateNode<InitDeclaratorListAST>(m_pool); |
|
1718 InitDeclaratorAST *decl = 0; |
|
1719 |
|
1720 if (!parseInitDeclarator(decl)) { |
|
1721 return false; |
|
1722 } |
|
1723 ast->addInitDeclarator(decl); |
|
1724 |
|
1725 while (tokenStream->lookAhead() == ',') { |
|
1726 advance(); |
|
1727 |
|
1728 if (!parseInitDeclarator(decl)) { |
|
1729 syntaxError(); |
|
1730 break; |
|
1731 } |
|
1732 ast->addInitDeclarator(decl); |
|
1733 } |
|
1734 |
|
1735 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1736 node = ast; |
|
1737 |
|
1738 return true; |
|
1739 } |
|
1740 |
|
1741 bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node) |
|
1742 { |
|
1743 int start = tokenStream->cursor(); |
|
1744 |
|
1745 ParameterDeclarationClauseAST *ast = CreateNode<ParameterDeclarationClauseAST>(m_pool); |
|
1746 |
|
1747 ParameterDeclarationListAST *params = 0; |
|
1748 if (!parseParameterDeclarationList(params)) { |
|
1749 |
|
1750 if (tokenStream->lookAhead() == ')') |
|
1751 goto good; |
|
1752 |
|
1753 if (tokenStream->lookAhead() == Token_ellipsis && tokenStream->lookAhead(1) == ')') { |
|
1754 AST_FROM_TOKEN(ellipsis, tokenStream->cursor()); |
|
1755 ast->setEllipsis(ellipsis); |
|
1756 advance(); |
|
1757 goto good; |
|
1758 } |
|
1759 return false; |
|
1760 } |
|
1761 |
|
1762 if (tokenStream->lookAhead() == Token_ellipsis) { |
|
1763 AST_FROM_TOKEN(ellipsis, tokenStream->cursor()); |
|
1764 ast->setEllipsis(ellipsis); |
|
1765 advance(); |
|
1766 } |
|
1767 |
|
1768 good: |
|
1769 ast->setParameterDeclarationList(params); |
|
1770 |
|
1771 /// @todo add ellipsis |
|
1772 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1773 node = ast; |
|
1774 |
|
1775 return true; |
|
1776 } |
|
1777 |
|
1778 bool Parser::parseParameterDeclarationList(ParameterDeclarationListAST *&node) |
|
1779 { |
|
1780 int start = tokenStream->cursor(); |
|
1781 |
|
1782 ParameterDeclarationListAST *ast = CreateNode<ParameterDeclarationListAST>(m_pool); |
|
1783 |
|
1784 ParameterDeclarationAST *param = 0; |
|
1785 if (!parseParameterDeclaration(param)) { |
|
1786 tokenStream->rewind(start); |
|
1787 return false; |
|
1788 } |
|
1789 ast->addParameter(param); |
|
1790 |
|
1791 while (tokenStream->lookAhead() == ',') { |
|
1792 advance(); |
|
1793 |
|
1794 if (tokenStream->lookAhead() == Token_ellipsis) |
|
1795 break; |
|
1796 |
|
1797 if (!parseParameterDeclaration(param)) { |
|
1798 tokenStream->rewind(start); |
|
1799 return false; |
|
1800 } |
|
1801 ast->addParameter(param); |
|
1802 } |
|
1803 |
|
1804 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1805 node = ast; |
|
1806 |
|
1807 return true; |
|
1808 } |
|
1809 |
|
1810 bool Parser::parseParameterDeclaration(ParameterDeclarationAST *&node) |
|
1811 { |
|
1812 int start = tokenStream->cursor(); |
|
1813 |
|
1814 AST *storage = 0; |
|
1815 parseStorageClassSpecifier(storage); |
|
1816 |
|
1817 // parse decl spec |
|
1818 TypeSpecifierAST *spec = 0; |
|
1819 if (!parseTypeSpecifier(spec)) { |
|
1820 tokenStream->rewind(start); |
|
1821 return false; |
|
1822 } |
|
1823 |
|
1824 int index = tokenStream->cursor(); |
|
1825 |
|
1826 DeclaratorAST *decl = 0; |
|
1827 if (!parseDeclarator(decl)) { |
|
1828 tokenStream->rewind(index); |
|
1829 |
|
1830 // try with abstract declarator |
|
1831 parseAbstractDeclarator(decl); |
|
1832 } |
|
1833 |
|
1834 AbstractExpressionAST *expr = 0; |
|
1835 if (tokenStream->lookAhead() == '=') { |
|
1836 advance(); |
|
1837 if (!parseLogicalOrExpression(expr,true)) { |
|
1838 //reportError(i18n("Expression expected")); |
|
1839 } |
|
1840 } |
|
1841 |
|
1842 ParameterDeclarationAST *ast = CreateNode<ParameterDeclarationAST>(m_pool); |
|
1843 ast->setTypeSpec(spec); |
|
1844 ast->setDeclarator(decl); |
|
1845 ast->setExpression(expr); |
|
1846 |
|
1847 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1848 node = ast; |
|
1849 |
|
1850 return true; |
|
1851 } |
|
1852 |
|
1853 bool Parser::parseClassSpecifier(TypeSpecifierAST *&node) |
|
1854 { |
|
1855 int start = tokenStream->cursor(); |
|
1856 |
|
1857 AST *classKey = 0; |
|
1858 int classKeyStart = tokenStream->cursor(); |
|
1859 |
|
1860 int kind = tokenStream->lookAhead(); |
|
1861 if (kind == Token_class || kind == Token_struct || kind == Token_union) { |
|
1862 AST *asn = CreateNode<AST>(m_pool); |
|
1863 classKey = asn; |
|
1864 advance(); |
|
1865 UPDATE_POS(classKey, classKeyStart, tokenStream->cursor()); |
|
1866 } else { |
|
1867 return false; |
|
1868 } |
|
1869 |
|
1870 AST *winDeclSpec = 0; |
|
1871 parseWinDeclSpec(winDeclSpec); |
|
1872 |
|
1873 while (tokenStream->lookAhead() == Token_identifier && tokenStream->lookAhead(1) == Token_identifier) |
|
1874 advance(); |
|
1875 |
|
1876 NameAST *name = 0; |
|
1877 parseName(name); |
|
1878 |
|
1879 BaseClauseAST *bases = 0; |
|
1880 if (tokenStream->lookAhead() == ':') { |
|
1881 if (!parseBaseClause(bases)) { |
|
1882 skipUntil('{'); |
|
1883 } |
|
1884 } |
|
1885 |
|
1886 if (tokenStream->lookAhead() != '{') { |
|
1887 tokenStream->rewind(start); |
|
1888 return false; |
|
1889 } |
|
1890 |
|
1891 ADVANCE('{', "{"); |
|
1892 |
|
1893 ClassSpecifierAST *ast = CreateNode<ClassSpecifierAST>(m_pool); |
|
1894 ast->setWinDeclSpec(winDeclSpec); |
|
1895 ast->setClassKey(classKey); |
|
1896 ast->setName(name); |
|
1897 ast->setBaseClause(bases); |
|
1898 |
|
1899 while (tokenStream->lookAhead()) { |
|
1900 if (tokenStream->lookAhead() == '}') |
|
1901 break; |
|
1902 |
|
1903 DeclarationAST *memSpec = 0; |
|
1904 int startDecl = tokenStream->cursor(); |
|
1905 if (!parseMemberSpecification(memSpec)) { |
|
1906 if (startDecl == tokenStream->cursor()) |
|
1907 advance(); // skip at least one token |
|
1908 skipUntilDeclaration(); |
|
1909 } else |
|
1910 ast->addDeclaration(memSpec); |
|
1911 } |
|
1912 |
|
1913 if (tokenStream->lookAhead() != '}') { |
|
1914 reportError(i18n("} missing")); |
|
1915 } else |
|
1916 advance(); |
|
1917 |
|
1918 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1919 node = ast; |
|
1920 |
|
1921 return true; |
|
1922 } |
|
1923 |
|
1924 bool Parser::parseAccessSpecifier(AST *&node) |
|
1925 { |
|
1926 int start = tokenStream->cursor(); |
|
1927 |
|
1928 switch(tokenStream->lookAhead()) { |
|
1929 case Token_public: |
|
1930 case Token_protected: |
|
1931 case Token_private: { |
|
1932 AST *asn = CreateNode<AST>(m_pool); |
|
1933 node = asn; |
|
1934 advance(); |
|
1935 UPDATE_POS(node, start, tokenStream->cursor()); |
|
1936 return true; |
|
1937 } |
|
1938 } |
|
1939 |
|
1940 return false; |
|
1941 } |
|
1942 |
|
1943 bool Parser::parseMemberSpecification(DeclarationAST *&node) |
|
1944 { |
|
1945 int start = tokenStream->cursor(); |
|
1946 |
|
1947 AST *access = 0; |
|
1948 |
|
1949 if (tokenStream->lookAhead() == ';') { |
|
1950 advance(); |
|
1951 return true; |
|
1952 } else if (tokenStream->lookAhead() == Token_Q_OBJECT || tokenStream->lookAhead() == Token_K_DCOP) { |
|
1953 advance(); |
|
1954 return true; |
|
1955 } else if (tokenStream->lookAhead() == Token_signals |
|
1956 || tokenStream->lookAhead() == Token_k_dcop |
|
1957 || tokenStream->lookAhead() == Token_k_dcop_signals) { |
|
1958 AccessDeclarationAST *ast = CreateNode<AccessDeclarationAST>(m_pool); |
|
1959 advance(); |
|
1960 AST *n = CreateNode<AST>(m_pool); |
|
1961 UPDATE_POS(n, start, tokenStream->cursor()); |
|
1962 ast->addAccess(n); |
|
1963 ADVANCE(':', ":"); |
|
1964 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1965 node = ast; |
|
1966 return true; |
|
1967 } else if (parseTypedef(node)) { |
|
1968 return true; |
|
1969 } else if (parseUsing(node)) { |
|
1970 return true; |
|
1971 } else if (parseTemplateDeclaration(node)) { |
|
1972 return true; |
|
1973 } else if (parseAccessSpecifier(access)) { |
|
1974 AccessDeclarationAST *ast = CreateNode<AccessDeclarationAST>(m_pool); |
|
1975 ast->addAccess(access); |
|
1976 |
|
1977 int startSlot = tokenStream->cursor(); |
|
1978 if (tokenStream->lookAhead() == Token_slots) { |
|
1979 advance(); |
|
1980 AST *sl = CreateNode<AST>(m_pool); |
|
1981 UPDATE_POS(sl, startSlot, tokenStream->cursor()); |
|
1982 ast->addAccess(sl); |
|
1983 } |
|
1984 ADVANCE(':', ":"); |
|
1985 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
1986 node = ast; |
|
1987 return true; |
|
1988 } |
|
1989 |
|
1990 tokenStream->rewind(start); |
|
1991 |
|
1992 AST *storageSpec = 0; |
|
1993 parseStorageClassSpecifier(storageSpec); |
|
1994 |
|
1995 AST *cv = 0; |
|
1996 parseCvQualify(cv); |
|
1997 |
|
1998 TypeSpecifierAST *spec = 0; |
|
1999 if (parseEnumSpecifier(spec) || parseClassSpecifier(spec)) { |
|
2000 spec->setCvQualify(cv); |
|
2001 |
|
2002 AST *cv2 = 0; |
|
2003 parseCvQualify(cv2); |
|
2004 spec->setCv2Qualify(cv2); |
|
2005 |
|
2006 InitDeclaratorListAST *declarators = 0; |
|
2007 parseInitDeclaratorList(declarators); |
|
2008 ADVANCE(';', ";"); |
|
2009 |
|
2010 SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool); |
|
2011 ast->setTypeSpec(spec); |
|
2012 ast->setInitDeclaratorList(declarators); |
|
2013 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2014 node = ast; |
|
2015 |
|
2016 return true; |
|
2017 } |
|
2018 |
|
2019 tokenStream->rewind(start); |
|
2020 return parseDeclarationInternal(node); |
|
2021 } |
|
2022 |
|
2023 bool Parser::parseCtorInitializer(AST *&/*node*/) |
|
2024 { |
|
2025 if (tokenStream->lookAhead() != ':') { |
|
2026 return false; |
|
2027 } |
|
2028 advance(); |
|
2029 |
|
2030 AST *inits = 0; |
|
2031 if (!parseMemInitializerList(inits)) { |
|
2032 reportError(i18n("Member initializers expected")); |
|
2033 } |
|
2034 |
|
2035 return true; |
|
2036 } |
|
2037 |
|
2038 bool Parser::parseElaboratedTypeSpecifier(TypeSpecifierAST *&node) |
|
2039 { |
|
2040 int start = tokenStream->cursor(); |
|
2041 |
|
2042 int tk = tokenStream->lookAhead(); |
|
2043 if (tk == Token_class || |
|
2044 tk == Token_struct || |
|
2045 tk == Token_union || |
|
2046 tk == Token_enum || |
|
2047 tk == Token_typename) |
|
2048 { |
|
2049 AST *kind = CreateNode<AST>(m_pool); |
|
2050 advance(); |
|
2051 UPDATE_POS(kind, start, tokenStream->cursor()); |
|
2052 |
|
2053 NameAST *name = 0; |
|
2054 |
|
2055 if (parseName(name)) { |
|
2056 ElaboratedTypeSpecifierAST *ast = CreateNode<ElaboratedTypeSpecifierAST>(m_pool); |
|
2057 ast->setKind(kind); |
|
2058 ast->setName(name); |
|
2059 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2060 node = ast; |
|
2061 |
|
2062 return true; |
|
2063 } |
|
2064 } |
|
2065 |
|
2066 tokenStream->rewind(start); |
|
2067 return false; |
|
2068 } |
|
2069 |
|
2070 bool Parser::parseDeclaratorId(NameAST *&node) |
|
2071 { |
|
2072 return parseName(node); |
|
2073 } |
|
2074 |
|
2075 bool Parser::parseExceptionSpecification(AST *&node) |
|
2076 { |
|
2077 if (tokenStream->lookAhead() != Token_throw) { |
|
2078 return false; |
|
2079 } |
|
2080 advance(); |
|
2081 |
|
2082 ADVANCE('(', "("); |
|
2083 if (tokenStream->lookAhead() == Token_ellipsis) { |
|
2084 // extension found in MSVC++ 7.x headers |
|
2085 int start = tokenStream->cursor(); |
|
2086 AST *ast = CreateNode<AST>(m_pool); |
|
2087 AST_FROM_TOKEN(ellipsis, tokenStream->cursor()); |
|
2088 ellipsis->setParent(ast); |
|
2089 advance(); |
|
2090 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2091 node = ast; |
|
2092 } else { |
|
2093 parseTypeIdList(node); |
|
2094 } |
|
2095 ADVANCE(')', ")"); |
|
2096 |
|
2097 return true; |
|
2098 } |
|
2099 |
|
2100 bool Parser::parseEnumerator(EnumeratorAST *&node) |
|
2101 { |
|
2102 int start = tokenStream->cursor(); |
|
2103 |
|
2104 if (tokenStream->lookAhead() != Token_identifier) { |
|
2105 return false; |
|
2106 } |
|
2107 advance(); |
|
2108 |
|
2109 EnumeratorAST *ena = CreateNode<EnumeratorAST>(m_pool); |
|
2110 node = ena; |
|
2111 |
|
2112 AST *id = CreateNode<AST>(m_pool); |
|
2113 UPDATE_POS(id, start, tokenStream->cursor()); |
|
2114 node->setId(id); |
|
2115 |
|
2116 if (tokenStream->lookAhead() == '=') { |
|
2117 advance(); |
|
2118 |
|
2119 AbstractExpressionAST *expr = 0; |
|
2120 if (!parseConstantExpression(expr)) { |
|
2121 reportError(i18n("Constant expression expected")); |
|
2122 } |
|
2123 node->setExpression(expr); |
|
2124 } |
|
2125 |
|
2126 UPDATE_POS(node, start, tokenStream->cursor()); |
|
2127 |
|
2128 return true; |
|
2129 } |
|
2130 |
|
2131 bool Parser::parseInitDeclarator(InitDeclaratorAST *&node) |
|
2132 { |
|
2133 int start = tokenStream->cursor(); |
|
2134 |
|
2135 DeclaratorAST *decl = 0; |
|
2136 AST *init = 0; |
|
2137 if (!parseDeclarator(decl)) { |
|
2138 return false; |
|
2139 } |
|
2140 |
|
2141 parseInitializer(init); |
|
2142 |
|
2143 InitDeclaratorAST *ast = CreateNode<InitDeclaratorAST>(m_pool); |
|
2144 ast->setDeclarator(decl); |
|
2145 ast->setInitializer(init); |
|
2146 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2147 node = ast; |
|
2148 |
|
2149 return true; |
|
2150 } |
|
2151 |
|
2152 |
|
2153 |
|
2154 bool Parser::parseBaseClause(BaseClauseAST *&node) |
|
2155 { |
|
2156 int start = tokenStream->cursor(); |
|
2157 if (tokenStream->lookAhead() != ':') { |
|
2158 return false; |
|
2159 } |
|
2160 advance(); |
|
2161 |
|
2162 BaseClauseAST *bca = CreateNode<BaseClauseAST>(m_pool); |
|
2163 |
|
2164 BaseSpecifierAST *baseSpec = 0; |
|
2165 if (parseBaseSpecifier(baseSpec)) { |
|
2166 bca->addBaseSpecifier(baseSpec); |
|
2167 |
|
2168 while (tokenStream->lookAhead() == ',') { |
|
2169 advance(); |
|
2170 |
|
2171 if (!parseBaseSpecifier(baseSpec)) { |
|
2172 reportError(i18n("Base class specifier expected")); |
|
2173 return false; |
|
2174 } |
|
2175 bca->addBaseSpecifier(baseSpec); |
|
2176 } |
|
2177 } else |
|
2178 return false; |
|
2179 |
|
2180 UPDATE_POS(bca, start, tokenStream->cursor()); |
|
2181 node = bca; |
|
2182 |
|
2183 return true; |
|
2184 } |
|
2185 |
|
2186 bool Parser::parseInitializer(AST *&node) |
|
2187 { |
|
2188 if (tokenStream->lookAhead() == '=') { |
|
2189 advance(); |
|
2190 |
|
2191 if (!parseInitializerClause(node)) { |
|
2192 reportError(i18n("Initializer clause expected")); |
|
2193 return false; |
|
2194 } |
|
2195 return true; |
|
2196 } else if (tokenStream->lookAhead() == '(') { |
|
2197 advance(); |
|
2198 AbstractExpressionAST *expr = 0; |
|
2199 skipCommaExpression(expr); |
|
2200 CHECK(')', ")"); |
|
2201 node = expr; |
|
2202 return true; |
|
2203 } |
|
2204 |
|
2205 return false; |
|
2206 } |
|
2207 |
|
2208 bool Parser::parseMemInitializerList(AST *&/*node*/) |
|
2209 { |
|
2210 AST *init = 0; |
|
2211 if (!parseMemInitializer(init)) { |
|
2212 return false; |
|
2213 } |
|
2214 |
|
2215 while (tokenStream->lookAhead() == ',') { |
|
2216 advance(); |
|
2217 |
|
2218 if (!parseMemInitializer(init)) { |
|
2219 break; |
|
2220 } |
|
2221 } |
|
2222 |
|
2223 return true; |
|
2224 } |
|
2225 |
|
2226 bool Parser::parseMemInitializer(AST *&/*node*/) |
|
2227 { |
|
2228 NameAST *initId = 0; |
|
2229 if (!parseMemInitializerId(initId)) { |
|
2230 reportError(i18n("Identifier expected")); |
|
2231 return false; |
|
2232 } |
|
2233 ADVANCE('(', "("); |
|
2234 AbstractExpressionAST *expr = 0; |
|
2235 skipCommaExpression(expr); |
|
2236 ADVANCE(')', ")"); |
|
2237 |
|
2238 return true; |
|
2239 } |
|
2240 |
|
2241 bool Parser::parseTypeIdList(AST *&node) |
|
2242 { |
|
2243 |
|
2244 int start = tokenStream->cursor(); |
|
2245 |
|
2246 TypeIdAST *typeId = 0; |
|
2247 if (!parseTypeId(typeId)) { |
|
2248 return false; |
|
2249 } |
|
2250 |
|
2251 AST *ast = CreateNode<AST>(m_pool); |
|
2252 typeId->setParent(ast); |
|
2253 |
|
2254 while (tokenStream->lookAhead() == ',') { |
|
2255 advance(); |
|
2256 if (parseTypeId(typeId)) { |
|
2257 typeId->setParent(ast); |
|
2258 } else { |
|
2259 reportError(i18n("Type id expected")); |
|
2260 break; |
|
2261 } |
|
2262 } |
|
2263 |
|
2264 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2265 node = ast; |
|
2266 return true; |
|
2267 } |
|
2268 |
|
2269 bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node) |
|
2270 { |
|
2271 int start = tokenStream->cursor(); |
|
2272 BaseSpecifierAST *ast = CreateNode<BaseSpecifierAST>(m_pool); |
|
2273 |
|
2274 AST *access = 0; |
|
2275 if (tokenStream->lookAhead() == Token_virtual) { |
|
2276 AST_FROM_TOKEN(virt, tokenStream->cursor()); |
|
2277 ast->setIsVirtual(virt); |
|
2278 |
|
2279 advance(); |
|
2280 |
|
2281 parseAccessSpecifier(access); |
|
2282 } else { |
|
2283 parseAccessSpecifier(access); |
|
2284 |
|
2285 if (tokenStream->lookAhead() == Token_virtual) { |
|
2286 AST_FROM_TOKEN(virt, tokenStream->cursor()); |
|
2287 ast->setIsVirtual(virt); |
|
2288 advance(); |
|
2289 } |
|
2290 } |
|
2291 |
|
2292 NameAST *name = 0; |
|
2293 if (!parseName(name)) { |
|
2294 reportError(i18n("Class name expected")); |
|
2295 } |
|
2296 |
|
2297 ast->setAccess(access); |
|
2298 ast->setName(name); |
|
2299 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2300 node = ast; |
|
2301 |
|
2302 return true; |
|
2303 } |
|
2304 |
|
2305 |
|
2306 bool Parser::parseInitializerClause(AST *&node) |
|
2307 { |
|
2308 if (tokenStream->lookAhead() == '{') { |
|
2309 if (!skip('{','}')) { |
|
2310 reportError(i18n("} missing")); |
|
2311 } else |
|
2312 advance(); |
|
2313 } else { |
|
2314 AbstractExpressionAST *expr = 0; |
|
2315 if (!parseAssignmentExpression(expr)) { |
|
2316 //reportError(i18n("Expression expected")); |
|
2317 } |
|
2318 node = expr; |
|
2319 } |
|
2320 |
|
2321 return true; |
|
2322 } |
|
2323 |
|
2324 bool Parser::parseMemInitializerId(NameAST *&node) |
|
2325 { |
|
2326 |
|
2327 return parseName(node); |
|
2328 } |
|
2329 |
|
2330 bool Parser::parsePtrToMember(AST *&/*node*/) /// ### create the AST node |
|
2331 { |
|
2332 int start = tokenStream->cursor(); |
|
2333 |
|
2334 if (tokenStream->lookAhead() == Token_scope) |
|
2335 advance(); |
|
2336 |
|
2337 ClassOrNamespaceNameAST *name = 0; |
|
2338 while (tokenStream->lookAhead() == Token_identifier) { |
|
2339 |
|
2340 if (!parseUnqualifiedName(name)) |
|
2341 break; |
|
2342 |
|
2343 if (tokenStream->lookAhead() == Token_scope |
|
2344 && tokenStream->lookAhead(1) == '*') { |
|
2345 advance(); |
|
2346 advance(); |
|
2347 return true; |
|
2348 } |
|
2349 |
|
2350 if (tokenStream->lookAhead() == Token_scope) |
|
2351 advance(); |
|
2352 } |
|
2353 |
|
2354 tokenStream->rewind(start); |
|
2355 return false; |
|
2356 } |
|
2357 |
|
2358 bool Parser::parseUnqualifiedName(ClassOrNamespaceNameAST *&node, bool parseTemplateId) |
|
2359 { |
|
2360 int start = tokenStream->cursor(); |
|
2361 bool isDestructor = false; |
|
2362 |
|
2363 ClassOrNamespaceNameAST *ast = CreateNode<ClassOrNamespaceNameAST>(m_pool); |
|
2364 |
|
2365 if (tokenStream->lookAhead() == Token_identifier) { |
|
2366 int startName = tokenStream->cursor(); |
|
2367 AST *n = CreateNode<AST>(m_pool); |
|
2368 advance(); |
|
2369 UPDATE_POS(n, startName, tokenStream->cursor()); |
|
2370 ast->setName(n); |
|
2371 } else if (tokenStream->lookAhead() == '~' && tokenStream->lookAhead(1) == Token_identifier) { |
|
2372 int startName = tokenStream->cursor(); |
|
2373 AST *n = CreateNode<AST>(m_pool); |
|
2374 advance(); // skip ~ |
|
2375 advance(); // skip classname |
|
2376 UPDATE_POS(n, startName, tokenStream->cursor()); |
|
2377 ast->setName(n); |
|
2378 isDestructor = true; |
|
2379 } else if (tokenStream->lookAhead() == Token_operator) { |
|
2380 AST *n = 0; |
|
2381 if (!parseOperatorFunctionId(n)) |
|
2382 return false; |
|
2383 ast->setName(n); |
|
2384 } else { |
|
2385 return false; |
|
2386 } |
|
2387 |
|
2388 if (parseTemplateId && !isDestructor) { |
|
2389 |
|
2390 int index = tokenStream->cursor(); |
|
2391 |
|
2392 if (tokenStream->lookAhead() == '<') { |
|
2393 advance(); |
|
2394 |
|
2395 // optional template arguments |
|
2396 TemplateArgumentListAST *args = 0; |
|
2397 parseTemplateArgumentList(args); |
|
2398 |
|
2399 if (tokenStream->lookAhead() != '>') { |
|
2400 tokenStream->rewind(index); |
|
2401 } else { |
|
2402 advance(); |
|
2403 ast->setTemplateArgumentList(args); |
|
2404 } |
|
2405 } |
|
2406 } |
|
2407 |
|
2408 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2409 node = ast; |
|
2410 |
|
2411 return true; |
|
2412 } |
|
2413 |
|
2414 bool Parser::parseStringLiteral(AST *&node) |
|
2415 { |
|
2416 int start = tokenStream->cursor(); |
|
2417 |
|
2418 while (tokenStream->lookAhead()) { |
|
2419 if (tokenStream->lookAhead() == Token_identifier && |
|
2420 tokenStream->currentTokenText() == "L" && tokenStream->lookAhead(1) == Token_string_literal) { |
|
2421 |
|
2422 advance(); |
|
2423 advance(); |
|
2424 } else if (tokenStream->lookAhead() == Token_string_literal) { |
|
2425 advance(); |
|
2426 } else |
|
2427 return false; |
|
2428 } |
|
2429 |
|
2430 AST *ast = CreateNode<AST>(m_pool); |
|
2431 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2432 node = ast; |
|
2433 return true; |
|
2434 } |
|
2435 |
|
2436 bool Parser::skipExpressionStatement(StatementAST *&node) |
|
2437 { |
|
2438 int start = tokenStream->cursor(); |
|
2439 |
|
2440 AbstractExpressionAST *expr = 0; |
|
2441 skipCommaExpression(expr); |
|
2442 |
|
2443 ADVANCE(';', ";"); |
|
2444 |
|
2445 ExpressionStatementAST *ast = CreateNode<ExpressionStatementAST>(m_pool); |
|
2446 ast->setExpression(expr); |
|
2447 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2448 node = ast; |
|
2449 |
|
2450 return true; |
|
2451 } |
|
2452 |
|
2453 bool Parser::parseStatement(StatementAST *&node) |
|
2454 { |
|
2455 int start = tokenStream->cursor(); |
|
2456 |
|
2457 switch(tokenStream->lookAhead()) { |
|
2458 |
|
2459 case Token_while: |
|
2460 return parseWhileStatement(node); |
|
2461 |
|
2462 case Token_do: |
|
2463 return parseDoStatement(node); |
|
2464 |
|
2465 case Token_for: |
|
2466 return parseForStatement(node); |
|
2467 |
|
2468 case Token_if: |
|
2469 return parseIfStatement(node); |
|
2470 |
|
2471 case Token_switch: |
|
2472 return parseSwitchStatement(node); |
|
2473 |
|
2474 case Token_try: |
|
2475 return parseTryBlockStatement(node); |
|
2476 |
|
2477 case Token_case: |
|
2478 case Token_default: |
|
2479 return parseLabeledStatement(node); |
|
2480 |
|
2481 case Token_break: |
|
2482 case Token_continue: |
|
2483 advance(); |
|
2484 ADVANCE(';', ";"); |
|
2485 return true; |
|
2486 |
|
2487 case Token_goto: |
|
2488 advance(); |
|
2489 ADVANCE(Token_identifier, "identifier"); |
|
2490 ADVANCE(';', ";"); |
|
2491 return true; |
|
2492 |
|
2493 case Token_return: |
|
2494 { |
|
2495 advance(); |
|
2496 AbstractExpressionAST *expr = 0; |
|
2497 skipCommaExpression(expr); |
|
2498 |
|
2499 ADVANCE(';', ";"); |
|
2500 |
|
2501 ReturnStatementAST *ast = CreateNode<ReturnStatementAST>(m_pool); |
|
2502 ast->setExpression(expr); |
|
2503 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2504 node = ast; |
|
2505 } |
|
2506 return true; |
|
2507 |
|
2508 case '{': |
|
2509 return parseCompoundStatement(node); |
|
2510 |
|
2511 case Token_identifier: |
|
2512 if (parseLabeledStatement(node)) |
|
2513 return true; |
|
2514 break; |
|
2515 } |
|
2516 |
|
2517 if (parseDeclarationStatement(node)) |
|
2518 return true; |
|
2519 |
|
2520 return skipExpressionStatement(node); |
|
2521 } |
|
2522 |
|
2523 bool Parser::parseCondition(ConditionAST *&node) |
|
2524 { |
|
2525 int start = tokenStream->cursor(); |
|
2526 |
|
2527 ConditionAST *ast = CreateNode<ConditionAST>(m_pool); |
|
2528 TypeSpecifierAST *spec = 0; |
|
2529 |
|
2530 if (parseTypeSpecifier(spec)) { |
|
2531 DeclaratorAST *decl = 0; |
|
2532 if (parseDeclarator(decl) && tokenStream->lookAhead() == '=') { |
|
2533 advance(); |
|
2534 |
|
2535 AbstractExpressionAST *expr = 0; |
|
2536 if (parseExpression(expr)) { |
|
2537 ast->setTypeSpec(spec); |
|
2538 ast->setDeclarator(decl); |
|
2539 ast->setExpression(expr); |
|
2540 |
|
2541 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2542 node = ast; |
|
2543 |
|
2544 return true; |
|
2545 } |
|
2546 } |
|
2547 } |
|
2548 |
|
2549 tokenStream->rewind(start); |
|
2550 |
|
2551 AbstractExpressionAST *expr = 0; |
|
2552 if (!skipCommaExpression(expr)) { |
|
2553 return false; |
|
2554 } |
|
2555 |
|
2556 ast->setExpression(expr); |
|
2557 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2558 node = ast; |
|
2559 return true; |
|
2560 } |
|
2561 |
|
2562 |
|
2563 bool Parser::parseWhileStatement(StatementAST *&node) |
|
2564 { |
|
2565 int start = tokenStream->cursor(); |
|
2566 |
|
2567 ADVANCE(Token_while, "while"); |
|
2568 ADVANCE('(' , "("); |
|
2569 |
|
2570 ConditionAST *cond = 0; |
|
2571 if (!parseCondition(cond)) { |
|
2572 reportError(i18n("condition expected")); |
|
2573 return false; |
|
2574 } |
|
2575 ADVANCE(')', ")"); |
|
2576 |
|
2577 StatementAST *body = 0; |
|
2578 if (!parseStatement(body)) { |
|
2579 reportError(i18n("statement expected")); |
|
2580 return false; |
|
2581 } |
|
2582 |
|
2583 WhileStatementAST *ast = CreateNode<WhileStatementAST>(m_pool); |
|
2584 ast->setCondition(cond); |
|
2585 ast->setStatement(body); |
|
2586 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2587 node = ast; |
|
2588 |
|
2589 return true; |
|
2590 } |
|
2591 |
|
2592 bool Parser::parseDoStatement(StatementAST *&node) |
|
2593 { |
|
2594 int start = tokenStream->cursor(); |
|
2595 |
|
2596 ADVANCE(Token_do, "do"); |
|
2597 |
|
2598 StatementAST *body = 0; |
|
2599 if (!parseStatement(body)) { |
|
2600 reportError(i18n("statement expected")); |
|
2601 //return false; |
|
2602 } |
|
2603 |
|
2604 ADVANCE_NR(Token_while, "while"); |
|
2605 ADVANCE_NR('(' , "("); |
|
2606 |
|
2607 AbstractExpressionAST *expr = 0; |
|
2608 if (!skipCommaExpression(expr)) { |
|
2609 reportError(i18n("expression expected")); |
|
2610 //return false; |
|
2611 } |
|
2612 |
|
2613 ADVANCE_NR(')', ")"); |
|
2614 ADVANCE_NR(';', ";"); |
|
2615 |
|
2616 DoStatementAST *ast = CreateNode<DoStatementAST>(m_pool); |
|
2617 ast->setStatement(body); |
|
2618 //ast->setCondition(condition); |
|
2619 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2620 node = ast; |
|
2621 |
|
2622 return true; |
|
2623 } |
|
2624 |
|
2625 bool Parser::parseForStatement(StatementAST *&node) |
|
2626 { |
|
2627 int start = tokenStream->cursor(); |
|
2628 |
|
2629 ADVANCE(Token_for, "for"); |
|
2630 ADVANCE('(', "("); |
|
2631 |
|
2632 StatementAST *init = 0; |
|
2633 if (!parseForInitStatement(init)) { |
|
2634 reportError(i18n("for initialization expected")); |
|
2635 return false; |
|
2636 } |
|
2637 |
|
2638 ConditionAST *cond = 0; |
|
2639 parseCondition(cond); |
|
2640 ADVANCE(';', ";"); |
|
2641 |
|
2642 AbstractExpressionAST *expr = 0; |
|
2643 skipCommaExpression(expr); |
|
2644 ADVANCE(')', ")"); |
|
2645 |
|
2646 StatementAST *body = 0; |
|
2647 if (!parseStatement(body)) |
|
2648 return false; |
|
2649 |
|
2650 ForStatementAST *ast = CreateNode<ForStatementAST>(m_pool); |
|
2651 ast->setInitStatement(init); |
|
2652 ast->setCondition(cond); |
|
2653 // ast->setExpression(expression); |
|
2654 ast->setStatement(body); |
|
2655 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2656 node = ast; |
|
2657 |
|
2658 return true; |
|
2659 } |
|
2660 |
|
2661 bool Parser::parseForInitStatement(StatementAST *&node) |
|
2662 { |
|
2663 if (parseDeclarationStatement(node)) |
|
2664 return true; |
|
2665 |
|
2666 return skipExpressionStatement(node); |
|
2667 } |
|
2668 |
|
2669 bool Parser::parseCompoundStatement(StatementAST *&node) |
|
2670 { |
|
2671 int start = tokenStream->cursor(); |
|
2672 |
|
2673 if (tokenStream->lookAhead() != '{') { |
|
2674 return false; |
|
2675 } |
|
2676 advance(); |
|
2677 |
|
2678 StatementListAST *ast = CreateNode<StatementListAST>(m_pool); |
|
2679 |
|
2680 while (tokenStream->lookAhead()) { |
|
2681 if (tokenStream->lookAhead() == '}') |
|
2682 break; |
|
2683 |
|
2684 StatementAST *stmt = 0; |
|
2685 int startStmt = tokenStream->cursor(); |
|
2686 if (!parseStatement(stmt)) { |
|
2687 if (startStmt == tokenStream->cursor()) |
|
2688 advance(); |
|
2689 skipUntilStatement(); |
|
2690 } else { |
|
2691 ast->addStatement(stmt); |
|
2692 } |
|
2693 } |
|
2694 |
|
2695 if (tokenStream->lookAhead() != '}') { |
|
2696 reportError(i18n("} expected")); |
|
2697 } else { |
|
2698 advance(); |
|
2699 } |
|
2700 |
|
2701 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2702 node = ast; |
|
2703 |
|
2704 return true; |
|
2705 } |
|
2706 |
|
2707 bool Parser::parseIfStatement(StatementAST *&node) |
|
2708 { |
|
2709 int start = tokenStream->cursor(); |
|
2710 |
|
2711 ADVANCE(Token_if, "if"); |
|
2712 |
|
2713 ADVANCE('(' , "("); |
|
2714 |
|
2715 IfStatementAST *ast = CreateNode<IfStatementAST>(m_pool); |
|
2716 |
|
2717 ConditionAST *cond = 0; |
|
2718 if (!parseCondition(cond)) { |
|
2719 reportError(i18n("condition expected")); |
|
2720 return false; |
|
2721 } |
|
2722 ADVANCE(')', ")"); |
|
2723 |
|
2724 StatementAST *stmt = 0; |
|
2725 if (!parseStatement(stmt)) { |
|
2726 reportError(i18n("statement expected")); |
|
2727 return false; |
|
2728 } |
|
2729 |
|
2730 ast->setCondition(cond); |
|
2731 ast->setStatement(stmt); |
|
2732 |
|
2733 if (tokenStream->lookAhead() == Token_else) { |
|
2734 advance(); |
|
2735 StatementAST *elseStmt = 0; |
|
2736 if (!parseStatement(elseStmt)) { |
|
2737 reportError(i18n("statement expected")); |
|
2738 return false; |
|
2739 } |
|
2740 ast->setElseStatement(elseStmt); |
|
2741 } |
|
2742 |
|
2743 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2744 node = ast; |
|
2745 |
|
2746 return true; |
|
2747 } |
|
2748 |
|
2749 bool Parser::parseSwitchStatement(StatementAST *&node) |
|
2750 { |
|
2751 int start = tokenStream->cursor(); |
|
2752 ADVANCE(Token_switch, "switch"); |
|
2753 |
|
2754 ADVANCE('(' , "("); |
|
2755 |
|
2756 ConditionAST *cond = 0; |
|
2757 if (!parseCondition(cond)) { |
|
2758 reportError(i18n("condition expected")); |
|
2759 return false; |
|
2760 } |
|
2761 ADVANCE(')', ")"); |
|
2762 |
|
2763 StatementAST *stmt = 0; |
|
2764 if (!parseStatement(stmt)) { |
|
2765 syntaxError(); |
|
2766 return false; |
|
2767 } |
|
2768 |
|
2769 SwitchStatementAST *ast = CreateNode<SwitchStatementAST>(m_pool); |
|
2770 ast->setCondition(cond); |
|
2771 ast->setStatement(stmt); |
|
2772 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2773 node = ast; |
|
2774 |
|
2775 return true; |
|
2776 } |
|
2777 |
|
2778 bool Parser::parseLabeledStatement(StatementAST *&node) |
|
2779 { |
|
2780 switch(tokenStream->lookAhead()) { |
|
2781 case Token_identifier: |
|
2782 case Token_default: |
|
2783 if (tokenStream->lookAhead(1) == ':') { |
|
2784 advance(); |
|
2785 advance(); |
|
2786 |
|
2787 StatementAST *stmt = 0; |
|
2788 LabeledStatementAST *ast = CreateNode<LabeledStatementAST>(m_pool); |
|
2789 node = ast; |
|
2790 if (parseStatement(stmt)) { |
|
2791 ast->setStatement(stmt); |
|
2792 return true; |
|
2793 } |
|
2794 } |
|
2795 break; |
|
2796 |
|
2797 case Token_case: |
|
2798 { |
|
2799 advance(); |
|
2800 AbstractExpressionAST *expr = 0; |
|
2801 if (!parseConstantExpression(expr)) { |
|
2802 reportError(i18n("expression expected")); |
|
2803 } else if (tokenStream->lookAhead() == Token_ellipsis) { |
|
2804 advance(); |
|
2805 |
|
2806 AbstractExpressionAST *expr2 = 0; |
|
2807 if (!parseConstantExpression(expr2)) { |
|
2808 reportError(i18n("expression expected")); |
|
2809 } |
|
2810 } |
|
2811 ADVANCE(':', ":"); |
|
2812 |
|
2813 StatementAST *stmt = 0; |
|
2814 LabeledStatementAST *ast = CreateNode<LabeledStatementAST>(m_pool); |
|
2815 node = ast; |
|
2816 ast->setExpression(expr); |
|
2817 |
|
2818 if (parseStatement(stmt)) { |
|
2819 ast->setStatement(stmt); |
|
2820 return true; |
|
2821 } |
|
2822 } |
|
2823 break; |
|
2824 |
|
2825 } |
|
2826 return false; |
|
2827 } |
|
2828 |
|
2829 bool Parser::parseBlockDeclaration(DeclarationAST *&node) |
|
2830 { |
|
2831 switch(tokenStream->lookAhead()) { |
|
2832 case Token_typedef: |
|
2833 return parseTypedef(node); |
|
2834 case Token_using: |
|
2835 return parseUsing(node); |
|
2836 case Token_asm: |
|
2837 return parseAsmDefinition(node); |
|
2838 case Token_namespace: |
|
2839 return parseNamespaceAliasDefinition(node); |
|
2840 } |
|
2841 |
|
2842 int start = tokenStream->cursor(); |
|
2843 |
|
2844 AST *storageSpec = 0; |
|
2845 parseStorageClassSpecifier(storageSpec); |
|
2846 |
|
2847 AST *cv = 0; |
|
2848 parseCvQualify(cv); |
|
2849 |
|
2850 TypeSpecifierAST *spec = 0; |
|
2851 if (!parseTypeSpecifierOrClassSpec(spec)) { // replace with simpleTypeSpecifier?!?! |
|
2852 tokenStream->rewind(start); |
|
2853 return false; |
|
2854 } |
|
2855 spec->setCvQualify(cv); |
|
2856 |
|
2857 AST *cv2 = 0; |
|
2858 parseCvQualify(cv2); |
|
2859 spec->setCv2Qualify(cv2); |
|
2860 |
|
2861 InitDeclaratorListAST *declarators = 0; |
|
2862 parseInitDeclaratorList(declarators); |
|
2863 |
|
2864 if (tokenStream->lookAhead() != ';') { |
|
2865 tokenStream->rewind(start); |
|
2866 return false; |
|
2867 } |
|
2868 advance(); |
|
2869 |
|
2870 SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool); |
|
2871 ast->setTypeSpec(spec); |
|
2872 ast->setInitDeclaratorList(declarators); |
|
2873 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2874 node = ast; |
|
2875 |
|
2876 return true; |
|
2877 } |
|
2878 |
|
2879 bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&/*node*/) |
|
2880 { |
|
2881 if (tokenStream->lookAhead() != Token_namespace) { |
|
2882 return false; |
|
2883 } |
|
2884 advance(); |
|
2885 |
|
2886 ADVANCE(Token_identifier, "identifier"); |
|
2887 ADVANCE('=', "="); |
|
2888 |
|
2889 NameAST *name = 0; |
|
2890 if (!parseName(name)) { |
|
2891 reportError(i18n("Namespace name expected")); |
|
2892 } |
|
2893 |
|
2894 ADVANCE(';', ";"); |
|
2895 |
|
2896 return true; |
|
2897 |
|
2898 } |
|
2899 |
|
2900 bool Parser::parseDeclarationStatement(StatementAST *&node) |
|
2901 { |
|
2902 int start = tokenStream->cursor(); |
|
2903 |
|
2904 DeclarationAST *decl = 0; |
|
2905 if (!parseBlockDeclaration(decl)) |
|
2906 return false; |
|
2907 |
|
2908 DeclarationStatementAST *ast = CreateNode<DeclarationStatementAST>(m_pool); |
|
2909 ast->setDeclaration(decl); |
|
2910 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
2911 node = ast; |
|
2912 |
|
2913 return true; |
|
2914 } |
|
2915 |
|
2916 bool Parser::parseDeclarationInternal(DeclarationAST *&node) |
|
2917 { |
|
2918 int start = tokenStream->cursor(); |
|
2919 |
|
2920 // that is for the case '__declspec(dllexport) int ...' or |
|
2921 // '__declspec(dllexport) inline int ...', etc. |
|
2922 AST *winDeclSpec = 0; |
|
2923 parseWinDeclSpec(winDeclSpec); |
|
2924 |
|
2925 AST *funSpec = 0; |
|
2926 bool hasFunSpec = parseFunctionSpecifier(funSpec); |
|
2927 |
|
2928 AST *storageSpec = 0; |
|
2929 bool hasStorageSpec = parseStorageClassSpecifier(storageSpec); |
|
2930 |
|
2931 if (hasStorageSpec && !hasFunSpec) |
|
2932 hasFunSpec = parseFunctionSpecifier(funSpec); |
|
2933 |
|
2934 // that is for the case 'friend __declspec(dllexport) ....' |
|
2935 AST *winDeclSpec2 = 0; |
|
2936 parseWinDeclSpec(winDeclSpec2); |
|
2937 |
|
2938 AST *cv = 0; |
|
2939 parseCvQualify(cv); |
|
2940 |
|
2941 int index = tokenStream->cursor(); |
|
2942 NameAST *name = 0; |
|
2943 if (parseName(name) && tokenStream->lookAhead() == '(') { |
|
2944 // no type specifier, maybe a constructor or a cast operator?? |
|
2945 |
|
2946 tokenStream->rewind(index); |
|
2947 |
|
2948 InitDeclaratorAST *declarator = 0; |
|
2949 if (parseInitDeclarator(declarator)) { |
|
2950 switch(tokenStream->lookAhead()) { |
|
2951 case ';': |
|
2952 { |
|
2953 advance(); |
|
2954 |
|
2955 InitDeclaratorListAST *declarators = CreateNode<InitDeclaratorListAST>(m_pool); |
|
2956 |
|
2957 // update declarators position |
|
2958 if (declarator) |
|
2959 declarators->setPosition(declarator->startToken(), declarator->endToken()); |
|
2960 declarators->addInitDeclarator(declarator); |
|
2961 |
|
2962 SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool); |
|
2963 ast->setInitDeclaratorList(declarators); |
|
2964 node = ast; |
|
2965 UPDATE_POS(node, start, tokenStream->cursor()); |
|
2966 return true; |
|
2967 |
|
2968 } |
|
2969 break; |
|
2970 |
|
2971 case ':': |
|
2972 { |
|
2973 AST *ctorInit = 0; |
|
2974 StatementListAST *funBody = 0; |
|
2975 if (parseCtorInitializer(ctorInit) && parseFunctionBody(funBody)) { |
|
2976 FunctionDefinitionAST *ast = CreateNode<FunctionDefinitionAST>(m_pool); |
|
2977 ast->setStorageSpecifier(storageSpec); |
|
2978 ast->setFunctionSpecifier(funSpec); |
|
2979 ast->setInitDeclarator(declarator); |
|
2980 ast->setFunctionBody(funBody); |
|
2981 node = ast; |
|
2982 UPDATE_POS(node, start, tokenStream->cursor()); |
|
2983 return true; |
|
2984 } |
|
2985 } |
|
2986 break; |
|
2987 |
|
2988 case '{': |
|
2989 { |
|
2990 StatementListAST *funBody = 0; |
|
2991 if (parseFunctionBody(funBody)) { |
|
2992 FunctionDefinitionAST *ast = CreateNode<FunctionDefinitionAST>(m_pool); |
|
2993 ast->setStorageSpecifier(storageSpec); |
|
2994 ast->setFunctionSpecifier(funSpec); |
|
2995 ast->setInitDeclarator(declarator); |
|
2996 ast->setFunctionBody(funBody); |
|
2997 node = ast; |
|
2998 UPDATE_POS(node, start, tokenStream->cursor()); |
|
2999 return true; |
|
3000 } |
|
3001 } |
|
3002 break; |
|
3003 |
|
3004 case '(': |
|
3005 case '[': |
|
3006 // ops!! it seems a declarator |
|
3007 goto start_decl; |
|
3008 break; |
|
3009 } |
|
3010 |
|
3011 } |
|
3012 } |
|
3013 |
|
3014 start_decl: |
|
3015 tokenStream->rewind(index); |
|
3016 |
|
3017 if (tokenStream->lookAhead() == Token_const && tokenStream->lookAhead(1) == Token_identifier && tokenStream->lookAhead(2) == '=') { |
|
3018 // constant definition |
|
3019 advance(); |
|
3020 InitDeclaratorListAST *declarators = 0; |
|
3021 if (parseInitDeclaratorList(declarators)) { |
|
3022 ADVANCE(';', ";"); |
|
3023 DeclarationAST *ast = CreateNode<DeclarationAST>(m_pool); |
|
3024 node = ast; |
|
3025 UPDATE_POS(node, start, tokenStream->cursor()); |
|
3026 return true; |
|
3027 } |
|
3028 syntaxError(); |
|
3029 return false; |
|
3030 } |
|
3031 |
|
3032 TypeSpecifierAST *spec = 0; |
|
3033 if (parseTypeSpecifier(spec)) { |
|
3034 if (!hasFunSpec) |
|
3035 parseFunctionSpecifier(funSpec); // e.g. "void inline" |
|
3036 spec->setCvQualify(cv); |
|
3037 |
|
3038 InitDeclaratorListAST *declarators = 0; |
|
3039 |
|
3040 InitDeclaratorAST *decl = 0; |
|
3041 int startDeclarator = tokenStream->cursor(); |
|
3042 bool maybeFunctionDefinition = false; |
|
3043 |
|
3044 if (tokenStream->lookAhead() != ';') { |
|
3045 if (parseInitDeclarator(decl) && tokenStream->lookAhead() == '{') { |
|
3046 // function definition |
|
3047 maybeFunctionDefinition = true; |
|
3048 } else { |
|
3049 tokenStream->rewind(startDeclarator); |
|
3050 if (!parseInitDeclaratorList(declarators)) { |
|
3051 syntaxError(); |
|
3052 return false; |
|
3053 } |
|
3054 } |
|
3055 } |
|
3056 |
|
3057 switch(tokenStream->lookAhead()) { |
|
3058 case ';': |
|
3059 { |
|
3060 advance(); |
|
3061 SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool); |
|
3062 ast->setStorageSpecifier(storageSpec); |
|
3063 ast->setFunctionSpecifier(funSpec); |
|
3064 ast->setTypeSpec(spec); |
|
3065 ast->setWinDeclSpec(winDeclSpec); |
|
3066 ast->setInitDeclaratorList(declarators); |
|
3067 node = ast; |
|
3068 UPDATE_POS(node, start, tokenStream->cursor()); |
|
3069 } |
|
3070 return true; |
|
3071 |
|
3072 case '{': |
|
3073 { |
|
3074 if (!maybeFunctionDefinition) { |
|
3075 syntaxError(); |
|
3076 return false; |
|
3077 } |
|
3078 StatementListAST *funBody = 0; |
|
3079 if (parseFunctionBody(funBody)) { |
|
3080 FunctionDefinitionAST *ast = CreateNode<FunctionDefinitionAST>(m_pool); |
|
3081 ast->setWinDeclSpec(winDeclSpec); |
|
3082 ast->setStorageSpecifier(storageSpec); |
|
3083 ast->setFunctionSpecifier(funSpec); |
|
3084 ast->setTypeSpec(spec); |
|
3085 ast->setInitDeclarator(decl); |
|
3086 ast->setFunctionBody(funBody); |
|
3087 node = ast; |
|
3088 UPDATE_POS(node, start, tokenStream->cursor()); |
|
3089 return true; |
|
3090 } |
|
3091 } |
|
3092 break; |
|
3093 |
|
3094 } |
|
3095 } |
|
3096 |
|
3097 syntaxError(); |
|
3098 return false; |
|
3099 } |
|
3100 |
|
3101 bool Parser::parseFunctionBody(StatementListAST *&node) |
|
3102 { |
|
3103 int start = tokenStream->cursor(); |
|
3104 if (tokenStream->lookAhead() != '{') { |
|
3105 return false; |
|
3106 } |
|
3107 advance(); |
|
3108 |
|
3109 StatementListAST *ast = CreateNode<StatementListAST>(m_pool); |
|
3110 |
|
3111 while (tokenStream->lookAhead()) { |
|
3112 if (tokenStream->lookAhead() == '}') |
|
3113 break; |
|
3114 |
|
3115 StatementAST *stmt = 0; |
|
3116 int startStmt = tokenStream->cursor(); |
|
3117 if (!parseStatement(stmt)) { |
|
3118 syntaxError(); |
|
3119 if (startStmt == tokenStream->cursor()) |
|
3120 advance(); |
|
3121 skipUntilStatement(); |
|
3122 } else |
|
3123 ast->addStatement(stmt); |
|
3124 } |
|
3125 |
|
3126 if (tokenStream->lookAhead() != '}') { |
|
3127 reportError(i18n("} expected")); |
|
3128 } else |
|
3129 advance(); |
|
3130 |
|
3131 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3132 node = ast; |
|
3133 |
|
3134 return true; |
|
3135 } |
|
3136 |
|
3137 bool Parser::parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node) |
|
3138 { |
|
3139 if (parseClassSpecifier(node)) |
|
3140 return true; |
|
3141 else if (parseEnumSpecifier(node)) |
|
3142 return true; |
|
3143 else if (parseTypeSpecifier(node)) |
|
3144 return true; |
|
3145 |
|
3146 return false; |
|
3147 } |
|
3148 |
|
3149 bool Parser::parseTryBlockStatement(StatementAST *&node) |
|
3150 { |
|
3151 if (tokenStream->lookAhead() != Token_try) { |
|
3152 return false; |
|
3153 } |
|
3154 advance(); |
|
3155 |
|
3156 StatementAST *stmt = 0; |
|
3157 if (!parseCompoundStatement(stmt)) { |
|
3158 syntaxError(); |
|
3159 return false; |
|
3160 } |
|
3161 |
|
3162 if (tokenStream->lookAhead() != Token_catch) { |
|
3163 reportError(i18n("catch expected")); |
|
3164 return false; |
|
3165 } |
|
3166 |
|
3167 while (tokenStream->lookAhead() == Token_catch) { |
|
3168 advance(); |
|
3169 ADVANCE('(', "("); |
|
3170 ConditionAST *cond = 0; |
|
3171 if (tokenStream->lookAhead() == Token_ellipsis) { |
|
3172 advance(); |
|
3173 } else if (!parseCondition(cond)) { |
|
3174 reportError(i18n("condition expected")); |
|
3175 return false; |
|
3176 } |
|
3177 ADVANCE(')', ")"); |
|
3178 |
|
3179 StatementAST *body = 0; |
|
3180 if (!parseCompoundStatement(body)) { |
|
3181 syntaxError(); |
|
3182 return false; |
|
3183 } |
|
3184 } |
|
3185 |
|
3186 node = stmt; |
|
3187 return true; |
|
3188 } |
|
3189 |
|
3190 bool Parser::parsePrimaryExpression(AbstractExpressionAST *&node) |
|
3191 { |
|
3192 int start = tokenStream->cursor(); |
|
3193 |
|
3194 AbstractExpressionAST *ast = CreateExpression<NodeType_PrimaryExpression>(m_pool); |
|
3195 |
|
3196 switch(tokenStream->lookAhead()) { |
|
3197 case Token_string_literal: |
|
3198 { |
|
3199 AST *lit = 0; |
|
3200 parseStringLiteral(lit); |
|
3201 if (lit) |
|
3202 lit->setParent(ast); |
|
3203 } |
|
3204 break; |
|
3205 |
|
3206 case Token_number_literal: |
|
3207 case Token_char_literal: |
|
3208 case Token_true: |
|
3209 case Token_false: |
|
3210 case Token_this: |
|
3211 { |
|
3212 AST_FROM_TOKEN(opNode, tokenStream->cursor()); |
|
3213 opNode->setParent(ast); |
|
3214 advance(); |
|
3215 } |
|
3216 break; |
|
3217 |
|
3218 case '(': |
|
3219 { |
|
3220 advance(); |
|
3221 |
|
3222 if (tokenStream->lookAhead() == '{') { |
|
3223 StatementAST *stmt = 0; |
|
3224 if (!parseCompoundStatement(stmt)) |
|
3225 return false; |
|
3226 if (stmt) |
|
3227 stmt->setParent(ast); |
|
3228 } else { |
|
3229 AbstractExpressionAST *expr = 0; |
|
3230 if (!parseExpression(expr)) { |
|
3231 return false; |
|
3232 } |
|
3233 if (expr) |
|
3234 expr->setParent(ast); |
|
3235 } |
|
3236 CHECK(')', ")"); |
|
3237 } |
|
3238 break; |
|
3239 |
|
3240 default: |
|
3241 { |
|
3242 /* ### reenable me |
|
3243 TypeSpecifierAST *typeSpec = 0; |
|
3244 if (parseSimpleTypeSpecifier(typeSpec) && tokenStream->lookAhead() == '(') { |
|
3245 Q_ASSERT (0); |
|
3246 advance(); |
|
3247 AbstractExpressionAST *expr = 0; |
|
3248 parseCommaExpression(expr); |
|
3249 CHECK(')', ")"); |
|
3250 break; |
|
3251 |
|
3252 if (typeSpec) |
|
3253 typeSpec->setParent(ast); |
|
3254 |
|
3255 if (expr) |
|
3256 expr->setParent(ast); |
|
3257 } |
|
3258 |
|
3259 tokenStream->rewind(start); |
|
3260 */ |
|
3261 |
|
3262 NameAST *name = 0; |
|
3263 if (!parseName(name, false)) |
|
3264 return false; |
|
3265 |
|
3266 if (name) |
|
3267 name->setParent(ast); |
|
3268 |
|
3269 break; |
|
3270 } |
|
3271 } |
|
3272 |
|
3273 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3274 node = ast; |
|
3275 return true; |
|
3276 } |
|
3277 |
|
3278 |
|
3279 /* |
|
3280 postfix-expression-internal: |
|
3281 [ expression ] |
|
3282 ( expression-list [opt] ) |
|
3283 (.|->) template [opt] id-expression |
|
3284 (.|->) pseudo-destructor-name |
|
3285 ++ |
|
3286 -- |
|
3287 */ |
|
3288 bool Parser::parsePostfixExpressionInternal(AbstractExpressionAST *postfixExpr, AbstractExpressionAST *&node) |
|
3289 { |
|
3290 Q_ASSERT (postfixExpr); |
|
3291 |
|
3292 int start = tokenStream->cursor(); |
|
3293 |
|
3294 switch (tokenStream->lookAhead()) { |
|
3295 case '[': |
|
3296 { |
|
3297 advance(); |
|
3298 AbstractExpressionAST *expr = 0; |
|
3299 parseExpression(expr); |
|
3300 CHECK(']', "]"); |
|
3301 |
|
3302 SubscriptingAST *ast = CreateNode<SubscriptingAST>(m_pool); |
|
3303 ast->setExpression(postfixExpr); |
|
3304 ast->setSubscript(expr); |
|
3305 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3306 node = ast; |
|
3307 } |
|
3308 return true; |
|
3309 |
|
3310 case '(': |
|
3311 { |
|
3312 advance(); |
|
3313 AbstractExpressionAST *expr = 0; |
|
3314 parseExpression(expr); |
|
3315 CHECK(')', ")"); |
|
3316 |
|
3317 FunctionCallAST *ast = CreateNode<FunctionCallAST>(m_pool); |
|
3318 ast->setExpression(postfixExpr); |
|
3319 ast->setArguments(expr); |
|
3320 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3321 node = ast; |
|
3322 } |
|
3323 return true; |
|
3324 |
|
3325 case '.': |
|
3326 case Token_arrow: |
|
3327 { |
|
3328 AST_FROM_TOKEN(op, tokenStream->cursor()); |
|
3329 |
|
3330 advance(); |
|
3331 if (tokenStream->lookAhead() == Token_template) |
|
3332 advance(); |
|
3333 |
|
3334 NameAST *name = 0; |
|
3335 if (!parseName(name)) |
|
3336 return false; |
|
3337 |
|
3338 ClassMemberAccessAST *ast = CreateNode<ClassMemberAccessAST>(m_pool); |
|
3339 ast->setOp(op); |
|
3340 ast->setExpression(postfixExpr); |
|
3341 ast->setName(name); |
|
3342 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3343 node = ast; |
|
3344 } |
|
3345 return true; |
|
3346 |
|
3347 case Token_incr: |
|
3348 case Token_decr: |
|
3349 { |
|
3350 AST_FROM_TOKEN(op, tokenStream->cursor()); |
|
3351 advance(); |
|
3352 |
|
3353 IncrDecrAST *ast = CreateNode<IncrDecrAST>(m_pool); |
|
3354 ast->setExpression(postfixExpr); |
|
3355 ast->setOp(op); |
|
3356 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3357 node = ast; |
|
3358 } |
|
3359 return true; |
|
3360 |
|
3361 default: |
|
3362 return false; |
|
3363 } |
|
3364 } |
|
3365 |
|
3366 /* |
|
3367 postfix-expression: |
|
3368 simple-type-specifier ( expression-list [opt] ) |
|
3369 primary-expression postfix-expression-internal* |
|
3370 */ |
|
3371 bool Parser::parsePostfixExpression(AbstractExpressionAST *&node) |
|
3372 { |
|
3373 int start = tokenStream->cursor(); |
|
3374 |
|
3375 switch (tokenStream->lookAhead()) { |
|
3376 case Token_dynamic_cast: |
|
3377 case Token_static_cast: |
|
3378 case Token_reinterpret_cast: |
|
3379 case Token_const_cast: |
|
3380 { |
|
3381 AST_FROM_TOKEN(castOp, tokenStream->cursor()); |
|
3382 |
|
3383 advance(); |
|
3384 CHECK('<', "<"); |
|
3385 TypeIdAST *typeId = 0; |
|
3386 parseTypeId(typeId); |
|
3387 CHECK('>', ">"); |
|
3388 |
|
3389 CHECK('(', ")"); |
|
3390 AbstractExpressionAST *expr = 0; |
|
3391 parseCommaExpression(expr); |
|
3392 CHECK(')', ")"); |
|
3393 |
|
3394 CppCastExpressionAST *tmp = CreateNode<CppCastExpressionAST>(m_pool); |
|
3395 tmp->setCastOp(castOp); |
|
3396 tmp->setTypeId(typeId); |
|
3397 tmp->setExpression(expr); |
|
3398 |
|
3399 AbstractExpressionAST *ast = tmp; |
|
3400 AbstractExpressionAST *e = 0; |
|
3401 while (parsePostfixExpressionInternal(ast, e)) { |
|
3402 ast = e; |
|
3403 } |
|
3404 |
|
3405 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3406 node = ast; |
|
3407 } |
|
3408 return true; |
|
3409 |
|
3410 case Token_typename: |
|
3411 { |
|
3412 advance(); |
|
3413 |
|
3414 NameAST* name = 0; |
|
3415 if (!parseName(name)) |
|
3416 return false; |
|
3417 |
|
3418 CHECK('(', "("); |
|
3419 AbstractExpressionAST *expr = 0; |
|
3420 parseCommaExpression(expr); |
|
3421 CHECK(')', ")"); |
|
3422 |
|
3423 // ### AST |
|
3424 } |
|
3425 return true; |
|
3426 |
|
3427 case Token_typeid: |
|
3428 { |
|
3429 advance(); |
|
3430 |
|
3431 CHECK('(', "("); |
|
3432 AbstractExpressionAST *expr = 0; |
|
3433 parseCommaExpression(expr); |
|
3434 CHECK(')', ")"); |
|
3435 |
|
3436 // ### AST |
|
3437 } |
|
3438 return true; |
|
3439 |
|
3440 default: |
|
3441 break; |
|
3442 } |
|
3443 |
|
3444 TypeSpecifierAST *typeSpec = 0; |
|
3445 AbstractExpressionAST *expr = 0; |
|
3446 |
|
3447 if (parseSimpleTypeSpecifier(typeSpec/*, true*/) && tokenStream->lookAhead() == '(') { |
|
3448 advance(); // skip '(' |
|
3449 parseCommaExpression(expr); |
|
3450 CHECK(')', ")"); |
|
3451 } else { |
|
3452 tokenStream->rewind(start); |
|
3453 |
|
3454 if (!parsePrimaryExpression(expr)) |
|
3455 return false; |
|
3456 } |
|
3457 |
|
3458 AbstractExpressionAST *ast = CreateExpression<NodeType_PostfixExpression>(m_pool); |
|
3459 if (typeSpec) |
|
3460 typeSpec->setParent(ast); |
|
3461 |
|
3462 if (expr) |
|
3463 expr->setParent(ast); |
|
3464 |
|
3465 AbstractExpressionAST *e = 0; |
|
3466 while (parsePostfixExpressionInternal(ast, e)) { |
|
3467 ast = e; |
|
3468 } |
|
3469 |
|
3470 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3471 node = ast; |
|
3472 return true; |
|
3473 } |
|
3474 |
|
3475 bool Parser::parseUnaryExpression(AbstractExpressionAST *&node) |
|
3476 { |
|
3477 int start = tokenStream->cursor(); |
|
3478 |
|
3479 switch(tokenStream->lookAhead()) { |
|
3480 case Token_incr: |
|
3481 case Token_decr: |
|
3482 case '*': |
|
3483 case '&': |
|
3484 case '+': |
|
3485 case '-': |
|
3486 case '!': |
|
3487 case '~': |
|
3488 { |
|
3489 AST_FROM_TOKEN(opNode, tokenStream->cursor()); |
|
3490 |
|
3491 advance(); |
|
3492 AbstractExpressionAST *expr = 0; |
|
3493 if (!parseCastExpression(expr)) |
|
3494 return false; |
|
3495 |
|
3496 AbstractExpressionAST *ast = CreateExpression<NodeType_UnaryExpression>(m_pool); |
|
3497 |
|
3498 opNode->setParent(ast); |
|
3499 if (expr) |
|
3500 expr->setParent(ast); |
|
3501 |
|
3502 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3503 node = ast; |
|
3504 return true; |
|
3505 } |
|
3506 |
|
3507 case Token_sizeof: |
|
3508 { |
|
3509 AbstractExpressionAST *ast = CreateExpression<NodeType_UnaryExpression>(m_pool); |
|
3510 |
|
3511 AST_FROM_TOKEN(opNode, tokenStream->cursor()); |
|
3512 opNode->setParent(ast); |
|
3513 |
|
3514 advance(); |
|
3515 int index = tokenStream->cursor(); |
|
3516 if (tokenStream->lookAhead() == '(') { |
|
3517 advance(); |
|
3518 TypeIdAST *typeId = 0; |
|
3519 if (parseTypeId(typeId) && tokenStream->lookAhead() == ')') { |
|
3520 if (typeId) |
|
3521 typeId->setParent(ast); |
|
3522 |
|
3523 advance(); |
|
3524 |
|
3525 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3526 node = ast; |
|
3527 return true; |
|
3528 } |
|
3529 tokenStream->rewind(index); |
|
3530 } |
|
3531 AbstractExpressionAST *expr = 0; |
|
3532 if (!parseUnaryExpression(expr)) |
|
3533 return false; |
|
3534 |
|
3535 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3536 node = ast; |
|
3537 return true; |
|
3538 } |
|
3539 |
|
3540 case Token_new: |
|
3541 return parseNewExpression(node); |
|
3542 |
|
3543 case Token_delete: |
|
3544 return parseDeleteExpression(node); |
|
3545 } |
|
3546 |
|
3547 return parsePostfixExpression(node); |
|
3548 } |
|
3549 |
|
3550 bool Parser::parseNewExpression(AbstractExpressionAST *&node) |
|
3551 { |
|
3552 int start = tokenStream->cursor(); |
|
3553 |
|
3554 AbstractExpressionAST *ast = CreateExpression<NodeType_NewExpression>(m_pool); |
|
3555 |
|
3556 if (tokenStream->lookAhead() == Token_scope && tokenStream->lookAhead(1) == Token_new) { |
|
3557 AST_FROM_TOKEN(scopeNode, tokenStream->cursor()); |
|
3558 scopeNode->setParent(ast); |
|
3559 advance(); |
|
3560 } |
|
3561 |
|
3562 AST_FROM_TOKEN(newNode, tokenStream->cursor()); |
|
3563 newNode->setParent(ast); |
|
3564 |
|
3565 CHECK(Token_new, "new"); |
|
3566 |
|
3567 if (tokenStream->lookAhead() == '(') { |
|
3568 advance(); |
|
3569 AbstractExpressionAST *expr = 0; |
|
3570 parseCommaExpression(expr); |
|
3571 if (expr) |
|
3572 expr->setParent(ast); |
|
3573 CHECK(')', ")"); |
|
3574 } |
|
3575 |
|
3576 if (tokenStream->lookAhead() == '(') { |
|
3577 advance(); |
|
3578 TypeIdAST *typeId = 0; |
|
3579 parseTypeId(typeId); |
|
3580 if (typeId) |
|
3581 typeId->setParent(ast); |
|
3582 CHECK(')', ")"); |
|
3583 } else { |
|
3584 AbstractExpressionAST *typeId = 0; |
|
3585 parseNewTypeId(typeId); |
|
3586 if (typeId) |
|
3587 typeId->setParent(ast); |
|
3588 } |
|
3589 |
|
3590 AbstractExpressionAST *init = 0; |
|
3591 parseNewInitializer(init); |
|
3592 if (init) |
|
3593 init->setParent(ast); |
|
3594 |
|
3595 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3596 node = ast; |
|
3597 return true; |
|
3598 } |
|
3599 |
|
3600 bool Parser::parseNewTypeId(AbstractExpressionAST *&node) |
|
3601 { |
|
3602 int start = tokenStream->cursor(); |
|
3603 |
|
3604 TypeSpecifierAST *typeSpec = 0; |
|
3605 if (!parseTypeSpecifier(typeSpec)) |
|
3606 return false; |
|
3607 |
|
3608 AbstractExpressionAST *ast = CreateExpression<NodeType_NewTypeId>(m_pool); |
|
3609 |
|
3610 if (typeSpec) |
|
3611 typeSpec->setParent(ast); |
|
3612 |
|
3613 AbstractExpressionAST *declarator = 0; |
|
3614 parseNewDeclarator(declarator); |
|
3615 if (declarator) |
|
3616 declarator->setParent(ast); |
|
3617 |
|
3618 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3619 node = ast; |
|
3620 return true; |
|
3621 } |
|
3622 |
|
3623 bool Parser::parseNewDeclarator(AbstractExpressionAST *&node) |
|
3624 { |
|
3625 int start = tokenStream->cursor(); |
|
3626 |
|
3627 AbstractExpressionAST *ast = CreateExpression<NodeType_NewInitializer>(m_pool); |
|
3628 |
|
3629 AST *ptrOp = 0; |
|
3630 if (parsePtrOperator(ptrOp)) { |
|
3631 if (ptrOp) |
|
3632 ptrOp->setParent(ast); |
|
3633 |
|
3634 AbstractExpressionAST *declarator = 0; |
|
3635 parseNewDeclarator(declarator); |
|
3636 |
|
3637 if (declarator) |
|
3638 declarator->setParent(ast); |
|
3639 } |
|
3640 |
|
3641 while (tokenStream->lookAhead() == '[') { |
|
3642 advance(); |
|
3643 AbstractExpressionAST *expr = 0; |
|
3644 parseExpression(expr); |
|
3645 ADVANCE(']', "]"); |
|
3646 |
|
3647 if (expr) |
|
3648 expr->setParent(ast); |
|
3649 } |
|
3650 |
|
3651 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3652 node = ast; |
|
3653 return true; |
|
3654 } |
|
3655 |
|
3656 bool Parser::parseNewInitializer(AbstractExpressionAST *&node) |
|
3657 { |
|
3658 int start = tokenStream->cursor(); |
|
3659 |
|
3660 if (tokenStream->lookAhead() != '(') |
|
3661 return false; |
|
3662 |
|
3663 AbstractExpressionAST *ast = CreateExpression<NodeType_NewInitializer>(m_pool); |
|
3664 |
|
3665 advance(); |
|
3666 AbstractExpressionAST *expr = 0; |
|
3667 parseCommaExpression(expr); |
|
3668 |
|
3669 if (expr) |
|
3670 expr->setParent(ast); |
|
3671 |
|
3672 CHECK(')', ")"); |
|
3673 |
|
3674 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3675 node = ast; |
|
3676 return true; |
|
3677 } |
|
3678 |
|
3679 bool Parser::parseDeleteExpression(AbstractExpressionAST *&node) |
|
3680 { |
|
3681 int start = tokenStream->cursor(); |
|
3682 |
|
3683 AbstractExpressionAST *ast = CreateExpression<NodeType_DeleteExpression>(m_pool); |
|
3684 |
|
3685 if (tokenStream->lookAhead() == Token_scope && tokenStream->lookAhead(1) == Token_delete) { |
|
3686 AST_FROM_TOKEN(scopeNode, tokenStream->cursor()); |
|
3687 scopeNode->setParent(ast); |
|
3688 advance(); |
|
3689 } |
|
3690 |
|
3691 AST_FROM_TOKEN(deleteNode, tokenStream->cursor()); |
|
3692 deleteNode->setParent(ast); |
|
3693 |
|
3694 CHECK(Token_delete, "delete"); |
|
3695 |
|
3696 if (tokenStream->lookAhead() == '[') { |
|
3697 int beg = tokenStream->cursor(); |
|
3698 advance(); |
|
3699 CHECK(']', "]"); |
|
3700 |
|
3701 AST *n = CreateNode<AST>(m_pool); |
|
3702 UPDATE_POS(n, beg, tokenStream->cursor()); |
|
3703 n->setParent(ast); |
|
3704 } |
|
3705 |
|
3706 AbstractExpressionAST *expr = 0; |
|
3707 if (!parseCastExpression(expr)) |
|
3708 return false; |
|
3709 |
|
3710 if (expr) |
|
3711 expr->setParent(ast); |
|
3712 |
|
3713 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3714 node = ast; |
|
3715 return true; |
|
3716 } |
|
3717 |
|
3718 bool Parser::parseCastExpression(AbstractExpressionAST *&node) |
|
3719 { |
|
3720 int start = tokenStream->cursor(); |
|
3721 |
|
3722 if (tokenStream->lookAhead() == '(') { |
|
3723 AbstractExpressionAST *ast = CreateExpression<NodeType_CastExpression>(m_pool); |
|
3724 |
|
3725 advance(); |
|
3726 TypeIdAST *typeId = 0; |
|
3727 if (parseTypeId(typeId)) { |
|
3728 |
|
3729 if (typeId) |
|
3730 typeId->setParent(ast); |
|
3731 |
|
3732 if (tokenStream->lookAhead() == ')') { |
|
3733 advance(); |
|
3734 |
|
3735 AbstractExpressionAST *expr = 0; |
|
3736 if (parseCastExpression(expr)) { |
|
3737 if (expr) |
|
3738 expr->setParent(ast); |
|
3739 |
|
3740 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3741 node = ast; |
|
3742 return true; |
|
3743 } |
|
3744 } |
|
3745 } |
|
3746 } |
|
3747 |
|
3748 tokenStream->rewind(start); |
|
3749 return parseUnaryExpression(node); |
|
3750 } |
|
3751 |
|
3752 bool Parser::parsePmExpression(AbstractExpressionAST *&node) |
|
3753 { |
|
3754 int start = tokenStream->cursor(); |
|
3755 |
|
3756 AbstractExpressionAST *ast = 0; |
|
3757 if (!parseCastExpression(ast) || !ast) // ### fixme |
|
3758 return false; |
|
3759 |
|
3760 while (tokenStream->lookAhead() == Token_ptrmem) { |
|
3761 int startOp = tokenStream->cursor(); |
|
3762 AST_FROM_TOKEN(op, startOp); |
|
3763 advance(); |
|
3764 |
|
3765 AbstractExpressionAST *rightExpr = 0; |
|
3766 if (!parseCastExpression(rightExpr)) |
|
3767 return false; |
|
3768 |
|
3769 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
3770 tmp->setOp(op); |
|
3771 tmp->setLeftExpression(ast); |
|
3772 tmp->setRightExpression(rightExpr); |
|
3773 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
3774 ast = tmp; |
|
3775 } |
|
3776 |
|
3777 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3778 node = ast; |
|
3779 return true; |
|
3780 } |
|
3781 |
|
3782 bool Parser::parseMultiplicativeExpression(AbstractExpressionAST *&node) |
|
3783 { |
|
3784 int start = tokenStream->cursor(); |
|
3785 |
|
3786 AbstractExpressionAST *ast = 0; |
|
3787 if (!parsePmExpression(ast)) |
|
3788 return false; |
|
3789 |
|
3790 while (tokenStream->lookAhead() == '*' || tokenStream->lookAhead() == '/' || tokenStream->lookAhead() == '%') { |
|
3791 int startOp = tokenStream->cursor(); |
|
3792 AST_FROM_TOKEN(op, startOp); |
|
3793 advance(); |
|
3794 |
|
3795 AbstractExpressionAST *rightExpr = 0; |
|
3796 if (!parsePmExpression(rightExpr)) |
|
3797 return false; |
|
3798 |
|
3799 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
3800 tmp->setOp(op); |
|
3801 tmp->setLeftExpression(ast); |
|
3802 tmp->setRightExpression(rightExpr); |
|
3803 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
3804 ast = tmp; |
|
3805 } |
|
3806 |
|
3807 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3808 node = ast; |
|
3809 return true; |
|
3810 } |
|
3811 |
|
3812 |
|
3813 bool Parser::parseAdditiveExpression(AbstractExpressionAST *&node) |
|
3814 { |
|
3815 int start = tokenStream->cursor(); |
|
3816 |
|
3817 AbstractExpressionAST *ast = 0; |
|
3818 if (!parseMultiplicativeExpression(ast)) |
|
3819 return false; |
|
3820 |
|
3821 while (tokenStream->lookAhead() == '+' || tokenStream->lookAhead() == '-') { |
|
3822 int startOp = tokenStream->cursor(); |
|
3823 AST_FROM_TOKEN(op, startOp); |
|
3824 advance(); |
|
3825 |
|
3826 AbstractExpressionAST *rightExpr = 0; |
|
3827 if (!parseMultiplicativeExpression(rightExpr)) |
|
3828 return false; |
|
3829 |
|
3830 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
3831 tmp->setOp(op); |
|
3832 tmp->setLeftExpression(ast); |
|
3833 tmp->setRightExpression(rightExpr); |
|
3834 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
3835 ast = tmp; |
|
3836 } |
|
3837 |
|
3838 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3839 node = ast; |
|
3840 return true; |
|
3841 } |
|
3842 |
|
3843 bool Parser::parseShiftExpression(AbstractExpressionAST *&node) |
|
3844 { |
|
3845 int start = tokenStream->cursor(); |
|
3846 |
|
3847 AbstractExpressionAST *ast = 0; |
|
3848 if (!parseAdditiveExpression(ast)) |
|
3849 return false; |
|
3850 |
|
3851 while (tokenStream->lookAhead() == Token_shift) { |
|
3852 int startOp = tokenStream->cursor(); |
|
3853 AST_FROM_TOKEN(op, startOp); |
|
3854 advance(); |
|
3855 |
|
3856 AbstractExpressionAST *rightExpr = 0; |
|
3857 if (!parseAdditiveExpression(rightExpr)) |
|
3858 return false; |
|
3859 |
|
3860 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
3861 tmp->setOp(op); |
|
3862 tmp->setLeftExpression(ast); |
|
3863 tmp->setRightExpression(rightExpr); |
|
3864 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
3865 ast = tmp; |
|
3866 } |
|
3867 |
|
3868 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3869 node = ast; |
|
3870 return true; |
|
3871 } |
|
3872 |
|
3873 bool Parser::parseRelationalExpression(AbstractExpressionAST *&node, bool templArgs) |
|
3874 { |
|
3875 int start = tokenStream->cursor(); |
|
3876 |
|
3877 AbstractExpressionAST *ast = 0; |
|
3878 if (!parseShiftExpression(ast)) |
|
3879 return false; |
|
3880 |
|
3881 while (tokenStream->lookAhead() == '<' || (tokenStream->lookAhead() == '>' && !templArgs) || |
|
3882 tokenStream->lookAhead() == Token_leq || tokenStream->lookAhead() == Token_geq) { |
|
3883 int startOp = tokenStream->cursor(); |
|
3884 AST_FROM_TOKEN(op, startOp); |
|
3885 advance(); |
|
3886 |
|
3887 AbstractExpressionAST *rightExpr = 0; |
|
3888 if (!parseShiftExpression(rightExpr)) |
|
3889 return false; |
|
3890 |
|
3891 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
3892 tmp->setOp(op); |
|
3893 tmp->setLeftExpression(ast); |
|
3894 tmp->setRightExpression(rightExpr); |
|
3895 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
3896 ast = tmp; |
|
3897 } |
|
3898 |
|
3899 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3900 node = ast; |
|
3901 return true; |
|
3902 } |
|
3903 |
|
3904 bool Parser::parseEqualityExpression(AbstractExpressionAST *&node, bool templArgs) |
|
3905 { |
|
3906 int start = tokenStream->cursor(); |
|
3907 |
|
3908 AbstractExpressionAST *ast = 0; |
|
3909 if (!parseRelationalExpression(ast, templArgs)) |
|
3910 return false; |
|
3911 |
|
3912 while (tokenStream->lookAhead() == Token_eq || tokenStream->lookAhead() == Token_not_eq) { |
|
3913 int startOp = tokenStream->cursor(); |
|
3914 AST_FROM_TOKEN(op, startOp); |
|
3915 advance(); |
|
3916 |
|
3917 AbstractExpressionAST *rightExpr = 0; |
|
3918 if (!parseRelationalExpression(rightExpr, templArgs)) |
|
3919 return false; |
|
3920 |
|
3921 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
3922 tmp->setOp(op); |
|
3923 tmp->setLeftExpression(ast); |
|
3924 tmp->setRightExpression(rightExpr); |
|
3925 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
3926 ast = tmp; |
|
3927 } |
|
3928 |
|
3929 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3930 node = ast; |
|
3931 return true; |
|
3932 } |
|
3933 |
|
3934 bool Parser::parseAndExpression(AbstractExpressionAST *&node, bool templArgs) |
|
3935 { |
|
3936 int start = tokenStream->cursor(); |
|
3937 |
|
3938 AbstractExpressionAST *ast = 0; |
|
3939 if (!parseEqualityExpression(ast, templArgs)) |
|
3940 return false; |
|
3941 |
|
3942 while (tokenStream->lookAhead() == '&') { |
|
3943 int startOp = tokenStream->cursor(); |
|
3944 AST_FROM_TOKEN(op, startOp); |
|
3945 advance(); |
|
3946 |
|
3947 AbstractExpressionAST *rightExpr = 0; |
|
3948 if (!parseEqualityExpression(rightExpr, templArgs)) |
|
3949 return false; |
|
3950 |
|
3951 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
3952 tmp->setOp(op); |
|
3953 tmp->setLeftExpression(ast); |
|
3954 tmp->setRightExpression(rightExpr); |
|
3955 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
3956 ast = tmp; |
|
3957 } |
|
3958 |
|
3959 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3960 node = ast; |
|
3961 return true; |
|
3962 } |
|
3963 |
|
3964 bool Parser::parseExclusiveOrExpression(AbstractExpressionAST *&node, bool templArgs) |
|
3965 { |
|
3966 int start = tokenStream->cursor(); |
|
3967 |
|
3968 AbstractExpressionAST *ast = 0; |
|
3969 if (!parseAndExpression(ast, templArgs)) |
|
3970 return false; |
|
3971 |
|
3972 while (tokenStream->lookAhead() == '^') { |
|
3973 int startOp = tokenStream->cursor(); |
|
3974 AST_FROM_TOKEN(op, startOp); |
|
3975 advance(); |
|
3976 |
|
3977 AbstractExpressionAST *rightExpr = 0; |
|
3978 if (!parseAndExpression(rightExpr, templArgs)) |
|
3979 return false; |
|
3980 |
|
3981 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
3982 tmp->setOp(op); |
|
3983 tmp->setLeftExpression(ast); |
|
3984 tmp->setRightExpression(rightExpr); |
|
3985 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
3986 ast = tmp; |
|
3987 } |
|
3988 |
|
3989 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
3990 node = ast; |
|
3991 return true; |
|
3992 } |
|
3993 |
|
3994 bool Parser::parseInclusiveOrExpression(AbstractExpressionAST *&node, bool templArgs) |
|
3995 { |
|
3996 int start = tokenStream->cursor(); |
|
3997 |
|
3998 AbstractExpressionAST *ast = 0; |
|
3999 if (!parseExclusiveOrExpression(ast, templArgs)) |
|
4000 return false; |
|
4001 |
|
4002 while (tokenStream->lookAhead() == '|') { |
|
4003 int startOp = tokenStream->cursor(); |
|
4004 AST_FROM_TOKEN(op, startOp); |
|
4005 advance(); |
|
4006 |
|
4007 AbstractExpressionAST *rightExpr = 0; |
|
4008 if (!parseExclusiveOrExpression(rightExpr, templArgs)) |
|
4009 return false; |
|
4010 |
|
4011 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
4012 tmp->setOp(op); |
|
4013 tmp->setLeftExpression(ast); |
|
4014 tmp->setRightExpression(rightExpr); |
|
4015 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
4016 ast = tmp; |
|
4017 } |
|
4018 |
|
4019 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
4020 node = ast; |
|
4021 return true; |
|
4022 } |
|
4023 |
|
4024 bool Parser::parseLogicalAndExpression(AbstractExpressionAST *&node, bool templArgs) |
|
4025 { |
|
4026 int start = tokenStream->cursor(); |
|
4027 |
|
4028 AbstractExpressionAST *ast = 0; |
|
4029 if (!parseInclusiveOrExpression(ast, templArgs)) |
|
4030 return false; |
|
4031 |
|
4032 while (tokenStream->lookAhead() == Token_and) { |
|
4033 int startOp = tokenStream->cursor(); |
|
4034 AST_FROM_TOKEN(op, startOp); |
|
4035 advance(); |
|
4036 |
|
4037 AbstractExpressionAST *rightExpr = 0; |
|
4038 if (!parseInclusiveOrExpression(rightExpr, templArgs)) |
|
4039 return false; |
|
4040 |
|
4041 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
4042 tmp->setOp(op); |
|
4043 tmp->setLeftExpression(ast); |
|
4044 tmp->setRightExpression(rightExpr); |
|
4045 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
4046 ast = tmp; |
|
4047 } |
|
4048 |
|
4049 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
4050 node = ast; |
|
4051 return true; |
|
4052 } |
|
4053 |
|
4054 bool Parser::parseLogicalOrExpression(AbstractExpressionAST *&node, bool templArgs) |
|
4055 { |
|
4056 int start = tokenStream->cursor(); |
|
4057 |
|
4058 AbstractExpressionAST *ast = 0; |
|
4059 if (!parseLogicalAndExpression(ast, templArgs)) |
|
4060 return false; |
|
4061 |
|
4062 while (tokenStream->lookAhead() == Token_or) { |
|
4063 int startOp = tokenStream->cursor(); |
|
4064 AST_FROM_TOKEN(op, startOp); |
|
4065 advance(); |
|
4066 |
|
4067 AbstractExpressionAST *rightExpr = 0; |
|
4068 if (!parseLogicalAndExpression(rightExpr, templArgs)) |
|
4069 return false; |
|
4070 |
|
4071 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
4072 tmp->setOp(op); |
|
4073 tmp->setLeftExpression(ast); |
|
4074 tmp->setRightExpression(rightExpr); |
|
4075 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
4076 ast = tmp; |
|
4077 } |
|
4078 |
|
4079 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
4080 node = ast; |
|
4081 return true; |
|
4082 } |
|
4083 |
|
4084 bool Parser::parseConditionalExpression(AbstractExpressionAST *&node) |
|
4085 { |
|
4086 int start = tokenStream->cursor(); |
|
4087 AbstractExpressionAST *ast = 0; |
|
4088 if (!parseLogicalOrExpression(ast)) |
|
4089 return false; |
|
4090 |
|
4091 if (tokenStream->lookAhead() == '?') { |
|
4092 advance(); |
|
4093 |
|
4094 AbstractExpressionAST *leftExpr = 0; |
|
4095 if (!parseExpression(leftExpr)) |
|
4096 return false; |
|
4097 |
|
4098 CHECK(':', ":"); |
|
4099 |
|
4100 AbstractExpressionAST *rightExpr = 0; |
|
4101 if (!parseAssignmentExpression(rightExpr)) |
|
4102 return false; |
|
4103 |
|
4104 ConditionalExpressionAST *tmp = CreateNode<ConditionalExpressionAST>(m_pool); |
|
4105 tmp->setCondition(ast); |
|
4106 tmp->setLeftExpression(leftExpr); |
|
4107 tmp->setRightExpression(rightExpr); |
|
4108 ast = tmp; |
|
4109 } |
|
4110 |
|
4111 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
4112 node = ast; |
|
4113 return true; |
|
4114 } |
|
4115 |
|
4116 bool Parser::parseAssignmentExpression(AbstractExpressionAST *&node) |
|
4117 { |
|
4118 int start = tokenStream->cursor(); |
|
4119 |
|
4120 AbstractExpressionAST *ast = 0; |
|
4121 if (tokenStream->lookAhead() == Token_throw && !parseThrowExpression(ast)) |
|
4122 return false; |
|
4123 else if (!parseConditionalExpression(ast)) |
|
4124 return false; |
|
4125 |
|
4126 while (tokenStream->lookAhead() == Token_assign || tokenStream->lookAhead() == '=') { |
|
4127 int startOp = tokenStream->cursor(); |
|
4128 AST_FROM_TOKEN(op, startOp); |
|
4129 advance(); |
|
4130 |
|
4131 AbstractExpressionAST *rightExpr = 0; |
|
4132 if (!parseConditionalExpression(rightExpr)) |
|
4133 return false; |
|
4134 |
|
4135 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
4136 tmp->setOp(op); |
|
4137 tmp->setLeftExpression(ast); |
|
4138 tmp->setRightExpression(rightExpr); |
|
4139 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
4140 ast = tmp; |
|
4141 } |
|
4142 |
|
4143 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
4144 node = ast; |
|
4145 return true; |
|
4146 } |
|
4147 |
|
4148 bool Parser::parseConstantExpression(AbstractExpressionAST *&node) |
|
4149 { |
|
4150 return parseConditionalExpression(node); |
|
4151 } |
|
4152 |
|
4153 bool Parser::parseExpression(AbstractExpressionAST *&node) |
|
4154 { |
|
4155 return parseCommaExpression(node); |
|
4156 } |
|
4157 |
|
4158 bool Parser::parseCommaExpression(AbstractExpressionAST *&node) |
|
4159 { |
|
4160 int start = tokenStream->cursor(); |
|
4161 |
|
4162 AbstractExpressionAST *ast = 0; |
|
4163 if (!parseAssignmentExpression(ast)) |
|
4164 return false; |
|
4165 |
|
4166 while (tokenStream->lookAhead() == ',') { |
|
4167 int startOp = tokenStream->cursor(); |
|
4168 AST_FROM_TOKEN(op, startOp); |
|
4169 advance(); |
|
4170 |
|
4171 AbstractExpressionAST *rightExpr = 0; |
|
4172 if (!parseAssignmentExpression(rightExpr)) |
|
4173 return false; |
|
4174 |
|
4175 BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool); |
|
4176 tmp->setOp(op); |
|
4177 tmp->setLeftExpression(ast); |
|
4178 tmp->setRightExpression(rightExpr); |
|
4179 UPDATE_POS(tmp, startOp, tokenStream->cursor()); |
|
4180 ast = tmp; |
|
4181 } |
|
4182 |
|
4183 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
4184 node = ast; |
|
4185 return true; |
|
4186 } |
|
4187 |
|
4188 bool Parser::parseThrowExpression(AbstractExpressionAST *&node) |
|
4189 { |
|
4190 if (tokenStream->lookAhead() != Token_throw) |
|
4191 return false; |
|
4192 |
|
4193 int start = tokenStream->cursor(); |
|
4194 |
|
4195 AST_FROM_TOKEN(throwNode, tokenStream->cursor()); |
|
4196 CHECK(Token_throw, "throw"); |
|
4197 AbstractExpressionAST *expr = 0; |
|
4198 if (!parseAssignmentExpression(expr)) |
|
4199 return false; |
|
4200 |
|
4201 AbstractExpressionAST *ast = CreateExpression<NodeType_ThrowExpression>(m_pool); |
|
4202 throwNode->setParent(ast); |
|
4203 if (expr) |
|
4204 expr->setParent(ast); |
|
4205 |
|
4206 UPDATE_POS(ast, start, tokenStream->cursor()); |
|
4207 node = ast; |
|
4208 |
|
4209 return true; |
|
4210 } |
|
4211 |
|
4212 |
|
4213 // ### Objective C++ |
|
4214 bool Parser::parseIvarDeclList(AST *& node) |
|
4215 { |
|
4216 Q_UNUSED(node); |
|
4217 return false; |
|
4218 } |
|
4219 |
|
4220 bool Parser::parseIvarDecls(AST *& node) |
|
4221 { |
|
4222 Q_UNUSED(node); |
|
4223 return false; |
|
4224 } |
|
4225 |
|
4226 bool Parser::parseIvarDecl(AST *& node) |
|
4227 { |
|
4228 Q_UNUSED(node); |
|
4229 return false; |
|
4230 } |
|
4231 |
|
4232 bool Parser::parseIvars(AST *& node) |
|
4233 { |
|
4234 Q_UNUSED(node); |
|
4235 return false; |
|
4236 } |
|
4237 |
|
4238 bool Parser::parseIvarDeclarator(AST *& node) |
|
4239 { |
|
4240 Q_UNUSED(node); |
|
4241 return false; |
|
4242 } |
|
4243 |
|
4244 bool Parser::parseMethodDecl(AST *& node) |
|
4245 { |
|
4246 Q_UNUSED(node); |
|
4247 return false; |
|
4248 } |
|
4249 |
|
4250 bool Parser::parseUnarySelector(AST *& node) |
|
4251 { |
|
4252 Q_UNUSED(node); |
|
4253 return false; |
|
4254 } |
|
4255 |
|
4256 bool Parser::parseKeywordSelector(AST *& node) |
|
4257 { |
|
4258 Q_UNUSED(node); |
|
4259 return false; |
|
4260 } |
|
4261 |
|
4262 bool Parser::parseSelector(AST *& node) |
|
4263 { |
|
4264 Q_UNUSED(node); |
|
4265 return false; |
|
4266 } |
|
4267 |
|
4268 bool Parser::parseKeywordDecl(AST *& node) |
|
4269 { |
|
4270 Q_UNUSED(node); |
|
4271 return false; |
|
4272 } |
|
4273 |
|
4274 bool Parser::parseReceiver(AST *& node) |
|
4275 { |
|
4276 Q_UNUSED(node); |
|
4277 return false; |
|
4278 } |
|
4279 |
|
4280 bool Parser::parseObjcMessageExpr(AST *& node) |
|
4281 { |
|
4282 Q_UNUSED(node); |
|
4283 return false; |
|
4284 } |
|
4285 |
|
4286 bool Parser::parseMessageArgs(AST *& node) |
|
4287 { |
|
4288 Q_UNUSED(node); |
|
4289 return false; |
|
4290 } |
|
4291 |
|
4292 bool Parser::parseKeywordExpr(AST *& node) |
|
4293 { |
|
4294 Q_UNUSED(node); |
|
4295 return false; |
|
4296 } |
|
4297 |
|
4298 bool Parser::parseKeywordArgList(AST *& node) |
|
4299 { |
|
4300 Q_UNUSED(node); |
|
4301 return false; |
|
4302 } |
|
4303 |
|
4304 bool Parser::parseKeywordArg(AST *& node) |
|
4305 { |
|
4306 Q_UNUSED(node); |
|
4307 return false; |
|
4308 } |
|
4309 |
|
4310 bool Parser::parseReservedWord(AST *& node) |
|
4311 { |
|
4312 Q_UNUSED(node); |
|
4313 return false; |
|
4314 } |
|
4315 |
|
4316 bool Parser::parseMyParms(AST *& node) |
|
4317 { |
|
4318 Q_UNUSED(node); |
|
4319 return false; |
|
4320 } |
|
4321 |
|
4322 bool Parser::parseMyParm(AST *& node) |
|
4323 { |
|
4324 Q_UNUSED(node); |
|
4325 return false; |
|
4326 } |
|
4327 |
|
4328 bool Parser::parseOptParmList(AST *& node) |
|
4329 { |
|
4330 Q_UNUSED(node); |
|
4331 return false; |
|
4332 } |
|
4333 |
|
4334 bool Parser::parseObjcSelectorExpr(AST *& node) |
|
4335 { |
|
4336 Q_UNUSED(node); |
|
4337 return false; |
|
4338 } |
|
4339 |
|
4340 bool Parser::parseSelectorArg(AST *& node) |
|
4341 { |
|
4342 Q_UNUSED(node); |
|
4343 return false; |
|
4344 } |
|
4345 |
|
4346 bool Parser::parseKeywordNameList(AST *& node) |
|
4347 { |
|
4348 Q_UNUSED(node); |
|
4349 return false; |
|
4350 } |
|
4351 |
|
4352 bool Parser::parseKeywordName(AST *& node) |
|
4353 { |
|
4354 Q_UNUSED(node); |
|
4355 return false; |
|
4356 } |
|
4357 |
|
4358 bool Parser::parseObjcEncodeExpr(AST *& node) |
|
4359 { |
|
4360 Q_UNUSED(node); |
|
4361 return false; |
|
4362 } |
|
4363 |
|
4364 bool Parser::parseObjcString(AST *& node) |
|
4365 { |
|
4366 Q_UNUSED(node); |
|
4367 return false; |
|
4368 } |
|
4369 |
|
4370 bool Parser::parseProtocolRefs(AST *& node) |
|
4371 { |
|
4372 Q_UNUSED(node); |
|
4373 return false; |
|
4374 } |
|
4375 |
|
4376 bool Parser::parseIdentifierList(AST *& node) |
|
4377 { |
|
4378 int start = tokenStream->cursor(); |
|
4379 |
|
4380 if (tokenStream->lookAhead() != Token_identifier) |
|
4381 return false; |
|
4382 |
|
4383 AST *ast = CreateNode<AST>(m_pool); |
|
4384 |
|
4385 AST_FROM_TOKEN(tk, tokenStream->cursor()); |
|
4386 tk->setParent(ast); |
|
4387 advance(); |
|
4388 |
|
4389 while (tokenStream->lookAhead() == ',') { |
|
4390 advance(); |
|
4391 if (tokenStream->lookAhead() == Token_identifier) { |
|
4392 AST_FROM_TOKEN(tk, tokenStream->cursor()); |
|
4393 tk->setParent(ast); |
|
4394 advance(); |
|
4395 } |
|
4396 ADVANCE(Token_identifier, "identifier"); |
|
4397 } |
|
4398 |
|
4399 node = ast; |
|
4400 UPDATE_POS(node, start, tokenStream->cursor()); |
|
4401 return true; |
|
4402 } |
|
4403 |
|
4404 bool Parser::parseIdentifierColon(AST *& node) |
|
4405 { |
|
4406 Q_UNUSED(node); |
|
4407 |
|
4408 if (tokenStream->lookAhead() == Token_identifier && tokenStream->lookAhead(1) == ':') { |
|
4409 advance(); |
|
4410 advance(); |
|
4411 return true; |
|
4412 } // ### else if PTYPENAME -> return true ; |
|
4413 |
|
4414 return false; |
|
4415 } |
|
4416 |
|
4417 bool Parser::parseObjcProtocolExpr(AST *& node) |
|
4418 { |
|
4419 Q_UNUSED(node); |
|
4420 return false; |
|
4421 } |
|
4422 |
|
4423 bool Parser::parseObjcOpenBracketExpr(AST *& node) |
|
4424 { |
|
4425 Q_UNUSED(node); |
|
4426 return false; |
|
4427 } |
|
4428 |
|
4429 bool Parser::parseObjcCloseBracket(AST *& node) |
|
4430 { |
|
4431 Q_UNUSED(node); |
|
4432 return false; |
|
4433 } |
|
4434 |
|
4435 bool Parser::parseObjcDef(DeclarationAST *& node) |
|
4436 { |
|
4437 Q_UNUSED(node); |
|
4438 return false; |
|
4439 } |
|
4440 |
|
4441 bool Parser::parseObjcClassDef(DeclarationAST *& node) |
|
4442 { |
|
4443 Q_UNUSED(node); |
|
4444 return false; |
|
4445 } |
|
4446 |
|
4447 bool Parser::parseObjcClassDecl(DeclarationAST *& node) |
|
4448 { |
|
4449 Q_UNUSED(node); |
|
4450 |
|
4451 ADVANCE(OBJC_CLASS, "@class"); |
|
4452 |
|
4453 AST *idList = 0; |
|
4454 parseIdentifierList(idList); |
|
4455 ADVANCE(';', ";"); |
|
4456 |
|
4457 return true; |
|
4458 } |
|
4459 |
|
4460 bool Parser::parseObjcProtocolDecl(DeclarationAST *& node) |
|
4461 { |
|
4462 Q_UNUSED(node); |
|
4463 |
|
4464 ADVANCE(OBJC_PROTOCOL, "@protocol"); |
|
4465 |
|
4466 AST *idList = 0; |
|
4467 parseIdentifierList(idList); |
|
4468 ADVANCE(';', ";"); |
|
4469 |
|
4470 return true; |
|
4471 } |
|
4472 |
|
4473 bool Parser::parseObjcAliasDecl(DeclarationAST *& node) |
|
4474 { |
|
4475 Q_UNUSED(node); |
|
4476 |
|
4477 ADVANCE(OBJC_ALIAS, "@alias"); |
|
4478 |
|
4479 AST *idList = 0; |
|
4480 parseIdentifierList(idList); |
|
4481 ADVANCE(';', ";"); |
|
4482 |
|
4483 return true; |
|
4484 } |
|
4485 |
|
4486 bool Parser::parseObjcProtocolDef(DeclarationAST *& node) |
|
4487 { |
|
4488 Q_UNUSED(node); |
|
4489 return false; |
|
4490 } |
|
4491 |
|
4492 bool Parser::parseObjcMethodDef(DeclarationAST *& node) |
|
4493 { |
|
4494 Q_UNUSED(node); |
|
4495 return false; |
|
4496 } |
|
4497 |
|
4498 bool Parser::parseWinDeclSpec(AST *& node) |
|
4499 { |
|
4500 if (tokenStream->lookAhead() == Token_identifier |
|
4501 && tokenStream->lookAhead(1) == '(' |
|
4502 && tokenStream->currentTokenText() == "__declspec") { |
|
4503 int start = tokenStream->cursor(); |
|
4504 advance(); |
|
4505 advance(); // skip '(' |
|
4506 |
|
4507 parseIdentifierList(node); |
|
4508 ADVANCE(')', ")"); |
|
4509 |
|
4510 UPDATE_POS(node, start, tokenStream->cursor()); |
|
4511 return true; |
|
4512 } |
|
4513 |
|
4514 return false; |
|
4515 } |
|
4516 |
|
4517 void Parser::advance() |
|
4518 { |
|
4519 for (;;) { |
|
4520 tokenStream->nextToken(); |
|
4521 if (!tokenStream->isHidden(tokenStream->cursor())) |
|
4522 break; |
|
4523 } |
|
4524 } |
|
4525 |
|
4526 QT_END_NAMESPACE |