|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 // Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com> |
|
42 // |
|
43 // Permission is hereby granted, free of charge, to any person obtaining a copy |
|
44 // of this software and associated documentation files (the "Software"), to deal |
|
45 // in the Software without restriction, including without limitation the rights |
|
46 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
47 // copies of the Software, and to permit persons to whom the Software is |
|
48 // furnished to do so, subject to the following conditions: |
|
49 // |
|
50 // The above copyright notice and this permission notice shall be included in |
|
51 // all copies or substantial portions of the Software. |
|
52 // |
|
53 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
54 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
55 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
56 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
57 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
58 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
59 // THE SOFTWARE. |
|
60 |
|
61 #include "Parser.h" |
|
62 #include "Token.h" |
|
63 #include "Lexer.h" |
|
64 #include "Control.h" |
|
65 #include "AST.h" |
|
66 #include "Literals.h" |
|
67 #include "ObjectiveCTypeQualifiers.h" |
|
68 #include <cstdio> // for putchar |
|
69 #ifdef ICHECK_BUILD |
|
70 # include <QString> |
|
71 #endif |
|
72 |
|
73 #define CPLUSPLUS_NO_DEBUG_RULE |
|
74 #define MAX_EXPRESSION_DEPTH 100 |
|
75 |
|
76 using namespace CPlusPlus; |
|
77 |
|
78 namespace { |
|
79 |
|
80 class DebugRule { |
|
81 const char *name; |
|
82 static int depth; |
|
83 |
|
84 public: |
|
85 DebugRule(const char *name) |
|
86 : name(name) |
|
87 { |
|
88 for (int i = 0; i < depth; ++i) |
|
89 putchar(' '); |
|
90 |
|
91 ++depth; |
|
92 printf("%s\n", name); |
|
93 } |
|
94 |
|
95 ~DebugRule() |
|
96 { --depth; } |
|
97 }; |
|
98 |
|
99 int DebugRule::depth = 0; |
|
100 |
|
101 inline bool lookAtAssignmentOperator(int tokenKind) |
|
102 { |
|
103 switch (tokenKind) { |
|
104 case T_EQUAL: |
|
105 case T_AMPER_EQUAL: |
|
106 case T_CARET_EQUAL: |
|
107 case T_SLASH_EQUAL: |
|
108 case T_GREATER_GREATER_EQUAL: |
|
109 case T_LESS_LESS_EQUAL: |
|
110 case T_MINUS_EQUAL: |
|
111 case T_PERCENT_EQUAL: |
|
112 case T_PIPE_EQUAL: |
|
113 case T_PLUS_EQUAL: |
|
114 case T_STAR_EQUAL: |
|
115 case T_TILDE_EQUAL: |
|
116 return true; |
|
117 default: |
|
118 return false; |
|
119 } // switch |
|
120 } |
|
121 |
|
122 namespace Prec { |
|
123 enum { |
|
124 Unknown = 0, |
|
125 Comma = 1, |
|
126 Assignment = 2, |
|
127 Conditional = 3, |
|
128 LogicalOr = 4, |
|
129 LogicalAnd = 5, |
|
130 InclusiveOr = 6, |
|
131 ExclusiveOr = 7, |
|
132 And = 8, |
|
133 Equality = 9, |
|
134 Relational = 10, |
|
135 Shift = 11, |
|
136 Additive = 12, |
|
137 Multiplicative = 13, |
|
138 PointerToMember = 14 |
|
139 }; |
|
140 } // end of namespace Precedece |
|
141 |
|
142 inline int precedence(int tokenKind, bool templateArguments) |
|
143 { |
|
144 // ### this will/might need some tuning for C++0x |
|
145 // (see: [temp.names]p3) |
|
146 if (templateArguments && tokenKind == T_GREATER) |
|
147 return -1; |
|
148 |
|
149 if (lookAtAssignmentOperator(tokenKind)) |
|
150 return Prec::Assignment; |
|
151 |
|
152 switch (tokenKind) { |
|
153 case T_COMMA: return Prec::Comma; |
|
154 case T_QUESTION: return Prec::Conditional; |
|
155 case T_PIPE_PIPE: return Prec::LogicalOr; |
|
156 case T_AMPER_AMPER: return Prec::LogicalAnd; |
|
157 case T_PIPE: return Prec::InclusiveOr; |
|
158 case T_CARET: return Prec::ExclusiveOr; |
|
159 case T_AMPER: return Prec::And; |
|
160 case T_EQUAL_EQUAL: |
|
161 case T_EXCLAIM_EQUAL: return Prec::Equality; |
|
162 case T_GREATER: |
|
163 case T_LESS: |
|
164 case T_LESS_EQUAL: |
|
165 case T_GREATER_EQUAL: return Prec::Relational; |
|
166 case T_LESS_LESS: |
|
167 case T_GREATER_GREATER: return Prec::ExclusiveOr; |
|
168 case T_PLUS: |
|
169 case T_MINUS: return Prec::Additive; |
|
170 case T_STAR: |
|
171 case T_SLASH: |
|
172 case T_PERCENT: return Prec::Multiplicative; |
|
173 case T_ARROW_STAR: |
|
174 case T_DOT_STAR: return Prec::PointerToMember; |
|
175 default: return Prec::Unknown; |
|
176 } |
|
177 } |
|
178 |
|
179 inline bool isBinaryOperator(int tokenKind) |
|
180 { return precedence(tokenKind, false) != Prec::Unknown; } |
|
181 |
|
182 inline bool isRightAssociative(int tokenKind) |
|
183 { |
|
184 const int prec = precedence(tokenKind, false); |
|
185 return prec == Prec::Conditional || prec == Prec::Assignment; |
|
186 } |
|
187 |
|
188 } // end of anonymous namespace |
|
189 |
|
190 #ifndef CPLUSPLUS_NO_DEBUG_RULE |
|
191 # define DEBUG_THIS_RULE() DebugRule __debug_rule__(__func__) |
|
192 #else |
|
193 # define DEBUG_THIS_RULE() do {} while (0) |
|
194 #endif |
|
195 |
|
196 #define PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, minPrecedence) { \ |
|
197 if (LA() == T_THROW) { \ |
|
198 if (!parseThrowExpression(node)) \ |
|
199 return false; \ |
|
200 } else if (!parseCastExpression(node)) \ |
|
201 return false; \ |
|
202 \ |
|
203 parseExpressionWithOperatorPrecedence(node, minPrecedence); \ |
|
204 return true; \ |
|
205 } |
|
206 |
|
207 class Parser::Rewind |
|
208 { |
|
209 Parser *_parser; |
|
210 MemoryPool::State _state; |
|
211 |
|
212 public: |
|
213 inline Rewind(Parser *parser) |
|
214 : _parser(parser) {} |
|
215 |
|
216 inline void operator()(unsigned tokenIndex) |
|
217 { rewind(tokenIndex); } |
|
218 |
|
219 inline void mark() |
|
220 { _state = _parser->_pool->state(); } |
|
221 |
|
222 inline void rewind(unsigned tokenIndex) |
|
223 { |
|
224 _parser->rewind(tokenIndex); |
|
225 |
|
226 if (_state.isValid()) |
|
227 _parser->_pool->rewind(_state); |
|
228 } |
|
229 }; |
|
230 |
|
231 Parser::Parser(TranslationUnit *unit) |
|
232 : _translationUnit(unit), |
|
233 _control(_translationUnit->control()), |
|
234 _pool(_translationUnit->memoryPool()), |
|
235 _tokenIndex(1), |
|
236 _templateArguments(0), |
|
237 _qtMocRunEnabled(false), |
|
238 _objCEnabled(false), |
|
239 _inFunctionBody(false), |
|
240 _inObjCImplementationContext(false), |
|
241 _expressionDepth(0) |
|
242 { } |
|
243 |
|
244 Parser::~Parser() |
|
245 { } |
|
246 |
|
247 bool Parser::qtMocRunEnabled() const |
|
248 { return _qtMocRunEnabled; } |
|
249 |
|
250 void Parser::setQtMocRunEnabled(bool onoff) |
|
251 { _qtMocRunEnabled = onoff; } |
|
252 |
|
253 bool Parser::objCEnabled() const |
|
254 { return _objCEnabled; } |
|
255 |
|
256 void Parser::setObjCEnabled(bool onoff) |
|
257 { _objCEnabled = onoff; } |
|
258 |
|
259 bool Parser::switchTemplateArguments(bool templateArguments) |
|
260 { |
|
261 bool previousTemplateArguments = _templateArguments; |
|
262 _templateArguments = templateArguments; |
|
263 return previousTemplateArguments; |
|
264 } |
|
265 |
|
266 bool Parser::blockErrors(bool block) |
|
267 { return _translationUnit->blockErrors(block); } |
|
268 |
|
269 bool Parser::skipUntil(int token) |
|
270 { |
|
271 while (int tk = LA()) { |
|
272 if (tk == token) |
|
273 return true; |
|
274 |
|
275 consumeToken(); |
|
276 } |
|
277 |
|
278 return false; |
|
279 } |
|
280 |
|
281 void Parser::skipUntilDeclaration() |
|
282 { |
|
283 for (; ; consumeToken()) { |
|
284 switch (LA()) { |
|
285 case T_EOF_SYMBOL: |
|
286 |
|
287 // names |
|
288 case T_IDENTIFIER: |
|
289 case T_COLON_COLON: |
|
290 case T_TILDE: |
|
291 case T_OPERATOR: |
|
292 |
|
293 // empty declaration |
|
294 case T_SEMICOLON: |
|
295 |
|
296 // member specification |
|
297 case T_USING: |
|
298 case T_TEMPLATE: |
|
299 case T_PUBLIC: |
|
300 case T_PROTECTED: |
|
301 case T_PRIVATE: |
|
302 case T_Q_SIGNALS: |
|
303 case T_Q_SLOTS: |
|
304 |
|
305 // declarations |
|
306 case T_ENUM: |
|
307 case T_NAMESPACE: |
|
308 case T_ASM: |
|
309 case T_EXPORT: |
|
310 case T_AT_CLASS: |
|
311 case T_AT_INTERFACE: |
|
312 case T_AT_PROTOCOL: |
|
313 case T_AT_IMPLEMENTATION: |
|
314 case T_AT_END: |
|
315 return; |
|
316 |
|
317 default: |
|
318 if (lookAtBuiltinTypeSpecifier() || lookAtClassKey() || |
|
319 lookAtFunctionSpecifier() || lookAtStorageClassSpecifier()) |
|
320 return; |
|
321 } // switch |
|
322 } |
|
323 } |
|
324 |
|
325 bool Parser::skipUntilStatement() |
|
326 { |
|
327 while (int tk = LA()) { |
|
328 switch (tk) { |
|
329 case T_SEMICOLON: |
|
330 case T_LBRACE: |
|
331 case T_RBRACE: |
|
332 case T_CONST: |
|
333 case T_VOLATILE: |
|
334 case T_IDENTIFIER: |
|
335 case T_CASE: |
|
336 case T_DEFAULT: |
|
337 case T_IF: |
|
338 case T_SWITCH: |
|
339 case T_WHILE: |
|
340 case T_DO: |
|
341 case T_FOR: |
|
342 case T_BREAK: |
|
343 case T_CONTINUE: |
|
344 case T_RETURN: |
|
345 case T_GOTO: |
|
346 case T_TRY: |
|
347 case T_CATCH: |
|
348 case T_THROW: |
|
349 case T_CHAR: |
|
350 case T_WCHAR_T: |
|
351 case T_BOOL: |
|
352 case T_SHORT: |
|
353 case T_INT: |
|
354 case T_LONG: |
|
355 case T_SIGNED: |
|
356 case T_UNSIGNED: |
|
357 case T_FLOAT: |
|
358 case T_DOUBLE: |
|
359 case T_VOID: |
|
360 case T_CLASS: |
|
361 case T_STRUCT: |
|
362 case T_UNION: |
|
363 case T_ENUM: |
|
364 case T_COLON_COLON: |
|
365 case T_TEMPLATE: |
|
366 case T_USING: |
|
367 return true; |
|
368 |
|
369 case T_AT_SYNCHRONIZED: |
|
370 if (objCEnabled()) |
|
371 return true; |
|
372 |
|
373 default: |
|
374 consumeToken(); |
|
375 } |
|
376 } |
|
377 |
|
378 return false; |
|
379 } |
|
380 |
|
381 bool Parser::skip(int l, int r) |
|
382 { |
|
383 int count = 0; |
|
384 |
|
385 while (int tk = LA()) { |
|
386 if (tk == l) |
|
387 ++count; |
|
388 else if (tk == r) |
|
389 --count; |
|
390 else if (l != T_LBRACE && (tk == T_LBRACE || |
|
391 tk == T_RBRACE || |
|
392 tk == T_SEMICOLON)) |
|
393 return false; |
|
394 |
|
395 if (count == 0) |
|
396 return true; |
|
397 |
|
398 consumeToken(); |
|
399 } |
|
400 |
|
401 return false; |
|
402 } |
|
403 |
|
404 void Parser::match(int kind, unsigned *token) |
|
405 { |
|
406 if (LA() == kind) |
|
407 *token = consumeToken(); |
|
408 else { |
|
409 *token = 0; |
|
410 _translationUnit->error(_tokenIndex, "expected token `%s' got `%s'", |
|
411 Token::name(kind), tok().spell()); |
|
412 } |
|
413 } |
|
414 |
|
415 bool Parser::parseClassOrNamespaceName(NameAST *&node) |
|
416 { |
|
417 DEBUG_THIS_RULE(); |
|
418 if (LA() == T_IDENTIFIER) { |
|
419 unsigned identifier_token = cursor(); |
|
420 |
|
421 if (LA(2) == T_LESS && parseTemplateId(node) && LA() == T_COLON_COLON) |
|
422 return true; |
|
423 |
|
424 rewind(identifier_token); |
|
425 |
|
426 if (LA(2) == T_COLON_COLON) { |
|
427 SimpleNameAST *ast = new (_pool) SimpleNameAST; |
|
428 ast->identifier_token = consumeToken(); |
|
429 node = ast; |
|
430 return true; |
|
431 } |
|
432 } else if (LA() == T_TEMPLATE) { |
|
433 unsigned template_token = consumeToken(); |
|
434 if (parseTemplateId(node)) |
|
435 return true; |
|
436 rewind(template_token); |
|
437 } |
|
438 return false; |
|
439 } |
|
440 |
|
441 bool Parser::parseTemplateId(NameAST *&node) |
|
442 { |
|
443 DEBUG_THIS_RULE(); |
|
444 |
|
445 const unsigned start = cursor(); |
|
446 |
|
447 if (LA() == T_IDENTIFIER && LA(2) == T_LESS) { |
|
448 TemplateIdAST *ast = new (_pool) TemplateIdAST; |
|
449 ast->identifier_token = consumeToken(); |
|
450 ast->less_token = consumeToken(); |
|
451 if (LA() == T_GREATER || parseTemplateArgumentList( |
|
452 ast->template_argument_list)) { |
|
453 if (LA() == T_GREATER) { |
|
454 ast->greater_token = consumeToken(); |
|
455 node = ast; |
|
456 return true; |
|
457 } |
|
458 } |
|
459 } |
|
460 |
|
461 rewind(start); |
|
462 |
|
463 return false; |
|
464 } |
|
465 |
|
466 bool Parser::parseNestedNameSpecifier(NestedNameSpecifierListAST *&node, |
|
467 bool /*acceptTemplateId*/) |
|
468 { |
|
469 DEBUG_THIS_RULE(); |
|
470 NestedNameSpecifierListAST **nested_name_specifier = &node; |
|
471 NameAST *class_or_namespace_name = 0; |
|
472 if (parseClassOrNamespaceName(class_or_namespace_name) && LA() == T_COLON_COLON) { |
|
473 unsigned scope_token = consumeToken(); |
|
474 |
|
475 NestedNameSpecifierAST *name = new (_pool) NestedNameSpecifierAST; |
|
476 name->class_or_namespace_name = class_or_namespace_name; |
|
477 name->scope_token = scope_token; |
|
478 |
|
479 *nested_name_specifier = new (_pool) NestedNameSpecifierListAST(name); |
|
480 nested_name_specifier = &(*nested_name_specifier)->next; |
|
481 |
|
482 while (parseClassOrNamespaceName(class_or_namespace_name) && LA() == T_COLON_COLON) { |
|
483 scope_token = consumeToken(); |
|
484 |
|
485 name = new (_pool) NestedNameSpecifierAST; |
|
486 name->class_or_namespace_name = class_or_namespace_name; |
|
487 name->scope_token = scope_token; |
|
488 |
|
489 *nested_name_specifier = new (_pool) NestedNameSpecifierListAST(name); |
|
490 nested_name_specifier = &(*nested_name_specifier)->next; |
|
491 } |
|
492 |
|
493 // ### ugly hack |
|
494 rewind(scope_token); |
|
495 consumeToken(); |
|
496 return true; |
|
497 } |
|
498 |
|
499 return false; |
|
500 } |
|
501 |
|
502 bool Parser::parseNestedNameSpecifierOpt(NestedNameSpecifierListAST *&name, bool acceptTemplateId) |
|
503 { |
|
504 DEBUG_THIS_RULE(); |
|
505 unsigned start = cursor(); |
|
506 if (! parseNestedNameSpecifier(name, acceptTemplateId)) |
|
507 rewind(start); |
|
508 return true; |
|
509 } |
|
510 |
|
511 bool Parser::parseName(NameAST *&node, bool acceptTemplateId) |
|
512 { |
|
513 DEBUG_THIS_RULE(); |
|
514 unsigned global_scope_token = 0; |
|
515 if (LA() == T_COLON_COLON) |
|
516 global_scope_token = consumeToken(); |
|
517 |
|
518 NestedNameSpecifierListAST *nested_name_specifier = 0; |
|
519 parseNestedNameSpecifierOpt(nested_name_specifier, |
|
520 /*acceptTemplateId=*/ true); |
|
521 |
|
522 NameAST *unqualified_name = 0; |
|
523 if (parseUnqualifiedName(unqualified_name, |
|
524 /*acceptTemplateId=*/ acceptTemplateId || nested_name_specifier != 0)) { |
|
525 if (! global_scope_token && ! nested_name_specifier) { |
|
526 node = unqualified_name; |
|
527 return true; |
|
528 } |
|
529 |
|
530 QualifiedNameAST *ast = new (_pool) QualifiedNameAST; |
|
531 ast->global_scope_token = global_scope_token; |
|
532 ast->nested_name_specifier_list = nested_name_specifier; |
|
533 ast->unqualified_name = unqualified_name; |
|
534 node = ast; |
|
535 return true; |
|
536 } |
|
537 |
|
538 return false; |
|
539 } |
|
540 |
|
541 bool Parser::parseTranslationUnit(TranslationUnitAST *&node) |
|
542 { |
|
543 DEBUG_THIS_RULE(); |
|
544 TranslationUnitAST *ast = new (_pool) TranslationUnitAST; |
|
545 DeclarationListAST **decl = &ast->declaration_list; |
|
546 |
|
547 while (LA()) { |
|
548 unsigned start_declaration = cursor(); |
|
549 |
|
550 DeclarationAST *declaration = 0; |
|
551 |
|
552 if (parseDeclaration(declaration)) { |
|
553 *decl = new (_pool) DeclarationListAST; |
|
554 (*decl)->value = declaration; |
|
555 decl = &(*decl)->next; |
|
556 } else { |
|
557 _translationUnit->error(start_declaration, "expected a declaration"); |
|
558 rewind(start_declaration + 1); |
|
559 skipUntilDeclaration(); |
|
560 } |
|
561 |
|
562 _templateArgumentList.clear(); |
|
563 } |
|
564 |
|
565 node = ast; |
|
566 return true; |
|
567 } |
|
568 |
|
569 bool Parser::parseEmptyDeclaration(DeclarationAST *&node) |
|
570 { |
|
571 DEBUG_THIS_RULE(); |
|
572 if (LA() == T_SEMICOLON) { |
|
573 EmptyDeclarationAST *ast = new (_pool) EmptyDeclarationAST; |
|
574 ast->semicolon_token = consumeToken(); |
|
575 node = ast; |
|
576 return true; |
|
577 } |
|
578 return false; |
|
579 } |
|
580 |
|
581 bool Parser::parseDeclaration(DeclarationAST *&node) |
|
582 { |
|
583 DEBUG_THIS_RULE(); |
|
584 switch (LA()) { |
|
585 case T_SEMICOLON: |
|
586 return parseEmptyDeclaration(node); |
|
587 |
|
588 case T_NAMESPACE: |
|
589 return parseNamespace(node); |
|
590 |
|
591 case T_USING: |
|
592 return parseUsing(node); |
|
593 |
|
594 case T_ASM: |
|
595 return parseAsmDefinition(node); |
|
596 |
|
597 case T_TEMPLATE: |
|
598 case T_EXPORT: |
|
599 return parseTemplateDeclaration(node); |
|
600 |
|
601 // ObjcC++ |
|
602 case T_AT_CLASS: |
|
603 return parseObjCClassForwardDeclaration(node); |
|
604 |
|
605 case T_AT_INTERFACE: |
|
606 return parseObjCInterface(node); |
|
607 |
|
608 case T_AT_PROTOCOL: |
|
609 return parseObjCProtocol(node); |
|
610 |
|
611 case T_AT_IMPLEMENTATION: |
|
612 return parseObjCImplementation(node); |
|
613 |
|
614 case T_AT_END: |
|
615 // TODO: should this be done here, or higher-up? |
|
616 _translationUnit->error(cursor(), "skip stray token `%s'", tok().spell()); |
|
617 consumeToken(); |
|
618 break; |
|
619 |
|
620 default: { |
|
621 if (_objCEnabled && LA() == T___ATTRIBUTE__) { |
|
622 const unsigned start = cursor(); |
|
623 SpecifierListAST *attributes = 0, **attr = &attributes; |
|
624 while (parseAttributeSpecifier(*attr)) |
|
625 attr = &(*attr)->next; |
|
626 if (LA() == T_AT_INTERFACE) |
|
627 return parseObjCInterface(node, attributes); |
|
628 else if (LA() == T_AT_PROTOCOL) |
|
629 return parseObjCProtocol(node, attributes); |
|
630 else if (LA() == T_AT_PROPERTY) |
|
631 return parseObjCPropertyDeclaration(node, attributes); |
|
632 rewind(start); |
|
633 } |
|
634 |
|
635 if (LA() == T_EXTERN && LA(2) == T_TEMPLATE) |
|
636 return parseTemplateDeclaration(node); |
|
637 else if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) |
|
638 return parseLinkageSpecification(node); |
|
639 else |
|
640 return parseSimpleDeclaration(node); |
|
641 } break; // default |
|
642 |
|
643 } // end switch |
|
644 |
|
645 return false; |
|
646 } |
|
647 |
|
648 bool Parser::parseLinkageSpecification(DeclarationAST *&node) |
|
649 { |
|
650 DEBUG_THIS_RULE(); |
|
651 if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) { |
|
652 LinkageSpecificationAST *ast = new (_pool) LinkageSpecificationAST; |
|
653 ast->extern_token = consumeToken(); |
|
654 ast->extern_type_token = consumeToken(); |
|
655 |
|
656 if (LA() == T_LBRACE) |
|
657 parseLinkageBody(ast->declaration); |
|
658 else |
|
659 parseDeclaration(ast->declaration); |
|
660 |
|
661 node = ast; |
|
662 return true; |
|
663 } |
|
664 |
|
665 return false; |
|
666 } |
|
667 |
|
668 bool Parser::parseLinkageBody(DeclarationAST *&node) |
|
669 { |
|
670 DEBUG_THIS_RULE(); |
|
671 if (LA() == T_LBRACE) { |
|
672 LinkageBodyAST *ast = new (_pool) LinkageBodyAST; |
|
673 ast->lbrace_token = consumeToken(); |
|
674 DeclarationListAST **declaration_ptr = &ast->declaration_list; |
|
675 |
|
676 while (int tk = LA()) { |
|
677 if (tk == T_RBRACE) |
|
678 break; |
|
679 |
|
680 unsigned start_declaration = cursor(); |
|
681 DeclarationAST *declaration = 0; |
|
682 if (parseDeclaration(declaration)) { |
|
683 *declaration_ptr = new (_pool) DeclarationListAST; |
|
684 (*declaration_ptr)->value = declaration; |
|
685 declaration_ptr = &(*declaration_ptr)->next; |
|
686 } else { |
|
687 _translationUnit->error(start_declaration, "expected a declaration"); |
|
688 rewind(start_declaration + 1); |
|
689 skipUntilDeclaration(); |
|
690 } |
|
691 |
|
692 _templateArgumentList.clear(); |
|
693 } |
|
694 match(T_RBRACE, &ast->rbrace_token); |
|
695 node = ast; |
|
696 return true; |
|
697 } |
|
698 return false; |
|
699 } |
|
700 |
|
701 // ### rename parseNamespaceAliarOrDeclaration? |
|
702 bool Parser::parseNamespace(DeclarationAST *&node) |
|
703 { |
|
704 DEBUG_THIS_RULE(); |
|
705 if (LA() != T_NAMESPACE) |
|
706 return false; |
|
707 |
|
708 unsigned namespace_token = consumeToken(); |
|
709 |
|
710 if (LA() == T_IDENTIFIER && LA(2) == T_EQUAL) { |
|
711 NamespaceAliasDefinitionAST *ast = |
|
712 new (_pool) NamespaceAliasDefinitionAST; |
|
713 ast->namespace_token = namespace_token; |
|
714 ast->namespace_name_token = consumeToken(); |
|
715 ast->equal_token = consumeToken(); |
|
716 parseName(ast->name); |
|
717 match(T_SEMICOLON, &ast->semicolon_token); |
|
718 node = ast; |
|
719 return true; |
|
720 } |
|
721 |
|
722 NamespaceAST *ast = new (_pool) NamespaceAST; |
|
723 ast->namespace_token = namespace_token; |
|
724 if (LA() == T_IDENTIFIER) |
|
725 ast->identifier_token = consumeToken(); |
|
726 SpecifierListAST **attr_ptr = &ast->attribute_list; |
|
727 while (LA() == T___ATTRIBUTE__) { |
|
728 parseAttributeSpecifier(*attr_ptr); |
|
729 attr_ptr = &(*attr_ptr)->next; |
|
730 } |
|
731 if (LA() == T_LBRACE) |
|
732 parseLinkageBody(ast->linkage_body); |
|
733 node = ast; |
|
734 return true; |
|
735 } |
|
736 |
|
737 bool Parser::parseUsing(DeclarationAST *&node) |
|
738 { |
|
739 DEBUG_THIS_RULE(); |
|
740 if (LA() != T_USING) |
|
741 return false; |
|
742 |
|
743 if (LA(2) == T_NAMESPACE) |
|
744 return parseUsingDirective(node); |
|
745 |
|
746 UsingAST *ast = new (_pool) UsingAST; |
|
747 ast->using_token = consumeToken(); |
|
748 |
|
749 if (LA() == T_TYPENAME) |
|
750 ast->typename_token = consumeToken(); |
|
751 |
|
752 parseName(ast->name); |
|
753 match(T_SEMICOLON, &ast->semicolon_token); |
|
754 node = ast; |
|
755 return true; |
|
756 } |
|
757 |
|
758 bool Parser::parseUsingDirective(DeclarationAST *&node) |
|
759 { |
|
760 DEBUG_THIS_RULE(); |
|
761 if (LA() == T_USING && LA(2) == T_NAMESPACE) { |
|
762 UsingDirectiveAST *ast = new (_pool) UsingDirectiveAST; |
|
763 ast->using_token = consumeToken(); |
|
764 ast->namespace_token = consumeToken(); |
|
765 if (! parseName(ast->name)) |
|
766 _translationUnit->warning(cursor(), "expected `namespace name' before `%s'", |
|
767 tok().spell()); |
|
768 match(T_SEMICOLON, &ast->semicolon_token); |
|
769 node = ast; |
|
770 return true; |
|
771 } |
|
772 return false; |
|
773 } |
|
774 |
|
775 bool Parser::parseConversionFunctionId(NameAST *&node) |
|
776 { |
|
777 DEBUG_THIS_RULE(); |
|
778 if (LA() != T_OPERATOR) |
|
779 return false; |
|
780 unsigned operator_token = consumeToken(); |
|
781 SpecifierListAST *type_specifier = 0; |
|
782 if (! parseTypeSpecifier(type_specifier)) { |
|
783 return false; |
|
784 } |
|
785 PtrOperatorListAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators; |
|
786 while (parsePtrOperator(*ptr_operators_tail)) |
|
787 ptr_operators_tail = &(*ptr_operators_tail)->next; |
|
788 |
|
789 ConversionFunctionIdAST *ast = new (_pool) ConversionFunctionIdAST; |
|
790 ast->operator_token = operator_token; |
|
791 ast->type_specifier_list = type_specifier; |
|
792 ast->ptr_operator_list = ptr_operators; |
|
793 node = ast; |
|
794 return true; |
|
795 } |
|
796 |
|
797 bool Parser::parseOperatorFunctionId(NameAST *&node) |
|
798 { |
|
799 DEBUG_THIS_RULE(); |
|
800 if (LA() != T_OPERATOR) |
|
801 return false; |
|
802 unsigned operator_token = consumeToken(); |
|
803 |
|
804 OperatorAST *op = 0; |
|
805 if (! parseOperator(op)) |
|
806 return false; |
|
807 |
|
808 OperatorFunctionIdAST *ast = new (_pool) OperatorFunctionIdAST; |
|
809 ast->operator_token = operator_token; |
|
810 ast->op = op; |
|
811 node = ast; |
|
812 return true; |
|
813 } |
|
814 |
|
815 Parser::TemplateArgumentListEntry *Parser::templateArgumentListEntry(unsigned tokenIndex) |
|
816 { |
|
817 std::map<unsigned, TemplateArgumentListEntry>::iterator it =_templateArgumentList.find(tokenIndex); |
|
818 if (it != _templateArgumentList.end()) |
|
819 return &it->second; |
|
820 |
|
821 return 0; |
|
822 } |
|
823 |
|
824 bool Parser::parseTemplateArgumentList(TemplateArgumentListAST *&node) |
|
825 { |
|
826 if (TemplateArgumentListEntry *entry = templateArgumentListEntry(cursor())) { |
|
827 rewind(entry->cursor); |
|
828 node = entry->ast; |
|
829 return entry->ast != 0; |
|
830 } |
|
831 |
|
832 unsigned start = cursor(); |
|
833 |
|
834 DEBUG_THIS_RULE(); |
|
835 TemplateArgumentListAST **template_argument_ptr = &node; |
|
836 ExpressionAST *template_argument = 0; |
|
837 if (parseTemplateArgument(template_argument)) { |
|
838 *template_argument_ptr = new (_pool) TemplateArgumentListAST; |
|
839 (*template_argument_ptr)->value = template_argument; |
|
840 template_argument_ptr = &(*template_argument_ptr)->next; |
|
841 while (LA() == T_COMMA) { |
|
842 consumeToken(); // consume T_COMMA |
|
843 |
|
844 if (parseTemplateArgument(template_argument)) { |
|
845 *template_argument_ptr = new (_pool) TemplateArgumentListAST; |
|
846 (*template_argument_ptr)->value = template_argument; |
|
847 template_argument_ptr = &(*template_argument_ptr)->next; |
|
848 } |
|
849 } |
|
850 |
|
851 _templateArgumentList.insert(std::make_pair(cursor(), TemplateArgumentListEntry(start, cursor(), node))); |
|
852 return true; |
|
853 } |
|
854 |
|
855 _templateArgumentList.insert(std::make_pair(cursor(), TemplateArgumentListEntry(start, cursor(), 0))); |
|
856 |
|
857 return false; |
|
858 } |
|
859 |
|
860 bool Parser::parseAsmDefinition(DeclarationAST *&node) |
|
861 { |
|
862 DEBUG_THIS_RULE(); |
|
863 if (LA() != T_ASM) |
|
864 return false; |
|
865 |
|
866 AsmDefinitionAST *ast = new (_pool) AsmDefinitionAST; |
|
867 ast->asm_token = consumeToken(); |
|
868 |
|
869 if (LA() == T_VOLATILE) |
|
870 ast->volatile_token = consumeToken(); |
|
871 |
|
872 match(T_LPAREN, &ast->lparen_token); |
|
873 unsigned string_literal_token = 0; |
|
874 match(T_STRING_LITERAL, &string_literal_token); |
|
875 while (LA() == T_STRING_LITERAL) { |
|
876 consumeToken(); |
|
877 } |
|
878 if (LA() == T_COLON) { |
|
879 consumeToken(); // skip T_COLON |
|
880 parseAsmOperandList(); |
|
881 if (LA() == T_COLON) { |
|
882 consumeToken(); |
|
883 parseAsmOperandList(); |
|
884 if (LA() == T_COLON) { |
|
885 consumeToken(); |
|
886 parseAsmClobberList(); |
|
887 } |
|
888 } else if (LA() == T_COLON_COLON) { |
|
889 consumeToken(); |
|
890 parseAsmClobberList(); |
|
891 } |
|
892 } else if (LA() == T_COLON_COLON) { |
|
893 consumeToken(); |
|
894 parseAsmClobberList(); |
|
895 } |
|
896 match(T_RPAREN, &ast->rparen_token); |
|
897 match(T_SEMICOLON, &ast->semicolon_token); |
|
898 node = ast; |
|
899 return true; |
|
900 } |
|
901 |
|
902 bool Parser::parseAsmOperandList() |
|
903 { |
|
904 DEBUG_THIS_RULE(); |
|
905 if (LA() != T_STRING_LITERAL) |
|
906 return true; |
|
907 |
|
908 if (parseAsmOperand()) { |
|
909 while (LA() == T_COMMA) { |
|
910 consumeToken(); |
|
911 parseAsmOperand(); |
|
912 } |
|
913 return true; |
|
914 } |
|
915 |
|
916 return false; |
|
917 } |
|
918 |
|
919 bool Parser::parseAsmOperand() |
|
920 { |
|
921 DEBUG_THIS_RULE(); |
|
922 unsigned string_literal_token = 0; |
|
923 match(T_STRING_LITERAL, &string_literal_token); |
|
924 |
|
925 if (LA() == T_LBRACKET) { |
|
926 /*unsigned lbracket_token = */ consumeToken(); |
|
927 match(T_STRING_LITERAL, &string_literal_token); |
|
928 unsigned rbracket_token = 0; |
|
929 match(T_RBRACKET, &rbracket_token); |
|
930 } |
|
931 |
|
932 unsigned lparen_token = 0, rparen_token = 0; |
|
933 match(T_LPAREN, &lparen_token); |
|
934 ExpressionAST *expression = 0; |
|
935 parseExpression(expression); |
|
936 match(T_RPAREN, &rparen_token); |
|
937 return true; |
|
938 } |
|
939 |
|
940 bool Parser::parseAsmClobberList() |
|
941 { |
|
942 DEBUG_THIS_RULE(); |
|
943 if (LA() != T_STRING_LITERAL) |
|
944 return false; |
|
945 |
|
946 unsigned string_literal_token = consumeToken(); |
|
947 |
|
948 while (LA() == T_COMMA) { |
|
949 consumeToken(); |
|
950 match(T_STRING_LITERAL, &string_literal_token); |
|
951 } |
|
952 |
|
953 return true; |
|
954 } |
|
955 |
|
956 bool Parser::parseTemplateDeclaration(DeclarationAST *&node) |
|
957 { |
|
958 DEBUG_THIS_RULE(); |
|
959 if (! (LA(1) == T_TEMPLATE || ((LA(1) == T_EXPORT || LA(1) == T_EXTERN) |
|
960 && LA(2) == T_TEMPLATE))) |
|
961 return false; |
|
962 |
|
963 TemplateDeclarationAST *ast = new (_pool) TemplateDeclarationAST; |
|
964 |
|
965 if (LA() == T_EXPORT || LA() == T_EXPORT) |
|
966 ast->export_token = consumeToken(); |
|
967 |
|
968 ast->template_token = consumeToken(); |
|
969 |
|
970 if (LA() == T_LESS) { |
|
971 ast->less_token = consumeToken(); |
|
972 if (LA() == T_GREATER || parseTemplateParameterList(ast->template_parameter_list)) |
|
973 match(T_GREATER, &ast->greater_token); |
|
974 } |
|
975 |
|
976 parseDeclaration(ast->declaration); |
|
977 node = ast; |
|
978 return true; |
|
979 } |
|
980 |
|
981 bool Parser::parseOperator(OperatorAST *&node) // ### FIXME |
|
982 { |
|
983 DEBUG_THIS_RULE(); |
|
984 OperatorAST *ast = new (_pool) OperatorAST; |
|
985 |
|
986 switch (LA()) { |
|
987 case T_NEW: |
|
988 case T_DELETE: { |
|
989 ast->op_token = consumeToken(); |
|
990 if (LA() == T_LBRACKET) { |
|
991 ast->open_token = consumeToken(); |
|
992 match(T_RBRACKET, &ast->close_token); |
|
993 } |
|
994 } break; |
|
995 |
|
996 case T_PLUS: |
|
997 case T_MINUS: |
|
998 case T_STAR: |
|
999 case T_SLASH: |
|
1000 case T_PERCENT: |
|
1001 case T_CARET: |
|
1002 case T_AMPER: |
|
1003 case T_PIPE: |
|
1004 case T_TILDE: |
|
1005 case T_EXCLAIM: |
|
1006 case T_LESS: |
|
1007 case T_GREATER: |
|
1008 case T_COMMA: |
|
1009 case T_AMPER_EQUAL: |
|
1010 case T_CARET_EQUAL: |
|
1011 case T_SLASH_EQUAL: |
|
1012 case T_EQUAL: |
|
1013 case T_EQUAL_EQUAL: |
|
1014 case T_EXCLAIM_EQUAL: |
|
1015 case T_GREATER_EQUAL: |
|
1016 case T_GREATER_GREATER_EQUAL: |
|
1017 case T_LESS_EQUAL: |
|
1018 case T_LESS_LESS_EQUAL: |
|
1019 case T_MINUS_EQUAL: |
|
1020 case T_PERCENT_EQUAL: |
|
1021 case T_PIPE_EQUAL: |
|
1022 case T_PLUS_EQUAL: |
|
1023 case T_STAR_EQUAL: |
|
1024 case T_TILDE_EQUAL: |
|
1025 case T_LESS_LESS: |
|
1026 case T_GREATER_GREATER: |
|
1027 case T_AMPER_AMPER: |
|
1028 case T_PIPE_PIPE: |
|
1029 case T_PLUS_PLUS: |
|
1030 case T_MINUS_MINUS: |
|
1031 case T_ARROW_STAR: |
|
1032 case T_DOT_STAR: |
|
1033 case T_ARROW: |
|
1034 ast->op_token = consumeToken(); |
|
1035 break; |
|
1036 |
|
1037 default: |
|
1038 if (LA() == T_LPAREN && LA(2) == T_RPAREN) { |
|
1039 ast->op_token = ast->open_token = consumeToken(); |
|
1040 ast->close_token = consumeToken(); |
|
1041 } else if (LA() == T_LBRACKET && LA(2) == T_RBRACKET) { |
|
1042 ast->op_token = ast->open_token = consumeToken(); |
|
1043 ast->close_token = consumeToken(); |
|
1044 } else { |
|
1045 return false; |
|
1046 } |
|
1047 } |
|
1048 |
|
1049 node = ast; |
|
1050 return true; |
|
1051 } |
|
1052 |
|
1053 bool Parser::parseCvQualifiers(SpecifierListAST *&node) |
|
1054 { |
|
1055 DEBUG_THIS_RULE(); |
|
1056 |
|
1057 unsigned start = cursor(); |
|
1058 |
|
1059 SpecifierListAST **ast = &node; |
|
1060 while (*ast) |
|
1061 ast = &(*ast)->next; |
|
1062 |
|
1063 while (int tk = LA()) { |
|
1064 if (tk == T_CONST || tk == T_VOLATILE) { |
|
1065 SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST; |
|
1066 spec->specifier_token = consumeToken(); |
|
1067 *ast = new (_pool) SpecifierListAST(spec); |
|
1068 ast = &(*ast)->next; |
|
1069 } else if(LA() == T___ATTRIBUTE__) { |
|
1070 parseAttributeSpecifier(*ast); |
|
1071 ast = &(*ast)->next; |
|
1072 } else { |
|
1073 break; |
|
1074 } |
|
1075 } |
|
1076 |
|
1077 return start != cursor(); |
|
1078 } |
|
1079 |
|
1080 bool Parser::parsePtrOperator(PtrOperatorListAST *&node) |
|
1081 { |
|
1082 DEBUG_THIS_RULE(); |
|
1083 if (LA() == T_AMPER) { |
|
1084 ReferenceAST *ast = new (_pool) ReferenceAST; |
|
1085 ast->amp_token = consumeToken(); |
|
1086 node = new (_pool) PtrOperatorListAST(ast); |
|
1087 return true; |
|
1088 } else if (LA() == T_STAR) { |
|
1089 PointerAST *ast = new (_pool) PointerAST; |
|
1090 ast->star_token = consumeToken(); |
|
1091 parseCvQualifiers(ast->cv_qualifier_list); |
|
1092 node = new (_pool) PtrOperatorListAST(ast); |
|
1093 return true; |
|
1094 } else if (LA() == T_COLON_COLON || LA() == T_IDENTIFIER) { |
|
1095 unsigned scope_or_identifier_token = cursor(); |
|
1096 |
|
1097 unsigned global_scope_token = 0; |
|
1098 if (LA() == T_COLON_COLON) |
|
1099 global_scope_token = consumeToken(); |
|
1100 |
|
1101 NestedNameSpecifierListAST *nested_name_specifiers = 0; |
|
1102 bool has_nested_name_specifier = parseNestedNameSpecifier(nested_name_specifiers, true); |
|
1103 if (has_nested_name_specifier && LA() == T_STAR) { |
|
1104 PointerToMemberAST *ast = new (_pool) PointerToMemberAST; |
|
1105 ast->global_scope_token = global_scope_token; |
|
1106 ast->nested_name_specifier_list = nested_name_specifiers; |
|
1107 ast->star_token = consumeToken(); |
|
1108 parseCvQualifiers(ast->cv_qualifier_list); |
|
1109 node = new (_pool) PtrOperatorListAST(ast); |
|
1110 return true; |
|
1111 } |
|
1112 rewind(scope_or_identifier_token); |
|
1113 } |
|
1114 return false; |
|
1115 } |
|
1116 |
|
1117 bool Parser::parseTemplateArgument(ExpressionAST *&node) |
|
1118 { |
|
1119 DEBUG_THIS_RULE(); |
|
1120 unsigned start = cursor(); |
|
1121 if (parseTypeId(node) && (LA() == T_COMMA || LA() == T_GREATER)) |
|
1122 return true; |
|
1123 |
|
1124 rewind(start); |
|
1125 bool previousTemplateArguments = switchTemplateArguments(true); |
|
1126 bool parsed = parseLogicalOrExpression(node); |
|
1127 (void) switchTemplateArguments(previousTemplateArguments); |
|
1128 return parsed; |
|
1129 } |
|
1130 |
|
1131 bool Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq, |
|
1132 bool onlyTypeSpecifiers, |
|
1133 bool simplified) |
|
1134 { |
|
1135 DEBUG_THIS_RULE(); |
|
1136 bool has_type_specifier = false; |
|
1137 NameAST *named_type_specifier = 0; |
|
1138 SpecifierListAST **decl_specifier_seq_ptr = &decl_specifier_seq; |
|
1139 for (;;) { |
|
1140 if (lookAtCVQualifier()) { |
|
1141 SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST; |
|
1142 spec->specifier_token = consumeToken(); |
|
1143 *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec); |
|
1144 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
1145 } else if (! onlyTypeSpecifiers && lookAtStorageClassSpecifier()) { |
|
1146 SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST; |
|
1147 spec->specifier_token = consumeToken(); |
|
1148 *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec); |
|
1149 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
1150 } else if (! named_type_specifier && lookAtBuiltinTypeSpecifier()) { |
|
1151 parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr); |
|
1152 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
1153 has_type_specifier = true; |
|
1154 } else if (! has_type_specifier && (LA() == T_COLON_COLON || |
|
1155 LA() == T_IDENTIFIER)) { |
|
1156 if (! parseName(named_type_specifier)) |
|
1157 return false; |
|
1158 NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST; |
|
1159 spec->name = named_type_specifier; |
|
1160 *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec); |
|
1161 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
1162 has_type_specifier = true; |
|
1163 } else if (! simplified && ! has_type_specifier && (LA() == T_TYPENAME || |
|
1164 LA() == T_ENUM || |
|
1165 lookAtClassKey())) { |
|
1166 unsigned startOfElaboratedTypeSpecifier = cursor(); |
|
1167 if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) { |
|
1168 _translationUnit->error(startOfElaboratedTypeSpecifier, |
|
1169 "expected an elaborated type specifier"); |
|
1170 break; |
|
1171 } |
|
1172 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
1173 has_type_specifier = true; |
|
1174 } else |
|
1175 break; |
|
1176 } |
|
1177 |
|
1178 return decl_specifier_seq != 0; |
|
1179 } |
|
1180 |
|
1181 bool Parser::parseDeclaratorOrAbstractDeclarator(DeclaratorAST *&node) |
|
1182 { |
|
1183 DEBUG_THIS_RULE(); |
|
1184 unsigned start = cursor(); |
|
1185 bool blocked = blockErrors(true); |
|
1186 if (parseDeclarator(node)) { |
|
1187 blockErrors(blocked); |
|
1188 return true; |
|
1189 } |
|
1190 blockErrors(blocked); |
|
1191 rewind(start); |
|
1192 return parseAbstractDeclarator(node); |
|
1193 } |
|
1194 |
|
1195 bool Parser::parseCoreDeclarator(DeclaratorAST *&node) |
|
1196 { |
|
1197 DEBUG_THIS_RULE(); |
|
1198 unsigned start = cursor(); |
|
1199 SpecifierListAST *attributes = 0; |
|
1200 SpecifierListAST **attribute_ptr = &attributes; |
|
1201 while (LA() == T___ATTRIBUTE__) { |
|
1202 parseAttributeSpecifier(*attribute_ptr); |
|
1203 attribute_ptr = &(*attribute_ptr)->next; |
|
1204 } |
|
1205 |
|
1206 PtrOperatorListAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators; |
|
1207 while (parsePtrOperator(*ptr_operators_tail)) |
|
1208 ptr_operators_tail = &(*ptr_operators_tail)->next; |
|
1209 |
|
1210 if (LA() == T_COLON_COLON || LA() == T_IDENTIFIER || LA() == T_TILDE |
|
1211 || LA() == T_OPERATOR) { |
|
1212 NameAST *name = 0; |
|
1213 if (parseName(name)) { |
|
1214 DeclaratorIdAST *declarator_id = new (_pool) DeclaratorIdAST; |
|
1215 declarator_id->name = name; |
|
1216 DeclaratorAST *ast = new (_pool) DeclaratorAST; |
|
1217 ast->attribute_list = attributes; |
|
1218 ast->ptr_operator_list = ptr_operators; |
|
1219 ast->core_declarator = declarator_id; |
|
1220 node = ast; |
|
1221 return true; |
|
1222 } |
|
1223 } else if (LA() == T_LPAREN) { |
|
1224 if (attributes) |
|
1225 _translationUnit->warning(attributes->firstToken(), "unexpected attribtues"); |
|
1226 |
|
1227 unsigned lparen_token = consumeToken(); |
|
1228 DeclaratorAST *declarator = 0; |
|
1229 if (parseDeclarator(declarator) && LA() == T_RPAREN) { |
|
1230 NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST; |
|
1231 nested_declarator->lparen_token = lparen_token; |
|
1232 nested_declarator->declarator = declarator; |
|
1233 nested_declarator->rparen_token = consumeToken(); |
|
1234 DeclaratorAST *ast = new (_pool) DeclaratorAST; |
|
1235 ast->ptr_operator_list = ptr_operators; |
|
1236 ast->core_declarator = nested_declarator; |
|
1237 node = ast; |
|
1238 return true; |
|
1239 } |
|
1240 } |
|
1241 rewind(start); |
|
1242 return false; |
|
1243 } |
|
1244 |
|
1245 bool Parser::parseDeclarator(DeclaratorAST *&node, bool stopAtCppInitializer) |
|
1246 { |
|
1247 DEBUG_THIS_RULE(); |
|
1248 if (! parseCoreDeclarator(node)) |
|
1249 return false; |
|
1250 |
|
1251 PostfixDeclaratorListAST **postfix_ptr = &node->postfix_declarator_list; |
|
1252 |
|
1253 for (;;) { |
|
1254 unsigned startOfPostDeclarator = cursor(); |
|
1255 |
|
1256 if (LA() == T_LPAREN) { |
|
1257 if (stopAtCppInitializer) { |
|
1258 unsigned lparen_token = cursor(); |
|
1259 ExpressionAST *initializer = 0; |
|
1260 |
|
1261 bool blocked = blockErrors(true); |
|
1262 if (parseInitializer(initializer, &node->equals_token)) { |
|
1263 if (NestedExpressionAST *expr = initializer->asNestedExpression()) { |
|
1264 if (expr->expression && expr->rparen_token && (LA() == T_COMMA || LA() == T_SEMICOLON)) { |
|
1265 rewind(lparen_token); |
|
1266 |
|
1267 // check for ambiguous declarators. |
|
1268 |
|
1269 consumeToken(); |
|
1270 ParameterDeclarationClauseAST *parameter_declaration_clause = 0; |
|
1271 if (parseParameterDeclarationClause(parameter_declaration_clause) && LA() == T_RPAREN) { |
|
1272 unsigned rparen_token = consumeToken(); |
|
1273 |
|
1274 FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST; |
|
1275 ast->lparen_token = lparen_token; |
|
1276 ast->parameters = parameter_declaration_clause; |
|
1277 ast->as_cpp_initializer = initializer; |
|
1278 ast->rparen_token = rparen_token; |
|
1279 *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast); |
|
1280 postfix_ptr = &(*postfix_ptr)->next; |
|
1281 |
|
1282 blockErrors(blocked); |
|
1283 return true; |
|
1284 } |
|
1285 |
|
1286 |
|
1287 blockErrors(blocked); |
|
1288 rewind(lparen_token); |
|
1289 return true; |
|
1290 } |
|
1291 } |
|
1292 } |
|
1293 |
|
1294 blockErrors(blocked); |
|
1295 rewind(lparen_token); |
|
1296 } |
|
1297 |
|
1298 FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST; |
|
1299 ast->lparen_token = consumeToken(); |
|
1300 parseParameterDeclarationClause(ast->parameters); |
|
1301 if (LA() != T_RPAREN) { |
|
1302 rewind(startOfPostDeclarator); |
|
1303 break; |
|
1304 } |
|
1305 |
|
1306 ast->rparen_token = consumeToken(); |
|
1307 parseCvQualifiers(ast->cv_qualifier_list); |
|
1308 parseExceptionSpecification(ast->exception_specification); |
|
1309 *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast); |
|
1310 postfix_ptr = &(*postfix_ptr)->next; |
|
1311 } else if (LA() == T_LBRACKET) { |
|
1312 ArrayDeclaratorAST *ast = new (_pool) ArrayDeclaratorAST; |
|
1313 ast->lbracket_token = consumeToken(); |
|
1314 if (LA() == T_RBRACKET || parseConstantExpression(ast->expression)) { |
|
1315 match(T_RBRACKET, &ast->rbracket_token); |
|
1316 } |
|
1317 *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast); |
|
1318 postfix_ptr = &(*postfix_ptr)->next; |
|
1319 } else |
|
1320 break; |
|
1321 } |
|
1322 |
|
1323 if (LA() == T___ASM__ && LA(2) == T_LPAREN) { // ### store the asm specifier in the AST |
|
1324 consumeToken(); // skip __asm__ |
|
1325 consumeToken(); // skip T_LPAREN |
|
1326 |
|
1327 if (skipUntil(T_RPAREN)) |
|
1328 consumeToken(); // skip T_RPAREN |
|
1329 } |
|
1330 |
|
1331 SpecifierListAST **spec_ptr = &node->post_attribute_list; |
|
1332 while (LA() == T___ATTRIBUTE__) { |
|
1333 parseAttributeSpecifier(*spec_ptr); |
|
1334 spec_ptr = &(*spec_ptr)->next; |
|
1335 } |
|
1336 |
|
1337 return true; |
|
1338 } |
|
1339 |
|
1340 bool Parser::parseAbstractCoreDeclarator(DeclaratorAST *&node) |
|
1341 { |
|
1342 DEBUG_THIS_RULE(); |
|
1343 |
|
1344 PtrOperatorListAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators; |
|
1345 while (parsePtrOperator(*ptr_operators_tail)) |
|
1346 ptr_operators_tail = &(*ptr_operators_tail)->next; |
|
1347 |
|
1348 unsigned after_ptr_operators = cursor(); |
|
1349 |
|
1350 if (LA() == T_LPAREN) { |
|
1351 unsigned lparen_token = consumeToken(); |
|
1352 DeclaratorAST *declarator = 0; |
|
1353 if (parseAbstractDeclarator(declarator) && LA() == T_RPAREN) { |
|
1354 NestedDeclaratorAST *nested_declarator = new (_pool) NestedDeclaratorAST; |
|
1355 nested_declarator->lparen_token = lparen_token; |
|
1356 nested_declarator->declarator = declarator; |
|
1357 nested_declarator->rparen_token = consumeToken(); |
|
1358 DeclaratorAST *ast = new (_pool) DeclaratorAST; |
|
1359 ast->ptr_operator_list = ptr_operators; |
|
1360 ast->core_declarator = nested_declarator; |
|
1361 node = ast; |
|
1362 return true; |
|
1363 } |
|
1364 } |
|
1365 |
|
1366 rewind(after_ptr_operators); |
|
1367 if (ptr_operators) { |
|
1368 DeclaratorAST *ast = new (_pool) DeclaratorAST; |
|
1369 ast->ptr_operator_list = ptr_operators; |
|
1370 node = ast; |
|
1371 } |
|
1372 |
|
1373 return true; |
|
1374 } |
|
1375 |
|
1376 bool Parser::parseAbstractDeclarator(DeclaratorAST *&node) |
|
1377 { |
|
1378 DEBUG_THIS_RULE(); |
|
1379 if (! parseAbstractCoreDeclarator(node)) |
|
1380 return false; |
|
1381 |
|
1382 PostfixDeclaratorListAST *postfix_declarators = 0, |
|
1383 **postfix_ptr = &postfix_declarators; |
|
1384 |
|
1385 for (;;) { |
|
1386 if (LA() == T_LPAREN) { |
|
1387 FunctionDeclaratorAST *ast = new (_pool) FunctionDeclaratorAST; |
|
1388 ast->lparen_token = consumeToken(); |
|
1389 if (LA() == T_RPAREN || parseParameterDeclarationClause(ast->parameters)) { |
|
1390 if (LA() == T_RPAREN) |
|
1391 ast->rparen_token = consumeToken(); |
|
1392 } |
|
1393 parseCvQualifiers(ast->cv_qualifier_list); |
|
1394 parseExceptionSpecification(ast->exception_specification); |
|
1395 *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast); |
|
1396 postfix_ptr = &(*postfix_ptr)->next; |
|
1397 } else if (LA() == T_LBRACKET) { |
|
1398 ArrayDeclaratorAST *ast = new (_pool) ArrayDeclaratorAST; |
|
1399 ast->lbracket_token = consumeToken(); |
|
1400 if (LA() == T_RBRACKET || parseConstantExpression(ast->expression)) { |
|
1401 if (LA() == T_RBRACKET) |
|
1402 ast->rbracket_token = consumeToken(); |
|
1403 } |
|
1404 *postfix_ptr = new (_pool) PostfixDeclaratorListAST(ast); |
|
1405 postfix_ptr = &(*postfix_ptr)->next; |
|
1406 } else |
|
1407 break; |
|
1408 } |
|
1409 |
|
1410 if (postfix_declarators) { |
|
1411 if (! node) |
|
1412 node = new (_pool) DeclaratorAST; |
|
1413 |
|
1414 node->postfix_declarator_list = postfix_declarators; |
|
1415 } |
|
1416 |
|
1417 return true; |
|
1418 } |
|
1419 |
|
1420 bool Parser::parseEnumSpecifier(SpecifierListAST *&node) |
|
1421 { |
|
1422 DEBUG_THIS_RULE(); |
|
1423 if (LA() == T_ENUM) { |
|
1424 unsigned enum_token = consumeToken(); |
|
1425 NameAST *name = 0; |
|
1426 parseName(name); |
|
1427 if (LA() == T_LBRACE) { |
|
1428 EnumSpecifierAST *ast = new (_pool) EnumSpecifierAST; |
|
1429 ast->enum_token = enum_token; |
|
1430 ast->name = name; |
|
1431 ast->lbrace_token = consumeToken(); |
|
1432 unsigned comma_token = 0; |
|
1433 EnumeratorListAST **enumerator_ptr = &ast->enumerator_list; |
|
1434 while (int tk = LA()) { |
|
1435 if (tk == T_RBRACE) |
|
1436 break; |
|
1437 |
|
1438 if (LA() != T_IDENTIFIER) { |
|
1439 _translationUnit->error(cursor(), "expected identifier before '%s'", tok().spell()); |
|
1440 skipUntil(T_IDENTIFIER); |
|
1441 } |
|
1442 |
|
1443 if (parseEnumerator(*enumerator_ptr)) { |
|
1444 enumerator_ptr = &(*enumerator_ptr)->next; |
|
1445 } |
|
1446 |
|
1447 if (LA() != T_RBRACE) |
|
1448 match(T_COMMA, &comma_token); |
|
1449 } |
|
1450 match(T_RBRACE, &ast->rbrace_token); |
|
1451 node = new (_pool) SpecifierListAST(ast); |
|
1452 return true; |
|
1453 } |
|
1454 } |
|
1455 return false; |
|
1456 } |
|
1457 |
|
1458 bool Parser::parseTemplateParameterList(DeclarationListAST *&node) |
|
1459 { |
|
1460 DEBUG_THIS_RULE(); |
|
1461 DeclarationListAST **template_parameter_ptr = &node; |
|
1462 DeclarationAST *declaration = 0; |
|
1463 if (parseTemplateParameter(declaration)) { |
|
1464 *template_parameter_ptr = new (_pool) DeclarationListAST; |
|
1465 (*template_parameter_ptr)->value = declaration; |
|
1466 template_parameter_ptr = &(*template_parameter_ptr)->next; |
|
1467 |
|
1468 while (LA() == T_COMMA) { |
|
1469 consumeToken(); // XXX Store this token somewhere |
|
1470 |
|
1471 declaration = 0; |
|
1472 if (parseTemplateParameter(declaration)) { |
|
1473 *template_parameter_ptr = new (_pool) DeclarationListAST; |
|
1474 (*template_parameter_ptr)->value = declaration; |
|
1475 template_parameter_ptr = &(*template_parameter_ptr)->next; |
|
1476 } |
|
1477 } |
|
1478 return true; |
|
1479 } |
|
1480 return false; |
|
1481 } |
|
1482 |
|
1483 bool Parser::parseTemplateParameter(DeclarationAST *&node) |
|
1484 { |
|
1485 DEBUG_THIS_RULE(); |
|
1486 if (parseTypeParameter(node)) |
|
1487 return true; |
|
1488 bool previousTemplateArguments = switchTemplateArguments(true); |
|
1489 bool parsed = parseParameterDeclaration(node); |
|
1490 (void) switchTemplateArguments(previousTemplateArguments); |
|
1491 return parsed; |
|
1492 } |
|
1493 |
|
1494 bool Parser::parseTypenameTypeParameter(DeclarationAST *&node) |
|
1495 { |
|
1496 DEBUG_THIS_RULE(); |
|
1497 if (LA() == T_CLASS || LA() == T_TYPENAME) { |
|
1498 TypenameTypeParameterAST *ast = new (_pool) TypenameTypeParameterAST; |
|
1499 ast->classkey_token = consumeToken(); |
|
1500 parseName(ast->name); |
|
1501 if (LA() == T_EQUAL) { |
|
1502 ast->equal_token = consumeToken(); |
|
1503 parseTypeId(ast->type_id); |
|
1504 } |
|
1505 node = ast; |
|
1506 return true; |
|
1507 } |
|
1508 return false; |
|
1509 } |
|
1510 |
|
1511 bool Parser::parseTemplateTypeParameter(DeclarationAST *&node) |
|
1512 { |
|
1513 DEBUG_THIS_RULE(); |
|
1514 if (LA() == T_TEMPLATE) { |
|
1515 TemplateTypeParameterAST *ast = new (_pool) TemplateTypeParameterAST; |
|
1516 ast->template_token = consumeToken(); |
|
1517 if (LA() == T_LESS) |
|
1518 ast->less_token = consumeToken(); |
|
1519 parseTemplateParameterList(ast->template_parameter_list); |
|
1520 if (LA() == T_GREATER) |
|
1521 ast->greater_token = consumeToken(); |
|
1522 if (LA() == T_CLASS) |
|
1523 ast->class_token = consumeToken(); |
|
1524 |
|
1525 // parse optional name |
|
1526 parseName(ast->name); |
|
1527 |
|
1528 if (LA() == T_EQUAL) { |
|
1529 ast->equal_token = consumeToken(); |
|
1530 parseTypeId(ast->type_id); |
|
1531 } |
|
1532 node = ast; |
|
1533 return true; |
|
1534 } |
|
1535 return false; |
|
1536 } |
|
1537 |
|
1538 bool Parser::parseTypeParameter(DeclarationAST *&node) |
|
1539 { |
|
1540 DEBUG_THIS_RULE(); |
|
1541 if (LA() == T_CLASS || LA() == T_TYPENAME) |
|
1542 return parseTypenameTypeParameter(node); |
|
1543 else if (LA() == T_TEMPLATE) |
|
1544 return parseTemplateTypeParameter(node); |
|
1545 else |
|
1546 return false; |
|
1547 } |
|
1548 |
|
1549 bool Parser::parseTypeId(ExpressionAST *&node) |
|
1550 { |
|
1551 DEBUG_THIS_RULE(); |
|
1552 SpecifierListAST *type_specifier = 0; |
|
1553 if (parseTypeSpecifier(type_specifier)) { |
|
1554 TypeIdAST *ast = new (_pool) TypeIdAST; |
|
1555 ast->type_specifier_list = type_specifier; |
|
1556 parseAbstractDeclarator(ast->declarator); |
|
1557 node = ast; |
|
1558 return true; |
|
1559 } |
|
1560 return false; |
|
1561 } |
|
1562 |
|
1563 bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node) |
|
1564 { |
|
1565 DEBUG_THIS_RULE(); |
|
1566 if (LA() == T_RPAREN) |
|
1567 return true; // nothing to do |
|
1568 |
|
1569 DeclarationListAST *parameter_declarations = 0; |
|
1570 |
|
1571 unsigned dot_dot_dot_token = 0; |
|
1572 if (LA() == T_DOT_DOT_DOT) |
|
1573 dot_dot_dot_token = consumeToken(); |
|
1574 else { |
|
1575 parseParameterDeclarationList(parameter_declarations); |
|
1576 |
|
1577 if (LA() == T_DOT_DOT_DOT) { |
|
1578 dot_dot_dot_token = consumeToken(); |
|
1579 } else if (LA() == T_COMMA && LA(2) == T_DOT_DOT_DOT) { |
|
1580 consumeToken(); // skip comma |
|
1581 dot_dot_dot_token = consumeToken(); |
|
1582 } |
|
1583 } |
|
1584 |
|
1585 if (parameter_declarations || dot_dot_dot_token) { |
|
1586 ParameterDeclarationClauseAST *ast = new (_pool) ParameterDeclarationClauseAST; |
|
1587 ast->parameter_declaration_list = parameter_declarations; |
|
1588 ast->dot_dot_dot_token = dot_dot_dot_token; |
|
1589 node = ast; |
|
1590 } |
|
1591 |
|
1592 return true; |
|
1593 } |
|
1594 |
|
1595 bool Parser::parseParameterDeclarationList(DeclarationListAST *&node) |
|
1596 { |
|
1597 DEBUG_THIS_RULE(); |
|
1598 if (LA() == T_DOT_DOT_DOT || (LA() == T_COMMA && LA(2) == T_DOT_DOT_DOT)) |
|
1599 return false; // nothing to do. |
|
1600 |
|
1601 DeclarationListAST **parameter_declaration_ptr = &node; |
|
1602 DeclarationAST *declaration = 0; |
|
1603 if (parseParameterDeclaration(declaration)) { |
|
1604 *parameter_declaration_ptr = new (_pool) DeclarationListAST; |
|
1605 (*parameter_declaration_ptr)->value = declaration; |
|
1606 parameter_declaration_ptr = &(*parameter_declaration_ptr)->next; |
|
1607 while (LA() == T_COMMA) { |
|
1608 consumeToken(); |
|
1609 |
|
1610 if (LA() == T_DOT_DOT_DOT) |
|
1611 break; |
|
1612 |
|
1613 declaration = 0; |
|
1614 if (parseParameterDeclaration(declaration)) { |
|
1615 *parameter_declaration_ptr = new (_pool) DeclarationListAST; |
|
1616 (*parameter_declaration_ptr)->value = declaration; |
|
1617 parameter_declaration_ptr = &(*parameter_declaration_ptr)->next; |
|
1618 } |
|
1619 } |
|
1620 return true; |
|
1621 } |
|
1622 return false; |
|
1623 } |
|
1624 |
|
1625 bool Parser::parseParameterDeclaration(DeclarationAST *&node) |
|
1626 { |
|
1627 DEBUG_THIS_RULE(); |
|
1628 SpecifierListAST *decl_specifier_seq = 0; |
|
1629 if (parseDeclSpecifierSeq(decl_specifier_seq)) { |
|
1630 ParameterDeclarationAST *ast = new (_pool) ParameterDeclarationAST; |
|
1631 ast->type_specifier_list = decl_specifier_seq; |
|
1632 parseDeclaratorOrAbstractDeclarator(ast->declarator); |
|
1633 if (LA() == T_EQUAL) { |
|
1634 ast->equal_token = consumeToken(); |
|
1635 parseLogicalOrExpression(ast->expression); |
|
1636 } |
|
1637 |
|
1638 node = ast; |
|
1639 return true; |
|
1640 } |
|
1641 return false; |
|
1642 } |
|
1643 |
|
1644 bool Parser::parseClassSpecifier(SpecifierListAST *&node) |
|
1645 { |
|
1646 DEBUG_THIS_RULE(); |
|
1647 if (! lookAtClassKey()) |
|
1648 return false; |
|
1649 |
|
1650 unsigned classkey_token = consumeToken(); |
|
1651 |
|
1652 SpecifierListAST *attributes = 0, **attr_ptr = &attributes; |
|
1653 while (LA() == T___ATTRIBUTE__) { |
|
1654 parseAttributeSpecifier(*attr_ptr); |
|
1655 attr_ptr = &(*attr_ptr)->next; |
|
1656 } |
|
1657 |
|
1658 if (LA(1) == T_IDENTIFIER && LA(2) == T_IDENTIFIER) { |
|
1659 _translationUnit->warning(cursor(), "skip identifier `%s'", |
|
1660 tok().spell()); |
|
1661 consumeToken(); |
|
1662 } |
|
1663 |
|
1664 NameAST *name = 0; |
|
1665 parseName(name); |
|
1666 |
|
1667 bool parsed = false; |
|
1668 |
|
1669 const bool previousInFunctionBody = _inFunctionBody; |
|
1670 _inFunctionBody = false; |
|
1671 |
|
1672 unsigned colon_token = 0; |
|
1673 |
|
1674 if (LA() == T_COLON || LA() == T_LBRACE) { |
|
1675 BaseSpecifierListAST *base_clause_list = 0; |
|
1676 |
|
1677 if (LA() == T_COLON) { |
|
1678 colon_token = cursor(); |
|
1679 |
|
1680 parseBaseClause(base_clause_list); |
|
1681 |
|
1682 if (LA() != T_LBRACE) { |
|
1683 _translationUnit->error(cursor(), "expected `{' before `%s'", tok().spell()); |
|
1684 |
|
1685 const unsigned saved = cursor(); |
|
1686 |
|
1687 for (int n = 0; n < 3 && LA() != T_EOF_SYMBOL; ++n, consumeToken()) { |
|
1688 if (LA() == T_LBRACE) |
|
1689 break; |
|
1690 } |
|
1691 |
|
1692 if (LA() != T_LBRACE) |
|
1693 rewind(saved); |
|
1694 } |
|
1695 } |
|
1696 |
|
1697 ClassSpecifierAST *ast = new (_pool) ClassSpecifierAST; |
|
1698 ast->classkey_token = classkey_token; |
|
1699 ast->attribute_list = attributes; |
|
1700 ast->name = name; |
|
1701 ast->colon_token = colon_token; |
|
1702 ast->base_clause_list = base_clause_list; |
|
1703 |
|
1704 if (LA() == T_LBRACE) |
|
1705 ast->lbrace_token = consumeToken(); |
|
1706 |
|
1707 DeclarationListAST **declaration_ptr = &ast->member_specifier_list; |
|
1708 while (int tk = LA()) { |
|
1709 if (tk == T_RBRACE) { |
|
1710 ast->rbrace_token = consumeToken(); |
|
1711 break; |
|
1712 } |
|
1713 |
|
1714 unsigned start_declaration = cursor(); |
|
1715 DeclarationAST *declaration = 0; |
|
1716 if (parseMemberSpecification(declaration)) { |
|
1717 if (declaration) { // paranoia check |
|
1718 *declaration_ptr = new (_pool) DeclarationListAST; |
|
1719 (*declaration_ptr)->value = declaration; |
|
1720 declaration_ptr = &(*declaration_ptr)->next; |
|
1721 } |
|
1722 |
|
1723 if (cursor() == start_declaration) { // more paranoia |
|
1724 rewind(start_declaration + 1); |
|
1725 skipUntilDeclaration(); |
|
1726 } |
|
1727 } else { |
|
1728 _translationUnit->error(start_declaration, "expected a declaration"); |
|
1729 rewind(start_declaration + 1); |
|
1730 skipUntilDeclaration(); |
|
1731 } |
|
1732 } |
|
1733 node = new (_pool) SpecifierListAST(ast); |
|
1734 parsed = true; |
|
1735 } |
|
1736 |
|
1737 _inFunctionBody = previousInFunctionBody; |
|
1738 |
|
1739 return parsed; |
|
1740 } |
|
1741 |
|
1742 bool Parser::parseAccessSpecifier(SpecifierAST *&node) |
|
1743 { |
|
1744 DEBUG_THIS_RULE(); |
|
1745 switch (LA()) { |
|
1746 case T_PUBLIC: |
|
1747 case T_PROTECTED: |
|
1748 case T_PRIVATE: { |
|
1749 SimpleSpecifierAST *ast = new (_pool) SimpleSpecifierAST; |
|
1750 ast->specifier_token = consumeToken(); |
|
1751 node = ast; |
|
1752 return true; |
|
1753 } |
|
1754 |
|
1755 default: |
|
1756 return false; |
|
1757 } // switch |
|
1758 } |
|
1759 |
|
1760 bool Parser::parseAccessDeclaration(DeclarationAST *&node) |
|
1761 { |
|
1762 DEBUG_THIS_RULE(); |
|
1763 if (LA() == T_PUBLIC || LA() == T_PROTECTED || LA() == T_PRIVATE || LA() == T_Q_SIGNALS || LA() == T_Q_SLOTS) { |
|
1764 bool isSignals = LA() == T_Q_SIGNALS; |
|
1765 bool isSlots = LA() == T_Q_SLOTS; |
|
1766 AccessDeclarationAST *ast = new (_pool) AccessDeclarationAST; |
|
1767 ast->access_specifier_token = consumeToken(); |
|
1768 if (! isSignals && (LA() == T_Q_SLOTS || isSlots)) |
|
1769 ast->slots_token = consumeToken(); |
|
1770 match(T_COLON, &ast->colon_token); |
|
1771 node = ast; |
|
1772 return true; |
|
1773 } |
|
1774 return false; |
|
1775 } |
|
1776 |
|
1777 #ifdef ICHECK_BUILD |
|
1778 bool Parser::parseQPropertyDeclaration(DeclarationAST *&node) |
|
1779 { |
|
1780 /* |
|
1781 Q_PROPERTY(type name |
|
1782 READ getFunction |
|
1783 [WRITE setFunction] |
|
1784 [RESET resetFunction] |
|
1785 [NOTIFY notifySignal] |
|
1786 [DESIGNABLE bool] |
|
1787 [SCRIPTABLE bool] |
|
1788 [STORED bool] |
|
1789 [USER bool] |
|
1790 [CONSTANT] |
|
1791 [FINAL])*/ |
|
1792 DEBUG_THIS_RULE(); |
|
1793 if (LA() == T_Q_PROPERTY) { |
|
1794 QPropertyDeclarationAST *ast = new (_pool)QPropertyDeclarationAST; |
|
1795 ast->property_specifier_token = consumeToken(); |
|
1796 if(LA() == T_LPAREN){ |
|
1797 ast->lparen_token = consumeToken(); |
|
1798 QString tokenstr; |
|
1799 tokenstr = tok().spell(); |
|
1800 //read the type and the name of the type |
|
1801 if(tokenstr != "READ" ){ |
|
1802 ast->type_token = consumeToken(); |
|
1803 tokenstr = tok().spell(); |
|
1804 } |
|
1805 if(tokenstr != "READ" ){ |
|
1806 ast->type_name_token = consumeToken(); |
|
1807 tokenstr = tok().spell(); |
|
1808 } |
|
1809 unsigned fctdefinition = 0; |
|
1810 unsigned fctname = 0; |
|
1811 for(int i = 0; i < 18; i++){ |
|
1812 if(cursor() < _translationUnit->tokenCount() - 1){ |
|
1813 if(LA() == T_RPAREN){ |
|
1814 ast->rparen_token = consumeToken(); |
|
1815 break; |
|
1816 } |
|
1817 tokenstr = tok().spell(); |
|
1818 fctdefinition = consumeToken(); |
|
1819 fctname = consumeToken(); |
|
1820 if(tokenstr == "READ"){ |
|
1821 ast->read_token = fctdefinition; |
|
1822 ast->read_function_token = fctname; |
|
1823 } |
|
1824 else if(tokenstr == "WRITE"){ |
|
1825 ast->write_token = fctdefinition; |
|
1826 ast->write_function_token = fctname; |
|
1827 } |
|
1828 else if(tokenstr == "RESET"){ |
|
1829 ast->reset_token = fctdefinition; |
|
1830 ast->reset_function_token = fctname; |
|
1831 } |
|
1832 else if(tokenstr == "NOTIFY"){ |
|
1833 ast->notify_token = fctdefinition; |
|
1834 ast->notify_function_token = fctname; |
|
1835 } |
|
1836 } |
|
1837 } |
|
1838 } |
|
1839 node = ast; |
|
1840 return true; |
|
1841 } |
|
1842 return false; |
|
1843 } |
|
1844 |
|
1845 bool Parser::parseQEnumDeclaration(DeclarationAST *&node) |
|
1846 { |
|
1847 /*Q_ENUMS(ConnectionState)*/ |
|
1848 DEBUG_THIS_RULE(); |
|
1849 if (LA() == T_Q_ENUMS) { |
|
1850 QEnumDeclarationAST *ast = new (_pool)QEnumDeclarationAST; |
|
1851 ast->enum_specifier_token = consumeToken(); |
|
1852 EnumeratorListAST** enumerator_list_ptr; |
|
1853 enumerator_list_ptr = &ast->enumerator_list; |
|
1854 |
|
1855 if(LA() == T_LPAREN){ |
|
1856 ast->lparen_token = consumeToken(); |
|
1857 while(LA() != T_EOF_SYMBOL && LA() != T_RPAREN){ |
|
1858 *enumerator_list_ptr = new (_pool) EnumeratorListAST; |
|
1859 EnumeratorAST *pdecl = new (_pool) EnumeratorAST; |
|
1860 pdecl->identifier_token = consumeToken(); |
|
1861 (*enumerator_list_ptr)->value = pdecl; |
|
1862 enumerator_list_ptr = &(*enumerator_list_ptr)->next; |
|
1863 if (LA() == T_COMMA) |
|
1864 consumeToken(); |
|
1865 } |
|
1866 if(LA() == T_RPAREN) |
|
1867 ast->rparen_token = consumeToken(); |
|
1868 } |
|
1869 node = ast; |
|
1870 return true; |
|
1871 } |
|
1872 return false; |
|
1873 } |
|
1874 |
|
1875 bool Parser::parseQFlags(DeclarationAST *&node) |
|
1876 { |
|
1877 /*Q_FLAGS(enum1 enum2 flags1)*/ |
|
1878 DEBUG_THIS_RULE(); |
|
1879 if (LA() == T_Q_FLAGS) { |
|
1880 QFlagsDeclarationAST *ast = new (_pool)QFlagsDeclarationAST; |
|
1881 ast->flags_specifier_token = consumeToken(); |
|
1882 EnumeratorListAST** enumerator_list_ptr; |
|
1883 enumerator_list_ptr = &ast->enumerator_list; |
|
1884 if(LA() == T_LPAREN){ |
|
1885 ast->lparen_token = consumeToken(); |
|
1886 while(LA() != T_EOF_SYMBOL && LA() != T_RPAREN){ |
|
1887 *enumerator_list_ptr = new (_pool) EnumeratorListAST; |
|
1888 EnumeratorAST *pdecl = new (_pool) EnumeratorAST; |
|
1889 pdecl->identifier_token = consumeToken(); |
|
1890 (*enumerator_list_ptr)->value = pdecl; |
|
1891 enumerator_list_ptr = &(*enumerator_list_ptr)->next; |
|
1892 if (LA() == T_COMMA) |
|
1893 consumeToken(); |
|
1894 } |
|
1895 if(LA() == T_RPAREN) |
|
1896 ast->rparen_token = consumeToken(); |
|
1897 } |
|
1898 node = ast; |
|
1899 return true; |
|
1900 } |
|
1901 return false; |
|
1902 } |
|
1903 |
|
1904 bool Parser::parseQDeclareFlags(DeclarationAST *&node) |
|
1905 { |
|
1906 /*Q_DECLARE_FLAGS(flag enum)*/ |
|
1907 DEBUG_THIS_RULE(); |
|
1908 if (LA() == T_Q_DECLARE_FLAGS) { |
|
1909 QDeclareFlagsDeclarationAST *ast = new (_pool)QDeclareFlagsDeclarationAST; |
|
1910 ast->declareflags_specifier_token = consumeToken(); |
|
1911 if(LA() == T_LPAREN){ |
|
1912 ast->lparen_token = consumeToken(); |
|
1913 if(LA() != T_EOF_SYMBOL) |
|
1914 ast->flag_token = consumeToken(); |
|
1915 if(LA() == T_COMMA && LA() != T_EOF_SYMBOL) |
|
1916 consumeToken(); |
|
1917 if(LA() != T_EOF_SYMBOL) |
|
1918 ast->enum_token = consumeToken(); |
|
1919 if(LA() != T_EOF_SYMBOL && LA() == T_RPAREN) |
|
1920 ast->rparen_token = consumeToken(); |
|
1921 } |
|
1922 node = ast; |
|
1923 return true; |
|
1924 } |
|
1925 return false; |
|
1926 } |
|
1927 #endif |
|
1928 |
|
1929 bool Parser::parseMemberSpecification(DeclarationAST *&node) |
|
1930 { |
|
1931 DEBUG_THIS_RULE(); |
|
1932 switch (LA()) { |
|
1933 case T_SEMICOLON: |
|
1934 return parseEmptyDeclaration(node); |
|
1935 |
|
1936 case T_USING: |
|
1937 return parseUsing(node); |
|
1938 |
|
1939 case T_TEMPLATE: |
|
1940 return parseTemplateDeclaration(node); |
|
1941 |
|
1942 case T_Q_SIGNALS: |
|
1943 case T_PUBLIC: |
|
1944 case T_PROTECTED: |
|
1945 case T_PRIVATE: |
|
1946 case T_Q_SLOTS: |
|
1947 return parseAccessDeclaration(node); |
|
1948 |
|
1949 #ifdef ICHECK_BUILD |
|
1950 case T_Q_PROPERTY: |
|
1951 return parseQPropertyDeclaration(node); |
|
1952 |
|
1953 case T_Q_ENUMS: |
|
1954 return parseQEnumDeclaration(node); |
|
1955 |
|
1956 case T_Q_FLAGS: |
|
1957 return parseQFlags(node); |
|
1958 |
|
1959 case T_Q_DECLARE_FLAGS: |
|
1960 return parseQDeclareFlags(node); |
|
1961 #endif |
|
1962 |
|
1963 default: |
|
1964 return parseSimpleDeclaration(node, /*acceptStructDeclarator=*/true); |
|
1965 } // switch |
|
1966 } |
|
1967 |
|
1968 bool Parser::parseCtorInitializer(CtorInitializerAST *&node) |
|
1969 { |
|
1970 DEBUG_THIS_RULE(); |
|
1971 if (LA() == T_COLON) { |
|
1972 unsigned colon_token = consumeToken(); |
|
1973 |
|
1974 CtorInitializerAST *ast = new (_pool) CtorInitializerAST; |
|
1975 ast->colon_token = colon_token; |
|
1976 |
|
1977 parseMemInitializerList(ast->member_initializer_list); |
|
1978 node = ast; |
|
1979 return true; |
|
1980 } |
|
1981 return false; |
|
1982 } |
|
1983 |
|
1984 bool Parser::parseElaboratedTypeSpecifier(SpecifierListAST *&node) |
|
1985 { |
|
1986 DEBUG_THIS_RULE(); |
|
1987 if (lookAtClassKey() || LA() == T_ENUM || LA() == T_TYPENAME) { |
|
1988 unsigned classkey_token = consumeToken(); |
|
1989 NameAST *name = 0; |
|
1990 if (parseName(name)) { |
|
1991 ElaboratedTypeSpecifierAST *ast = new (_pool) ElaboratedTypeSpecifierAST; |
|
1992 ast->classkey_token = classkey_token; |
|
1993 ast->name = name; |
|
1994 node = new (_pool) SpecifierListAST(ast); |
|
1995 return true; |
|
1996 } |
|
1997 } |
|
1998 return false; |
|
1999 } |
|
2000 |
|
2001 bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node) |
|
2002 { |
|
2003 DEBUG_THIS_RULE(); |
|
2004 if (LA() == T_THROW) { |
|
2005 ExceptionSpecificationAST *ast = new (_pool) ExceptionSpecificationAST; |
|
2006 ast->throw_token = consumeToken(); |
|
2007 if (LA() == T_LPAREN) |
|
2008 ast->lparen_token = consumeToken(); |
|
2009 if (LA() == T_DOT_DOT_DOT) |
|
2010 ast->dot_dot_dot_token = consumeToken(); |
|
2011 else |
|
2012 parseTypeIdList(ast->type_id_list); |
|
2013 if (LA() == T_RPAREN) |
|
2014 ast->rparen_token = consumeToken(); |
|
2015 node = ast; |
|
2016 return true; |
|
2017 } |
|
2018 return false; |
|
2019 } |
|
2020 |
|
2021 bool Parser::parseEnumerator(EnumeratorListAST *&node) |
|
2022 { |
|
2023 DEBUG_THIS_RULE(); |
|
2024 if (LA() == T_IDENTIFIER) { |
|
2025 EnumeratorAST *ast = new (_pool) EnumeratorAST; |
|
2026 ast->identifier_token = consumeToken(); |
|
2027 |
|
2028 if (LA() == T_EQUAL) { |
|
2029 ast->equal_token = consumeToken(); |
|
2030 parseConstantExpression(ast->expression); |
|
2031 } |
|
2032 |
|
2033 node = new (_pool) EnumeratorListAST; |
|
2034 node->value = ast; |
|
2035 return true; |
|
2036 } |
|
2037 return false; |
|
2038 } |
|
2039 |
|
2040 bool Parser::parseInitDeclarator(DeclaratorAST *&node, |
|
2041 bool acceptStructDeclarator) |
|
2042 { |
|
2043 DEBUG_THIS_RULE(); |
|
2044 unsigned start = cursor(); |
|
2045 |
|
2046 if (acceptStructDeclarator && LA() == T_COLON) { |
|
2047 // anonymous bit-field declaration. |
|
2048 // ### TODO create the AST |
|
2049 } else if (! parseDeclarator(node, /*stopAtCppInitializer = */ ! acceptStructDeclarator)) { |
|
2050 return false; |
|
2051 } |
|
2052 |
|
2053 if (LA() == T_ASM && LA(2) == T_LPAREN) { // ### FIXME |
|
2054 consumeToken(); |
|
2055 |
|
2056 if (skip(T_LPAREN, T_RPAREN)) |
|
2057 consumeToken(); |
|
2058 } |
|
2059 |
|
2060 if (acceptStructDeclarator && node && |
|
2061 ! node->postfix_declarator_list && |
|
2062 node->core_declarator && |
|
2063 node->core_declarator->asNestedDeclarator()) { |
|
2064 rewind(start); |
|
2065 return false; |
|
2066 } |
|
2067 |
|
2068 if (acceptStructDeclarator && LA() == T_COLON |
|
2069 && (! node || ! node->postfix_declarator_list)) { |
|
2070 unsigned colon_token = consumeToken(); |
|
2071 ExpressionAST *expression = 0; |
|
2072 if (parseConstantExpression(expression) && (LA() == T_COMMA || |
|
2073 LA() == T_SEMICOLON)) { |
|
2074 // recognized a bitfielddeclarator. |
|
2075 // ### TODO create the AST |
|
2076 return true; |
|
2077 } |
|
2078 rewind(colon_token); |
|
2079 } else if (LA() == T_EQUAL || (! acceptStructDeclarator && LA() == T_LPAREN)) { |
|
2080 parseInitializer(node->initializer, &node->equals_token); |
|
2081 } |
|
2082 return true; |
|
2083 } |
|
2084 |
|
2085 bool Parser::parseBaseClause(BaseSpecifierListAST *&node) |
|
2086 { |
|
2087 DEBUG_THIS_RULE(); |
|
2088 |
|
2089 if (LA() == T_COLON) { |
|
2090 consumeToken(); // ### remove me |
|
2091 |
|
2092 BaseSpecifierListAST **ast = &node; |
|
2093 if (parseBaseSpecifier(*ast)) { |
|
2094 ast = &(*ast)->next; |
|
2095 |
|
2096 while (LA() == T_COMMA) { |
|
2097 consumeToken(); // consume T_COMMA |
|
2098 |
|
2099 if (parseBaseSpecifier(*ast)) |
|
2100 ast = &(*ast)->next; |
|
2101 } |
|
2102 } |
|
2103 |
|
2104 return true; |
|
2105 } |
|
2106 return false; |
|
2107 } |
|
2108 |
|
2109 bool Parser::parseInitializer(ExpressionAST *&node, unsigned *equals_token) |
|
2110 { |
|
2111 DEBUG_THIS_RULE(); |
|
2112 if (LA() == T_LPAREN) { |
|
2113 return parsePrimaryExpression(node); |
|
2114 } else if (LA() == T_EQUAL) { |
|
2115 (*equals_token) = consumeToken(); |
|
2116 return parseInitializerClause(node); |
|
2117 } |
|
2118 return false; |
|
2119 } |
|
2120 |
|
2121 bool Parser::parseMemInitializerList(MemInitializerListAST *&node) |
|
2122 { |
|
2123 DEBUG_THIS_RULE(); |
|
2124 MemInitializerListAST **initializer = &node; |
|
2125 |
|
2126 if (parseMemInitializer(*initializer)) { |
|
2127 initializer = &(*initializer)->next; |
|
2128 |
|
2129 while (true) { |
|
2130 |
|
2131 if (LA() == T_LBRACE) |
|
2132 break; |
|
2133 |
|
2134 else if (LA() == T_COMMA || (LA() == T_IDENTIFIER && (LA(2) == T_LPAREN || LA(2) == T_COLON_COLON))) { |
|
2135 if (LA() != T_COMMA) |
|
2136 _translationUnit->error(cursor(), "expected `,'"); |
|
2137 else |
|
2138 consumeToken(); |
|
2139 |
|
2140 if (parseMemInitializer(*initializer)) |
|
2141 initializer = &(*initializer)->next; |
|
2142 else |
|
2143 _translationUnit->error(cursor(), "expected a member initializer"); |
|
2144 |
|
2145 } else break; |
|
2146 } |
|
2147 |
|
2148 if (LA() != T_LBRACE) |
|
2149 _translationUnit->error(cursor(), "expected `{'"); |
|
2150 |
|
2151 return true; |
|
2152 } |
|
2153 |
|
2154 return false; |
|
2155 } |
|
2156 |
|
2157 bool Parser::parseMemInitializer(MemInitializerListAST *&node) |
|
2158 { |
|
2159 DEBUG_THIS_RULE(); |
|
2160 NameAST *name = 0; |
|
2161 if (! parseName(name)) |
|
2162 return false; |
|
2163 |
|
2164 MemInitializerAST *ast = new (_pool) MemInitializerAST; |
|
2165 ast->name = name; |
|
2166 match(T_LPAREN, &ast->lparen_token); |
|
2167 parseExpressionList(ast->expression_list); |
|
2168 match(T_RPAREN, &ast->rparen_token); |
|
2169 |
|
2170 node = new (_pool) MemInitializerListAST; |
|
2171 node->value = ast; |
|
2172 return true; |
|
2173 } |
|
2174 |
|
2175 bool Parser::parseTypeIdList(ExpressionListAST *&node) |
|
2176 { |
|
2177 DEBUG_THIS_RULE(); |
|
2178 ExpressionListAST **expression_list_ptr = &node; |
|
2179 ExpressionAST *typeId = 0; |
|
2180 if (parseTypeId(typeId)) { |
|
2181 *expression_list_ptr = new (_pool) ExpressionListAST; |
|
2182 (*expression_list_ptr)->value = typeId; |
|
2183 expression_list_ptr = &(*expression_list_ptr)->next; |
|
2184 while (LA() == T_COMMA) { |
|
2185 consumeToken(); |
|
2186 |
|
2187 if (parseTypeId(typeId)) { |
|
2188 *expression_list_ptr = new (_pool) ExpressionListAST; |
|
2189 (*expression_list_ptr)->value = typeId; |
|
2190 expression_list_ptr = &(*expression_list_ptr)->next; |
|
2191 } |
|
2192 } |
|
2193 return true; |
|
2194 } |
|
2195 |
|
2196 return false; |
|
2197 } |
|
2198 |
|
2199 bool Parser::parseExpressionList(ExpressionListAST *&node) |
|
2200 { |
|
2201 DEBUG_THIS_RULE(); |
|
2202 ExpressionListAST **expression_list_ptr = &node; |
|
2203 ExpressionAST *expression = 0; |
|
2204 if (parseAssignmentExpression(expression)) { |
|
2205 *expression_list_ptr = new (_pool) ExpressionListAST; |
|
2206 (*expression_list_ptr)->value = expression; |
|
2207 expression_list_ptr = &(*expression_list_ptr)->next; |
|
2208 while (LA() == T_COMMA) { |
|
2209 consumeToken(); // consume T_COMMA |
|
2210 |
|
2211 if (parseAssignmentExpression(expression)) { |
|
2212 *expression_list_ptr = new (_pool) ExpressionListAST; |
|
2213 (*expression_list_ptr)->value = expression; |
|
2214 expression_list_ptr = &(*expression_list_ptr)->next; |
|
2215 } |
|
2216 } |
|
2217 return true; |
|
2218 } |
|
2219 return false; |
|
2220 } |
|
2221 |
|
2222 bool Parser::parseBaseSpecifier(BaseSpecifierListAST *&node) |
|
2223 { |
|
2224 DEBUG_THIS_RULE(); |
|
2225 BaseSpecifierAST *ast = new (_pool) BaseSpecifierAST; |
|
2226 |
|
2227 if (LA() == T_VIRTUAL) { |
|
2228 ast->virtual_token = consumeToken(); |
|
2229 |
|
2230 int tk = LA(); |
|
2231 if (tk == T_PUBLIC || tk == T_PROTECTED || tk == T_PRIVATE) |
|
2232 ast->access_specifier_token = consumeToken(); |
|
2233 } else { |
|
2234 int tk = LA(); |
|
2235 if (tk == T_PUBLIC || tk == T_PROTECTED || tk == T_PRIVATE) |
|
2236 ast->access_specifier_token = consumeToken(); |
|
2237 |
|
2238 if (LA() == T_VIRTUAL) |
|
2239 ast->virtual_token = consumeToken(); |
|
2240 } |
|
2241 |
|
2242 parseName(ast->name); |
|
2243 if (! ast->name) |
|
2244 _translationUnit->error(cursor(), "expected class-name"); |
|
2245 |
|
2246 node = new (_pool) BaseSpecifierListAST; |
|
2247 node->value = ast; |
|
2248 return true; |
|
2249 } |
|
2250 |
|
2251 bool Parser::parseInitializerList(ExpressionListAST *&node) |
|
2252 { |
|
2253 DEBUG_THIS_RULE(); |
|
2254 ExpressionListAST **initializer_ptr = &node; |
|
2255 ExpressionAST *initializer = 0; |
|
2256 if (parseInitializerClause(initializer)) { |
|
2257 *initializer_ptr = new (_pool) ExpressionListAST; |
|
2258 (*initializer_ptr)->value = initializer; |
|
2259 initializer_ptr = &(*initializer_ptr)->next; |
|
2260 while (LA() == T_COMMA) { |
|
2261 consumeToken(); // consume T_COMMA |
|
2262 initializer = 0; |
|
2263 parseInitializerClause(initializer); |
|
2264 *initializer_ptr = new (_pool) ExpressionListAST; |
|
2265 (*initializer_ptr)->value = initializer; |
|
2266 initializer_ptr = &(*initializer_ptr)->next; |
|
2267 } |
|
2268 } |
|
2269 return true; |
|
2270 } |
|
2271 |
|
2272 bool Parser::parseInitializerClause(ExpressionAST *&node) |
|
2273 { |
|
2274 DEBUG_THIS_RULE(); |
|
2275 if (LA() == T_LBRACE) { |
|
2276 ArrayInitializerAST *ast = new (_pool) ArrayInitializerAST; |
|
2277 ast->lbrace_token = consumeToken(); |
|
2278 parseInitializerList(ast->expression_list); |
|
2279 match(T_RBRACE, &ast->rbrace_token); |
|
2280 node = ast; |
|
2281 return true; |
|
2282 } |
|
2283 return parseAssignmentExpression(node); |
|
2284 } |
|
2285 |
|
2286 bool Parser::parseUnqualifiedName(NameAST *&node, bool acceptTemplateId) |
|
2287 { |
|
2288 DEBUG_THIS_RULE(); |
|
2289 if (LA() == T_TILDE && LA(2) == T_IDENTIFIER) { |
|
2290 DestructorNameAST *ast = new (_pool) DestructorNameAST; |
|
2291 ast->tilde_token = consumeToken(); |
|
2292 ast->identifier_token = consumeToken(); |
|
2293 node = ast; |
|
2294 return true; |
|
2295 } else if (LA() == T_OPERATOR) { |
|
2296 unsigned operator_token = cursor(); |
|
2297 if (parseOperatorFunctionId(node)) |
|
2298 return true; |
|
2299 rewind(operator_token); |
|
2300 return parseConversionFunctionId(node); |
|
2301 } else if (LA() == T_IDENTIFIER) { |
|
2302 unsigned identifier_token = cursor(); |
|
2303 if (acceptTemplateId && LA(2) == T_LESS && parseTemplateId(node)) { |
|
2304 if (! _templateArguments || (LA() == T_COMMA || LA() == T_GREATER || |
|
2305 LA() == T_LPAREN || LA() == T_RPAREN || |
|
2306 LA() == T_COLON_COLON)) |
|
2307 return true; |
|
2308 } |
|
2309 rewind(identifier_token); |
|
2310 SimpleNameAST *ast = new (_pool) SimpleNameAST; |
|
2311 ast->identifier_token = consumeToken(); |
|
2312 node = ast; |
|
2313 return true; |
|
2314 } else if (LA() == T_TEMPLATE) { |
|
2315 unsigned template_token = consumeToken(); |
|
2316 if (parseTemplateId(node)) |
|
2317 return true; |
|
2318 rewind(template_token); |
|
2319 } |
|
2320 return false; |
|
2321 } |
|
2322 |
|
2323 bool Parser::parseStringLiteral(ExpressionAST *&node) |
|
2324 { |
|
2325 DEBUG_THIS_RULE(); |
|
2326 if (! (LA() == T_STRING_LITERAL || LA() == T_WIDE_STRING_LITERAL)) |
|
2327 return false; |
|
2328 |
|
2329 StringLiteralAST **ast = reinterpret_cast<StringLiteralAST **> (&node); |
|
2330 |
|
2331 while (LA() == T_STRING_LITERAL || LA() == T_WIDE_STRING_LITERAL) { |
|
2332 *ast = new (_pool) StringLiteralAST; |
|
2333 (*ast)->literal_token = consumeToken(); |
|
2334 ast = &(*ast)->next; |
|
2335 } |
|
2336 return true; |
|
2337 } |
|
2338 |
|
2339 bool Parser::parseExpressionStatement(StatementAST *&node) |
|
2340 { |
|
2341 DEBUG_THIS_RULE(); |
|
2342 if (LA() == T_SEMICOLON) { |
|
2343 ExpressionStatementAST *ast = new (_pool) ExpressionStatementAST; |
|
2344 match(T_SEMICOLON, &ast->semicolon_token); |
|
2345 node = ast; |
|
2346 return true; |
|
2347 } |
|
2348 |
|
2349 ExpressionAST *expression = 0; |
|
2350 MemoryPool *oldPool = _pool; |
|
2351 MemoryPool tmp; |
|
2352 _pool = &tmp; |
|
2353 if (parseExpression(expression)) { |
|
2354 ExpressionStatementAST *ast = new (oldPool) ExpressionStatementAST; |
|
2355 ast->expression = expression->clone(oldPool); |
|
2356 match(T_SEMICOLON, &ast->semicolon_token); |
|
2357 node = ast; |
|
2358 _pool = oldPool; |
|
2359 return true; |
|
2360 } |
|
2361 _pool = oldPool; |
|
2362 |
|
2363 return false; |
|
2364 } |
|
2365 |
|
2366 bool Parser::parseStatement(StatementAST *&node) |
|
2367 { |
|
2368 DEBUG_THIS_RULE(); |
|
2369 switch (LA()) { |
|
2370 case T_WHILE: |
|
2371 return parseWhileStatement(node); |
|
2372 |
|
2373 case T_DO: |
|
2374 return parseDoStatement(node); |
|
2375 |
|
2376 case T_Q_FOREACH: |
|
2377 return parseForeachStatement(node); |
|
2378 |
|
2379 case T_FOR: |
|
2380 return parseForStatement(node); |
|
2381 |
|
2382 case T_IF: |
|
2383 return parseIfStatement(node); |
|
2384 |
|
2385 case T_SWITCH: |
|
2386 return parseSwitchStatement(node); |
|
2387 |
|
2388 case T_TRY: |
|
2389 return parseTryBlockStatement(node); |
|
2390 |
|
2391 case T_CASE: |
|
2392 case T_DEFAULT: |
|
2393 return parseLabeledStatement(node); |
|
2394 |
|
2395 case T_BREAK: |
|
2396 return parseBreakStatement(node); |
|
2397 |
|
2398 case T_CONTINUE: |
|
2399 return parseContinueStatement(node); |
|
2400 |
|
2401 case T_GOTO: |
|
2402 return parseGotoStatement(node); |
|
2403 |
|
2404 case T_RETURN: |
|
2405 return parseReturnStatement(node); |
|
2406 |
|
2407 case T_LBRACE: |
|
2408 return parseCompoundStatement(node); |
|
2409 |
|
2410 case T_ASM: |
|
2411 case T_NAMESPACE: |
|
2412 case T_USING: |
|
2413 case T_TEMPLATE: |
|
2414 case T_CLASS: case T_STRUCT: case T_UNION: |
|
2415 return parseDeclarationStatement(node); |
|
2416 |
|
2417 case T_SEMICOLON: { |
|
2418 ExpressionStatementAST *ast = new (_pool) ExpressionStatementAST; |
|
2419 ast->semicolon_token = consumeToken(); |
|
2420 node = ast; |
|
2421 return true; |
|
2422 } |
|
2423 |
|
2424 case T_AT_SYNCHRONIZED: |
|
2425 return objCEnabled() && parseObjCSynchronizedStatement(node); |
|
2426 |
|
2427 case T_Q_D: |
|
2428 case T_Q_Q: { |
|
2429 QtMemberDeclarationAST *ast = new (_pool) QtMemberDeclarationAST; |
|
2430 ast->q_token = consumeToken(); |
|
2431 match(T_LPAREN, &ast->lparen_token); |
|
2432 parseTypeId(ast->type_id); |
|
2433 match(T_RPAREN, &ast->rparen_token); |
|
2434 node = ast; |
|
2435 } return true; |
|
2436 |
|
2437 default: |
|
2438 if (LA() == T_IDENTIFIER && LA(2) == T_COLON) |
|
2439 return parseLabeledStatement(node); |
|
2440 |
|
2441 return parseExpressionOrDeclarationStatement(node); |
|
2442 } // switch |
|
2443 return false; //Avoid compiler warning |
|
2444 } |
|
2445 |
|
2446 bool Parser::parseBreakStatement(StatementAST *&node) |
|
2447 { |
|
2448 DEBUG_THIS_RULE(); |
|
2449 if (LA() == T_BREAK) { |
|
2450 BreakStatementAST *ast = new (_pool) BreakStatementAST; |
|
2451 ast->break_token = consumeToken(); |
|
2452 match(T_SEMICOLON, &ast->semicolon_token); |
|
2453 node = ast; |
|
2454 return true; |
|
2455 } |
|
2456 return false; |
|
2457 } |
|
2458 |
|
2459 bool Parser::parseContinueStatement(StatementAST *&node) |
|
2460 { |
|
2461 DEBUG_THIS_RULE(); |
|
2462 if (LA() == T_CONTINUE) { |
|
2463 ContinueStatementAST *ast = new (_pool) ContinueStatementAST; |
|
2464 ast->continue_token = consumeToken(); |
|
2465 match(T_SEMICOLON, &ast->semicolon_token); |
|
2466 node = ast; |
|
2467 return true; |
|
2468 } |
|
2469 return false; |
|
2470 } |
|
2471 |
|
2472 bool Parser::parseGotoStatement(StatementAST *&node) |
|
2473 { |
|
2474 DEBUG_THIS_RULE(); |
|
2475 if (LA() == T_GOTO) { |
|
2476 GotoStatementAST *ast = new (_pool) GotoStatementAST; |
|
2477 ast->goto_token = consumeToken(); |
|
2478 match(T_IDENTIFIER, &ast->identifier_token); |
|
2479 match(T_SEMICOLON, &ast->semicolon_token); |
|
2480 node = ast; |
|
2481 return true; |
|
2482 } |
|
2483 return false; |
|
2484 } |
|
2485 |
|
2486 bool Parser::parseReturnStatement(StatementAST *&node) |
|
2487 { |
|
2488 DEBUG_THIS_RULE(); |
|
2489 if (LA() == T_RETURN) { |
|
2490 ReturnStatementAST *ast = new (_pool) ReturnStatementAST; |
|
2491 ast->return_token = consumeToken(); |
|
2492 parseExpression(ast->expression); |
|
2493 match(T_SEMICOLON, &ast->semicolon_token); |
|
2494 node = ast; |
|
2495 return true; |
|
2496 } |
|
2497 return false; |
|
2498 } |
|
2499 |
|
2500 bool Parser::isPointerDeclaration(DeclarationStatementAST *ast) const |
|
2501 { |
|
2502 if (! ast) |
|
2503 return false; |
|
2504 |
|
2505 if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) { |
|
2506 if (SpecifierListAST *spec = declaration->decl_specifier_list) { |
|
2507 if (spec->value->asNamedTypeSpecifier() && ! spec->next) { |
|
2508 if (DeclaratorListAST *declarators = declaration->declarator_list) { |
|
2509 if (DeclaratorAST *declarator = declarators->value) { |
|
2510 if (declarator->ptr_operator_list && declarator->equals_token && declarator->initializer) { |
|
2511 return true; |
|
2512 } |
|
2513 } |
|
2514 } |
|
2515 } |
|
2516 } |
|
2517 } |
|
2518 |
|
2519 return false; |
|
2520 } |
|
2521 |
|
2522 bool Parser::maybeAmbiguousStatement(DeclarationStatementAST *ast) const |
|
2523 { |
|
2524 if (! ast) |
|
2525 return false; |
|
2526 |
|
2527 if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) { |
|
2528 if (SpecifierListAST *spec = declaration->decl_specifier_list) { |
|
2529 if (spec->value->asNamedTypeSpecifier() && ! spec->next) { |
|
2530 if (DeclaratorListAST *declarators = declaration->declarator_list) { |
|
2531 if (DeclaratorAST *declarator = declarators->value) { |
|
2532 if (declarator->core_declarator && |
|
2533 declarator->core_declarator->asNestedDeclarator()) { |
|
2534 // recognized name(id-expression) |
|
2535 return true; |
|
2536 } |
|
2537 } |
|
2538 } |
|
2539 } |
|
2540 |
|
2541 } else if (DeclaratorListAST *declarators = declaration->declarator_list) { |
|
2542 // no decl_specifiers... |
|
2543 if (DeclaratorAST *declarator = declarators->value) { |
|
2544 if (declarator->postfix_declarator_list && declarator->postfix_declarator_list->value->asFunctionDeclarator() |
|
2545 && ! declarator->initializer) { |
|
2546 return false; |
|
2547 } |
|
2548 } |
|
2549 |
|
2550 return true; |
|
2551 } |
|
2552 } |
|
2553 |
|
2554 return false; |
|
2555 } |
|
2556 |
|
2557 bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node) |
|
2558 { |
|
2559 DEBUG_THIS_RULE(); |
|
2560 if (LA() == T_SEMICOLON) |
|
2561 return parseExpressionStatement(node); |
|
2562 |
|
2563 unsigned start = cursor(); |
|
2564 bool blocked = blockErrors(true); |
|
2565 |
|
2566 if (parseDeclarationStatement(node)) { |
|
2567 DeclarationStatementAST *stmt = static_cast<DeclarationStatementAST *>(node); |
|
2568 |
|
2569 if (isPointerDeclaration(stmt)) { |
|
2570 blockErrors(blocked); |
|
2571 return true; |
|
2572 } |
|
2573 |
|
2574 if (! maybeAmbiguousStatement(stmt)) { |
|
2575 unsigned end_of_declaration_statement = cursor(); |
|
2576 rewind(start); |
|
2577 |
|
2578 StatementAST *expression = 0; |
|
2579 if (parseExpressionStatement(expression) && cursor() == end_of_declaration_statement) { |
|
2580 // it's an ambiguous expression-or-declaration statement. |
|
2581 ExpressionOrDeclarationStatementAST *ast = new (_pool) ExpressionOrDeclarationStatementAST; |
|
2582 ast->declaration = node; |
|
2583 ast->expression = expression; |
|
2584 node = ast; |
|
2585 } |
|
2586 |
|
2587 rewind(end_of_declaration_statement); |
|
2588 blockErrors(blocked); |
|
2589 return true; |
|
2590 } |
|
2591 } |
|
2592 |
|
2593 // it's not a declaration statement. |
|
2594 blockErrors(blocked); |
|
2595 rewind(start); |
|
2596 return parseExpressionStatement(node); |
|
2597 } |
|
2598 |
|
2599 bool Parser::parseCondition(ExpressionAST *&node) |
|
2600 { |
|
2601 DEBUG_THIS_RULE(); |
|
2602 unsigned start = cursor(); |
|
2603 |
|
2604 bool blocked = blockErrors(true); |
|
2605 SpecifierListAST *type_specifier = 0; |
|
2606 if (parseTypeSpecifier(type_specifier)) { |
|
2607 DeclaratorAST *declarator = 0; |
|
2608 if (parseInitDeclarator(declarator, /*acceptStructDeclarator=*/false)) { |
|
2609 if (declarator->initializer) { |
|
2610 ConditionAST *ast = new (_pool) ConditionAST; |
|
2611 ast->type_specifier_list = type_specifier; |
|
2612 ast->declarator = declarator; |
|
2613 node = ast; |
|
2614 blockErrors(blocked); |
|
2615 return true; |
|
2616 } |
|
2617 } |
|
2618 } |
|
2619 |
|
2620 blockErrors(blocked); |
|
2621 rewind(start); |
|
2622 return parseExpression(node); |
|
2623 } |
|
2624 |
|
2625 bool Parser::parseWhileStatement(StatementAST *&node) |
|
2626 { |
|
2627 DEBUG_THIS_RULE(); |
|
2628 if (LA() == T_WHILE) { |
|
2629 WhileStatementAST *ast = new (_pool) WhileStatementAST; |
|
2630 ast->while_token = consumeToken(); |
|
2631 match(T_LPAREN, &ast->lparen_token); |
|
2632 parseCondition(ast->condition); |
|
2633 match(T_RPAREN, &ast->rparen_token); |
|
2634 parseStatement(ast->statement); |
|
2635 node = ast; |
|
2636 return true; |
|
2637 } |
|
2638 return true; |
|
2639 } |
|
2640 |
|
2641 bool Parser::parseDoStatement(StatementAST *&node) |
|
2642 { |
|
2643 DEBUG_THIS_RULE(); |
|
2644 if (LA() == T_DO) { |
|
2645 DoStatementAST *ast = new (_pool) DoStatementAST; |
|
2646 ast->do_token = consumeToken(); |
|
2647 parseStatement(ast->statement); |
|
2648 match(T_WHILE, &ast->while_token); |
|
2649 match(T_LPAREN, &ast->lparen_token); |
|
2650 parseExpression(ast->expression); |
|
2651 match(T_RPAREN, &ast->rparen_token); |
|
2652 match(T_SEMICOLON, &ast->semicolon_token); |
|
2653 node = ast; |
|
2654 return true; |
|
2655 } |
|
2656 return false; |
|
2657 } |
|
2658 |
|
2659 bool Parser::parseForeachStatement(StatementAST *&node) |
|
2660 { |
|
2661 DEBUG_THIS_RULE(); |
|
2662 if (LA() == T_Q_FOREACH) { |
|
2663 ForeachStatementAST *ast = new (_pool) ForeachStatementAST; |
|
2664 ast->foreach_token = consumeToken(); |
|
2665 match(T_LPAREN, &ast->lparen_token); |
|
2666 |
|
2667 unsigned startOfTypeSpecifier = cursor(); |
|
2668 bool blocked = blockErrors(true); |
|
2669 |
|
2670 if (parseTypeSpecifier(ast->type_specifier_list)) |
|
2671 parseDeclarator(ast->declarator); |
|
2672 |
|
2673 if (! ast->type_specifier_list || ! ast->declarator) { |
|
2674 ast->type_specifier_list = 0; |
|
2675 ast->declarator = 0; |
|
2676 |
|
2677 blockErrors(blocked); |
|
2678 rewind(startOfTypeSpecifier); |
|
2679 parseAssignmentExpression(ast->initializer); |
|
2680 } |
|
2681 |
|
2682 blockErrors(blocked); |
|
2683 |
|
2684 match(T_COMMA, &ast->comma_token); |
|
2685 parseExpression(ast->expression); |
|
2686 match(T_RPAREN, &ast->rparen_token); |
|
2687 parseStatement(ast->statement); |
|
2688 |
|
2689 node = ast; |
|
2690 return true; |
|
2691 } |
|
2692 return false; |
|
2693 } |
|
2694 |
|
2695 bool Parser::parseForStatement(StatementAST *&node) |
|
2696 { |
|
2697 DEBUG_THIS_RULE(); |
|
2698 if (LA() != T_FOR) |
|
2699 return false; |
|
2700 |
|
2701 unsigned for_token = consumeToken(); |
|
2702 unsigned lparen_token = 0; |
|
2703 match(T_LPAREN, &lparen_token); |
|
2704 |
|
2705 unsigned startOfTypeSpecifier = cursor(); |
|
2706 bool blocked = blockErrors(true); |
|
2707 |
|
2708 if (objCEnabled()) { |
|
2709 ObjCFastEnumerationAST *ast = new (_pool) ObjCFastEnumerationAST; |
|
2710 ast->for_token = for_token; |
|
2711 ast->lparen_token = lparen_token; |
|
2712 |
|
2713 if (parseTypeSpecifier(ast->type_specifier_list)) |
|
2714 parseDeclarator(ast->declarator); |
|
2715 |
|
2716 if ((ast->type_specifier_list || ast->declarator) && !peekAtObjCContextKeyword(Token_in)) { |
|
2717 // woops, probably parsed too much: "in" got parsed as a declarator. Let's redo it: |
|
2718 ast->type_specifier_list = 0; |
|
2719 ast->declarator = 0; |
|
2720 |
|
2721 rewind(startOfTypeSpecifier); |
|
2722 parseDeclarator(ast->declarator); |
|
2723 } |
|
2724 |
|
2725 if (! ast->type_specifier_list || ! ast->declarator) { |
|
2726 ast->type_specifier_list = 0; |
|
2727 ast->declarator = 0; |
|
2728 |
|
2729 rewind(startOfTypeSpecifier); |
|
2730 parseAssignmentExpression(ast->initializer); |
|
2731 } |
|
2732 |
|
2733 if (parseObjCContextKeyword(Token_in, ast->in_token)) { |
|
2734 blockErrors(blocked); |
|
2735 |
|
2736 parseExpression(ast->fast_enumeratable_expression); |
|
2737 match(T_RPAREN, &ast->rparen_token); |
|
2738 parseStatement(ast->statement); |
|
2739 |
|
2740 node = ast; |
|
2741 return true; |
|
2742 } |
|
2743 |
|
2744 // there was no "in" token, so we continue with a normal for-statement |
|
2745 rewind(startOfTypeSpecifier); |
|
2746 } |
|
2747 |
|
2748 blockErrors(blocked); |
|
2749 |
|
2750 // Normal C/C++ for-statement parsing |
|
2751 ForStatementAST *ast = new (_pool) ForStatementAST; |
|
2752 |
|
2753 ast->for_token = for_token; |
|
2754 ast->lparen_token = lparen_token; |
|
2755 parseForInitStatement(ast->initializer); |
|
2756 parseCondition(ast->condition); |
|
2757 match(T_SEMICOLON, &ast->semicolon_token); |
|
2758 parseExpression(ast->expression); |
|
2759 match(T_RPAREN, &ast->rparen_token); |
|
2760 parseStatement(ast->statement); |
|
2761 |
|
2762 node = ast; |
|
2763 return true; |
|
2764 } |
|
2765 |
|
2766 bool Parser::parseForInitStatement(StatementAST *&node) |
|
2767 { |
|
2768 DEBUG_THIS_RULE(); |
|
2769 return parseExpressionOrDeclarationStatement(node); |
|
2770 } |
|
2771 |
|
2772 bool Parser::parseCompoundStatement(StatementAST *&node) |
|
2773 { |
|
2774 DEBUG_THIS_RULE(); |
|
2775 if (LA() == T_LBRACE) { |
|
2776 CompoundStatementAST *ast = new (_pool) CompoundStatementAST; |
|
2777 ast->lbrace_token = consumeToken(); |
|
2778 |
|
2779 // ### TODO: the GNU "local label" extension: "__label__ X, Y, Z;" |
|
2780 // These are only allowed at the start of a compound stmt regardless of the language. |
|
2781 |
|
2782 StatementListAST **statement_ptr = &ast->statement_list; |
|
2783 while (int tk = LA()) { |
|
2784 if (tk == T_RBRACE) |
|
2785 break; |
|
2786 |
|
2787 unsigned start_statement = cursor(); |
|
2788 StatementAST *statement = 0; |
|
2789 if (! parseStatement(statement)) { |
|
2790 rewind(start_statement + 1); |
|
2791 skipUntilStatement(); |
|
2792 } else { |
|
2793 *statement_ptr = new (_pool) StatementListAST; |
|
2794 (*statement_ptr)->value = statement; |
|
2795 statement_ptr = &(*statement_ptr)->next; |
|
2796 } |
|
2797 } |
|
2798 match(T_RBRACE, &ast->rbrace_token); |
|
2799 node = ast; |
|
2800 return true; |
|
2801 } |
|
2802 return false; |
|
2803 } |
|
2804 |
|
2805 bool Parser::parseIfStatement(StatementAST *&node) |
|
2806 { |
|
2807 DEBUG_THIS_RULE(); |
|
2808 if (LA() == T_IF) { |
|
2809 IfStatementAST *ast = new (_pool) IfStatementAST; |
|
2810 ast->if_token = consumeToken(); |
|
2811 match(T_LPAREN, &ast->lparen_token); |
|
2812 parseCondition(ast->condition); |
|
2813 match(T_RPAREN, &ast->rparen_token); |
|
2814 if (! parseStatement(ast->statement)) |
|
2815 _translationUnit->error(cursor(), "expected statement"); |
|
2816 if (LA() == T_ELSE) { |
|
2817 ast->else_token = consumeToken(); |
|
2818 if (! parseStatement(ast->else_statement)) |
|
2819 _translationUnit->error(cursor(), "expected statement"); |
|
2820 } |
|
2821 node = ast; |
|
2822 return true; |
|
2823 } |
|
2824 return false; |
|
2825 } |
|
2826 |
|
2827 bool Parser::parseSwitchStatement(StatementAST *&node) |
|
2828 { |
|
2829 DEBUG_THIS_RULE(); |
|
2830 if (LA() == T_SWITCH) { |
|
2831 SwitchStatementAST *ast = new (_pool) SwitchStatementAST; |
|
2832 ast->switch_token = consumeToken(); |
|
2833 match(T_LPAREN, &ast->lparen_token); |
|
2834 parseCondition(ast->condition); |
|
2835 match(T_RPAREN, &ast->rparen_token); |
|
2836 parseStatement(ast->statement); |
|
2837 node = ast; |
|
2838 return true; |
|
2839 } |
|
2840 return false; |
|
2841 } |
|
2842 |
|
2843 bool Parser::parseLabeledStatement(StatementAST *&node) |
|
2844 { |
|
2845 DEBUG_THIS_RULE(); |
|
2846 switch (LA()) { |
|
2847 case T_IDENTIFIER: |
|
2848 if (LA(2) == T_COLON) { |
|
2849 LabeledStatementAST *ast = new (_pool) LabeledStatementAST; |
|
2850 ast->label_token = consumeToken(); |
|
2851 ast->colon_token = consumeToken(); |
|
2852 parseStatement(ast->statement); |
|
2853 node = ast; |
|
2854 return true; |
|
2855 } |
|
2856 break; |
|
2857 |
|
2858 case T_DEFAULT: { |
|
2859 LabeledStatementAST *ast = new (_pool) LabeledStatementAST; |
|
2860 ast->label_token = consumeToken(); |
|
2861 match(T_COLON, &ast->colon_token); |
|
2862 parseStatement(ast->statement); |
|
2863 node = ast; |
|
2864 return true; |
|
2865 } |
|
2866 |
|
2867 case T_CASE: { |
|
2868 CaseStatementAST *ast = new (_pool) CaseStatementAST; |
|
2869 ast->case_token = consumeToken(); |
|
2870 parseConstantExpression(ast->expression); |
|
2871 match(T_COLON, &ast->colon_token); |
|
2872 parseStatement(ast->statement); |
|
2873 node = ast; |
|
2874 return true; |
|
2875 } |
|
2876 |
|
2877 default: |
|
2878 break; |
|
2879 } // switch |
|
2880 return false; |
|
2881 } |
|
2882 |
|
2883 bool Parser::parseBlockDeclaration(DeclarationAST *&node) |
|
2884 { |
|
2885 DEBUG_THIS_RULE(); |
|
2886 switch (LA()) { |
|
2887 case T_USING: |
|
2888 return parseUsing(node); |
|
2889 |
|
2890 case T_ASM: |
|
2891 return parseAsmDefinition(node); |
|
2892 |
|
2893 case T_NAMESPACE: |
|
2894 return parseNamespaceAliasDefinition(node); |
|
2895 |
|
2896 default: |
|
2897 return parseSimpleDeclaration(node); |
|
2898 } // switch |
|
2899 |
|
2900 } |
|
2901 |
|
2902 bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&node) |
|
2903 { |
|
2904 DEBUG_THIS_RULE(); |
|
2905 if (LA() == T_NAMESPACE && LA(2) == T_IDENTIFIER && LA(3) == T_EQUAL) { |
|
2906 NamespaceAliasDefinitionAST *ast = new (_pool) NamespaceAliasDefinitionAST; |
|
2907 ast->namespace_token = consumeToken(); |
|
2908 ast->namespace_name_token = consumeToken(); |
|
2909 ast->equal_token = consumeToken(); |
|
2910 parseName(ast->name); |
|
2911 match(T_SEMICOLON, &ast->semicolon_token); |
|
2912 node = ast; |
|
2913 return true; |
|
2914 } |
|
2915 return false; |
|
2916 } |
|
2917 |
|
2918 bool Parser::parseDeclarationStatement(StatementAST *&node) |
|
2919 { |
|
2920 DEBUG_THIS_RULE(); |
|
2921 unsigned start = cursor(); |
|
2922 DeclarationAST *declaration = 0; |
|
2923 if (! parseBlockDeclaration(declaration)) |
|
2924 return false; |
|
2925 |
|
2926 if (SimpleDeclarationAST *simpleDeclaration = declaration->asSimpleDeclaration()) { |
|
2927 if (! simpleDeclaration->decl_specifier_list) { |
|
2928 rewind(start); |
|
2929 return false; |
|
2930 } |
|
2931 } |
|
2932 |
|
2933 DeclarationStatementAST *ast = new (_pool) DeclarationStatementAST; |
|
2934 ast->declaration = declaration; |
|
2935 node = ast; |
|
2936 return true; |
|
2937 } |
|
2938 |
|
2939 bool Parser::lookAtCVQualifier() const |
|
2940 { |
|
2941 switch (LA()) { |
|
2942 case T_CONST: |
|
2943 case T_VOLATILE: |
|
2944 return true; |
|
2945 default: |
|
2946 return false; |
|
2947 } |
|
2948 } |
|
2949 |
|
2950 bool Parser::lookAtFunctionSpecifier() const |
|
2951 { |
|
2952 switch (LA()) { |
|
2953 case T_INLINE: |
|
2954 case T_VIRTUAL: |
|
2955 case T_EXPLICIT: |
|
2956 return true; |
|
2957 default: |
|
2958 return false; |
|
2959 } |
|
2960 } |
|
2961 |
|
2962 bool Parser::lookAtStorageClassSpecifier() const |
|
2963 { |
|
2964 switch (LA()) { |
|
2965 case T_FRIEND: |
|
2966 case T_AUTO: |
|
2967 case T_REGISTER: |
|
2968 case T_STATIC: |
|
2969 case T_EXTERN: |
|
2970 case T_MUTABLE: |
|
2971 case T_TYPEDEF: |
|
2972 return true; |
|
2973 default: |
|
2974 return false; |
|
2975 } |
|
2976 } |
|
2977 |
|
2978 bool Parser::lookAtBuiltinTypeSpecifier() const |
|
2979 { |
|
2980 switch (LA()) { |
|
2981 case T_CHAR: |
|
2982 case T_WCHAR_T: |
|
2983 case T_BOOL: |
|
2984 case T_SHORT: |
|
2985 case T_INT: |
|
2986 case T_LONG: |
|
2987 case T_SIGNED: |
|
2988 case T_UNSIGNED: |
|
2989 case T_FLOAT: |
|
2990 case T_DOUBLE: |
|
2991 case T_VOID: |
|
2992 return true; |
|
2993 // [gcc] extensions |
|
2994 case T___TYPEOF__: |
|
2995 case T___ATTRIBUTE__: |
|
2996 return true; |
|
2997 default: |
|
2998 return false; |
|
2999 } |
|
3000 } |
|
3001 |
|
3002 bool Parser::lookAtClassKey() const |
|
3003 { |
|
3004 switch (LA()) { |
|
3005 case T_CLASS: |
|
3006 case T_STRUCT: |
|
3007 case T_UNION: |
|
3008 return true; |
|
3009 default: |
|
3010 return false; |
|
3011 } |
|
3012 } |
|
3013 |
|
3014 bool Parser::parseAttributeSpecifier(SpecifierListAST *&node) |
|
3015 { |
|
3016 DEBUG_THIS_RULE(); |
|
3017 if (LA() != T___ATTRIBUTE__) |
|
3018 return false; |
|
3019 |
|
3020 AttributeSpecifierAST *ast = new (_pool) AttributeSpecifierAST; |
|
3021 ast->attribute_token = consumeToken(); |
|
3022 match(T_LPAREN, &ast->first_lparen_token); |
|
3023 match(T_LPAREN, &ast->second_lparen_token); |
|
3024 parseAttributeList(ast->attribute_list); |
|
3025 match(T_RPAREN, &ast->first_rparen_token); |
|
3026 match(T_RPAREN, &ast->second_rparen_token); |
|
3027 node = new (_pool) SpecifierListAST(ast); |
|
3028 return true; |
|
3029 } |
|
3030 |
|
3031 bool Parser::parseAttributeList(AttributeListAST *&node) |
|
3032 { |
|
3033 DEBUG_THIS_RULE(); |
|
3034 |
|
3035 AttributeListAST **iter = &node; |
|
3036 while (LA() == T_CONST || LA() == T_IDENTIFIER) { |
|
3037 *iter = new (_pool) AttributeListAST; |
|
3038 |
|
3039 if (LA() == T_CONST) { |
|
3040 AttributeAST *attr = new (_pool) AttributeAST; |
|
3041 attr->identifier_token = consumeToken(); |
|
3042 |
|
3043 (*iter)->value = attr; |
|
3044 iter = &(*iter)->next; |
|
3045 } else if (LA() == T_IDENTIFIER) { |
|
3046 AttributeAST *attr = new (_pool) AttributeAST; |
|
3047 attr->identifier_token = consumeToken(); |
|
3048 if (LA() == T_LPAREN) { |
|
3049 attr->lparen_token = consumeToken(); |
|
3050 parseExpressionList(attr->expression_list); |
|
3051 match(T_RPAREN, &attr->rparen_token); |
|
3052 } |
|
3053 |
|
3054 (*iter)->value = attr; |
|
3055 iter = &(*iter)->next; |
|
3056 } |
|
3057 |
|
3058 if (LA() != T_COMMA) |
|
3059 break; |
|
3060 |
|
3061 consumeToken(); // skip T_COMMA |
|
3062 } |
|
3063 |
|
3064 return true; |
|
3065 } |
|
3066 |
|
3067 bool Parser::parseBuiltinTypeSpecifier(SpecifierListAST *&node) |
|
3068 { |
|
3069 DEBUG_THIS_RULE(); |
|
3070 if (LA() == T___ATTRIBUTE__) { |
|
3071 return parseAttributeSpecifier(node); |
|
3072 } else if (LA() == T___TYPEOF__) { |
|
3073 TypeofSpecifierAST *ast = new (_pool) TypeofSpecifierAST; |
|
3074 ast->typeof_token = consumeToken(); |
|
3075 if (LA() == T_LPAREN) { |
|
3076 unsigned lparen_token = consumeToken(); |
|
3077 if (parseTypeId(ast->expression) && LA() == T_RPAREN) { |
|
3078 ast->lparen_token = lparen_token; |
|
3079 ast->rparen_token = consumeToken(); |
|
3080 node = new (_pool) SpecifierListAST(ast); |
|
3081 return true; |
|
3082 } |
|
3083 rewind(lparen_token); |
|
3084 } |
|
3085 parseUnaryExpression(ast->expression); |
|
3086 node = new (_pool) SpecifierListAST(ast); |
|
3087 return true; |
|
3088 } else if (lookAtBuiltinTypeSpecifier()) { |
|
3089 SimpleSpecifierAST *ast = new (_pool) SimpleSpecifierAST; |
|
3090 ast->specifier_token = consumeToken(); |
|
3091 node = new (_pool) SpecifierListAST(ast); |
|
3092 return true; |
|
3093 } |
|
3094 return false; |
|
3095 } |
|
3096 |
|
3097 bool Parser::parseSimpleDeclaration(DeclarationAST *&node, |
|
3098 bool acceptStructDeclarator) |
|
3099 { |
|
3100 DEBUG_THIS_RULE(); |
|
3101 unsigned qt_invokable_token = 0; |
|
3102 if (acceptStructDeclarator && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT)) |
|
3103 qt_invokable_token = consumeToken(); |
|
3104 #ifdef ICHECK_BUILD |
|
3105 unsigned invoke_token = 0; |
|
3106 if (LA() == T_Q_INVOKABLE) |
|
3107 invoke_token = consumeToken(); |
|
3108 #endif |
|
3109 |
|
3110 // parse a simple declaration, a function definition, |
|
3111 // or a contructor declaration. |
|
3112 bool has_type_specifier = false; |
|
3113 bool has_complex_type_specifier = false; |
|
3114 unsigned startOfNamedTypeSpecifier = 0; |
|
3115 NameAST *named_type_specifier = 0; |
|
3116 SpecifierListAST *decl_specifier_seq = 0, |
|
3117 **decl_specifier_seq_ptr = &decl_specifier_seq; |
|
3118 for (;;) { |
|
3119 if (lookAtCVQualifier() || lookAtFunctionSpecifier() |
|
3120 || lookAtStorageClassSpecifier()) { |
|
3121 SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST; |
|
3122 spec->specifier_token = consumeToken(); |
|
3123 *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec); |
|
3124 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
3125 } else if (LA() == T___ATTRIBUTE__) { |
|
3126 parseAttributeSpecifier(*decl_specifier_seq_ptr); |
|
3127 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
3128 } else if (! named_type_specifier && ! has_complex_type_specifier && lookAtBuiltinTypeSpecifier()) { |
|
3129 parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr); |
|
3130 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
3131 has_type_specifier = true; |
|
3132 } else if (! has_type_specifier && (LA() == T_COLON_COLON || |
|
3133 LA() == T_IDENTIFIER)) { |
|
3134 startOfNamedTypeSpecifier = cursor(); |
|
3135 if (parseName(named_type_specifier)) { |
|
3136 NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST; |
|
3137 spec->name = named_type_specifier; |
|
3138 *decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec); |
|
3139 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
3140 has_type_specifier = true; |
|
3141 } else { |
|
3142 rewind(startOfNamedTypeSpecifier); |
|
3143 break; |
|
3144 } |
|
3145 } else if (! has_type_specifier && LA() == T_ENUM) { |
|
3146 unsigned startOfTypeSpecifier = cursor(); |
|
3147 if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr) || LA() == T_LBRACE) { |
|
3148 rewind(startOfTypeSpecifier); |
|
3149 if (! parseEnumSpecifier(*decl_specifier_seq_ptr)) { |
|
3150 _translationUnit->error(startOfTypeSpecifier, |
|
3151 "expected an enum specifier"); |
|
3152 break; |
|
3153 } |
|
3154 has_complex_type_specifier = true; |
|
3155 } |
|
3156 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
3157 has_type_specifier = true; |
|
3158 } else if (! has_type_specifier && LA() == T_TYPENAME) { |
|
3159 unsigned startOfElaboratedTypeSpecifier = cursor(); |
|
3160 if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) { |
|
3161 _translationUnit->error(startOfElaboratedTypeSpecifier, |
|
3162 "expected an elaborated type specifier"); |
|
3163 break; |
|
3164 } |
|
3165 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
3166 has_type_specifier = true; |
|
3167 } else if (! has_type_specifier && lookAtClassKey()) { |
|
3168 unsigned startOfTypeSpecifier = cursor(); |
|
3169 if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr) || |
|
3170 (LA() == T_COLON || LA() == T_LBRACE || (LA(0) == T_IDENTIFIER && LA(1) == T_IDENTIFIER && |
|
3171 (LA(2) == T_COLON || LA(2) == T_LBRACE)))) { |
|
3172 rewind(startOfTypeSpecifier); |
|
3173 if (! parseClassSpecifier(*decl_specifier_seq_ptr)) { |
|
3174 _translationUnit->error(startOfTypeSpecifier, |
|
3175 "wrong type specifier"); |
|
3176 break; |
|
3177 } |
|
3178 has_complex_type_specifier = true; |
|
3179 } |
|
3180 decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; |
|
3181 has_type_specifier = true; |
|
3182 } else |
|
3183 break; |
|
3184 } |
|
3185 |
|
3186 DeclaratorListAST *declarator_list = 0, |
|
3187 **declarator_ptr = &declarator_list; |
|
3188 |
|
3189 DeclaratorAST *declarator = 0; |
|
3190 |
|
3191 if (LA() != T_SEMICOLON) { |
|
3192 const bool maybeCtor = (LA() == T_LPAREN && named_type_specifier); |
|
3193 if (! parseInitDeclarator(declarator, acceptStructDeclarator) && maybeCtor) { |
|
3194 rewind(startOfNamedTypeSpecifier); |
|
3195 named_type_specifier = 0; |
|
3196 // pop the named type specifier from the decl-specifier-seq |
|
3197 SpecifierListAST **spec_ptr = &decl_specifier_seq; |
|
3198 for (; *spec_ptr; spec_ptr = &(*spec_ptr)->next) { |
|
3199 if (! (*spec_ptr)->next) { |
|
3200 *spec_ptr = 0; |
|
3201 break; |
|
3202 } |
|
3203 } |
|
3204 if (! parseInitDeclarator(declarator, acceptStructDeclarator)) |
|
3205 return false; |
|
3206 } |
|
3207 } |
|
3208 |
|
3209 // if there is no valid declarator |
|
3210 // and it doesn't look like a fwd or a class declaration |
|
3211 // then it's not a declarations |
|
3212 if (! declarator && ! maybeForwardOrClassDeclaration(decl_specifier_seq)) |
|
3213 return false; |
|
3214 |
|
3215 DeclaratorAST *firstDeclarator = declarator; |
|
3216 |
|
3217 if (declarator) { |
|
3218 *declarator_ptr = new (_pool) DeclaratorListAST; |
|
3219 (*declarator_ptr)->value = declarator; |
|
3220 declarator_ptr = &(*declarator_ptr)->next; |
|
3221 } |
|
3222 |
|
3223 if (LA() == T_COMMA || LA() == T_SEMICOLON || has_complex_type_specifier) { |
|
3224 while (LA() == T_COMMA) { |
|
3225 consumeToken(); // consume T_COMMA |
|
3226 |
|
3227 declarator = 0; |
|
3228 if (parseInitDeclarator(declarator, acceptStructDeclarator)) { |
|
3229 *declarator_ptr = new (_pool) DeclaratorListAST; |
|
3230 (*declarator_ptr)->value = declarator; |
|
3231 declarator_ptr = &(*declarator_ptr)->next; |
|
3232 } |
|
3233 } |
|
3234 SimpleDeclarationAST *ast = new (_pool) SimpleDeclarationAST; |
|
3235 ast->qt_invokable_token = qt_invokable_token; |
|
3236 #ifdef ICHECK_BUILD |
|
3237 ast->invoke_token = invoke_token; |
|
3238 #endif |
|
3239 ast->decl_specifier_list = decl_specifier_seq; |
|
3240 ast->declarator_list = declarator_list; |
|
3241 match(T_SEMICOLON, &ast->semicolon_token); |
|
3242 node = ast; |
|
3243 return true; |
|
3244 } else if (! _inFunctionBody && declarator && (LA() == T_COLON || LA() == T_LBRACE || LA() == T_TRY)) { |
|
3245 CtorInitializerAST *ctor_initializer = 0; |
|
3246 bool hasCtorInitializer = false; |
|
3247 if (LA() == T_COLON) { |
|
3248 hasCtorInitializer = true; |
|
3249 parseCtorInitializer(ctor_initializer); |
|
3250 |
|
3251 if (LA() != T_LBRACE) { |
|
3252 const unsigned pos = cursor(); |
|
3253 |
|
3254 for (int n = 0; n < 3 && LA(); consumeToken(), ++n) |
|
3255 if (LA() == T_LBRACE) |
|
3256 break; |
|
3257 |
|
3258 if (LA() != T_LBRACE) { |
|
3259 _translationUnit->error(pos, "unexpected token `%s'", _translationUnit->spell(pos)); |
|
3260 rewind(pos); |
|
3261 } |
|
3262 } |
|
3263 } |
|
3264 |
|
3265 if (LA() == T_LBRACE || hasCtorInitializer) { |
|
3266 FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST; |
|
3267 ast->qt_invokable_token = qt_invokable_token; |
|
3268 #ifdef ICHECK_BUILD |
|
3269 ast->invoke_token = invoke_token; |
|
3270 #endif |
|
3271 ast->decl_specifier_list = decl_specifier_seq; |
|
3272 ast->declarator = firstDeclarator; |
|
3273 ast->ctor_initializer = ctor_initializer; |
|
3274 parseFunctionBody(ast->function_body); |
|
3275 node = ast; |
|
3276 return true; // recognized a function definition. |
|
3277 } else if (LA() == T_TRY) { |
|
3278 FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST; |
|
3279 ast->qt_invokable_token = qt_invokable_token; |
|
3280 #ifdef ICHECK_BUILD |
|
3281 ast->invoke_token = invoke_token; |
|
3282 #endif |
|
3283 ast->decl_specifier_list = decl_specifier_seq; |
|
3284 ast->declarator = firstDeclarator; |
|
3285 ast->ctor_initializer = ctor_initializer; |
|
3286 parseTryBlockStatement(ast->function_body); |
|
3287 node = ast; |
|
3288 return true; // recognized a function definition. |
|
3289 } |
|
3290 } |
|
3291 |
|
3292 _translationUnit->error(cursor(), "unexpected token `%s'", tok().spell()); |
|
3293 return false; |
|
3294 } |
|
3295 |
|
3296 bool Parser::maybeForwardOrClassDeclaration(SpecifierListAST *decl_specifier_seq) const |
|
3297 { |
|
3298 // look at the decl_specifier for possible fwd or class declarations. |
|
3299 if (SpecifierListAST *it = decl_specifier_seq) { |
|
3300 while (it) { |
|
3301 SimpleSpecifierAST *spec = it->value->asSimpleSpecifier(); |
|
3302 if (spec && _translationUnit->tokenKind(spec->specifier_token) == T_FRIEND) |
|
3303 it = it->next; |
|
3304 else |
|
3305 break; |
|
3306 } |
|
3307 |
|
3308 if (it) { |
|
3309 SpecifierAST *spec = it->value; |
|
3310 |
|
3311 if (! it->next && (spec->asElaboratedTypeSpecifier() || |
|
3312 spec->asEnumSpecifier() || |
|
3313 spec->asClassSpecifier())) |
|
3314 return true; |
|
3315 } |
|
3316 } |
|
3317 |
|
3318 return false; |
|
3319 } |
|
3320 |
|
3321 bool Parser::parseFunctionBody(StatementAST *&node) |
|
3322 { |
|
3323 DEBUG_THIS_RULE(); |
|
3324 if (_translationUnit->skipFunctionBody()) { |
|
3325 unsigned token_lbrace = 0; |
|
3326 match(T_LBRACE, &token_lbrace); |
|
3327 if (! token_lbrace) |
|
3328 return false; |
|
3329 |
|
3330 const Token &tk = _translationUnit->tokenAt(token_lbrace); |
|
3331 if (tk.close_brace) |
|
3332 rewind(tk.close_brace); |
|
3333 unsigned token_rbrace = 0; |
|
3334 match(T_RBRACE, &token_rbrace); |
|
3335 return true; |
|
3336 } |
|
3337 |
|
3338 _inFunctionBody = true; |
|
3339 const bool parsed = parseCompoundStatement(node); |
|
3340 _inFunctionBody = false; |
|
3341 return parsed; |
|
3342 } |
|
3343 |
|
3344 bool Parser::parseTryBlockStatement(StatementAST *&node) |
|
3345 { |
|
3346 DEBUG_THIS_RULE(); |
|
3347 if (LA() == T_TRY) { |
|
3348 TryBlockStatementAST *ast = new (_pool) TryBlockStatementAST; |
|
3349 ast->try_token = consumeToken(); |
|
3350 parseCompoundStatement(ast->statement); |
|
3351 CatchClauseListAST **catch_clause_ptr = &ast->catch_clause_list; |
|
3352 while (parseCatchClause(*catch_clause_ptr)) |
|
3353 catch_clause_ptr = &(*catch_clause_ptr)->next; |
|
3354 node = ast; |
|
3355 return true; |
|
3356 } |
|
3357 return false; |
|
3358 } |
|
3359 |
|
3360 bool Parser::parseCatchClause(CatchClauseListAST *&node) |
|
3361 { |
|
3362 DEBUG_THIS_RULE(); |
|
3363 if (LA() == T_CATCH) { |
|
3364 CatchClauseAST *ast = new (_pool) CatchClauseAST; |
|
3365 ast->catch_token = consumeToken(); |
|
3366 match(T_LPAREN, &ast->lparen_token); |
|
3367 parseExceptionDeclaration(ast->exception_declaration); |
|
3368 match(T_RPAREN, &ast->rparen_token); |
|
3369 parseCompoundStatement(ast->statement); |
|
3370 node = new (_pool) CatchClauseListAST(ast); |
|
3371 return true; |
|
3372 } |
|
3373 return false; |
|
3374 } |
|
3375 |
|
3376 bool Parser::parseExceptionDeclaration(ExceptionDeclarationAST *&node) |
|
3377 { |
|
3378 DEBUG_THIS_RULE(); |
|
3379 if (LA() == T_DOT_DOT_DOT) { |
|
3380 ExceptionDeclarationAST *ast = new (_pool) ExceptionDeclarationAST; |
|
3381 ast->dot_dot_dot_token = consumeToken(); |
|
3382 node = ast; |
|
3383 return true; |
|
3384 } |
|
3385 |
|
3386 SpecifierListAST *type_specifier = 0; |
|
3387 if (parseTypeSpecifier(type_specifier)) { |
|
3388 ExceptionDeclarationAST *ast = new (_pool) ExceptionDeclarationAST; |
|
3389 ast->type_specifier_list = type_specifier; |
|
3390 parseDeclaratorOrAbstractDeclarator(ast->declarator); |
|
3391 node = ast; |
|
3392 return true; |
|
3393 } |
|
3394 return false; |
|
3395 } |
|
3396 |
|
3397 bool Parser::parseBoolLiteral(ExpressionAST *&node) |
|
3398 { |
|
3399 DEBUG_THIS_RULE(); |
|
3400 if (LA() == T_TRUE || LA() == T_FALSE) { |
|
3401 BoolLiteralAST *ast = new (_pool) BoolLiteralAST; |
|
3402 ast->literal_token = consumeToken(); |
|
3403 node = ast; |
|
3404 return true; |
|
3405 } |
|
3406 return false; |
|
3407 } |
|
3408 |
|
3409 bool Parser::parseNumericLiteral(ExpressionAST *&node) |
|
3410 { |
|
3411 DEBUG_THIS_RULE(); |
|
3412 if (LA() == T_NUMERIC_LITERAL || |
|
3413 LA() == T_CHAR_LITERAL || |
|
3414 LA() == T_WIDE_CHAR_LITERAL) { |
|
3415 NumericLiteralAST *ast = new (_pool) NumericLiteralAST; |
|
3416 ast->literal_token = consumeToken(); |
|
3417 node = ast; |
|
3418 return true; |
|
3419 } |
|
3420 return false; |
|
3421 } |
|
3422 |
|
3423 bool Parser::parseThisExpression(ExpressionAST *&node) |
|
3424 { |
|
3425 DEBUG_THIS_RULE(); |
|
3426 if (LA() == T_THIS) { |
|
3427 ThisExpressionAST *ast = new (_pool) ThisExpressionAST; |
|
3428 ast->this_token = consumeToken(); |
|
3429 node = ast; |
|
3430 return true; |
|
3431 } |
|
3432 return false; |
|
3433 } |
|
3434 |
|
3435 bool Parser::parsePrimaryExpression(ExpressionAST *&node) |
|
3436 { |
|
3437 DEBUG_THIS_RULE(); |
|
3438 switch (LA()) { |
|
3439 case T_STRING_LITERAL: |
|
3440 case T_WIDE_STRING_LITERAL: |
|
3441 return parseStringLiteral(node); |
|
3442 |
|
3443 case T_CHAR_LITERAL: // ### FIXME don't use NumericLiteral for chars |
|
3444 case T_WIDE_CHAR_LITERAL: |
|
3445 case T_NUMERIC_LITERAL: |
|
3446 return parseNumericLiteral(node); |
|
3447 |
|
3448 case T_TRUE: |
|
3449 case T_FALSE: |
|
3450 return parseBoolLiteral(node); |
|
3451 |
|
3452 case T_THIS: |
|
3453 return parseThisExpression(node); |
|
3454 |
|
3455 case T_LPAREN: |
|
3456 return parseNestedExpression(node); |
|
3457 |
|
3458 case T_SIGNAL: |
|
3459 case T_SLOT: |
|
3460 return parseQtMethod(node); |
|
3461 |
|
3462 case T_LBRACKET: |
|
3463 case T_AT_STRING_LITERAL: |
|
3464 case T_AT_ENCODE: |
|
3465 case T_AT_PROTOCOL: |
|
3466 case T_AT_SELECTOR: |
|
3467 return parseObjCExpression(node); |
|
3468 |
|
3469 default: { |
|
3470 NameAST *name = 0; |
|
3471 if (parseNameId(name)) { |
|
3472 node = name; |
|
3473 return true; |
|
3474 } |
|
3475 break; |
|
3476 } // default |
|
3477 |
|
3478 } // switch |
|
3479 |
|
3480 return false; |
|
3481 } |
|
3482 |
|
3483 bool Parser::parseObjCExpression(ExpressionAST *&node) |
|
3484 { |
|
3485 DEBUG_THIS_RULE(); |
|
3486 switch (LA()) { |
|
3487 case T_AT_ENCODE: |
|
3488 return parseObjCEncodeExpression(node); |
|
3489 |
|
3490 case T_AT_PROTOCOL: |
|
3491 return parseObjCProtocolExpression(node); |
|
3492 |
|
3493 case T_AT_SELECTOR: |
|
3494 return parseObjCSelectorExpression(node); |
|
3495 |
|
3496 case T_LBRACKET: |
|
3497 return parseObjCMessageExpression(node); |
|
3498 |
|
3499 case T_AT_STRING_LITERAL: |
|
3500 return parseObjCStringLiteral(node); |
|
3501 |
|
3502 default: |
|
3503 break; |
|
3504 } // switch |
|
3505 return false; |
|
3506 } |
|
3507 |
|
3508 bool Parser::parseObjCStringLiteral(ExpressionAST *&node) |
|
3509 { |
|
3510 DEBUG_THIS_RULE(); |
|
3511 if (LA() != T_AT_STRING_LITERAL) |
|
3512 return false; |
|
3513 |
|
3514 StringLiteralAST **ast = reinterpret_cast<StringLiteralAST **> (&node); |
|
3515 |
|
3516 while (LA() == T_AT_STRING_LITERAL) { |
|
3517 *ast = new (_pool) StringLiteralAST; |
|
3518 (*ast)->literal_token = consumeToken(); |
|
3519 ast = &(*ast)->next; |
|
3520 } |
|
3521 return true; |
|
3522 } |
|
3523 |
|
3524 bool Parser::parseObjCSynchronizedStatement(StatementAST *&node) |
|
3525 { |
|
3526 DEBUG_THIS_RULE(); |
|
3527 if (LA() != T_AT_SYNCHRONIZED) |
|
3528 return false; |
|
3529 |
|
3530 ObjCSynchronizedStatementAST *ast = new (_pool) ObjCSynchronizedStatementAST; |
|
3531 |
|
3532 ast->synchronized_token = consumeToken(); |
|
3533 match(T_LPAREN, &ast->lparen_token); |
|
3534 parseExpression(ast->synchronized_object); |
|
3535 match(T_RPAREN, &ast->rparen_token); |
|
3536 parseStatement(ast->statement); |
|
3537 |
|
3538 node = ast; |
|
3539 return true; |
|
3540 } |
|
3541 |
|
3542 bool Parser::parseObjCEncodeExpression(ExpressionAST *&node) |
|
3543 { |
|
3544 DEBUG_THIS_RULE(); |
|
3545 if (LA() != T_AT_ENCODE) |
|
3546 return false; |
|
3547 |
|
3548 ObjCEncodeExpressionAST *ast = new (_pool) ObjCEncodeExpressionAST; |
|
3549 ast->encode_token = consumeToken(); |
|
3550 parseObjCTypeName(ast->type_name); |
|
3551 node = ast; |
|
3552 return true; |
|
3553 } |
|
3554 |
|
3555 bool Parser::parseObjCProtocolExpression(ExpressionAST *&node) |
|
3556 { |
|
3557 DEBUG_THIS_RULE(); |
|
3558 if (LA() != T_AT_PROTOCOL) |
|
3559 return false; |
|
3560 |
|
3561 ObjCProtocolExpressionAST *ast = new (_pool) ObjCProtocolExpressionAST; |
|
3562 ast->protocol_token = consumeToken(); |
|
3563 match(T_LPAREN, &ast->lparen_token); |
|
3564 match(T_IDENTIFIER, &ast->identifier_token); |
|
3565 match(T_RPAREN, &ast->rparen_token); |
|
3566 node = ast; |
|
3567 return true; |
|
3568 } |
|
3569 |
|
3570 bool Parser::parseObjCSelectorExpression(ExpressionAST *&node) |
|
3571 { |
|
3572 DEBUG_THIS_RULE(); |
|
3573 if (LA() != T_AT_SELECTOR) |
|
3574 return false; |
|
3575 |
|
3576 ObjCSelectorExpressionAST *ast = new (_pool) ObjCSelectorExpressionAST; |
|
3577 ast->selector_token = consumeToken(); |
|
3578 match(T_LPAREN, &ast->lparen_token); |
|
3579 |
|
3580 unsigned identifier_token = 0; |
|
3581 match(T_IDENTIFIER, &identifier_token); |
|
3582 if (LA() == T_COLON) { |
|
3583 ObjCSelectorWithArgumentsAST *args = new (_pool) ObjCSelectorWithArgumentsAST; |
|
3584 ast->selector = args; |
|
3585 ObjCSelectorArgumentListAST *last = new (_pool) ObjCSelectorArgumentListAST; |
|
3586 args->selector_argument_list = last; |
|
3587 last->value = new (_pool) ObjCSelectorArgumentAST; |
|
3588 last->value->name_token = identifier_token; |
|
3589 last->value->colon_token = consumeToken(); |
|
3590 |
|
3591 while (LA() != T_RPAREN) { |
|
3592 last->next = new (_pool) ObjCSelectorArgumentListAST; |
|
3593 last = last->next; |
|
3594 last->value = new (_pool) ObjCSelectorArgumentAST; |
|
3595 match(T_IDENTIFIER, &last->value->name_token); |
|
3596 match(T_COLON, &last->value->colon_token); |
|
3597 } |
|
3598 } else { |
|
3599 ObjCSelectorWithoutArgumentsAST *args = new (_pool) ObjCSelectorWithoutArgumentsAST; |
|
3600 ast->selector = args; |
|
3601 args->name_token = identifier_token; |
|
3602 } |
|
3603 |
|
3604 match(T_RPAREN, &ast->rparen_token); |
|
3605 node = ast; |
|
3606 return true; |
|
3607 } |
|
3608 |
|
3609 bool Parser::parseObjCMessageExpression(ExpressionAST *&node) |
|
3610 { |
|
3611 DEBUG_THIS_RULE(); |
|
3612 if (LA() != T_LBRACKET) |
|
3613 return false; |
|
3614 |
|
3615 unsigned start = cursor(); |
|
3616 |
|
3617 unsigned lbracket_token = consumeToken(); |
|
3618 ExpressionAST *receiver_expression = 0; |
|
3619 ObjCSelectorAST *selector = 0; |
|
3620 ObjCMessageArgumentListAST *argument_list = 0; |
|
3621 |
|
3622 if (parseObjCMessageReceiver(receiver_expression) && |
|
3623 parseObjCMessageArguments(selector, argument_list)) { |
|
3624 |
|
3625 ObjCMessageExpressionAST *ast = new (_pool) ObjCMessageExpressionAST; |
|
3626 ast->lbracket_token = lbracket_token; |
|
3627 ast->receiver_expression = receiver_expression; |
|
3628 ast->selector = selector; |
|
3629 ast->argument_list = argument_list; |
|
3630 |
|
3631 match(T_RBRACKET, &ast->rbracket_token); |
|
3632 node = ast; |
|
3633 |
|
3634 return true; |
|
3635 } |
|
3636 |
|
3637 rewind(start); |
|
3638 return false; |
|
3639 } |
|
3640 |
|
3641 bool Parser::parseObjCMessageReceiver(ExpressionAST *&node) |
|
3642 { |
|
3643 DEBUG_THIS_RULE(); |
|
3644 return parseExpression(node); |
|
3645 } |
|
3646 |
|
3647 bool Parser::parseObjCMessageArguments(ObjCSelectorAST *&selNode, ObjCMessageArgumentListAST *& argNode) |
|
3648 { |
|
3649 DEBUG_THIS_RULE(); |
|
3650 if (LA() == T_RBRACKET) |
|
3651 return false; // nothing to do. |
|
3652 |
|
3653 unsigned start = cursor(); |
|
3654 |
|
3655 ObjCSelectorArgumentAST *selectorArgument = 0; |
|
3656 ObjCMessageArgumentAST *messageArgument = 0; |
|
3657 |
|
3658 if (parseObjCSelectorArg(selectorArgument, messageArgument)) { |
|
3659 ObjCSelectorArgumentListAST *selAst = new (_pool) ObjCSelectorArgumentListAST; |
|
3660 selAst->value = selectorArgument; |
|
3661 ObjCSelectorArgumentListAST *lastSelector = selAst; |
|
3662 |
|
3663 ObjCMessageArgumentListAST *argAst = new (_pool) ObjCMessageArgumentListAST; |
|
3664 argAst->value = messageArgument; |
|
3665 ObjCMessageArgumentListAST *lastArgument = argAst; |
|
3666 |
|
3667 while (parseObjCSelectorArg(selectorArgument, messageArgument)) { |
|
3668 // accept the selector args. |
|
3669 lastSelector->next = new (_pool) ObjCSelectorArgumentListAST; |
|
3670 lastSelector = lastSelector->next; |
|
3671 lastSelector->value = selectorArgument; |
|
3672 |
|
3673 lastArgument->next = new (_pool) ObjCMessageArgumentListAST; |
|
3674 lastArgument = lastArgument->next; |
|
3675 lastArgument->value = messageArgument; |
|
3676 } |
|
3677 |
|
3678 if (LA() == T_COMMA) { |
|
3679 ExpressionAST **lastExpression = &lastArgument->value->parameter_value_expression; |
|
3680 |
|
3681 while (LA() == T_COMMA) { |
|
3682 BinaryExpressionAST *binaryExpression = new (_pool) BinaryExpressionAST; |
|
3683 binaryExpression->left_expression = *lastExpression; |
|
3684 binaryExpression->binary_op_token = consumeToken(); // T_COMMA |
|
3685 parseAssignmentExpression(binaryExpression->right_expression); |
|
3686 lastExpression = &binaryExpression->right_expression; |
|
3687 } |
|
3688 } |
|
3689 |
|
3690 ObjCSelectorWithArgumentsAST *selWithArgs = new (_pool) ObjCSelectorWithArgumentsAST; |
|
3691 selWithArgs->selector_argument_list = selAst; |
|
3692 |
|
3693 selNode = selWithArgs; |
|
3694 argNode = argAst; |
|
3695 return true; |
|
3696 } else { |
|
3697 rewind(start); |
|
3698 unsigned name_token = 0; |
|
3699 if (!parseObjCSelector(name_token)) |
|
3700 return false; |
|
3701 ObjCSelectorWithoutArgumentsAST *sel = new (_pool) ObjCSelectorWithoutArgumentsAST; |
|
3702 sel->name_token = name_token; |
|
3703 selNode = sel; |
|
3704 argNode = 0; |
|
3705 return true; |
|
3706 } |
|
3707 |
|
3708 return false; |
|
3709 } |
|
3710 |
|
3711 bool Parser::parseObjCSelectorArg(ObjCSelectorArgumentAST *&selNode, ObjCMessageArgumentAST *&argNode) |
|
3712 { |
|
3713 DEBUG_THIS_RULE(); |
|
3714 unsigned selector_token = 0; |
|
3715 if (!parseObjCSelector(selector_token)) |
|
3716 return false; |
|
3717 |
|
3718 if (LA() != T_COLON) |
|
3719 return false; |
|
3720 |
|
3721 selNode = new (_pool) ObjCSelectorArgumentAST; |
|
3722 selNode->name_token = selector_token; |
|
3723 selNode->colon_token = consumeToken(); |
|
3724 |
|
3725 argNode = new (_pool) ObjCMessageArgumentAST; |
|
3726 ExpressionAST **expr = &argNode->parameter_value_expression; |
|
3727 unsigned expressionStart = cursor(); |
|
3728 if (parseAssignmentExpression(*expr) && LA() == T_COLON && (*expr)->asCastExpression()) { |
|
3729 rewind(expressionStart); |
|
3730 parseUnaryExpression(*expr); |
|
3731 // |
|
3732 } |
|
3733 return true; |
|
3734 } |
|
3735 |
|
3736 bool Parser::parseNameId(NameAST *&name) |
|
3737 { |
|
3738 DEBUG_THIS_RULE(); |
|
3739 unsigned start = cursor(); |
|
3740 if (! parseName(name)) |
|
3741 return false; |
|
3742 |
|
3743 if (LA() == T_RPAREN || LA() == T_COMMA) |
|
3744 return true; |
|
3745 |
|
3746 QualifiedNameAST *qualified_name_id = name->asQualifiedName(); |
|
3747 |
|
3748 TemplateIdAST *template_id = 0; |
|
3749 if (qualified_name_id) { |
|
3750 if (NameAST *unqualified_name = qualified_name_id->unqualified_name) |
|
3751 template_id = unqualified_name->asTemplateId(); |
|
3752 } else { |
|
3753 template_id = name->asTemplateId(); |
|
3754 } |
|
3755 |
|
3756 if (! template_id) |
|
3757 return true; // it's not a template-id, there's nothing to rewind. |
|
3758 |
|
3759 else if (LA() == T_LPAREN) { |
|
3760 // a template-id followed by a T_LPAREN |
|
3761 if (TemplateArgumentListAST *template_arguments = template_id->template_argument_list) { |
|
3762 if (! template_arguments->next && template_arguments->value && |
|
3763 template_arguments->value->asBinaryExpression()) { |
|
3764 |
|
3765 unsigned saved = cursor(); |
|
3766 ExpressionAST *expr = 0; |
|
3767 |
|
3768 bool blocked = blockErrors(true); |
|
3769 bool lookAtCastExpression = parseCastExpression(expr); |
|
3770 (void) blockErrors(blocked); |
|
3771 |
|
3772 if (lookAtCastExpression) { |
|
3773 if (CastExpressionAST *cast_expression = expr->asCastExpression()) { |
|
3774 if (cast_expression->lparen_token && cast_expression->rparen_token |
|
3775 && cast_expression->type_id && cast_expression->expression) { |
|
3776 rewind(start); |
|
3777 |
|
3778 name = 0; |
|
3779 return parseName(name, false); |
|
3780 } |
|
3781 } |
|
3782 } |
|
3783 rewind(saved); |
|
3784 } |
|
3785 } |
|
3786 } |
|
3787 |
|
3788 switch (LA()) { |
|
3789 case T_COMMA: |
|
3790 case T_SEMICOLON: |
|
3791 case T_LBRACKET: |
|
3792 case T_LPAREN: |
|
3793 return true; |
|
3794 |
|
3795 case T_IDENTIFIER: |
|
3796 case T_STATIC_CAST: |
|
3797 case T_DYNAMIC_CAST: |
|
3798 case T_REINTERPRET_CAST: |
|
3799 case T_CONST_CAST: |
|
3800 rewind(start); |
|
3801 return parseName(name, false); |
|
3802 |
|
3803 default: |
|
3804 if (tok().isLiteral() || tok().isOperator()) { |
|
3805 rewind(start); |
|
3806 return parseName(name, false); |
|
3807 } |
|
3808 } // switch |
|
3809 |
|
3810 return true; |
|
3811 } |
|
3812 |
|
3813 bool Parser::parseNestedExpression(ExpressionAST *&node) |
|
3814 { |
|
3815 DEBUG_THIS_RULE(); |
|
3816 if (LA() == T_LPAREN) { |
|
3817 unsigned lparen_token = consumeToken(); |
|
3818 |
|
3819 if (LA() == T_LBRACE) { |
|
3820 NestedExpressionAST *ast = new (_pool) NestedExpressionAST; |
|
3821 ast->lparen_token = lparen_token; |
|
3822 |
|
3823 // ### ast |
|
3824 StatementAST *statement = 0; |
|
3825 parseCompoundStatement(statement); |
|
3826 match(T_RPAREN, &ast->rparen_token); |
|
3827 node = ast; |
|
3828 return true; |
|
3829 } |
|
3830 |
|
3831 bool previousTemplateArguments = switchTemplateArguments(false); |
|
3832 |
|
3833 ExpressionAST *expression = 0; |
|
3834 if (parseExpression(expression) && LA() == T_RPAREN) { |
|
3835 NestedExpressionAST *ast = new (_pool) NestedExpressionAST; |
|
3836 ast->lparen_token = lparen_token; |
|
3837 ast->expression = expression; |
|
3838 ast->rparen_token = consumeToken(); |
|
3839 node = ast; |
|
3840 (void) switchTemplateArguments(previousTemplateArguments); |
|
3841 return true; |
|
3842 } |
|
3843 (void) switchTemplateArguments(previousTemplateArguments); |
|
3844 } |
|
3845 return false; |
|
3846 } |
|
3847 |
|
3848 bool Parser::parseCppCastExpression(ExpressionAST *&node) |
|
3849 { |
|
3850 DEBUG_THIS_RULE(); |
|
3851 if (LA() == T_DYNAMIC_CAST || LA() == T_STATIC_CAST || |
|
3852 LA() == T_REINTERPRET_CAST || LA() == T_CONST_CAST) { |
|
3853 CppCastExpressionAST *ast = new (_pool) CppCastExpressionAST; |
|
3854 ast->cast_token = consumeToken(); |
|
3855 match(T_LESS, &ast->less_token); |
|
3856 parseTypeId(ast->type_id); |
|
3857 match(T_GREATER, &ast->greater_token); |
|
3858 match(T_LPAREN, &ast->lparen_token); |
|
3859 parseExpression(ast->expression); |
|
3860 match(T_RPAREN, &ast->rparen_token); |
|
3861 node = ast; |
|
3862 return true; |
|
3863 } |
|
3864 return false; |
|
3865 } |
|
3866 |
|
3867 // typename ::opt nested-name-specifier identifier ( expression-listopt ) |
|
3868 // typename ::opt nested-name-specifier templateopt template-id ( expression-listopt ) |
|
3869 bool Parser::parseTypenameCallExpression(ExpressionAST *&node) |
|
3870 { |
|
3871 DEBUG_THIS_RULE(); |
|
3872 if (LA() == T_TYPENAME) { |
|
3873 unsigned typename_token = consumeToken(); |
|
3874 NameAST *name = 0; |
|
3875 if (parseName(name) && LA() == T_LPAREN) { |
|
3876 TypenameCallExpressionAST *ast = new (_pool) TypenameCallExpressionAST; |
|
3877 ast->typename_token = typename_token; |
|
3878 ast->name = name; |
|
3879 ast->lparen_token = consumeToken(); |
|
3880 parseExpressionList(ast->expression_list); |
|
3881 match(T_RPAREN, &ast->rparen_token); |
|
3882 node = ast; |
|
3883 return true; |
|
3884 } |
|
3885 } |
|
3886 return false; |
|
3887 } |
|
3888 |
|
3889 // typeid ( expression ) |
|
3890 // typeid ( type-id ) |
|
3891 bool Parser::parseTypeidExpression(ExpressionAST *&node) |
|
3892 { |
|
3893 DEBUG_THIS_RULE(); |
|
3894 if (LA() == T_TYPEID) { |
|
3895 TypeidExpressionAST *ast = new (_pool) TypeidExpressionAST; |
|
3896 ast->typeid_token = consumeToken(); |
|
3897 if (LA() == T_LPAREN) |
|
3898 ast->lparen_token = consumeToken(); |
|
3899 unsigned saved = cursor(); |
|
3900 if (! (parseTypeId(ast->expression) && LA() == T_RPAREN)) { |
|
3901 rewind(saved); |
|
3902 parseExpression(ast->expression); |
|
3903 } |
|
3904 match(T_RPAREN, &ast->rparen_token); |
|
3905 node = ast; |
|
3906 return true; |
|
3907 } |
|
3908 return false; |
|
3909 } |
|
3910 |
|
3911 bool Parser::parseCorePostfixExpression(ExpressionAST *&node) |
|
3912 { |
|
3913 DEBUG_THIS_RULE(); |
|
3914 |
|
3915 switch (LA()) { |
|
3916 case T_DYNAMIC_CAST: |
|
3917 case T_STATIC_CAST: |
|
3918 case T_REINTERPRET_CAST: |
|
3919 case T_CONST_CAST: |
|
3920 return parseCppCastExpression(node); |
|
3921 |
|
3922 case T_TYPENAME: |
|
3923 return parseTypenameCallExpression(node); |
|
3924 |
|
3925 case T_TYPEID: |
|
3926 return parseTypeidExpression(node); |
|
3927 |
|
3928 default: { |
|
3929 unsigned start = cursor(); |
|
3930 SpecifierListAST *type_specifier = 0; |
|
3931 bool blocked = blockErrors(true); |
|
3932 if (lookAtBuiltinTypeSpecifier() && |
|
3933 parseSimpleTypeSpecifier(type_specifier) && |
|
3934 LA() == T_LPAREN) { |
|
3935 unsigned lparen_token = consumeToken(); |
|
3936 ExpressionListAST *expression_list = 0; |
|
3937 parseExpressionList(expression_list); |
|
3938 if (LA() == T_RPAREN) { |
|
3939 unsigned rparen_token = consumeToken(); |
|
3940 TypeConstructorCallAST *ast = new (_pool) TypeConstructorCallAST; |
|
3941 ast->type_specifier_list = type_specifier; |
|
3942 ast->lparen_token = lparen_token; |
|
3943 ast->expression_list = expression_list; |
|
3944 ast->rparen_token = rparen_token; |
|
3945 node = ast; |
|
3946 blockErrors(blocked); |
|
3947 return true; |
|
3948 } |
|
3949 } |
|
3950 rewind(start); |
|
3951 |
|
3952 // look for compound literals |
|
3953 if (LA() == T_LPAREN) { |
|
3954 unsigned lparen_token = consumeToken(); |
|
3955 ExpressionAST *type_id = 0; |
|
3956 if (parseTypeId(type_id) && LA() == T_RPAREN) { |
|
3957 unsigned rparen_token = consumeToken(); |
|
3958 if (LA() == T_LBRACE) { |
|
3959 blockErrors(blocked); |
|
3960 |
|
3961 CompoundLiteralAST *ast = new (_pool) CompoundLiteralAST; |
|
3962 ast->lparen_token = lparen_token; |
|
3963 ast->type_id = type_id; |
|
3964 ast->rparen_token = rparen_token; |
|
3965 parseInitializerClause(ast->initializer); |
|
3966 node = ast; |
|
3967 return true; |
|
3968 } |
|
3969 } |
|
3970 rewind(start); |
|
3971 } |
|
3972 |
|
3973 blockErrors(blocked); |
|
3974 return parsePrimaryExpression(node); |
|
3975 } // default |
|
3976 } // switch |
|
3977 } |
|
3978 |
|
3979 bool Parser::parsePostfixExpression(ExpressionAST *&node) |
|
3980 { |
|
3981 DEBUG_THIS_RULE(); |
|
3982 if (parseCorePostfixExpression(node)) { |
|
3983 PostfixListAST *postfix_expressions = 0, |
|
3984 **postfix_ptr = &postfix_expressions; |
|
3985 while (LA()) { |
|
3986 if (LA() == T_LPAREN) { |
|
3987 CallAST *ast = new (_pool) CallAST; |
|
3988 ast->lparen_token = consumeToken(); |
|
3989 parseExpressionList(ast->expression_list); |
|
3990 match(T_RPAREN, &ast->rparen_token); |
|
3991 *postfix_ptr = new (_pool) PostfixListAST(ast); |
|
3992 postfix_ptr = &(*postfix_ptr)->next; |
|
3993 } else if (LA() == T_LBRACKET) { |
|
3994 ArrayAccessAST *ast = new (_pool) ArrayAccessAST; |
|
3995 ast->lbracket_token = consumeToken(); |
|
3996 parseExpression(ast->expression); |
|
3997 match(T_RBRACKET, &ast->rbracket_token); |
|
3998 *postfix_ptr = new (_pool) PostfixListAST(ast); |
|
3999 postfix_ptr = &(*postfix_ptr)->next; |
|
4000 } else if (LA() == T_PLUS_PLUS || LA() == T_MINUS_MINUS) { |
|
4001 PostIncrDecrAST *ast = new (_pool) PostIncrDecrAST; |
|
4002 ast->incr_decr_token = consumeToken(); |
|
4003 *postfix_ptr = new (_pool) PostfixListAST(ast); |
|
4004 postfix_ptr = &(*postfix_ptr)->next; |
|
4005 } else if (LA() == T_DOT || LA() == T_ARROW) { |
|
4006 MemberAccessAST *ast = new (_pool) MemberAccessAST; |
|
4007 ast->access_token = consumeToken(); |
|
4008 if (LA() == T_TEMPLATE) |
|
4009 ast->template_token = consumeToken(); |
|
4010 if (! parseNameId(ast->member_name)) |
|
4011 _translationUnit->error(cursor(), "expected unqualified-id before token `%s'", |
|
4012 tok().spell()); |
|
4013 *postfix_ptr = new (_pool) PostfixListAST(ast); |
|
4014 postfix_ptr = &(*postfix_ptr)->next; |
|
4015 } else break; |
|
4016 } // while |
|
4017 |
|
4018 if (postfix_expressions) { |
|
4019 PostfixExpressionAST *ast = new (_pool) PostfixExpressionAST; |
|
4020 ast->base_expression = node; |
|
4021 ast->postfix_expression_list = postfix_expressions; |
|
4022 node = ast; |
|
4023 } |
|
4024 return true; |
|
4025 } |
|
4026 return false; |
|
4027 } |
|
4028 |
|
4029 bool Parser::parseUnaryExpression(ExpressionAST *&node) |
|
4030 { |
|
4031 DEBUG_THIS_RULE(); |
|
4032 switch (LA()) { |
|
4033 case T_PLUS_PLUS: |
|
4034 case T_MINUS_MINUS: |
|
4035 case T_STAR: |
|
4036 case T_AMPER: |
|
4037 case T_PLUS: |
|
4038 case T_MINUS: |
|
4039 case T_EXCLAIM: { |
|
4040 unsigned op = cursor(); |
|
4041 UnaryExpressionAST *ast = new (_pool) UnaryExpressionAST; |
|
4042 ast->unary_op_token = consumeToken(); |
|
4043 if (! parseCastExpression(ast->expression)) { |
|
4044 _translationUnit->error(op, "expected expression after token `%s'", |
|
4045 _translationUnit->spell(op)); |
|
4046 } |
|
4047 node = ast; |
|
4048 return true; |
|
4049 } |
|
4050 |
|
4051 case T_TILDE: { |
|
4052 if (LA(2) == T_IDENTIFIER && LA(3) == T_LPAREN) |
|
4053 break; // prefer destructor names |
|
4054 |
|
4055 UnaryExpressionAST *ast = new (_pool) UnaryExpressionAST; |
|
4056 ast->unary_op_token = consumeToken(); |
|
4057 parseCastExpression(ast->expression); |
|
4058 node = ast; |
|
4059 return true; |
|
4060 } |
|
4061 |
|
4062 case T_SIZEOF: { |
|
4063 SizeofExpressionAST *ast = new (_pool) SizeofExpressionAST; |
|
4064 ast->sizeof_token = consumeToken(); |
|
4065 |
|
4066 if (LA() == T_LPAREN) { |
|
4067 unsigned lparen_token = consumeToken(); |
|
4068 if (parseTypeId(ast->expression) && LA() == T_RPAREN) { |
|
4069 ast->lparen_token = lparen_token; |
|
4070 ast->rparen_token = consumeToken(); |
|
4071 node = ast; |
|
4072 return true; |
|
4073 } else { |
|
4074 rewind(lparen_token); |
|
4075 } |
|
4076 } |
|
4077 |
|
4078 parseUnaryExpression(ast->expression); |
|
4079 node = ast; |
|
4080 return true; |
|
4081 } |
|
4082 |
|
4083 default: |
|
4084 break; |
|
4085 } // switch |
|
4086 |
|
4087 if (LA() == T_NEW || (LA(1) == T_COLON_COLON && |
|
4088 LA(2) == T_NEW)) |
|
4089 return parseNewExpression(node); |
|
4090 else if (LA() == T_DELETE || (LA(1) == T_COLON_COLON && |
|
4091 LA(2) == T_DELETE)) |
|
4092 return parseDeleteExpression(node); |
|
4093 else |
|
4094 return parsePostfixExpression(node); |
|
4095 } |
|
4096 |
|
4097 // new-placement ::= T_LPAREN expression-list T_RPAREN |
|
4098 bool Parser::parseNewPlacement(NewPlacementAST *&node) |
|
4099 { |
|
4100 DEBUG_THIS_RULE(); |
|
4101 if (LA() == T_LPAREN) { |
|
4102 unsigned lparen_token = consumeToken(); |
|
4103 ExpressionListAST *expression_list = 0; |
|
4104 if (parseExpressionList(expression_list) && expression_list && LA() == T_RPAREN) { |
|
4105 unsigned rparen_token = consumeToken(); |
|
4106 NewPlacementAST *ast = new (_pool) NewPlacementAST; |
|
4107 ast->lparen_token = lparen_token; |
|
4108 ast->expression_list = expression_list; |
|
4109 ast->rparen_token = rparen_token; |
|
4110 node = ast; |
|
4111 return true; |
|
4112 } |
|
4113 } |
|
4114 |
|
4115 return false; |
|
4116 } |
|
4117 |
|
4118 // new-expression ::= T_COLON_COLON? T_NEW new-placement.opt |
|
4119 // new-type-id new-initializer.opt |
|
4120 // new-expression ::= T_COLON_COLON? T_NEW new-placement.opt |
|
4121 // T_LPAREN type-id T_RPAREN new-initializer.opt |
|
4122 bool Parser::parseNewExpression(ExpressionAST *&node) |
|
4123 { |
|
4124 DEBUG_THIS_RULE(); |
|
4125 if (! (LA() == T_NEW || (LA() == T_COLON_COLON && LA(2) == T_NEW))) |
|
4126 return false; |
|
4127 |
|
4128 NewExpressionAST *ast = new (_pool) NewExpressionAST; |
|
4129 if (LA() == T_COLON_COLON) |
|
4130 ast->scope_token = consumeToken(); |
|
4131 |
|
4132 ast->new_token = consumeToken(); |
|
4133 |
|
4134 NewPlacementAST *new_placement = 0; |
|
4135 |
|
4136 if (parseNewPlacement(new_placement)) { |
|
4137 unsigned after_new_placement = cursor(); |
|
4138 |
|
4139 NewTypeIdAST *new_type_id = 0; |
|
4140 if (parseNewTypeId(new_type_id)) { |
|
4141 ast->new_placement = new_placement; |
|
4142 ast->new_type_id = new_type_id; |
|
4143 parseNewInitializer(ast->new_initializer); |
|
4144 // recognized new-placement.opt new-type-id new-initializer.opt |
|
4145 node = ast; |
|
4146 return true; |
|
4147 } |
|
4148 |
|
4149 rewind(after_new_placement); |
|
4150 if (LA() == T_LPAREN) { |
|
4151 unsigned lparen_token = consumeToken(); |
|
4152 ExpressionAST *type_id = 0; |
|
4153 if (parseTypeId(type_id) && LA() == T_RPAREN) { |
|
4154 ast->new_placement = new_placement; |
|
4155 ast->lparen_token = lparen_token; |
|
4156 ast->type_id = type_id; |
|
4157 ast->rparen_token = consumeToken(); |
|
4158 parseNewInitializer(ast->new_initializer); |
|
4159 node = ast; |
|
4160 return true; |
|
4161 } |
|
4162 } |
|
4163 } |
|
4164 |
|
4165 rewind(ast->new_token + 1); |
|
4166 |
|
4167 if (LA() == T_LPAREN) { |
|
4168 unsigned lparen_token = consumeToken(); |
|
4169 ExpressionAST *type_id = 0; |
|
4170 if (parseTypeId(type_id) && LA() == T_RPAREN) { |
|
4171 ast->lparen_token = lparen_token; |
|
4172 ast->type_id = type_id; |
|
4173 ast->rparen_token = consumeToken(); |
|
4174 parseNewInitializer(ast->new_initializer); |
|
4175 node = ast; |
|
4176 return true; |
|
4177 } |
|
4178 } |
|
4179 |
|
4180 parseNewTypeId(ast->new_type_id); |
|
4181 parseNewInitializer(ast->new_initializer); |
|
4182 node = ast; |
|
4183 return true; |
|
4184 } |
|
4185 |
|
4186 bool Parser::parseNewTypeId(NewTypeIdAST *&node) |
|
4187 { |
|
4188 DEBUG_THIS_RULE(); |
|
4189 SpecifierListAST *typeSpec = 0; |
|
4190 if (! parseTypeSpecifier(typeSpec)) |
|
4191 return false; |
|
4192 |
|
4193 NewTypeIdAST *ast = new (_pool) NewTypeIdAST; |
|
4194 ast->type_specifier_list = typeSpec; |
|
4195 |
|
4196 PtrOperatorListAST **ptrop_it = &ast->ptr_operator_list; |
|
4197 while (parsePtrOperator(*ptrop_it)) |
|
4198 ptrop_it = &(*ptrop_it)->next; |
|
4199 |
|
4200 NewArrayDeclaratorListAST **it = &ast->new_array_declarator_list; |
|
4201 while (parseNewArrayDeclarator(*it)) |
|
4202 it = &(*it)->next; |
|
4203 |
|
4204 node = ast; |
|
4205 return true; |
|
4206 } |
|
4207 |
|
4208 |
|
4209 bool Parser::parseNewArrayDeclarator(NewArrayDeclaratorListAST *&node) |
|
4210 { |
|
4211 DEBUG_THIS_RULE(); |
|
4212 if (LA() != T_LBRACKET) |
|
4213 return false; |
|
4214 |
|
4215 NewArrayDeclaratorAST *ast = new (_pool) NewArrayDeclaratorAST; |
|
4216 ast->lbracket_token = consumeToken(); |
|
4217 parseExpression(ast->expression); |
|
4218 match(T_RBRACKET, &ast->rbracket_token); |
|
4219 |
|
4220 node = new (_pool) NewArrayDeclaratorListAST; |
|
4221 node->value = ast; |
|
4222 return true; |
|
4223 } |
|
4224 |
|
4225 bool Parser::parseNewInitializer(NewInitializerAST *&node) |
|
4226 { |
|
4227 DEBUG_THIS_RULE(); |
|
4228 if (LA() == T_LPAREN) { |
|
4229 unsigned lparen_token = consumeToken(); |
|
4230 ExpressionAST *expression = 0; |
|
4231 if (LA() == T_RPAREN || parseExpression(expression)) { |
|
4232 NewInitializerAST *ast = new (_pool) NewInitializerAST; |
|
4233 ast->lparen_token = lparen_token; |
|
4234 ast->expression = expression; |
|
4235 match(T_RPAREN, &ast->rparen_token); |
|
4236 node = ast; |
|
4237 return true; |
|
4238 } |
|
4239 } |
|
4240 return false; |
|
4241 } |
|
4242 |
|
4243 bool Parser::parseDeleteExpression(ExpressionAST *&node) |
|
4244 { |
|
4245 DEBUG_THIS_RULE(); |
|
4246 if (LA() == T_DELETE || (LA() == T_COLON_COLON && LA(2) == T_DELETE)) { |
|
4247 DeleteExpressionAST *ast = new (_pool) DeleteExpressionAST; |
|
4248 |
|
4249 if (LA() == T_COLON_COLON) |
|
4250 ast->scope_token = consumeToken(); |
|
4251 |
|
4252 ast->delete_token = consumeToken(); |
|
4253 |
|
4254 if (LA() == T_LBRACKET) { |
|
4255 ast->lbracket_token = consumeToken(); |
|
4256 match(T_RBRACKET, &ast->rbracket_token); |
|
4257 } |
|
4258 |
|
4259 parseCastExpression(ast->expression); |
|
4260 node = ast; |
|
4261 return true; |
|
4262 } |
|
4263 return false; |
|
4264 } |
|
4265 |
|
4266 bool Parser::parseCastExpression(ExpressionAST *&node) |
|
4267 { |
|
4268 DEBUG_THIS_RULE(); |
|
4269 if (LA() == T_LPAREN) { |
|
4270 unsigned lparen_token = consumeToken(); |
|
4271 ExpressionAST *type_id = 0; |
|
4272 if (parseTypeId(type_id) && LA() == T_RPAREN) { |
|
4273 unsigned rparen_token = consumeToken(); |
|
4274 ExpressionAST *expression = 0; |
|
4275 if (parseCastExpression(expression)) { |
|
4276 CastExpressionAST *ast = new (_pool) CastExpressionAST; |
|
4277 ast->lparen_token = lparen_token; |
|
4278 ast->type_id = type_id; |
|
4279 ast->rparen_token = rparen_token; |
|
4280 ast->expression = expression; |
|
4281 node = ast; |
|
4282 return true; |
|
4283 } |
|
4284 } |
|
4285 rewind(lparen_token); |
|
4286 } |
|
4287 return parseUnaryExpression(node); |
|
4288 } |
|
4289 |
|
4290 bool Parser::parsePmExpression(ExpressionAST *&node) |
|
4291 { |
|
4292 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::PointerToMember) |
|
4293 } |
|
4294 |
|
4295 bool Parser::parseMultiplicativeExpression(ExpressionAST *&node) |
|
4296 { |
|
4297 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Multiplicative) |
|
4298 } |
|
4299 |
|
4300 bool Parser::parseAdditiveExpression(ExpressionAST *&node) |
|
4301 { |
|
4302 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Additive) |
|
4303 } |
|
4304 |
|
4305 bool Parser::parseShiftExpression(ExpressionAST *&node) |
|
4306 { |
|
4307 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Shift) |
|
4308 } |
|
4309 |
|
4310 bool Parser::parseRelationalExpression(ExpressionAST *&node) |
|
4311 { |
|
4312 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Relational) |
|
4313 } |
|
4314 |
|
4315 bool Parser::parseEqualityExpression(ExpressionAST *&node) |
|
4316 { |
|
4317 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Equality) |
|
4318 } |
|
4319 |
|
4320 bool Parser::parseAndExpression(ExpressionAST *&node) |
|
4321 { |
|
4322 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::And) |
|
4323 } |
|
4324 |
|
4325 bool Parser::parseExclusiveOrExpression(ExpressionAST *&node) |
|
4326 { |
|
4327 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::ExclusiveOr) |
|
4328 } |
|
4329 |
|
4330 bool Parser::parseInclusiveOrExpression(ExpressionAST *&node) |
|
4331 { |
|
4332 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::InclusiveOr) |
|
4333 } |
|
4334 |
|
4335 bool Parser::parseLogicalAndExpression(ExpressionAST *&node) |
|
4336 { |
|
4337 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::LogicalAnd) |
|
4338 } |
|
4339 |
|
4340 bool Parser::parseLogicalOrExpression(ExpressionAST *&node) |
|
4341 { |
|
4342 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::LogicalOr) |
|
4343 } |
|
4344 |
|
4345 bool Parser::parseConditionalExpression(ExpressionAST *&node) |
|
4346 { |
|
4347 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Conditional) |
|
4348 } |
|
4349 |
|
4350 bool Parser::parseAssignmentExpression(ExpressionAST *&node) |
|
4351 { |
|
4352 DEBUG_THIS_RULE(); |
|
4353 if (LA() == T_THROW) |
|
4354 return parseThrowExpression(node); |
|
4355 else |
|
4356 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Assignment) |
|
4357 } |
|
4358 |
|
4359 bool Parser::parseQtMethod(ExpressionAST *&node) |
|
4360 { |
|
4361 DEBUG_THIS_RULE(); |
|
4362 if (LA() == T_SIGNAL || LA() == T_SLOT) { |
|
4363 QtMethodAST *ast = new (_pool) QtMethodAST; |
|
4364 ast->method_token = consumeToken(); |
|
4365 match(T_LPAREN, &ast->lparen_token); |
|
4366 if (! parseDeclarator(ast->declarator)) |
|
4367 _translationUnit->error(cursor(), "expected a function declarator before token `%s'", |
|
4368 tok().spell()); |
|
4369 match(T_RPAREN, &ast->rparen_token); |
|
4370 node = ast; |
|
4371 return true; |
|
4372 } |
|
4373 return false; |
|
4374 } |
|
4375 |
|
4376 bool Parser::parseConstantExpression(ExpressionAST *&node) |
|
4377 { |
|
4378 DEBUG_THIS_RULE(); |
|
4379 return parseConditionalExpression(node); |
|
4380 } |
|
4381 |
|
4382 bool Parser::parseExpression(ExpressionAST *&node) |
|
4383 { |
|
4384 DEBUG_THIS_RULE(); |
|
4385 |
|
4386 if (_expressionDepth > MAX_EXPRESSION_DEPTH) |
|
4387 return false; |
|
4388 |
|
4389 ++_expressionDepth; |
|
4390 bool success = parseCommaExpression(node); |
|
4391 --_expressionDepth; |
|
4392 return success; |
|
4393 } |
|
4394 |
|
4395 void Parser::parseExpressionWithOperatorPrecedence(ExpressionAST *&lhs, int minPrecedence) |
|
4396 { |
|
4397 DEBUG_THIS_RULE(); |
|
4398 |
|
4399 while (precedence(tok().kind(), _templateArguments) >= minPrecedence) { |
|
4400 const int operPrecedence = precedence(tok().kind(), _templateArguments); |
|
4401 const int oper = consumeToken(); |
|
4402 |
|
4403 ConditionalExpressionAST *condExpr = 0; |
|
4404 if (operPrecedence == Prec::Conditional) { |
|
4405 condExpr = new (_pool) ConditionalExpressionAST; |
|
4406 condExpr->question_token = oper; |
|
4407 if (oper == T_COLON) { |
|
4408 // GNU extension: |
|
4409 // logical-or-expression '?' ':' conditional-expression |
|
4410 condExpr->left_expression = 0; |
|
4411 } else { |
|
4412 parseExpression(condExpr->left_expression); |
|
4413 } |
|
4414 match(T_COLON, &condExpr->colon_token); |
|
4415 } |
|
4416 |
|
4417 ExpressionAST *rhs = 0; |
|
4418 const bool isCPlusPlus = true; |
|
4419 if (operPrecedence <= Prec::Conditional && isCPlusPlus) { |
|
4420 // in C++ you can put a throw in the right-most expression of a conditional expression, |
|
4421 // or an assignment, so some special handling: |
|
4422 if (!parseAssignmentExpression(rhs)) |
|
4423 return; |
|
4424 } else { |
|
4425 // for C & all other expressions: |
|
4426 if (!parseCastExpression(rhs)) |
|
4427 return; |
|
4428 } |
|
4429 |
|
4430 for (int tokenKindAhead = tok().kind(), precedenceAhead = precedence(tokenKindAhead, _templateArguments); |
|
4431 precedenceAhead > operPrecedence && isBinaryOperator(tokenKindAhead) |
|
4432 || precedenceAhead == operPrecedence && isRightAssociative(tokenKindAhead); |
|
4433 tokenKindAhead = tok().kind(), precedenceAhead = precedence(tokenKindAhead, _templateArguments)) { |
|
4434 parseExpressionWithOperatorPrecedence(rhs, precedenceAhead); |
|
4435 } |
|
4436 |
|
4437 if (condExpr) { // we were parsing a ternairy conditional expression |
|
4438 condExpr->condition = lhs; |
|
4439 condExpr->right_expression = rhs; |
|
4440 lhs = condExpr; |
|
4441 } else { |
|
4442 BinaryExpressionAST *expr = new (_pool) BinaryExpressionAST; |
|
4443 expr->left_expression = lhs; |
|
4444 expr->binary_op_token = oper; |
|
4445 expr->right_expression = rhs; |
|
4446 lhs = expr; |
|
4447 } |
|
4448 } |
|
4449 } |
|
4450 |
|
4451 bool Parser::parseCommaExpression(ExpressionAST *&node) |
|
4452 { |
|
4453 PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, Prec::Comma) |
|
4454 } |
|
4455 |
|
4456 bool Parser::parseThrowExpression(ExpressionAST *&node) |
|
4457 { |
|
4458 DEBUG_THIS_RULE(); |
|
4459 if (LA() == T_THROW) { |
|
4460 ThrowExpressionAST *ast = new (_pool) ThrowExpressionAST; |
|
4461 ast->throw_token = consumeToken(); |
|
4462 parseAssignmentExpression(ast->expression); |
|
4463 node = ast; |
|
4464 return true; |
|
4465 } |
|
4466 return false; |
|
4467 } |
|
4468 |
|
4469 bool Parser::lookAtObjCSelector() const |
|
4470 { |
|
4471 switch (LA()) { |
|
4472 case T_IDENTIFIER: |
|
4473 case T_OR: |
|
4474 case T_AND: |
|
4475 case T_NOT: |
|
4476 case T_XOR: |
|
4477 case T_BITOR: |
|
4478 case T_COMPL: |
|
4479 case T_OR_EQ: |
|
4480 case T_AND_EQ: |
|
4481 case T_BITAND: |
|
4482 case T_NOT_EQ: |
|
4483 case T_XOR_EQ: |
|
4484 return true; |
|
4485 |
|
4486 default: |
|
4487 if (tok().isKeyword()) |
|
4488 return true; |
|
4489 } // switch |
|
4490 |
|
4491 return false; |
|
4492 } |
|
4493 |
|
4494 // objc-class-declaraton ::= T_AT_CLASS (T_IDENTIFIER @ T_COMMA) T_SEMICOLON |
|
4495 // |
|
4496 bool Parser::parseObjCClassForwardDeclaration(DeclarationAST *&node) |
|
4497 { |
|
4498 DEBUG_THIS_RULE(); |
|
4499 if (LA() != T_AT_CLASS) |
|
4500 return false; |
|
4501 |
|
4502 ObjCClassForwardDeclarationAST *ast = new (_pool) ObjCClassForwardDeclarationAST; |
|
4503 |
|
4504 ast->class_token = consumeToken(); |
|
4505 unsigned identifier_token = 0; |
|
4506 match(T_IDENTIFIER, &identifier_token); |
|
4507 |
|
4508 ast->identifier_list = new (_pool) ObjCIdentifierListAST; |
|
4509 SimpleNameAST *name = new (_pool) SimpleNameAST; |
|
4510 name->identifier_token = identifier_token; |
|
4511 ast->identifier_list->value = name; |
|
4512 ObjCIdentifierListAST **nextId = &ast->identifier_list->next; |
|
4513 |
|
4514 while (LA() == T_COMMA) { |
|
4515 consumeToken(); // consume T_COMMA |
|
4516 match(T_IDENTIFIER, &identifier_token); |
|
4517 |
|
4518 *nextId = new (_pool) ObjCIdentifierListAST; |
|
4519 name = new (_pool) SimpleNameAST; |
|
4520 name->identifier_token = identifier_token; |
|
4521 (*nextId)->value = name; |
|
4522 nextId = &(*nextId)->next; |
|
4523 } |
|
4524 |
|
4525 match(T_SEMICOLON, &ast->semicolon_token); |
|
4526 node = ast; |
|
4527 return true; |
|
4528 } |
|
4529 |
|
4530 // objc-interface ::= attribute-specifier-list-opt objc-class-interface |
|
4531 // objc-interface ::= objc-category-interface |
|
4532 // |
|
4533 // objc-class-interface ::= T_AT_INTERFACE T_IDENTIFIER (T_COLON T_IDENTIFIER)? |
|
4534 // objc-protocol-refs-opt |
|
4535 // objc-class-instance-variables-opt |
|
4536 // objc-interface-declaration-list |
|
4537 // T_AT_END |
|
4538 // |
|
4539 // objc-category-interface ::= T_AT_INTERFACE T_IDENTIFIER |
|
4540 // T_LPAREN T_IDENTIFIER? T_RPAREN |
|
4541 // objc-protocol-refs-opt |
|
4542 // objc-interface-declaration-list |
|
4543 // T_AT_END |
|
4544 // |
|
4545 bool Parser::parseObjCInterface(DeclarationAST *&node, |
|
4546 SpecifierListAST *attributes) |
|
4547 { |
|
4548 DEBUG_THIS_RULE(); |
|
4549 if (! attributes && LA() == T___ATTRIBUTE__) { |
|
4550 SpecifierListAST **attr = &attributes; |
|
4551 while (parseAttributeSpecifier(*attr)) |
|
4552 attr = &(*attr)->next; |
|
4553 } |
|
4554 |
|
4555 if (LA() != T_AT_INTERFACE) |
|
4556 return false; |
|
4557 |
|
4558 unsigned objc_interface_token = consumeToken(); |
|
4559 unsigned identifier_token = 0; |
|
4560 match(T_IDENTIFIER, &identifier_token); |
|
4561 |
|
4562 if (LA() == T_LPAREN) { |
|
4563 // a category interface |
|
4564 |
|
4565 if (attributes) |
|
4566 _translationUnit->error(attributes->firstToken(), |
|
4567 "invalid attributes for category interface declaration"); |
|
4568 |
|
4569 ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST; |
|
4570 ast->attribute_list = attributes; |
|
4571 ast->interface_token = objc_interface_token; |
|
4572 SimpleNameAST *class_name = new (_pool) SimpleNameAST; |
|
4573 class_name->identifier_token= identifier_token; |
|
4574 ast->class_name = class_name; |
|
4575 |
|
4576 match(T_LPAREN, &ast->lparen_token); |
|
4577 if (LA() == T_IDENTIFIER) { |
|
4578 SimpleNameAST *category_name = new (_pool) SimpleNameAST; |
|
4579 category_name->identifier_token = consumeToken(); |
|
4580 ast->category_name = category_name; |
|
4581 } |
|
4582 |
|
4583 match(T_RPAREN, &ast->rparen_token); |
|
4584 |
|
4585 parseObjCProtocolRefs(ast->protocol_refs); |
|
4586 |
|
4587 DeclarationListAST **nextMembers = &ast->member_declaration_list; |
|
4588 DeclarationAST *declaration = 0; |
|
4589 while (parseObjCInterfaceMemberDeclaration(declaration)) { |
|
4590 *nextMembers = new (_pool) DeclarationListAST; |
|
4591 (*nextMembers)->value = declaration; |
|
4592 nextMembers = &(*nextMembers)->next; |
|
4593 } |
|
4594 |
|
4595 match(T_AT_END, &ast->end_token); |
|
4596 |
|
4597 node = ast; |
|
4598 return true; |
|
4599 } else { |
|
4600 // a class interface declaration |
|
4601 ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST; |
|
4602 ast->attribute_list = attributes; |
|
4603 ast->interface_token = objc_interface_token; |
|
4604 SimpleNameAST* class_name = new (_pool) SimpleNameAST; |
|
4605 class_name->identifier_token = identifier_token; |
|
4606 ast->class_name = class_name; |
|
4607 |
|
4608 if (LA() == T_COLON) { |
|
4609 ast->colon_token = consumeToken(); |
|
4610 SimpleNameAST *superclass = new (_pool) SimpleNameAST; |
|
4611 match(T_IDENTIFIER, &superclass->identifier_token); |
|
4612 ast->superclass = superclass; |
|
4613 } |
|
4614 |
|
4615 parseObjCProtocolRefs(ast->protocol_refs); |
|
4616 parseObjClassInstanceVariables(ast->inst_vars_decl); |
|
4617 |
|
4618 DeclarationListAST **nextMembers = &ast->member_declaration_list; |
|
4619 DeclarationAST *declaration = 0; |
|
4620 while (parseObjCInterfaceMemberDeclaration(declaration)) { |
|
4621 *nextMembers = new (_pool) DeclarationListAST; |
|
4622 (*nextMembers)->value = declaration; |
|
4623 nextMembers = &(*nextMembers)->next; |
|
4624 } |
|
4625 |
|
4626 match(T_AT_END, &ast->end_token); |
|
4627 |
|
4628 node = ast; |
|
4629 return true; |
|
4630 } |
|
4631 } |
|
4632 |
|
4633 // objc-protocol ::= T_AT_PROTOCOL (T_IDENTIFIER @ T_COMMA) T_SEMICOLON |
|
4634 // |
|
4635 bool Parser::parseObjCProtocol(DeclarationAST *&node, |
|
4636 SpecifierListAST *attributes) |
|
4637 { |
|
4638 DEBUG_THIS_RULE(); |
|
4639 if (! attributes && LA() == T___ATTRIBUTE__) { |
|
4640 SpecifierListAST **attr = &attributes; |
|
4641 while (parseAttributeSpecifier(*attr)) |
|
4642 attr = &(*attr)->next; |
|
4643 } |
|
4644 |
|
4645 if (LA() != T_AT_PROTOCOL) |
|
4646 return false; |
|
4647 |
|
4648 unsigned protocol_token = consumeToken(); |
|
4649 unsigned identifier_token = 0; |
|
4650 match(T_IDENTIFIER, &identifier_token); |
|
4651 |
|
4652 if (LA() == T_COMMA || LA() == T_SEMICOLON) { |
|
4653 // a protocol forward declaration |
|
4654 |
|
4655 ObjCProtocolForwardDeclarationAST *ast = new (_pool) ObjCProtocolForwardDeclarationAST; |
|
4656 ast->attribute_list = attributes; |
|
4657 ast->protocol_token = protocol_token; |
|
4658 ast->identifier_list = new (_pool) ObjCIdentifierListAST; |
|
4659 SimpleNameAST *name = new (_pool) SimpleNameAST; |
|
4660 name->identifier_token = identifier_token; |
|
4661 ast->identifier_list->value = name; |
|
4662 ObjCIdentifierListAST **nextId = &ast->identifier_list->next; |
|
4663 |
|
4664 while (LA() == T_COMMA) { |
|
4665 consumeToken(); // consume T_COMMA |
|
4666 match(T_IDENTIFIER, &identifier_token); |
|
4667 |
|
4668 *nextId = new (_pool) ObjCIdentifierListAST; |
|
4669 name = new (_pool) SimpleNameAST; |
|
4670 name->identifier_token = identifier_token; |
|
4671 (*nextId)->value = name; |
|
4672 nextId = &(*nextId)->next; |
|
4673 } |
|
4674 |
|
4675 match(T_SEMICOLON, &ast->semicolon_token); |
|
4676 node = ast; |
|
4677 return true; |
|
4678 } else { |
|
4679 // a protocol definition |
|
4680 ObjCProtocolDeclarationAST *ast = new (_pool) ObjCProtocolDeclarationAST; |
|
4681 ast->attribute_list = attributes; |
|
4682 ast->protocol_token = protocol_token; |
|
4683 SimpleNameAST *name = new (_pool) SimpleNameAST; |
|
4684 name->identifier_token = identifier_token; |
|
4685 ast->name = name; |
|
4686 |
|
4687 parseObjCProtocolRefs(ast->protocol_refs); |
|
4688 |
|
4689 DeclarationListAST **nextMembers = &ast->member_declaration_list; |
|
4690 DeclarationAST *declaration = 0; |
|
4691 while (parseObjCInterfaceMemberDeclaration(declaration)) { |
|
4692 *nextMembers = new (_pool) DeclarationListAST; |
|
4693 (*nextMembers)->value = declaration; |
|
4694 nextMembers = &(*nextMembers)->next; |
|
4695 } |
|
4696 |
|
4697 match(T_AT_END, &ast->end_token); |
|
4698 |
|
4699 node = ast; |
|
4700 return true; |
|
4701 } |
|
4702 } |
|
4703 |
|
4704 // objc-implementation ::= T_AT_IMPLEMENTAION T_IDENTIFIER (T_COLON T_IDENTIFIER)? |
|
4705 // objc-class-instance-variables-opt |
|
4706 // objc-implementation ::= T_AT_IMPLEMENTAION T_IDENTIFIER T_LPAREN T_IDENTIFIER T_RPAREN |
|
4707 // |
|
4708 bool Parser::parseObjCImplementation(DeclarationAST *&node) |
|
4709 { |
|
4710 DEBUG_THIS_RULE(); |
|
4711 if (LA() != T_AT_IMPLEMENTATION) |
|
4712 return false; |
|
4713 |
|
4714 unsigned implementation_token = consumeToken(); |
|
4715 unsigned identifier_token = 0; |
|
4716 match(T_IDENTIFIER, &identifier_token); |
|
4717 |
|
4718 if (LA() == T_LPAREN) { |
|
4719 // a category implementation |
|
4720 ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST; |
|
4721 ast->implementation_token = implementation_token; |
|
4722 SimpleNameAST *class_name = new (_pool) SimpleNameAST; |
|
4723 class_name->identifier_token = identifier_token; |
|
4724 ast->class_name = class_name; |
|
4725 |
|
4726 match(T_LPAREN, &ast->lparen_token); |
|
4727 SimpleNameAST *category_name = new (_pool) SimpleNameAST; |
|
4728 match(T_IDENTIFIER, &category_name->identifier_token); |
|
4729 ast->category_name = category_name; |
|
4730 match(T_RPAREN, &ast->rparen_token); |
|
4731 |
|
4732 parseObjCMethodDefinitionList(ast->member_declaration_list); |
|
4733 match(T_AT_END, &ast->end_token); |
|
4734 |
|
4735 node = ast; |
|
4736 } else { |
|
4737 // a class implementation |
|
4738 ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST; |
|
4739 ast->implementation_token = implementation_token; |
|
4740 SimpleNameAST *class_name = new (_pool) SimpleNameAST; |
|
4741 class_name->identifier_token = identifier_token; |
|
4742 ast->class_name = class_name; |
|
4743 |
|
4744 if (LA() == T_COLON) { |
|
4745 ast->colon_token = consumeToken(); |
|
4746 SimpleNameAST *superclass = new (_pool) SimpleNameAST; |
|
4747 match(T_IDENTIFIER, &superclass->identifier_token); |
|
4748 ast->superclass = superclass; |
|
4749 } |
|
4750 |
|
4751 parseObjClassInstanceVariables(ast->inst_vars_decl); |
|
4752 parseObjCMethodDefinitionList(ast->member_declaration_list); |
|
4753 match(T_AT_END, &ast->end_token); |
|
4754 |
|
4755 node = ast; |
|
4756 } |
|
4757 |
|
4758 return true; |
|
4759 } |
|
4760 |
|
4761 bool Parser::parseObjCMethodDefinitionList(DeclarationListAST *&node) |
|
4762 { |
|
4763 DEBUG_THIS_RULE(); |
|
4764 DeclarationListAST **next = &node; |
|
4765 |
|
4766 while (LA() && LA() != T_AT_END) { |
|
4767 unsigned start = cursor(); |
|
4768 DeclarationAST *declaration = 0; |
|
4769 |
|
4770 switch (LA()) { |
|
4771 case T_PLUS: |
|
4772 case T_MINUS: |
|
4773 parseObjCMethodDefinition(declaration); |
|
4774 |
|
4775 if (start == cursor()) |
|
4776 consumeToken(); |
|
4777 break; |
|
4778 |
|
4779 case T_SEMICOLON: |
|
4780 consumeToken(); |
|
4781 break; |
|
4782 |
|
4783 case T_AT_SYNTHESIZE: { |
|
4784 ObjCSynthesizedPropertiesDeclarationAST *ast = new (_pool) ObjCSynthesizedPropertiesDeclarationAST; |
|
4785 ast->synthesized_token = consumeToken(); |
|
4786 ObjCSynthesizedPropertyListAST *last = new (_pool) ObjCSynthesizedPropertyListAST; |
|
4787 ast->property_identifier_list = last; |
|
4788 last->value = new (_pool) ObjCSynthesizedPropertyAST; |
|
4789 match(T_IDENTIFIER, &last->value->property_identifier_token); |
|
4790 |
|
4791 if (LA() == T_EQUAL) { |
|
4792 last->value->equals_token = consumeToken(); |
|
4793 |
|
4794 match(T_IDENTIFIER, &last->value->alias_identifier_token); |
|
4795 } |
|
4796 |
|
4797 while (LA() == T_COMMA) { |
|
4798 consumeToken(); // consume T_COMMA |
|
4799 |
|
4800 last->next = new (_pool) ObjCSynthesizedPropertyListAST; |
|
4801 last = last->next; |
|
4802 |
|
4803 last->value = new (_pool) ObjCSynthesizedPropertyAST; |
|
4804 match(T_IDENTIFIER, &last->value->property_identifier_token); |
|
4805 |
|
4806 if (LA() == T_EQUAL) { |
|
4807 last->value->equals_token = consumeToken(); |
|
4808 |
|
4809 match(T_IDENTIFIER, &last->value->alias_identifier_token); |
|
4810 } |
|
4811 } |
|
4812 |
|
4813 match(T_SEMICOLON, &ast->semicolon_token); |
|
4814 |
|
4815 declaration = ast; |
|
4816 break; |
|
4817 } |
|
4818 |
|
4819 case T_AT_DYNAMIC: { |
|
4820 ObjCDynamicPropertiesDeclarationAST *ast = new (_pool) ObjCDynamicPropertiesDeclarationAST; |
|
4821 ast->dynamic_token = consumeToken(); |
|
4822 ast->property_identifier_list = new (_pool) ObjCIdentifierListAST; |
|
4823 SimpleNameAST *name = new (_pool) SimpleNameAST; |
|
4824 match(T_IDENTIFIER, &name->identifier_token); |
|
4825 ast->property_identifier_list->value = name; |
|
4826 |
|
4827 ObjCIdentifierListAST *last = ast->property_identifier_list; |
|
4828 while (LA() == T_COMMA) { |
|
4829 consumeToken(); // consume T_COMMA |
|
4830 |
|
4831 last->next = new (_pool) ObjCIdentifierListAST; |
|
4832 last = last->next; |
|
4833 name = new (_pool) SimpleNameAST; |
|
4834 match(T_IDENTIFIER, &name->identifier_token); |
|
4835 last->value = name; |
|
4836 } |
|
4837 |
|
4838 match(T_SEMICOLON, &ast->semicolon_token); |
|
4839 |
|
4840 declaration = ast; |
|
4841 break; |
|
4842 } |
|
4843 |
|
4844 default: |
|
4845 if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) { |
|
4846 parseDeclaration(declaration); |
|
4847 } else { |
|
4848 if (! parseBlockDeclaration(declaration)) { |
|
4849 rewind(start); |
|
4850 _translationUnit->error(cursor(), |
|
4851 "skip token `%s'", tok().spell()); |
|
4852 |
|
4853 consumeToken(); |
|
4854 } |
|
4855 } |
|
4856 break; |
|
4857 } // switch |
|
4858 |
|
4859 if (declaration) { |
|
4860 *next = new (_pool) DeclarationListAST; |
|
4861 (*next)->value = declaration; |
|
4862 next = &(*next)->next; |
|
4863 } |
|
4864 } |
|
4865 |
|
4866 return true; |
|
4867 } |
|
4868 |
|
4869 bool Parser::parseObjCMethodDefinition(DeclarationAST *&node) |
|
4870 { |
|
4871 DEBUG_THIS_RULE(); |
|
4872 ObjCMethodPrototypeAST *method_prototype = 0; |
|
4873 if (! parseObjCMethodPrototype(method_prototype)) |
|
4874 return false; |
|
4875 |
|
4876 ObjCMethodDeclarationAST *ast = new (_pool) ObjCMethodDeclarationAST; |
|
4877 ast->method_prototype = method_prototype; |
|
4878 |
|
4879 // Objective-C allows you to write: |
|
4880 // - (void) foo; { body; } |
|
4881 // so a method is a forward declaration when it doesn't have a _body_. |
|
4882 // However, we still need to read the semicolon. |
|
4883 if (LA() == T_SEMICOLON) { |
|
4884 ast->semicolon_token = consumeToken(); |
|
4885 } |
|
4886 |
|
4887 parseFunctionBody(ast->function_body); |
|
4888 |
|
4889 node = ast; |
|
4890 return true; |
|
4891 } |
|
4892 |
|
4893 // objc-protocol-refs ::= T_LESS (T_IDENTIFIER @ T_COMMA) T_GREATER |
|
4894 // |
|
4895 bool Parser::parseObjCProtocolRefs(ObjCProtocolRefsAST *&node) |
|
4896 { |
|
4897 DEBUG_THIS_RULE(); |
|
4898 if (LA() != T_LESS) |
|
4899 return false; |
|
4900 |
|
4901 ObjCProtocolRefsAST *ast = new (_pool) ObjCProtocolRefsAST; |
|
4902 |
|
4903 match(T_LESS, &ast->less_token); |
|
4904 |
|
4905 unsigned identifier_token = 0; |
|
4906 match(T_IDENTIFIER, &identifier_token); |
|
4907 ast->identifier_list = new (_pool) ObjCIdentifierListAST; |
|
4908 SimpleNameAST *name = new (_pool) SimpleNameAST; |
|
4909 name->identifier_token = identifier_token; |
|
4910 ast->identifier_list->value = name; |
|
4911 ObjCIdentifierListAST **nextId = &ast->identifier_list->next; |
|
4912 |
|
4913 while (LA() == T_COMMA) { |
|
4914 consumeToken(); // consume T_COMMA |
|
4915 match(T_IDENTIFIER, &identifier_token); |
|
4916 |
|
4917 *nextId = new (_pool) ObjCIdentifierListAST; |
|
4918 name = new (_pool) SimpleNameAST; |
|
4919 name->identifier_token = identifier_token; |
|
4920 (*nextId)->value = name; |
|
4921 nextId = &(*nextId)->next; |
|
4922 } |
|
4923 |
|
4924 match(T_GREATER, &ast->greater_token); |
|
4925 node = ast; |
|
4926 return true; |
|
4927 } |
|
4928 |
|
4929 // objc-class-instance-variables ::= T_LBRACE |
|
4930 // objc-instance-variable-decl-list-opt |
|
4931 // T_RBRACE |
|
4932 // |
|
4933 bool Parser::parseObjClassInstanceVariables(ObjCInstanceVariablesDeclarationAST *&node) |
|
4934 { |
|
4935 DEBUG_THIS_RULE(); |
|
4936 if (LA() != T_LBRACE) |
|
4937 return false; |
|
4938 |
|
4939 ObjCInstanceVariablesDeclarationAST *ast = new (_pool) ObjCInstanceVariablesDeclarationAST; |
|
4940 match(T_LBRACE, &ast->lbrace_token); |
|
4941 |
|
4942 for (DeclarationListAST **next = &ast->instance_variable_list; LA(); next = &(*next)->next) { |
|
4943 if (LA() == T_RBRACE) |
|
4944 break; |
|
4945 |
|
4946 const unsigned start = cursor(); |
|
4947 |
|
4948 *next = new (_pool) DeclarationListAST; |
|
4949 parseObjCInstanceVariableDeclaration((*next)->value); |
|
4950 |
|
4951 if (start == cursor()) { |
|
4952 // skip stray token. |
|
4953 _translationUnit->error(cursor(), "skip stray token `%s'", tok().spell()); |
|
4954 consumeToken(); |
|
4955 } |
|
4956 } |
|
4957 |
|
4958 match(T_RBRACE, &ast->rbrace_token); |
|
4959 |
|
4960 node = ast; |
|
4961 return true; |
|
4962 } |
|
4963 |
|
4964 // objc-interface-declaration ::= T_AT_REQUIRED |
|
4965 // objc-interface-declaration ::= T_AT_OPTIONAL |
|
4966 // objc-interface-declaration ::= T_SEMICOLON |
|
4967 // objc-interface-declaration ::= objc-property-declaration |
|
4968 // objc-interface-declaration ::= objc-method-prototype |
|
4969 bool Parser::parseObjCInterfaceMemberDeclaration(DeclarationAST *&node) |
|
4970 { |
|
4971 DEBUG_THIS_RULE(); |
|
4972 switch (LA()) { |
|
4973 case T_AT_END: |
|
4974 return false; |
|
4975 |
|
4976 case T_AT_REQUIRED: |
|
4977 case T_AT_OPTIONAL: |
|
4978 consumeToken(); |
|
4979 return true; |
|
4980 |
|
4981 case T_SEMICOLON: |
|
4982 consumeToken(); |
|
4983 return true; |
|
4984 |
|
4985 case T_AT_PROPERTY: { |
|
4986 return parseObjCPropertyDeclaration(node); |
|
4987 } |
|
4988 |
|
4989 case T_PLUS: |
|
4990 case T_MINUS: { |
|
4991 ObjCMethodDeclarationAST *ast = new (_pool) ObjCMethodDeclarationAST; |
|
4992 if (parseObjCMethodPrototype(ast->method_prototype)) { |
|
4993 match(T_SEMICOLON, &ast->semicolon_token); |
|
4994 node = ast; |
|
4995 return true; |
|
4996 } else { |
|
4997 return false; |
|
4998 } |
|
4999 } |
|
5000 |
|
5001 case T_ENUM: |
|
5002 case T_CLASS: |
|
5003 case T_STRUCT: |
|
5004 case T_UNION: { |
|
5005 return parseSimpleDeclaration(node, /*accept struct declarators */ true); |
|
5006 } |
|
5007 |
|
5008 default: { |
|
5009 return parseSimpleDeclaration(node, /*accept struct declarators */ true); |
|
5010 } // default |
|
5011 |
|
5012 } // switch |
|
5013 } |
|
5014 |
|
5015 // objc-instance-variable-declaration ::= objc-visibility-specifier |
|
5016 // objc-instance-variable-declaration ::= block-declaration |
|
5017 // |
|
5018 bool Parser::parseObjCInstanceVariableDeclaration(DeclarationAST *&node) |
|
5019 { |
|
5020 DEBUG_THIS_RULE(); |
|
5021 switch (LA()) { |
|
5022 case T_AT_PRIVATE: |
|
5023 case T_AT_PROTECTED: |
|
5024 case T_AT_PUBLIC: |
|
5025 case T_AT_PACKAGE: { |
|
5026 ObjCVisibilityDeclarationAST *ast = new (_pool) ObjCVisibilityDeclarationAST; |
|
5027 ast->visibility_token = consumeToken(); |
|
5028 node = ast; |
|
5029 return true; |
|
5030 } |
|
5031 |
|
5032 default: |
|
5033 return parseSimpleDeclaration(node, true); |
|
5034 } |
|
5035 } |
|
5036 |
|
5037 // objc-property-declaration ::= |
|
5038 // T_AT_PROPERTY T_LPAREN (property-attribute @ T_COMMA) T_RPAREN simple-declaration |
|
5039 // |
|
5040 bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&node, SpecifierListAST *attributes) |
|
5041 { |
|
5042 DEBUG_THIS_RULE(); |
|
5043 if (LA() != T_AT_PROPERTY) |
|
5044 return false; |
|
5045 |
|
5046 ObjCPropertyDeclarationAST *ast = new (_pool) ObjCPropertyDeclarationAST; |
|
5047 ast->attribute_list = attributes; |
|
5048 ast->property_token = consumeToken(); |
|
5049 |
|
5050 if (LA() == T_LPAREN) { |
|
5051 match(T_LPAREN, &ast->lparen_token); |
|
5052 |
|
5053 ObjCPropertyAttributeAST *property_attribute = 0; |
|
5054 if (parseObjCPropertyAttribute(property_attribute)) { |
|
5055 ast->property_attribute_list = new (_pool) ObjCPropertyAttributeListAST; |
|
5056 ast->property_attribute_list->value = property_attribute; |
|
5057 ObjCPropertyAttributeListAST *last = ast->property_attribute_list; |
|
5058 |
|
5059 while (LA() == T_COMMA) { |
|
5060 consumeToken(); // consume T_COMMA |
|
5061 last->next = new (_pool) ObjCPropertyAttributeListAST; |
|
5062 last = last->next; |
|
5063 if (!parseObjCPropertyAttribute(last->value)) { |
|
5064 _translationUnit->error(_tokenIndex, "expected token `%s' got `%s'", |
|
5065 Token::name(T_IDENTIFIER), tok().spell()); |
|
5066 break; |
|
5067 } |
|
5068 } |
|
5069 } |
|
5070 |
|
5071 match(T_RPAREN, &ast->rparen_token); |
|
5072 } |
|
5073 |
|
5074 if (parseSimpleDeclaration(ast->simple_declaration, /*accept-struct-declarators = */ true)) |
|
5075 node = ast; |
|
5076 else |
|
5077 _translationUnit->error(_tokenIndex, "expected a simple declaration"); |
|
5078 |
|
5079 return true; |
|
5080 } |
|
5081 |
|
5082 // objc-method-prototype ::= (T_PLUS | T_MINUS) objc-method-decl objc-method-attrs-opt |
|
5083 // |
|
5084 // objc-method-decl ::= objc-type-name? objc-selector |
|
5085 // objc-method-decl ::= objc-type-name? objc-keyword-decl-list objc-parmlist-opt |
|
5086 // |
|
5087 bool Parser::parseObjCMethodPrototype(ObjCMethodPrototypeAST *&node) |
|
5088 { |
|
5089 DEBUG_THIS_RULE(); |
|
5090 if (LA() != T_PLUS && LA() != T_MINUS) |
|
5091 return false; |
|
5092 |
|
5093 ObjCMethodPrototypeAST *ast = new (_pool) ObjCMethodPrototypeAST; |
|
5094 ast->method_type_token = consumeToken(); |
|
5095 |
|
5096 parseObjCTypeName(ast->type_name); |
|
5097 |
|
5098 if ((lookAtObjCSelector() && LA(2) == T_COLON) || LA() == T_COLON) { |
|
5099 ObjCSelectorArgumentAST *argument = 0; |
|
5100 ObjCMessageArgumentDeclarationAST *declaration = 0; |
|
5101 parseObjCKeywordDeclaration(argument, declaration); |
|
5102 |
|
5103 ObjCSelectorWithArgumentsAST *sel = new (_pool) ObjCSelectorWithArgumentsAST; |
|
5104 ast->selector = sel; |
|
5105 ObjCSelectorArgumentListAST *lastSel = new (_pool) ObjCSelectorArgumentListAST; |
|
5106 sel->selector_argument_list = lastSel; |
|
5107 sel->selector_argument_list->value = argument; |
|
5108 |
|
5109 ast->argument_list = new (_pool) ObjCMessageArgumentDeclarationListAST; |
|
5110 ast->argument_list->value = declaration; |
|
5111 ObjCMessageArgumentDeclarationListAST *lastArg = ast->argument_list; |
|
5112 |
|
5113 while (parseObjCKeywordDeclaration(argument, declaration)) { |
|
5114 lastSel->next = new (_pool) ObjCSelectorArgumentListAST; |
|
5115 lastSel = lastSel->next; |
|
5116 lastSel->value = argument; |
|
5117 |
|
5118 lastArg->next = new (_pool) ObjCMessageArgumentDeclarationListAST; |
|
5119 lastArg = lastArg->next; |
|
5120 lastArg->value = declaration; |
|
5121 } |
|
5122 |
|
5123 while (LA() == T_COMMA) { |
|
5124 consumeToken(); |
|
5125 |
|
5126 if (LA() == T_DOT_DOT_DOT) { |
|
5127 ast->dot_dot_dot_token = consumeToken(); |
|
5128 break; |
|
5129 } |
|
5130 |
|
5131 // TODO: Is this still valid, and if so, should it be stored in the AST? (EV) |
|
5132 DeclarationAST *parameter_declaration = 0; |
|
5133 parseParameterDeclaration(parameter_declaration); |
|
5134 } |
|
5135 } else if (lookAtObjCSelector()) { |
|
5136 ObjCSelectorWithoutArgumentsAST *sel = new (_pool) ObjCSelectorWithoutArgumentsAST; |
|
5137 parseObjCSelector(sel->name_token); |
|
5138 ast->selector = sel; |
|
5139 } else { |
|
5140 _translationUnit->error(cursor(), "expected a selector"); |
|
5141 } |
|
5142 |
|
5143 SpecifierListAST **attr = &ast->attribute_list; |
|
5144 while (parseAttributeSpecifier(*attr)) |
|
5145 attr = &(*attr)->next; |
|
5146 |
|
5147 node = ast; |
|
5148 return true; |
|
5149 } |
|
5150 |
|
5151 // objc-property-attribute ::= getter '=' identifier |
|
5152 // objc-property-attribute ::= setter '=' identifier ':' |
|
5153 // objc-property-attribute ::= readonly |
|
5154 // objc-property-attribute ::= readwrite |
|
5155 // objc-property-attribute ::= assign |
|
5156 // objc-property-attribute ::= retain |
|
5157 // objc-property-attribute ::= copy |
|
5158 // objc-property-attribute ::= nonatomic |
|
5159 bool Parser::parseObjCPropertyAttribute(ObjCPropertyAttributeAST *&node) |
|
5160 { |
|
5161 DEBUG_THIS_RULE(); |
|
5162 if (LA() != T_IDENTIFIER) |
|
5163 return false; |
|
5164 |
|
5165 node = new (_pool) ObjCPropertyAttributeAST; |
|
5166 |
|
5167 const Identifier *id = tok().identifier; |
|
5168 const int k = classifyObjectiveCTypeQualifiers(id->chars(), id->size()); |
|
5169 switch (k) { |
|
5170 case Token_copy: |
|
5171 case Token_assign: |
|
5172 case Token_retain: |
|
5173 case Token_readonly: |
|
5174 case Token_readwrite: |
|
5175 case Token_nonatomic: |
|
5176 node->attribute_identifier_token = consumeToken(); |
|
5177 return true; |
|
5178 |
|
5179 case Token_getter: { |
|
5180 node->attribute_identifier_token = consumeToken(); |
|
5181 match(T_EQUAL, &node->equals_token); |
|
5182 ObjCSelectorWithoutArgumentsAST *selector = new (_pool) ObjCSelectorWithoutArgumentsAST; |
|
5183 match(T_IDENTIFIER, &selector->name_token); |
|
5184 node->method_selector = selector; |
|
5185 return true; |
|
5186 } |
|
5187 |
|
5188 case Token_setter: { |
|
5189 node->attribute_identifier_token = consumeToken(); |
|
5190 match(T_EQUAL, &node->equals_token); |
|
5191 ObjCSelectorWithArgumentsAST *selector = new (_pool) ObjCSelectorWithArgumentsAST; |
|
5192 selector->selector_argument_list = new (_pool) ObjCSelectorArgumentListAST; |
|
5193 selector->selector_argument_list->value = new (_pool) ObjCSelectorArgumentAST; |
|
5194 match(T_IDENTIFIER, &selector->selector_argument_list->value->name_token); |
|
5195 match(T_COLON, &selector->selector_argument_list->value->colon_token); |
|
5196 node->method_selector = selector; |
|
5197 return true; |
|
5198 } |
|
5199 |
|
5200 default: |
|
5201 return false; |
|
5202 } |
|
5203 } |
|
5204 |
|
5205 // objc-type-name ::= T_LPAREN objc-type-qualifiers-opt type-id T_RPAREN |
|
5206 // |
|
5207 bool Parser::parseObjCTypeName(ObjCTypeNameAST *&node) |
|
5208 { |
|
5209 DEBUG_THIS_RULE(); |
|
5210 if (LA() != T_LPAREN) |
|
5211 return false; |
|
5212 |
|
5213 ObjCTypeNameAST *ast = new (_pool) ObjCTypeNameAST; |
|
5214 match(T_LPAREN, &ast->lparen_token); |
|
5215 parseObjCTypeQualifiers(ast->type_qualifier_token); |
|
5216 parseTypeId(ast->type_id); |
|
5217 match(T_RPAREN, &ast->rparen_token); |
|
5218 node = ast; |
|
5219 return true; |
|
5220 } |
|
5221 |
|
5222 // objc-selector ::= T_IDENTIFIER | keyword |
|
5223 // |
|
5224 bool Parser::parseObjCSelector(unsigned &selector_token) |
|
5225 { |
|
5226 DEBUG_THIS_RULE(); |
|
5227 if (! lookAtObjCSelector()) |
|
5228 return false; |
|
5229 |
|
5230 selector_token = consumeToken(); |
|
5231 return true; |
|
5232 } |
|
5233 |
|
5234 // objc-keyword-decl ::= objc-selector? T_COLON objc-type-name? objc-keyword-attributes-opt T_IDENTIFIER |
|
5235 // |
|
5236 bool Parser::parseObjCKeywordDeclaration(ObjCSelectorArgumentAST *&argument, ObjCMessageArgumentDeclarationAST *&node) |
|
5237 { |
|
5238 DEBUG_THIS_RULE(); |
|
5239 if (! (LA() == T_COLON || (lookAtObjCSelector() && LA(2) == T_COLON))) |
|
5240 return false; |
|
5241 |
|
5242 node = new (_pool) ObjCMessageArgumentDeclarationAST; |
|
5243 argument = new (_pool) ObjCSelectorArgumentAST; |
|
5244 |
|
5245 parseObjCSelector(argument->name_token); |
|
5246 match(T_COLON, &argument->colon_token); |
|
5247 |
|
5248 parseObjCTypeName(node->type_name); |
|
5249 |
|
5250 SpecifierListAST **attr = &node->attribute_list; |
|
5251 while (parseAttributeSpecifier(*attr)) |
|
5252 attr = &(*attr)->next; |
|
5253 |
|
5254 match(T_IDENTIFIER, &node->param_name_token); |
|
5255 |
|
5256 return true; |
|
5257 } |
|
5258 |
|
5259 bool Parser::parseObjCTypeQualifiers(unsigned &type_qualifier) |
|
5260 { |
|
5261 DEBUG_THIS_RULE(); |
|
5262 if (LA() != T_IDENTIFIER) |
|
5263 return false; |
|
5264 |
|
5265 const Identifier *id = tok().identifier; |
|
5266 const int k = classifyObjectiveCTypeQualifiers(id->chars(), id->size()); |
|
5267 if (k == Token_identifier) |
|
5268 return false; |
|
5269 type_qualifier = consumeToken(); |
|
5270 return true; |
|
5271 } |
|
5272 |
|
5273 bool Parser::peekAtObjCContextKeyword(int kind) |
|
5274 { |
|
5275 if (LA() != T_IDENTIFIER) |
|
5276 return false; |
|
5277 |
|
5278 const Identifier *id = tok().identifier; |
|
5279 const int k = classifyObjectiveCTypeQualifiers(id->chars(), id->size()); |
|
5280 return k == kind; |
|
5281 } |
|
5282 |
|
5283 bool Parser::parseObjCContextKeyword(int kind, unsigned &in_token) |
|
5284 { |
|
5285 DEBUG_THIS_RULE(); |
|
5286 |
|
5287 if (peekAtObjCContextKeyword(kind)) { |
|
5288 in_token = consumeToken(); |
|
5289 return true; |
|
5290 } else { |
|
5291 return false; |
|
5292 } |
|
5293 } |
|
5294 |
|
5295 |