1
/*******************************************************************************
2
* Copyright (c) 2006, 2009 IBM Corporation and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* IBM Corporation - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.core.dom.lrparser.action.cpp;
13
import static org.eclipse.cdt.core.dom.lrparser.action.ParserUtil.*;
14
import static org.eclipse.cdt.core.parser.util.CollectionUtils.findFirstAndRemove;
15
import static org.eclipse.cdt.core.parser.util.CollectionUtils.reverseIterable;
16
import static org.eclipse.cdt.internal.core.dom.lrparser.cpp.CPPParsersym.*;
18
import java.util.Arrays;
19
import java.util.Collections;
20
import java.util.LinkedList;
21
import java.util.List;
23
import lpg.lpgjavaruntime.IToken;
25
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
26
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
27
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
28
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
29
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
30
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
31
import org.eclipse.cdt.core.dom.ast.IASTExpression;
32
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
33
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
34
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
35
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
36
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
37
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
38
import org.eclipse.cdt.core.dom.ast.IASTName;
39
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
40
import org.eclipse.cdt.core.dom.ast.IASTNode;
41
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
42
import org.eclipse.cdt.core.dom.ast.IASTPointer;
43
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
44
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
45
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
46
import org.eclipse.cdt.core.dom.ast.IASTStatement;
47
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
48
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
49
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
50
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
51
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument;
52
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
53
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
54
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
55
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
56
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
57
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
58
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
59
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
60
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
61
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
62
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
63
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
64
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock;
65
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
66
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
67
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
68
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
69
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
70
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName;
71
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
72
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember;
73
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
74
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator;
75
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
76
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression;
77
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
78
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
79
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
80
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
81
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
82
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter;
83
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement;
84
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypenameExpression;
85
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
86
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
87
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
88
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
89
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNodeFactory;
90
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
91
import org.eclipse.cdt.core.dom.lrparser.ISecondaryParser;
92
import org.eclipse.cdt.core.dom.lrparser.LPGTokenAdapter;
93
import org.eclipse.cdt.core.dom.lrparser.action.BuildASTParserAction;
94
import org.eclipse.cdt.core.dom.lrparser.action.ITokenMap;
95
import org.eclipse.cdt.core.dom.lrparser.action.ITokenStream;
96
import org.eclipse.cdt.core.dom.lrparser.action.ParserUtil;
97
import org.eclipse.cdt.core.dom.lrparser.action.ScopedStack;
98
import org.eclipse.cdt.core.dom.lrparser.action.TokenMap;
99
import org.eclipse.cdt.internal.core.dom.lrparser.cpp.CPPParsersym;
100
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
101
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression;
102
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement;
103
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTAmbiguousDeclarator;
104
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTAmbiguousExpression;
105
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTAmbiguousStatement;
106
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTAmbiguousTemplateArgument;
107
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
110
* Semantic actions that build the AST during the parse.
111
* These are the actions that are specific to the C++ parser, the superclass
112
* contains actions that can be shared with the C99 parser.
114
* @author Mike Kucera
116
@SuppressWarnings("restriction")
117
public class CPPBuildASTParserAction extends BuildASTParserAction {
119
/** Allows code in this class to refer to the token kinds in CPPParsersym */
120
private final ITokenMap tokenMap;
122
/** Used to create the AST node objects */
123
protected final ICPPNodeFactory nodeFactory;
125
protected final ICPPSecondaryParserFactory parserFactory;
127
/** Stack that provides easy access to the current class name, used to disambiguate declarators. */
128
protected final LinkedList<IASTName> classNames = new LinkedList<IASTName>();
133
* @param orderedTerminalSymbols When an instance of this class is created for a parser
134
* that parsers token kinds will be mapped back to the base C99 parser's token kinds.
136
public CPPBuildASTParserAction(ITokenStream parser, ScopedStack<Object> astStack, ICPPNodeFactory nodeFactory, ICPPSecondaryParserFactory parserFactory) {
137
super(parser, astStack, nodeFactory, parserFactory);
139
this.nodeFactory = nodeFactory;
140
this.parserFactory = parserFactory;
141
this.tokenMap = new TokenMap(CPPParsersym.orderedTerminalSymbols, parser.getOrderedTerminalSymbols());
145
private int baseKind(IToken token) {
146
return tokenMap.mapKind(token.getKind());
150
protected boolean isCompletionToken(IToken token) {
151
return baseKind(token) == TK_Completion;
155
protected boolean isIdentifierToken(IToken token) {
156
return baseKind(token) == TK_identifier;
160
protected IASTName createName(char[] image) {
161
return nodeFactory.newName(image);
166
public void consumeNewInitializer() {
167
if(astStack.peek() == null) { // if there is an empty set of parens
169
IASTExpression initializer = nodeFactory.newExpressionList();
170
setOffsetAndLength(initializer);
171
astStack.push(initializer);
177
// TODO can the new_array_expressions be removed? it looks like they parse as part of the type id
180
* ::= dcolon_opt 'new' new_placement_opt new_type_id <openscope-ast> new_array_expressions_op new_initializer_opt
181
* | dcolon_opt 'new' new_placement_opt '(' type_id ')' <openscope-ast> new_array_expressions_op new_initializer_opt
183
public void consumeExpressionNew(boolean isNewTypeId) {
184
IASTExpression initializer = (IASTExpression) astStack.pop(); // may be null
185
List<Object> arrayExpressions = astStack.closeScope();
186
IASTTypeId typeId = (IASTTypeId) astStack.pop();
187
IASTExpression placement = (IASTExpression) astStack.pop(); // may be null
188
boolean hasDoubleColon = astStack.pop() != null;
190
ICPPASTNewExpression newExpression = nodeFactory.newNewExpression(placement, initializer, typeId);
191
newExpression.setIsGlobal(hasDoubleColon);
192
newExpression.setIsNewTypeId(isNewTypeId);
193
setOffsetAndLength(newExpression);
195
for(Object expr : arrayExpressions)
196
newExpression.addNewTypeIdArrayExpression((IASTExpression)expr);
198
// handle ambiguities of the form: (A)(B)
199
if(!isNewTypeId && initializer == null &&
200
placement instanceof IASTIdExpression &&
201
typeId != null && typeId.getDeclSpecifier() instanceof IASTNamedTypeSpecifier) {
203
IASTName firstName = ((IASTIdExpression)placement).getName();
204
IASTName secondName = ((IASTNamedTypeSpecifier)typeId.getDeclSpecifier()).getName();
206
IASTNamedTypeSpecifier newTypeSpecifier = nodeFactory.newTypedefNameSpecifier(firstName.copy());
207
ParserUtil.setOffsetAndLength(newTypeSpecifier, firstName);
208
IASTDeclarator newDeclarator = nodeFactory.newDeclarator(nodeFactory.newName());
209
ParserUtil.setOffsetAndLength(newDeclarator, endOffset(firstName), 0);
210
IASTTypeId newTypeId = nodeFactory.newTypeId(newTypeSpecifier, newDeclarator);
211
ParserUtil.setOffsetAndLength(newTypeId, firstName);
213
IASTIdExpression newInitializer = nodeFactory.newIdExpression(secondName.copy());
214
ParserUtil.setOffsetAndLength(newInitializer, secondName);
216
ICPPASTNewExpression alternate = nodeFactory.newNewExpression(null, newInitializer, newTypeId);
217
ParserUtil.setOffsetAndLength(alternate, newExpression);
218
newExpression.setIsGlobal(hasDoubleColon);
219
newExpression.setIsNewTypeId(isNewTypeId);
221
IASTAmbiguousExpression ambiguity = createAmbiguousExpression(newExpression, alternate);
222
astStack.push(ambiguity);
225
astStack.push(newExpression);
231
* new_declarator -- pointer operators are part of the type id, held in an empty declarator
232
* ::= <openscope-ast> new_pointer_operators
234
public void consumeNewDeclarator() {
235
IASTName name = nodeFactory.newName();
236
IASTDeclarator declarator = nodeFactory.newDeclarator(name);
238
for(Object pointer : astStack.closeScope())
239
declarator.addPointerOperator((IASTPointerOperator)pointer);
241
setOffsetAndLength(declarator);
242
astStack.push(declarator);
249
* | 'throw' assignment_expression
251
public void consumeExpressionThrow(boolean hasExpr) {
252
IASTExpression operand = hasExpr ? (IASTExpression) astStack.pop() : null;
253
IASTUnaryExpression expr = nodeFactory.newUnaryExpression(ICPPASTUnaryExpression.op_throw, operand);
254
setOffsetAndLength(expr);
261
* ::= dcolon_opt 'delete' cast_expression
262
* | dcolon_opt 'delete' '[' ']' cast_expression
263
* @param isVectorized
265
public void consumeExpressionDelete(boolean isVectorized) {
266
IASTExpression operand = (IASTExpression) astStack.pop();
267
boolean hasDoubleColon = astStack.pop() != null;
269
ICPPASTDeleteExpression deleteExpr = nodeFactory.newDeleteExpression(operand);
270
deleteExpr.setIsGlobal(hasDoubleColon);
271
deleteExpr.setIsVectored(isVectorized);
273
setOffsetAndLength(deleteExpr);
274
astStack.push(deleteExpr);
281
public void consumeExpressionFieldReference(boolean isPointerDereference, boolean hasTemplateKeyword) {
282
IASTName name = (IASTName) astStack.pop();
283
IASTExpression owner = (IASTExpression) astStack.pop();
284
ICPPASTFieldReference expr = nodeFactory.newFieldReference(name, owner);
285
expr.setIsPointerDereference(isPointerDereference);
286
expr.setIsTemplate(hasTemplateKeyword);
288
setOffsetAndLength(expr);
294
* ::= simple_type_specifier '(' expression_list_opt ')'
296
public void consumeExpressionSimpleTypeConstructor() {
297
IASTExpression expression = (IASTExpression) astStack.pop();
298
IToken token = (IToken) astStack.pop();
300
int type = asICPPASTSimpleTypeConstructorExpressionType(token);
301
ICPPASTSimpleTypeConstructorExpression typeConstructor = nodeFactory.newSimpleTypeConstructorExpression(type, expression);
303
setOffsetAndLength(typeConstructor);
304
astStack.push(typeConstructor);
308
private int asICPPASTSimpleTypeConstructorExpressionType(IToken token) {
309
assert token != null;
311
switch(baseKind(token)) {
312
case TK_char : return ICPPASTSimpleTypeConstructorExpression.t_char;
313
case TK_wchar_t : return ICPPASTSimpleTypeConstructorExpression.t_wchar_t;
314
case TK_bool : return ICPPASTSimpleTypeConstructorExpression.t_bool;
315
case TK_short : return ICPPASTSimpleTypeConstructorExpression.t_short;
316
case TK_int : return ICPPASTSimpleTypeConstructorExpression.t_int;
317
case TK_long : return ICPPASTSimpleTypeConstructorExpression.t_long;
318
case TK_signed : return ICPPASTSimpleTypeConstructorExpression.t_signed;
319
case TK_unsigned : return ICPPASTSimpleTypeConstructorExpression.t_unsigned;
320
case TK_float : return ICPPASTSimpleTypeConstructorExpression.t_float;
321
case TK_double : return ICPPASTSimpleTypeConstructorExpression.t_double;
322
case TK_void : return ICPPASTSimpleTypeConstructorExpression.t_void;
325
assert false : "type parsed wrong"; //$NON-NLS-1$
326
return ICPPASTSimpleTypeConstructorExpression.t_unspecified;
333
* ::= 'typename' dcolon_opt nested_name_specifier <empty> identifier_name '(' expression_list_opt ')'
334
* | 'typename' dcolon_opt nested_name_specifier template_opt template_id '(' expression_list_opt ')'
336
@SuppressWarnings("unchecked")
337
public void consumeExpressionTypeName() {
338
IASTExpression expr = (IASTExpression) astStack.pop();
339
IASTName name = (IASTName) astStack.pop();
340
boolean isTemplate = astStack.pop() == PLACE_HOLDER;
341
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
342
IToken dColon = (IToken) astStack.pop();
344
nestedNames.addFirst(name);
346
int startOffset = dColon == null ? offset(nestedNames.getLast()) : offset(dColon);
347
int endOffset = endOffset(name);
348
IASTName qualifiedName = createQualifiedName(nestedNames, startOffset, endOffset, dColon != null);
350
ICPPASTTypenameExpression typenameExpr = nodeFactory.newTypenameExpression(qualifiedName, expr, isTemplate);
352
setOffsetAndLength(typenameExpr);
353
astStack.push(typenameExpr);
359
* ::= type_specifier_seq declarator '=' assignment_expression
361
public void consumeConditionDeclaration() {
362
IASTExpression expr = (IASTExpression) astStack.pop();
363
IASTDeclarator declarator = (IASTDeclarator) astStack.pop();
364
IASTDeclSpecifier declSpec = (IASTDeclSpecifier) astStack.pop();
366
IASTInitializerExpression initializer = nodeFactory.newInitializerExpression(expr);
367
ParserUtil.setOffsetAndLength(initializer, offset(expr), length(expr));
368
declarator.setInitializer(initializer);
370
IASTSimpleDeclaration declaration = nodeFactory.newSimpleDeclaration(declSpec);
371
declaration.addDeclarator(declarator);
373
setOffsetAndLength(declaration);
374
astStack.push(declaration);
380
* ::= identifier_name '<' <openscope-ast> template_argument_list_opt '>'
382
* operator_function_id
383
* ::= operator_id '<' <openscope-ast> template_argument_list_opt '>'
385
public void consumeTemplateId() {
386
List<Object> templateArguments = astStack.closeScope();
387
IASTName name = (IASTName) astStack.pop();
389
ICPPASTTemplateId templateId = nodeFactory.newTemplateId(name);
391
for(Object arg : templateArguments) {
392
if(arg instanceof IASTExpression)
393
templateId.addTemplateArgument((IASTExpression)arg);
394
else if(arg instanceof IASTTypeId)
395
templateId.addTemplateArgument((IASTTypeId)arg);
396
else if(arg instanceof ICPPASTAmbiguousTemplateArgument)
397
templateId.addTemplateArgument((ICPPASTAmbiguousTemplateArgument)arg);
400
setOffsetAndLength(templateId);
401
astStack.push(templateId);
406
* Disambiguates template arguments.
408
public void consumeTemplateArgumentTypeId() {
409
// TODO is this necessary? It should be able to tell if it looks like an id expression
410
ISecondaryParser<IASTExpression> secondaryParser = parserFactory.getExpressionParser(stream, properties);
411
IASTExpression result = runSecondaryParser(secondaryParser);
413
// The grammar rule allows assignment_expression, but the ambiguity
414
// only arises with id_expressions.
415
if(!(result instanceof IASTIdExpression))
418
IASTTypeId typeId = (IASTTypeId) astStack.pop();
419
IASTIdExpression expr = (IASTIdExpression) result;
421
ICPPASTAmbiguousTemplateArgument ambiguityNode = new CPPASTAmbiguousTemplateArgument(typeId, expr);
422
//setOffsetAndLength(ambiguityNode);
424
astStack.push(ambiguityNode);
429
* Disambiguates template arguments.
430
* Qualified names parse as an expression, so generate the corresponding
431
* typeId and create an ambiguity node.
433
public void consumeTemplateArgumentExpression() {
434
IASTExpression expr = (IASTExpression) astStack.peek();
436
if(expr instanceof IASTIdExpression) {
437
IASTName name = ((IASTIdExpression)expr).getName().copy();
439
IASTNamedTypeSpecifier declSpec = nodeFactory.newTypedefNameSpecifier(name);
440
ParserUtil.setOffsetAndLength(declSpec, name);
442
IASTDeclarator declarator = nodeFactory.newDeclarator(nodeFactory.newName());
443
ParserUtil.setOffsetAndLength(declarator, endOffset(declSpec), 0);
445
IASTTypeId typeId = nodeFactory.newTypeId(declSpec, declarator);
446
setOffsetAndLength(typeId);
448
ICPPASTAmbiguousTemplateArgument ambiguityNode = new CPPASTAmbiguousTemplateArgument(typeId, expr);
451
astStack.push(ambiguityNode);
458
* ::= 'operator' overloadable_operator
460
public void consumeOperatorName() {
461
List<IToken> tokens = stream.getRuleTokens();
462
tokens = tokens.subList(1, tokens.size());
463
OverloadableOperator operator = getOverloadableOperator(tokens);
465
ICPPASTOperatorName name = nodeFactory.newOperatorName(operator.toCharArray());
466
setOffsetAndLength(name);
471
private OverloadableOperator getOverloadableOperator(List<IToken> tokens) {
472
if(tokens.size() == 1) {
473
// TODO this is a hack that I did to save time
474
LPGTokenAdapter coreToken = (LPGTokenAdapter) tokens.get(0);
475
return OverloadableOperator.valueOf(coreToken.getWrappedToken());
477
else if(matchTokens(tokens, tokenMap, TK_new, TK_LeftBracket, TK_RightBracket)) {
478
return OverloadableOperator.NEW_ARRAY;
480
else if(matchTokens(tokens, tokenMap, TK_delete, TK_LeftBracket, TK_RightBracket)) {
481
return OverloadableOperator.DELETE_ARRAY;
483
else if(matchTokens(tokens, tokenMap, TK_LeftBracket, TK_RightBracket)) {
484
return OverloadableOperator.BRACKET;
486
else if(matchTokens(tokens, tokenMap, TK_LeftParen, TK_RightParen)) {
487
return OverloadableOperator.PAREN;
495
* conversion_function_id
496
* ::= 'operator' conversion_type_id
498
public void consumeConversionName() {
499
// Representation is computed by the conversion name itself, see bug 258054
500
// String rep = createStringRepresentation(parser.getRuleTokens());
501
// char[] chars = rep.toCharArray();
503
IASTTypeId typeId = (IASTTypeId) astStack.pop();
504
ICPPASTConversionName name = nodeFactory.newConversionName(typeId);
505
setOffsetAndLength(name);
514
* ::= '~' identifier_token
516
public void consumeDestructorName() {
517
char[] chars = ("~" + stream.getRightIToken()).toCharArray(); //$NON-NLS-1$
519
IASTName name = nodeFactory.newName(chars);
520
setOffsetAndLength(name);
526
* destructor_type_name
527
* ::= '~' template_id_name
529
public void consumeDestructorNameTemplateId() {
530
ICPPASTTemplateId templateId = (ICPPASTTemplateId) astStack.peek();
532
IASTName oldName = templateId.getTemplateName();
533
char[] newChars = ("~" + oldName).toCharArray(); //$NON-NLS-1$
535
IASTName newName = nodeFactory.newName(newChars);
537
int offset = offset(stream.getLeftIToken());
538
int length = offset - endOffset(oldName);
539
ParserUtil.setOffsetAndLength(newName, offset, length);
541
templateId.setTemplateName(newName);
548
* ::= '::' identifier_name
549
* | '::' operator_function_id
553
public void consumeGlobalQualifiedId() {
554
IASTName name = (IASTName) astStack.pop();
556
ICPPASTQualifiedName qualifiedName = nodeFactory.newQualifiedName();
557
qualifiedName.addName(name);
558
qualifiedName.setFullyQualified(true);
559
setOffsetAndLength(qualifiedName);
560
astStack.push(qualifiedName);
565
* selection_statement ::= switch '(' condition ')' statement
567
public void consumeStatementSwitch() {
568
IASTStatement body = (IASTStatement) astStack.pop();
570
Object condition = astStack.pop();
572
IASTSwitchStatement stat;
573
if(condition instanceof IASTExpression)
574
stat = nodeFactory.newSwitchStatement((IASTExpression)condition, body);
576
stat = nodeFactory.newSwitchStatement((IASTDeclaration)condition, body);
578
setOffsetAndLength(stat);
583
public void consumeStatementIf(boolean hasElse) {
584
IASTStatement elseClause = hasElse ? (IASTStatement)astStack.pop() : null;
585
IASTStatement thenClause = (IASTStatement) astStack.pop();
587
Object condition = astStack.pop();
589
IASTIfStatement ifStatement;
590
if(condition instanceof IASTExpression)
591
ifStatement = nodeFactory.newIfStatement((IASTExpression)condition, thenClause, elseClause);
593
ifStatement = nodeFactory.newIfStatement((IASTDeclaration)condition, thenClause, elseClause);
595
setOffsetAndLength(ifStatement);
596
astStack.push(ifStatement);
601
* iteration_statement ::= 'while' '(' condition ')' statement
603
public void consumeStatementWhileLoop() {
604
IASTStatement body = (IASTStatement) astStack.pop();
606
Object condition = astStack.pop();
608
IASTWhileStatement whileStatement;
609
if(condition instanceof IASTExpression)
610
whileStatement = nodeFactory.newWhileStatement((IASTExpression)condition, body);
612
whileStatement = nodeFactory.newWhileStatement((IASTDeclaration)condition, body);
614
setOffsetAndLength(whileStatement);
615
astStack.push(whileStatement);
621
public void consumeStatementForLoop() {
622
IASTStatement body = (IASTStatement) astStack.pop();
623
IASTExpression expr = (IASTExpression) astStack.pop();
624
Object condition = astStack.pop(); // can be an expression or a declaration
625
IASTStatement initializer = (IASTStatement) astStack.pop();
627
// bug 234463, fix for content assist to work in this case
628
int TK_EOC = TK_EndOfCompletion; // TODO: change this in the grammar file
629
List<IToken> tokens = stream.getRuleTokens();
630
if(matchTokens(tokens, tokenMap,
631
TK_for, TK_LeftParen, TK_Completion, TK_EOC, TK_EOC, TK_EOC, TK_EOC)) {
632
IASTName name = createName(tokens.get(2));
633
IASTIdExpression idExpression = nodeFactory.newIdExpression(name);
634
ParserUtil.setOffsetAndLength(idExpression, offset(name), length(name));
635
initializer = nodeFactory.newExpressionStatement(idExpression);
636
ParserUtil.setOffsetAndLength(initializer, offset(name), length(name));
640
IASTForStatement forStat;
641
if(condition instanceof IASTExpression)
642
forStat = nodeFactory.newForStatement(initializer, (IASTExpression)condition, expr, body);
643
else // its a declaration or its null
644
forStat = nodeFactory.newForStatement(initializer, (IASTDeclaration)condition, expr, body);
646
setOffsetAndLength(forStat);
647
astStack.push(forStat);
653
* ::= 'try' compound_statement <openscope-ast> handler_seq
655
public void consumeStatementTryBlock() {
656
List<Object> handlerSeq = astStack.closeScope();
657
IASTStatement body = (IASTStatement) astStack.pop();
659
ICPPASTTryBlockStatement tryStatement = nodeFactory.newTryBlockStatement(body);
661
for(Object handler : handlerSeq)
662
tryStatement.addCatchHandler((ICPPASTCatchHandler)handler);
664
setOffsetAndLength(tryStatement);
665
astStack.push(tryStatement);
671
* ::= 'catch' '(' exception_declaration ')' compound_statement
672
* | 'catch' '(' '...' ')' compound_statement
674
public void consumeStatementCatchHandler(boolean hasEllipsis) {
675
IASTStatement body = (IASTStatement) astStack.pop();
676
IASTDeclaration decl = hasEllipsis ? null : (IASTDeclaration) astStack.pop();
678
ICPPASTCatchHandler catchHandler = nodeFactory.newCatchHandler(decl, body);
679
catchHandler.setIsCatchAll(hasEllipsis);
681
setOffsetAndLength(catchHandler);
682
astStack.push(catchHandler);
687
* nested_name_specifier
688
* ::= class_or_namespace_name '::' nested_name_specifier_with_template
689
* | class_or_namespace_name '::'
691
* nested_name_specifier_with_template
692
* ::= class_or_namespace_name_with_template '::' nested_name_specifier_with_template
693
* | class_or_namespace_name_with_template '::'
696
* Creates and updates a list of the nested names on the stack.
697
* Important: the names in the list are in *reverse* order,
698
* this is because the actions fire in reverse order.
700
@SuppressWarnings("unchecked")
701
public void consumeNestedNameSpecifier(final boolean hasNested) {
702
LinkedList<IASTName> names;
704
names = (LinkedList<IASTName>) astStack.pop();
706
names = new LinkedList<IASTName>();
708
IASTName name = (IASTName) astStack.pop();
711
astStack.push(names);
715
public void consumeNestedNameSpecifierEmpty() {
716
// can't use Collections.EMPTY_LIST because we need a list thats mutable
717
astStack.push(new LinkedList<IASTName>());
724
* The template keyword is optional but must be the leftmost token.
726
* This just throws away the template keyword.
728
public void consumeNameWithTemplateKeyword() {
729
IASTName name = (IASTName) astStack.pop();
730
astStack.pop(); // pop the template keyword
738
* ::= dcolon_opt nested_name_specifier any_name
740
public void consumeQualifiedId(boolean hasTemplateKeyword) {
741
IASTName qualifiedName = subRuleQualifiedName(hasTemplateKeyword);
742
astStack.push(qualifiedName);
746
private IASTName createQualifiedName(LinkedList<IASTName> nestedNames, int startOffset, int endOffset, boolean startsWithColonColon) {
747
return createQualifiedName(nestedNames, startOffset, endOffset, startsWithColonColon, false);
752
* Creates a qualified name from a list of names (that must be in reverse order).
754
* @param names List of name nodes in reverse order
756
private IASTName createQualifiedName(LinkedList<IASTName> names, int startOffset, int endOffset, boolean startsWithColonColon, boolean endsWithColonColon) {
757
if(!endsWithColonColon && !startsWithColonColon && names.size() == 1)
758
return names.getFirst(); // its actually an unqualified name
760
ICPPASTQualifiedName qualifiedName = nodeFactory.newQualifiedName();
761
qualifiedName.setFullyQualified(startsWithColonColon);
762
ParserUtil.setOffsetAndLength(qualifiedName, startOffset, endOffset - startOffset);
763
for(IASTName name : reverseIterable(names))
764
qualifiedName.addName(name);
766
// there must be a dummy name in the AST after the last double colon, this happens with pointer to member names
767
if(endsWithColonColon) {
768
IASTName dummyName = nodeFactory.newName();
769
ParserUtil.setOffsetAndLength(dummyName, endOffset, 0);
770
qualifiedName.addName(dummyName);
773
return qualifiedName;
779
* Consumes grammar sub-rules of the following form:
781
* dcolon_opt nested_name_specifier_opt keyword_opt name
783
* Where name is any rule that produces an IASTName node on the stack.
784
* Does not place the resulting node on the stack, returns it instead.
786
@SuppressWarnings("unchecked")
787
private IASTName subRuleQualifiedName(boolean hasOptionalKeyword) {
788
IASTName lastName = (IASTName) astStack.pop();
790
if(hasOptionalKeyword) // this is usually a template keyword and can be ignored
793
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
794
IToken dColon = (IToken) astStack.pop();
796
if(nestedNames.isEmpty() && dColon == null) { // then its not a qualified name
800
nestedNames.addFirst(lastName); // the list of names is in reverse order
802
int startOffset = dColon == null ? offset(nestedNames.getLast()) : offset(dColon);
803
int endOffset = endOffset(lastName);
805
return createQualifiedName(nestedNames, startOffset, endOffset, dColon != null);
811
* pseudo_destructor_name
812
* ::= dcolon_opt nested_name_specifier_opt type_name '::' destructor_type_name
813
* | dcolon_opt nested_name_specifier 'template' template_id '::' destructor_type_name
814
* | dcolon_opt nested_name_specifier_opt destructor_type_name
816
@SuppressWarnings("unchecked")
817
public void consumePsudoDestructorName(boolean hasExtraTypeName) {
818
IASTName destructorTypeName = (IASTName) astStack.pop();
819
IASTName extraName = hasExtraTypeName ? (IASTName) astStack.pop() : null;
820
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
821
IToken dColon = (IToken) astStack.pop();
824
nestedNames.addFirst(extraName);
826
nestedNames.addFirst(destructorTypeName);
828
int startOffset = dColon == null ? offset(nestedNames.getLast()) : offset(dColon);
829
int endOffset = endOffset(destructorTypeName);
830
IASTName qualifiedName = createQualifiedName(nestedNames, startOffset, endOffset, dColon != null);
832
setOffsetAndLength(qualifiedName);
833
astStack.push(qualifiedName);
838
* namespace_alias_definition
839
* ::= 'namespace' 'identifier' '=' dcolon_opt nested_name_specifier_opt namespace_name ';'
841
public void consumeNamespaceAliasDefinition() {
842
IASTName qualifiedName = subRuleQualifiedName(false);
844
IASTName alias = createName(stream.getRuleTokens().get(1));
845
ICPPASTNamespaceAlias namespaceAlias = nodeFactory.newNamespaceAlias(alias, qualifiedName);
847
setOffsetAndLength(namespaceAlias);
848
astStack.push(namespaceAlias);
854
* ::= 'using' typename_opt dcolon_opt nested_name_specifier_opt unqualified_id ';'
856
public void consumeUsingDeclaration() {
857
IASTName qualifiedName = subRuleQualifiedName(false);
858
boolean hasTypenameKeyword = astStack.pop() == PLACE_HOLDER;
860
ICPPASTUsingDeclaration usingDeclaration = nodeFactory.newUsingDeclaration(qualifiedName);
861
usingDeclaration.setIsTypename(hasTypenameKeyword);
863
setOffsetAndLength(usingDeclaration);
864
astStack.push(usingDeclaration);
870
* ::= 'using' 'namespace' dcolon_opt nested_name_specifier_opt namespace_name ';'
872
public void consumeUsingDirective() {
873
IASTName qualifiedName = subRuleQualifiedName(false);
875
ICPPASTUsingDirective usingDirective = nodeFactory.newUsingDirective(qualifiedName);
876
setOffsetAndLength(usingDirective);
877
astStack.push(usingDirective);
882
* linkage_specification
883
* ::= 'extern' 'stringlit' '{' <openscope-ast> declaration_seq_opt '}'
884
* | 'extern' 'stringlit' <openscope-ast> declaration
886
public void consumeLinkageSpecification() {
887
String name = stream.getRuleTokens().get(1).toString();
888
ICPPASTLinkageSpecification linkageSpec = nodeFactory.newLinkageSpecification(name);
890
for(Object declaration : astStack.closeScope())
891
linkageSpec.addDeclaration((IASTDeclaration)declaration);
893
setOffsetAndLength(linkageSpec);
894
astStack.push(linkageSpec);
900
* original_namespace_definition
901
* ::= 'namespace' identifier_name '{' <openscope-ast> declaration_seq_opt '}'
903
* extension_namespace_definition
904
* ::= 'namespace' original_namespace_name '{' <openscope-ast> declaration_seq_opt '}'
906
* unnamed_namespace_definition
907
* ::= 'namespace' '{' <openscope-ast> declaration_seq_opt '}'
909
public void consumeNamespaceDefinition(boolean hasName) {
910
List<Object> declarations = astStack.closeScope();
911
IASTName namespaceName = hasName ? (IASTName)astStack.pop() : nodeFactory.newName();
913
ICPPASTNamespaceDefinition definition = nodeFactory.newNamespaceDefinition(namespaceName);
915
for(Object declaration : declarations)
916
definition.addDeclaration((IASTDeclaration)declaration);
918
setOffsetAndLength(definition);
919
astStack.push(definition);
924
* template_declaration
925
* ::= export_opt 'template' '<' <openscope-ast> template_parameter_list '>' declaration
927
public void consumeTemplateDeclaration() {
928
IASTDeclaration declaration = (IASTDeclaration) astStack.pop();
930
// For some reason ambiguous declarators cause bugs when they are a part of a template declaration.
931
// But it shouldn't be ambiguous anyway, so just throw away the ambiguity node.
932
resolveAmbiguousDeclaratorsToFunction(declaration);
934
ICPPASTTemplateDeclaration templateDeclaration = nodeFactory.newTemplateDeclaration(declaration);
936
for(Object param : astStack.closeScope())
937
templateDeclaration.addTemplateParamter((ICPPASTTemplateParameter)param);
939
boolean hasExportKeyword = astStack.pop() == PLACE_HOLDER;
940
templateDeclaration.setExported(hasExportKeyword);
942
setOffsetAndLength(templateDeclaration);
943
astStack.push(templateDeclaration);
948
* If we know that a declarator must be a function declarator then we can resolve
949
* the ambiguity without resorting to binding resolution.
951
private static void resolveAmbiguousDeclaratorsToFunction(IASTDeclaration declaration) {
952
if(declaration instanceof IASTSimpleDeclaration) {
953
for(IASTDeclarator declarator : ((IASTSimpleDeclaration)declaration).getDeclarators()) {
954
if(declarator instanceof CPPASTAmbiguousDeclarator) {
955
IASTAmbiguityParent owner = (IASTAmbiguityParent) declaration;
956
CPPASTAmbiguousDeclarator ambiguity = (CPPASTAmbiguousDeclarator)declarator;
957
owner.replace(ambiguity, ambiguity.getDeclarators()[0]);
965
* explicit_instantiation
966
* ::= 'template' declaration
968
public void consumeTemplateExplicitInstantiation() {
969
IASTDeclaration declaration = (IASTDeclaration) astStack.pop();
970
ICPPASTExplicitTemplateInstantiation instantiation = nodeFactory.newExplicitTemplateInstantiation(declaration);
972
setOffsetAndLength(instantiation);
973
astStack.push(instantiation);
978
* explicit_specialization
979
* ::= 'template' '<' '>' declaration
981
public void consumeTemplateExplicitSpecialization() {
982
IASTDeclaration declaration = (IASTDeclaration) astStack.pop();
983
ICPPASTTemplateSpecialization specialization = nodeFactory.newTemplateSpecialization(declaration);
985
setOffsetAndLength(specialization);
986
astStack.push(specialization);
991
* Sets a token specifier.
992
* Needs to be overrideable for new decl spec keywords.
994
* @param token Allows subclasses to override this method and use any
995
* object to determine how to set a specifier.
997
public void setSpecifier(ICPPASTDeclSpecifier node, Object specifier) {
998
if(!(specifier instanceof IToken))
1001
IToken token = (IToken)specifier;
1002
int kind = baseKind(token);
1004
case TK_typedef: node.setStorageClass(IASTDeclSpecifier.sc_typedef); return;
1005
case TK_extern: node.setStorageClass(IASTDeclSpecifier.sc_extern); return;
1006
case TK_static: node.setStorageClass(IASTDeclSpecifier.sc_static); return;
1007
case TK_auto: node.setStorageClass(IASTDeclSpecifier.sc_auto); return;
1008
case TK_register: node.setStorageClass(IASTDeclSpecifier.sc_register); return;
1009
case TK_mutable: node.setStorageClass(ICPPASTDeclSpecifier.sc_mutable); return;
1011
case TK_inline: node.setInline(true); return;
1012
case TK_const: node.setConst(true); return;
1013
case TK_friend: node.setFriend(true); return;
1014
case TK_virtual: node.setVirtual(true); return;
1015
case TK_volatile: node.setVolatile(true); return;
1016
case TK_explicit: node.setExplicit(true); return;
1019
if(node instanceof ICPPASTSimpleDeclSpecifier) {
1020
ICPPASTSimpleDeclSpecifier n = (ICPPASTSimpleDeclSpecifier) node;
1022
case TK_void: n.setType(IASTSimpleDeclSpecifier.t_void); return;
1023
case TK_char: n.setType(IASTSimpleDeclSpecifier.t_char); return;
1024
case TK_int: n.setType(IASTSimpleDeclSpecifier.t_int); return;
1025
case TK_float: n.setType(IASTSimpleDeclSpecifier.t_float); return;
1026
case TK_double: n.setType(IASTSimpleDeclSpecifier.t_double); return;
1027
case TK_bool: n.setType(ICPPASTSimpleDeclSpecifier.t_bool); return;
1028
case TK_wchar_t: n.setType(ICPPASTSimpleDeclSpecifier.t_wchar_t); return;
1030
case TK_signed: n.setSigned(true); return;
1031
case TK_unsigned: n.setUnsigned(true); return;
1032
case TK_long: n.setLong(true); return;
1033
case TK_short: n.setShort(true); return;
1039
public void consumeDeclarationSpecifiersSimple() {
1040
ICPPASTDeclSpecifier declSpec = nodeFactory.newSimpleDeclSpecifier();
1042
for(Object token : astStack.closeScope())
1043
setSpecifier(declSpec, token);
1045
setOffsetAndLength(declSpec);
1046
astStack.push(declSpec);
1051
* TODO: maybe move this into the superclass
1053
public void consumeDeclarationSpecifiersComposite() {
1054
List<Object> topScope = astStack.closeScope();
1056
// There's already a composite or elaborated or enum type specifier somewhere on the stack, find it.
1057
ICPPASTDeclSpecifier declSpec = findFirstAndRemove(topScope, ICPPASTDeclSpecifier.class);
1059
// now apply the rest of the specifiers
1060
for(Object token : topScope)
1061
setSpecifier(declSpec, token);
1063
setOffsetAndLength(declSpec);
1064
astStack.push(declSpec);
1071
// * declaration_specifiers ::= <openscope> type_name_declaration_specifiers
1073
public void consumeDeclarationSpecifiersTypeName() {
1074
List<Object> topScope = astStack.closeScope();
1075
// There's a name somewhere on the stack, find it
1076
IASTName typeName = findFirstAndRemove(topScope, IASTName.class);
1078
// TODO what does the second argument mean?
1079
ICPPASTNamedTypeSpecifier declSpec = nodeFactory.newTypedefNameSpecifier(typeName);
1081
// now apply the rest of the specifiers
1082
for(Object token : topScope) {
1083
setSpecifier(declSpec, token);
1086
// the only way there could be a typename token
1087
for(IToken token : stream.getRuleTokens()) {
1088
if(baseKind(token) == TK_typename) {
1089
declSpec.setIsTypename(true);
1094
setOffsetAndLength(declSpec);
1095
astStack.push(declSpec);
1100
* elaborated_type_specifier
1101
* ::= class_keyword dcolon_opt nested_name_specifier_opt identifier_name
1102
* | class_keyword dcolon_opt nested_name_specifier_opt template_opt template_id_name
1103
* | 'enum' dcolon_opt nested_name_specifier_opt identifier_name
1105
public void consumeTypeSpecifierElaborated(boolean hasOptionalTemplateKeyword) {
1106
IASTName name = subRuleQualifiedName(hasOptionalTemplateKeyword);
1107
int kind = getElaboratedTypeSpecifier(stream.getLeftIToken());
1109
IASTElaboratedTypeSpecifier typeSpecifier = nodeFactory.newElaboratedTypeSpecifier(kind, name);
1111
setOffsetAndLength(typeSpecifier);
1112
astStack.push(typeSpecifier);
1116
private int getElaboratedTypeSpecifier(IToken token) {
1117
int kind = baseKind(token);
1119
default: assert false : "wrong token kind: " + kind; //$NON-NLS-1$
1120
case TK_struct: return IASTElaboratedTypeSpecifier.k_struct;
1121
case TK_union: return IASTElaboratedTypeSpecifier.k_union;
1122
case TK_enum: return IASTElaboratedTypeSpecifier.k_enum;
1123
case TK_class: return ICPPASTElaboratedTypeSpecifier.k_class;
1130
* simple_declaration
1131
* ::= declaration_specifiers_opt <openscope-ast> init_declarator_list_opt ';'
1133
public void consumeDeclarationSimple(boolean hasDeclaratorList) {
1134
List<Object> declarators = hasDeclaratorList ? astStack.closeScope() : Collections.emptyList();
1135
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) astStack.pop(); // may be null
1137
List<IToken> ruleTokens = stream.getRuleTokens();
1138
IToken nameToken = null;
1141
// do not generate nodes for extra EOC tokens
1142
if(matchTokens(ruleTokens, tokenMap, TK_EndOfCompletion)) {
1146
// In the case that a single completion token is parsed then it needs
1147
// to be interpreted as a named type specifier for content assist to work.
1148
else if(matchTokens(ruleTokens, tokenMap, TK_Completion, TK_EndOfCompletion)) {
1149
IASTName name = createName(stream.getLeftIToken());
1150
declSpec = nodeFactory.newTypedefNameSpecifier(name);
1151
ParserUtil.setOffsetAndLength(declSpec, offset(name), length(name));
1152
declarators = Collections.emptyList(); // throw away the bogus declarator
1155
// can happen if implicit int is used
1156
else if(declSpec == null) {
1157
declSpec = nodeFactory.newSimpleDeclSpecifier();
1158
ParserUtil.setOffsetAndLength(declSpec, stream.getLeftIToken().getStartOffset(), 0);
1162
else if(declarators.size() == 1 && disambiguateToConstructor(declSpec, (IASTDeclarator)declarators.get(0))) { // puts results of disambiguation onto stack
1163
declSpec = (ICPPASTDeclSpecifier) astStack.pop();
1164
declarators = Arrays.asList(astStack.pop());
1167
// bug 80171, check for situation similar to: static var;
1168
// this will get parsed wrong, the following is a hack to rebuild the AST as it should have been parsed
1169
else if(declarators.isEmpty() &&
1170
declSpec instanceof ICPPASTNamedTypeSpecifier &&
1171
ruleTokens.size() >= 2 &&
1172
baseKind(nameToken = ruleTokens.get(ruleTokens.size() - 2)) == TK_identifier) {
1174
declSpec = nodeFactory.newSimpleDeclSpecifier();
1175
for(IToken t : ruleTokens.subList(0, ruleTokens.size()-1))
1176
setSpecifier(declSpec, t);
1178
int offset = offset(stream.getLeftIToken());
1179
int length = endOffset(ruleTokens.get(ruleTokens.size()-2)) - offset;
1180
ParserUtil.setOffsetAndLength(declSpec, offset, length);
1182
IASTName name = createName(nameToken);
1183
IASTDeclarator declarator = nodeFactory.newDeclarator(name);
1184
ParserUtil.setOffsetAndLength(declarator, nameToken);
1185
declarators.add(declarator);
1188
IASTSimpleDeclaration declaration = nodeFactory.newSimpleDeclaration(declSpec);
1189
setOffsetAndLength(declaration);
1190
for(Object declarator : declarators)
1191
declaration.addDeclarator((IASTDeclarator)declarator);
1193
// simple ambiguity resolutions
1194
// if(declSpecifier.isFriend())
1195
// resolveAmbiguousDeclaratorsToFunction(declaration);
1197
// if(declSpecifier instanceof IASTSimpleDeclSpecifier) {
1198
// IASTSimpleDeclSpecifier simple = (IASTSimpleDeclSpecifier) declSpecifier;
1199
// if(simple.getType() == IASTSimpleDeclSpecifier.t_void && declaration.getDeclarators()[0].getPointerOperators().length == 0)
1200
// resolveAmbiguousDeclaratorsToFunction(declaration);
1204
astStack.push(declaration);
1209
private boolean disambiguateToConstructor(IASTDeclSpecifier declSpec, IASTDeclarator declarator) {
1210
if(!(declSpec instanceof IASTNamedTypeSpecifier))
1213
IASTNamedTypeSpecifier namedTypeSpecifier = (IASTNamedTypeSpecifier) declSpec;
1214
IASTName name = namedTypeSpecifier.getName();
1215
IASTDeclarator nested = declarator.getNestedDeclarator();
1217
ICPPASTSimpleDeclSpecifier simpleDeclSpec = nodeFactory.newSimpleDeclSpecifier(); // empty
1218
ParserUtil.setOffsetAndLength(simpleDeclSpec, stream.getLeftIToken().getStartOffset(), 0);
1220
if(!classNames.isEmpty() && nested != null && ParserUtil.isSameName(name, classNames.getLast())) {
1222
IASTName paramTypeName = nested.getName(); // reuse the parameter name node
1223
IASTNamedTypeSpecifier paramName = nodeFactory.newTypedefNameSpecifier(paramTypeName);
1224
ParserUtil.setOffsetAndLength(paramName, paramTypeName);
1226
IASTDeclarator paramDeclarator = nodeFactory.newDeclarator(nodeFactory.newName());
1227
ParserUtil.setOffsetAndLength(paramDeclarator, offset(paramName) + length(paramName), 0);
1229
ICPPASTParameterDeclaration parameter = nodeFactory.newParameterDeclaration(paramName, paramDeclarator);
1230
ParserUtil.setOffsetAndLength(parameter, paramName);
1232
ICPPASTFunctionDeclarator constructorDeclarator = nodeFactory.newFunctionDeclarator(name); // reuse the name node
1233
constructorDeclarator.addParameterDeclaration(parameter);
1234
ParserUtil.setOffsetAndLength(constructorDeclarator, offset(simpleDeclSpec), endOffset(paramDeclarator) - offset(simpleDeclSpec) + 1);
1236
astStack.push(constructorDeclarator);
1237
astStack.push(simpleDeclSpec);
1241
if(declarator instanceof IASTFunctionDeclarator && declarator.getName() instanceof ICPPASTQualifiedName) {
1242
ICPPASTQualifiedName qualifiedName = (ICPPASTQualifiedName) declarator.getName();
1243
//IASTName lastName = qualifiedName.getLastName();
1245
if(qualifiedName.isFullyQualified()) {
1247
ICPPASTQualifiedName newQualifiedName = nodeFactory.newQualifiedName();
1248
newQualifiedName.addName(name);
1249
for(IASTName n : qualifiedName.getNames())
1250
newQualifiedName.addName(n);
1252
ParserUtil.setOffsetAndLength(newQualifiedName, offset(name), endOffset(qualifiedName.getLastName()) - offset(name));
1255
declarator.setName(newQualifiedName);
1256
ParserUtil.setOffsetAndLength(declarator, offset(name), length(declarator) + offset(declarator) - offset(name));
1258
astStack.push(declarator);
1259
astStack.push(simpleDeclSpec);
1269
public void consumeInitDeclaratorComplete() {
1270
// Don't do disambiguation when parsing for content assist,
1271
// trust me this makes things work out a lot better.
1272
if(completionNode != null)
1275
IASTDeclarator declarator = (IASTDeclarator) astStack.peek();
1276
if(!(declarator instanceof IASTFunctionDeclarator))
1279
ISecondaryParser<IASTDeclarator> secondaryParser = parserFactory.getNoFunctionDeclaratorParser(stream, properties);
1280
IASTDeclarator notFunctionDeclarator = runSecondaryParser(secondaryParser);
1282
if(notFunctionDeclarator == null)
1287
IASTNode ambiguityNode = new CPPASTAmbiguousDeclarator(declarator, notFunctionDeclarator);
1289
setOffsetAndLength(ambiguityNode);
1290
astStack.push(ambiguityNode);
1297
* ::= access_specifier_keyword ':'
1299
public void consumeVisibilityLabel() {
1300
IToken specifier = (IToken)astStack.pop();
1301
int visibility = getAccessSpecifier(specifier);
1302
ICPPASTVisibilityLabel visibilityLabel = nodeFactory.newVisibilityLabel(visibility);
1303
setOffsetAndLength(visibilityLabel);
1304
astStack.push(visibilityLabel);
1308
private int getAccessSpecifier(IToken token) {
1309
int kind = baseKind(token);
1311
default: assert false : "wrong token kind: " + kind; //$NON-NLS-1$
1312
case TK_private: return ICPPASTVisibilityLabel.v_private;
1313
case TK_public: return ICPPASTVisibilityLabel.v_public;
1314
case TK_protected: return ICPPASTVisibilityLabel.v_protected;
1321
* ::= dcolon_opt nested_name_specifier_opt class_name
1322
* | 'virtual' access_specifier_keyword_opt dcolon_opt nested_name_specifier_opt class_name
1323
* | access_specifier_keyword 'virtual' dcolon_opt nested_name_specifier_opt class_name
1324
* | access_specifier_keyword dcolon_opt nested_name_specifier_opt class_name
1326
public void consumeBaseSpecifier(boolean hasAccessSpecifier, boolean isVirtual) {
1327
IASTName name = subRuleQualifiedName(false);
1329
int visibility = 0; // this is the default value that the DOM parser uses
1330
if(hasAccessSpecifier) {
1331
IToken accessSpecifierToken = (IToken) astStack.pop();
1332
if(accessSpecifierToken != null)
1333
visibility = getAccessSpecifier(accessSpecifierToken);
1336
ICPPASTBaseSpecifier baseSpecifier = nodeFactory.newBaseSpecifier(name, visibility, isVirtual);
1337
setOffsetAndLength(baseSpecifier);
1338
astStack.push(baseSpecifier);
1344
* ::= class_head '{' <openscope-ast> member_declaration_list_opt '}'
1346
public void consumeClassSpecifier() {
1347
List<Object> declarations = astStack.closeScope();
1349
// the class specifier is created by the rule for class_head
1350
IASTCompositeTypeSpecifier classSpecifier = (IASTCompositeTypeSpecifier) astStack.peek();
1352
for(Object declaration : declarations)
1353
classSpecifier.addMemberDeclaration((IASTDeclaration)declaration);
1355
setOffsetAndLength(classSpecifier);
1357
classNames.removeLast(); // pop the stack of class names
1363
* ::= class_keyword identifier_name_opt <openscope-ast> base_clause_opt
1364
* | class_keyword template_id <openscope-ast> base_clause_opt
1365
* | class_keyword nested_name_specifier identifier_name <openscope-ast> base_clause_opt
1366
* | class_keyword nested_name_specifier template_id <openscope-ast> base_clause_opt
1368
@SuppressWarnings("unchecked")
1369
public void consumeClassHead(boolean hasNestedNameSpecifier) {
1370
int key = getCompositeTypeSpecifier(stream.getLeftIToken());
1371
List<Object> baseSpecifiers = astStack.closeScope();
1372
// may be null, but if it is then hasNestedNameSpecifier == false
1373
IASTName className = (IASTName) astStack.pop();
1375
if(hasNestedNameSpecifier) {
1376
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
1377
nestedNames.addFirst(className);
1378
int startOffset = offset(nestedNames.getLast());
1379
int endOffset = endOffset(className);
1380
className = createQualifiedName(nestedNames, startOffset, endOffset, false);
1383
if(className == null)
1384
className = nodeFactory.newName();
1386
ICPPASTCompositeTypeSpecifier classSpecifier = nodeFactory.newCompositeTypeSpecifier(key, className);
1388
for(Object base : baseSpecifiers)
1389
classSpecifier.addBaseSpecifier((ICPPASTBaseSpecifier)base);
1391
// the offset and length are set in consumeClassSpecifier()
1392
astStack.push(classSpecifier);
1393
classNames.add(className); // push
1397
private int getCompositeTypeSpecifier(IToken token) {
1398
final int kind = baseKind(token);
1400
default: assert false : "wrong token kind: " + kind; //$NON-NLS-1$
1401
case TK_struct: return IASTCompositeTypeSpecifier.k_struct;
1402
case TK_union: return IASTCompositeTypeSpecifier.k_union;
1403
case TK_class: return ICPPASTCompositeTypeSpecifier.k_class;
1410
* ::= '*' <openscope-ast> cv_qualifier_seq_opt
1412
public void consumePointer() {
1413
IASTPointer pointer = nodeFactory.newPointer();
1414
List<Object> tokens = astStack.closeScope();
1415
addCVQualifiersToPointer(pointer, tokens);
1416
setOffsetAndLength(pointer);
1417
astStack.push(pointer);
1421
protected void addCVQualifiersToPointer(IASTPointer pointer, List<Object> tokens) {
1422
for(Object t : tokens) {
1423
switch(baseKind((IToken) t)) {
1424
case TK_const: pointer.setConst(true); break;
1425
case TK_volatile: pointer.setVolatile(true); break;
1434
public void consumeReferenceOperator() {
1435
ICPPASTReferenceOperator referenceOperator = nodeFactory.newReferenceOperator();
1436
setOffsetAndLength(referenceOperator);
1437
astStack.push(referenceOperator);
1443
* ::= dcolon_opt nested_name_specifier '*' <openscope-ast> cv_qualifier_seq_opt
1445
@SuppressWarnings("unchecked")
1446
public void consumePointerToMember() {
1447
List<Object> qualifiers = astStack.closeScope();
1448
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
1449
IToken dColon = (IToken) astStack.pop();
1451
int startOffset = dColon == null ? offset(nestedNames.getLast()) : offset(dColon);
1452
int endOffset = endOffset(nestedNames.getFirst()); // temporary
1454
// find the last double colon by searching for it
1455
for(IToken t : reverseIterable(stream.getRuleTokens())) {
1456
if(baseKind(t) == TK_ColonColon) {
1457
endOffset = endOffset(t);
1462
IASTName name = createQualifiedName(nestedNames, startOffset, endOffset, dColon != null, true);
1464
ICPPASTPointerToMember pointer = nodeFactory.newPointerToMember(name);
1465
addCVQualifiersToPointer(pointer, qualifiers);
1466
setOffsetAndLength(pointer);
1467
astStack.push(pointer);
1474
* ::= '(' expression_list ')'
1476
public void consumeInitializerConstructor() {
1477
IASTExpression expression = (IASTExpression) astStack.pop();
1478
ICPPASTConstructorInitializer initializer = nodeFactory.newConstructorInitializer(expression);
1479
setOffsetAndLength(initializer);
1480
astStack.push(initializer);
1485
* function_direct_declarator
1486
* ::= basic_direct_declarator '(' <openscope-ast> parameter_declaration_clause ')'
1487
* <openscope-ast> cv_qualifier_seq_opt <openscope-ast> exception_specification_opt
1489
public void consumeDirectDeclaratorFunctionDeclarator(boolean hasDeclarator) {
1490
IASTName name = nodeFactory.newName();
1491
ICPPASTFunctionDeclarator declarator = nodeFactory.newFunctionDeclarator(name);
1493
List<Object> typeIds = astStack.closeScope();
1494
if(typeIds.size() == 1 && typeIds.get(0) == PLACE_HOLDER) { // fix for bug 86943
1495
declarator.setEmptyExceptionSpecification();
1498
for(Object typeId : typeIds) {
1499
declarator.addExceptionSpecificationTypeId((IASTTypeId) typeId);
1503
for(Object token : astStack.closeScope()) {
1504
int kind = baseKind((IToken)token);
1506
default: assert false : "wrong token kind: " + kind; //$NON-NLS-1$
1507
case TK_const: declarator.setConst(true); break;
1508
case TK_volatile: declarator.setVolatile(true); break;
1512
boolean isVarArgs = astStack.pop() == PLACE_HOLDER;
1513
declarator.setVarArgs(isVarArgs);
1515
for(Object o : astStack.closeScope()) {
1516
declarator.addParameterDeclaration((IASTParameterDeclaration)o);
1520
int endOffset = endOffset(stream.getRightIToken());
1521
addFunctionModifier(declarator, endOffset);
1524
setOffsetAndLength(declarator);
1525
astStack.push(declarator);
1531
* Consume an empty bracketed abstract declarator.
1533
public void consumeAbstractDeclaratorEmpty() {
1534
IASTName name = nodeFactory.newName();
1535
ParserUtil.setOffsetAndLength(name, offset(stream.getLeftIToken())+1, 0);
1536
IASTDeclarator declarator = nodeFactory.newDeclarator(name);
1537
setOffsetAndLength(declarator);
1538
astStack.push(declarator);
1544
* ::= mem_initializer_id '(' expression_list_opt ')'
1546
public void consumeConstructorChainInitializer() {
1547
IASTExpression expr = (IASTExpression) astStack.pop();
1548
IASTName name = (IASTName) astStack.pop();
1549
ICPPASTConstructorChainInitializer initializer = nodeFactory.newConstructorChainInitializer(name, expr);
1550
setOffsetAndLength(initializer);
1551
astStack.push(initializer);
1557
* function_definition
1558
* ::= declaration_specifiers_opt function_direct_declarator
1559
* <openscope-ast> ctor_initializer_list_opt function_body
1561
* | declaration_specifiers_opt function_direct_declarator
1562
* 'try' <openscope-ast> ctor_initializer_list_opt function_body <openscope-ast> handler_seq
1565
public void consumeFunctionDefinition(boolean isTryBlockDeclarator) {
1566
List<Object> handlers = isTryBlockDeclarator ? astStack.closeScope() : Collections.emptyList();
1567
IASTCompoundStatement body = (IASTCompoundStatement) astStack.pop();
1568
List<Object> initializers = astStack.closeScope();
1569
IASTFunctionDeclarator declarator = (IASTFunctionDeclarator) astStack.pop();
1570
IASTDeclSpecifier declSpec = (IASTDeclSpecifier) astStack.pop(); // may be null
1572
if(declSpec == null) { // can happen if implicit int is used
1573
declSpec = nodeFactory.newSimpleDeclSpecifier();
1574
ParserUtil.setOffsetAndLength(declSpec, stream.getLeftIToken().getStartOffset(), 0);
1576
else if(disambiguateToConstructor(declSpec, declarator)) {
1577
declSpec = (IASTDeclSpecifier) astStack.pop();
1578
declarator = (IASTFunctionDeclarator) astStack.pop();
1581
ICPPASTFunctionDefinition definition;
1582
if (isTryBlockDeclarator) {
1583
ICPPASTFunctionWithTryBlock tryblock= nodeFactory.newFunctionTryBlock(declSpec, declarator, body);
1584
for(Object handler : handlers)
1585
tryblock.addCatchHandler((ICPPASTCatchHandler)handler);
1586
definition = tryblock;
1588
definition = nodeFactory.newFunctionDefinition(declSpec, declarator, body);
1592
if(initializers != null && !initializers.isEmpty()) {
1593
for(Object initializer : initializers)
1594
definition.addMemberInitializer((ICPPASTConstructorChainInitializer)initializer);
1597
setOffsetAndLength(definition);
1598
astStack.push(definition);
1603
* member_declaration
1604
* ::= dcolon_opt nested_name_specifier template_opt unqualified_id_name ';'
1606
public void consumeMemberDeclarationQualifiedId() {
1607
IASTName qualifiedId = subRuleQualifiedName(true);
1609
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=92793
1610
ICPPASTUsingDeclaration declaration = nodeFactory.newUsingDeclaration(qualifiedId);
1611
setOffsetAndLength(declaration);
1613
astStack.push(declaration);
1619
* ::= declarator constant_initializer
1622
public void consumeMemberDeclaratorWithInitializer() {
1623
IASTInitializerExpression initializer = (IASTInitializerExpression) astStack.pop();
1624
IASTDeclarator declarator = (IASTDeclarator) astStack.peek();
1625
setOffsetAndLength(declarator);
1627
if(declarator instanceof ICPPASTFunctionDeclarator) {
1628
IASTExpression expr = initializer.getExpression();
1629
if(expr instanceof IASTLiteralExpression && "0".equals(expr.toString())) { //$NON-NLS-1$
1630
((ICPPASTFunctionDeclarator)declarator).setPureVirtual(true);
1635
declarator.setInitializer(initializer);
1641
* ::= 'class' identifier_name_opt -- simple type template parameter
1642
* | 'class' identifier_name_opt '=' type_id
1643
* | 'typename' identifier_name_opt
1644
* | 'typename' identifier_name_opt '=' type_id
1646
public void consumeSimpleTypeTemplateParameter(boolean hasTypeId) {
1647
IASTTypeId typeId = hasTypeId ? (IASTTypeId)astStack.pop() : null;
1649
IASTName name = (IASTName)astStack.pop();
1651
name = nodeFactory.newName();
1653
int type = getTemplateParameterType(stream.getLeftIToken());
1655
ICPPASTSimpleTypeTemplateParameter templateParameter = nodeFactory.newSimpleTypeTemplateParameter(type, name, typeId);
1657
setOffsetAndLength(templateParameter);
1658
astStack.push(templateParameter);
1662
private int getTemplateParameterType(IToken token) {
1663
int kind = baseKind(token);
1665
default: assert false : "wrong token kind: " + kind; //$NON-NLS-1$
1666
case TK_class: return ICPPASTSimpleTypeTemplateParameter.st_class;
1667
case TK_typename: return ICPPASTSimpleTypeTemplateParameter.st_typename;
1673
* Simple type template parameters using the 'class' keyword are being parsed
1674
* wrong due to an ambiguity between type_parameter and parameter_declaration.
1676
* eg) template <class T>
1678
* The 'class T' part is being parsed as an elaborated type specifier instead
1679
* of a simple type template parameter.
1681
* This method detects the incorrect parse, throws away the incorrect AST fragment,
1682
* and replaces it with the correct AST fragment.
1686
public void consumeTemplateParamterDeclaration() {
1687
ISecondaryParser<ICPPASTTemplateParameter> typeParameterParser = parserFactory.getTemplateTypeParameterParser(stream, properties);
1688
IASTNode alternate = runSecondaryParser(typeParameterParser);
1690
if(alternate == null)
1693
astStack.pop(); // throw away the incorrect AST
1694
astStack.push(alternate); // replace it with the correct AST
1701
* ::= 'template' '<' <openscope-ast> template_parameter_list '>' 'class' identifier_name_opt
1702
* | 'template' '<' <openscope-ast> template_parameter_list '>' 'class' identifier_name_opt '=' id_expression
1705
public void consumeTemplatedTypeTemplateParameter(boolean hasIdExpr) {
1706
IASTExpression idExpression = hasIdExpr ? (IASTExpression)astStack.pop() : null;
1707
IASTName name = (IASTName) astStack.pop();
1709
ICPPASTTemplatedTypeTemplateParameter templateParameter = nodeFactory.newTemplatedTypeTemplateParameter(name, idExpression);
1711
for(Object param : astStack.closeScope())
1712
templateParameter.addTemplateParamter((ICPPASTTemplateParameter)param);
1714
setOffsetAndLength(templateParameter);
1715
astStack.push(templateParameter);
1720
protected IASTAmbiguousExpression createAmbiguousExpression(IASTExpression... expressions) {
1721
return new CPPASTAmbiguousExpression(expressions);
1726
protected IASTAmbiguousStatement createAmbiguousStatement(IASTStatement... statements) {
1727
return new CPPASTAmbiguousStatement(statements);
b'\\ No newline at end of file'