diff options
Diffstat (limited to 'core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java')
-rw-r--r-- | core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java | 3461 |
1 files changed, 1732 insertions, 1729 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index e165c46e8d6..78e0b3ebf80 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -109,174 +109,172 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement; * Source parser for gnu-c syntax. */ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { - private static final int DEFAULT_POINTEROPS_LIST_SIZE = 4; - private static final int DEFAULT_PARAMETERS_LIST_SIZE = 4; + private static final int DEFAULT_POINTEROPS_LIST_SIZE = 4; + private static final int DEFAULT_PARAMETERS_LIST_SIZE = 4; - private final boolean supportGCCStyleDesignators; + private final boolean supportGCCStyleDesignators; private IIndex index; - protected IASTTranslationUnit translationUnit; - - private int fPreventKnrCheck= 0; - - public GNUCSourceParser(IScanner scanner, ParserMode parserMode, - IParserLogService logService, ICParserExtensionConfiguration config) { - this(scanner, parserMode, logService, config, null); - } - - public GNUCSourceParser(IScanner scanner, ParserMode parserMode, - IParserLogService logService, ICParserExtensionConfiguration config, - IIndex index) { - super(scanner, logService, parserMode, CNodeFactory.getDefault(), - config.supportStatementsInExpressions(), - config.supportTypeofUnaryExpressions(), - config.supportAlignOfUnaryExpression(), - config.supportKnRC(), - config.supportAttributeSpecifiers(), - config.supportDeclspecSpecifiers(), - config.getBuiltinBindingsProvider()); - supportGCCStyleDesignators = config.supportGCCStyleDesignators(); - supportParameterInfoBlock= config.supportParameterInfoBlock(); - supportExtendedSizeofOperator= config.supportExtendedSizeofOperator(); - supportFunctionStyleAsm= config.supportFunctionStyleAssembler(); - this.index= index; - } - - @Override - protected ICNodeFactory getNodeFactory() { - return (ICNodeFactory) super.getNodeFactory(); - } - - @Override - protected IASTInitializer optionalInitializer(IASTDeclarator dtor, DeclarationOptions options) throws EndOfFileException, BacktrackException { - if (options.fAllowInitializer && LTcatchEOF(1) == IToken.tASSIGN) { - final int offset= consume().getOffset(); - IASTInitializerClause initClause = initClause(); - IASTEqualsInitializer result= getNodeFactory().newEqualsInitializer(initClause); - return setRange(result, offset, calculateEndOffset(initClause)); - } - return null; - } - - private IASTInitializerClause initClause() throws EndOfFileException, BacktrackException { - final int offset = LA(1).getOffset(); - if (LT(1) != IToken.tLBRACE) - return expression(ExprKind.eAssignment); - - // it's an aggregate initializer - consume(IToken.tLBRACE); - IASTInitializerList result = getNodeFactory().newInitializerList(); - - // bug 196468, gcc accepts empty braces. - if (supportGCCStyleDesignators && LT(1) == IToken.tRBRACE) { - int endOffset= consume().getEndOffset(); - setRange(result, offset, endOffset); - return result; - } - - for (;;) { - final int checkOffset= LA(1).getOffset(); - // required at least one initializer list - // get designator list - List<? extends ICASTDesignator> designator= designatorList(); - if (designator == null) { - IASTInitializerClause clause= initClause(); - if (result.getSize() >= maximumTrivialExpressionsInAggregateInitializers && !ASTQueries.canContainName(clause)) { - translationUnit.setHasNodesOmitted(true); - clause= null; - } - // depending on value of skipTrivialItemsInCompoundInitializers initializer may be null - // in any way add the initializer such that the actual size can be tracked. - result.addClause(clause); - } else { - ICASTDesignatedInitializer desigInitializer = getNodeFactory().newDesignatedInitializer((IASTInitializerClause) null); - setRange(desigInitializer, designator.get(0)); - for (ICASTDesignator d : designator) { - desigInitializer.addDesignator(d); - } - - if (LT(1) != IToken.tEOC) { - // Gnu extension: the assign operator is optional - if (LT(1) == IToken.tASSIGN) - consume(IToken.tASSIGN); - - IASTInitializerClause clause= initClause(); - desigInitializer.setOperand(clause); - adjustLength(desigInitializer, clause); - } - result.addClause(desigInitializer); - } - - // can end with ", }" or "}" - boolean canContinue= LT(1) == IToken.tCOMMA; - if (canContinue) - consume(); - - switch (LT(1)) { - case IToken.tRBRACE: - int lastOffset = consume().getEndOffset(); - setRange(result, offset, lastOffset); - return result; - - case IToken.tEOC: - setRange(result, offset, LA(1).getOffset()); - return result; - } - - if (!canContinue || LA(1).getOffset() == checkOffset) { - throwBacktrack(offset, LA(1).getEndOffset() - offset); - } - } - // consume the closing brace - } - - - private List<? extends ICASTDesignator> designatorList() throws EndOfFileException, BacktrackException { - final int lt1= LT(1); - if (lt1 == IToken.tDOT || lt1 == IToken.tLBRACKET) { - List<ICASTDesignator> designatorList= null; - while (true) { - switch (LT(1)) { - case IToken.tDOT: - int offset = consume().getOffset(); - IASTName n = identifier(); - ICASTFieldDesignator fieldDesignator = getNodeFactory().newFieldDesignator(n); - setRange(fieldDesignator, offset, calculateEndOffset(n)); - if (designatorList == null) - designatorList = new ArrayList<>(DEFAULT_DESIGNATOR_LIST_SIZE); - designatorList.add(fieldDesignator); - break; - - case IToken.tLBRACKET: - offset = consume().getOffset(); - IASTExpression constantExpression = expression(); - if (supportGCCStyleDesignators && LT(1) == IToken.tELLIPSIS) { - consume(IToken.tELLIPSIS); - IASTExpression constantExpression2 = expression(); - int lastOffset = consume(IToken.tRBRACKET).getEndOffset(); - IGCCASTArrayRangeDesignator designator = getNodeFactory().newArrayRangeDesignatorGCC(constantExpression, constantExpression2); - setRange(designator, offset, lastOffset); - if (designatorList == null) - designatorList = new ArrayList<>(DEFAULT_DESIGNATOR_LIST_SIZE); - designatorList.add(designator); - } else { - int lastOffset = consume(IToken.tRBRACKET).getEndOffset(); - ICASTArrayDesignator designator = getNodeFactory().newArrayDesignator(constantExpression); - setRange(designator, offset, lastOffset); - if (designatorList == null) - designatorList = new ArrayList<>(DEFAULT_DESIGNATOR_LIST_SIZE); - designatorList.add(designator); - } - break; - - default: - return designatorList; - } - } - } + protected IASTTranslationUnit translationUnit; + + private int fPreventKnrCheck = 0; + + public GNUCSourceParser(IScanner scanner, ParserMode parserMode, IParserLogService logService, + ICParserExtensionConfiguration config) { + this(scanner, parserMode, logService, config, null); + } + + public GNUCSourceParser(IScanner scanner, ParserMode parserMode, IParserLogService logService, + ICParserExtensionConfiguration config, IIndex index) { + super(scanner, logService, parserMode, CNodeFactory.getDefault(), config.supportStatementsInExpressions(), + config.supportTypeofUnaryExpressions(), config.supportAlignOfUnaryExpression(), config.supportKnRC(), + config.supportAttributeSpecifiers(), config.supportDeclspecSpecifiers(), + config.getBuiltinBindingsProvider()); + supportGCCStyleDesignators = config.supportGCCStyleDesignators(); + supportParameterInfoBlock = config.supportParameterInfoBlock(); + supportExtendedSizeofOperator = config.supportExtendedSizeofOperator(); + supportFunctionStyleAsm = config.supportFunctionStyleAssembler(); + this.index = index; + } + + @Override + protected ICNodeFactory getNodeFactory() { + return (ICNodeFactory) super.getNodeFactory(); + } + + @Override + protected IASTInitializer optionalInitializer(IASTDeclarator dtor, DeclarationOptions options) + throws EndOfFileException, BacktrackException { + if (options.fAllowInitializer && LTcatchEOF(1) == IToken.tASSIGN) { + final int offset = consume().getOffset(); + IASTInitializerClause initClause = initClause(); + IASTEqualsInitializer result = getNodeFactory().newEqualsInitializer(initClause); + return setRange(result, offset, calculateEndOffset(initClause)); + } + return null; + } + + private IASTInitializerClause initClause() throws EndOfFileException, BacktrackException { + final int offset = LA(1).getOffset(); + if (LT(1) != IToken.tLBRACE) + return expression(ExprKind.eAssignment); + + // it's an aggregate initializer + consume(IToken.tLBRACE); + IASTInitializerList result = getNodeFactory().newInitializerList(); + + // bug 196468, gcc accepts empty braces. + if (supportGCCStyleDesignators && LT(1) == IToken.tRBRACE) { + int endOffset = consume().getEndOffset(); + setRange(result, offset, endOffset); + return result; + } + + for (;;) { + final int checkOffset = LA(1).getOffset(); + // required at least one initializer list + // get designator list + List<? extends ICASTDesignator> designator = designatorList(); + if (designator == null) { + IASTInitializerClause clause = initClause(); + if (result.getSize() >= maximumTrivialExpressionsInAggregateInitializers + && !ASTQueries.canContainName(clause)) { + translationUnit.setHasNodesOmitted(true); + clause = null; + } + // depending on value of skipTrivialItemsInCompoundInitializers initializer may be null + // in any way add the initializer such that the actual size can be tracked. + result.addClause(clause); + } else { + ICASTDesignatedInitializer desigInitializer = getNodeFactory() + .newDesignatedInitializer((IASTInitializerClause) null); + setRange(desigInitializer, designator.get(0)); + for (ICASTDesignator d : designator) { + desigInitializer.addDesignator(d); + } + + if (LT(1) != IToken.tEOC) { + // Gnu extension: the assign operator is optional + if (LT(1) == IToken.tASSIGN) + consume(IToken.tASSIGN); + + IASTInitializerClause clause = initClause(); + desigInitializer.setOperand(clause); + adjustLength(desigInitializer, clause); + } + result.addClause(desigInitializer); + } + + // can end with ", }" or "}" + boolean canContinue = LT(1) == IToken.tCOMMA; + if (canContinue) + consume(); + + switch (LT(1)) { + case IToken.tRBRACE: + int lastOffset = consume().getEndOffset(); + setRange(result, offset, lastOffset); + return result; + + case IToken.tEOC: + setRange(result, offset, LA(1).getOffset()); + return result; + } + + if (!canContinue || LA(1).getOffset() == checkOffset) { + throwBacktrack(offset, LA(1).getEndOffset() - offset); + } + } + // consume the closing brace + } + + private List<? extends ICASTDesignator> designatorList() throws EndOfFileException, BacktrackException { + final int lt1 = LT(1); + if (lt1 == IToken.tDOT || lt1 == IToken.tLBRACKET) { + List<ICASTDesignator> designatorList = null; + while (true) { + switch (LT(1)) { + case IToken.tDOT: + int offset = consume().getOffset(); + IASTName n = identifier(); + ICASTFieldDesignator fieldDesignator = getNodeFactory().newFieldDesignator(n); + setRange(fieldDesignator, offset, calculateEndOffset(n)); + if (designatorList == null) + designatorList = new ArrayList<>(DEFAULT_DESIGNATOR_LIST_SIZE); + designatorList.add(fieldDesignator); + break; + + case IToken.tLBRACKET: + offset = consume().getOffset(); + IASTExpression constantExpression = expression(); + if (supportGCCStyleDesignators && LT(1) == IToken.tELLIPSIS) { + consume(IToken.tELLIPSIS); + IASTExpression constantExpression2 = expression(); + int lastOffset = consume(IToken.tRBRACKET).getEndOffset(); + IGCCASTArrayRangeDesignator designator = getNodeFactory() + .newArrayRangeDesignatorGCC(constantExpression, constantExpression2); + setRange(designator, offset, lastOffset); + if (designatorList == null) + designatorList = new ArrayList<>(DEFAULT_DESIGNATOR_LIST_SIZE); + designatorList.add(designator); + } else { + int lastOffset = consume(IToken.tRBRACKET).getEndOffset(); + ICASTArrayDesignator designator = getNodeFactory().newArrayDesignator(constantExpression); + setRange(designator, offset, lastOffset); + if (designatorList == null) + designatorList = new ArrayList<>(DEFAULT_DESIGNATOR_LIST_SIZE); + designatorList.add(designator); + } + break; + + default: + return designatorList; + } + } + } // fix for 84176: if reach identifier and it's not a designator then return empty designator list if (supportGCCStyleDesignators && lt1 == IToken.tIDENTIFIER && LT(2) == IToken.tCOLON) { - int offset= LA(1).getOffset(); + int offset = LA(1).getOffset(); IASTName n = identifier(); int lastOffset = consume(IToken.tCOLON).getEndOffset(); ICASTFieldDesignator designator = getNodeFactory().newFieldDesignator(n); @@ -284,161 +282,164 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return Collections.singletonList(designator); } - return null; - } + return null; + } @Override - protected IASTDeclaration declaration(final DeclarationOptions declOption) throws EndOfFileException, BacktrackException { - switch (LT(1)) { - case IToken.t_asm: - return asmDeclaration(); - case IToken.tSEMI: - IToken semi= consume(); - IASTDeclSpecifier declspec= getNodeFactory().newSimpleDeclSpecifier(); - IASTSimpleDeclaration decl= getNodeFactory().newSimpleDeclaration(declspec); - decl.setDeclSpecifier(declspec); - ((ASTNode) declspec).setOffsetAndLength(semi.getOffset(), 0); - ((ASTNode) decl).setOffsetAndLength(semi.getOffset(), semi.getLength()); - return decl; - } - - return simpleDeclaration(declOption); - } - - private IASTDeclaration simpleDeclaration(final DeclarationOptions declOption) throws BacktrackException, EndOfFileException { - if (LT(1) == IToken.tLBRACE) - throwBacktrack(LA(1)); - - final int firstOffset= LA(1).getOffset(); - int endOffset= firstOffset; - boolean insertSemi= false; - - IASTDeclSpecifier declSpec= null; - IASTDeclarator dtor= null; - IASTDeclSpecifier altDeclSpec= null; - IASTDeclarator altDtor= null; - IToken markBeforDtor= null; - try { - Decl decl= declSpecifierSequence_initDeclarator(declOption, true); - markBeforDtor= decl.fDtorToken1; - declSpec= decl.fDeclSpec1; - dtor= decl.fDtor1; - altDeclSpec= decl.fDeclSpec2; - altDtor= decl.fDtor2; - } catch (FoundAggregateInitializer lie) { - declSpec= lie.fDeclSpec; - // scalability: don't keep references to tokens, initializer may be large - declarationMark= null; - dtor= addInitializer(lie, declOption); - } catch (BacktrackException e) { - IASTNode node= e.getNodeBeforeProblem(); - if (node instanceof IASTDeclSpecifier) { - IASTSimpleDeclaration d= getNodeFactory().newSimpleDeclaration((IASTDeclSpecifier) node); - setRange(d, node); - throwBacktrack(e.getProblem(), d); - } - throw e; - } - - IASTDeclarator[] declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY; - if (dtor != null) { - declarators= new IASTDeclarator[]{dtor}; - while (LTcatchEOF(1) == IToken.tCOMMA) { - consume(); - try { - dtor= initDeclarator(declSpec, declOption); - } catch (FoundAggregateInitializer e) { - // scalability: don't keep references to tokens, initializer may be large - declarationMark= null; - markBeforDtor= null; - dtor= addInitializer(e, declOption); - } - declarators= ArrayUtil.append(IASTDeclarator.class, declarators, dtor); - } - declarators= ArrayUtil.removeNulls(IASTDeclarator.class, declarators); - } - - final int lt1= LTcatchEOF(1); - switch (lt1) { - case IToken.tEOC: - endOffset= figureEndOffset(declSpec, declarators); - break; - case IToken.tSEMI: - endOffset= consume().getEndOffset(); - break; - case IToken.tLBRACE: - return functionDefinition(firstOffset, declSpec, declarators); - - default: - insertSemi= true; - if (declOption == DeclarationOptions.LOCAL) { - endOffset= figureEndOffset(declSpec, declarators); - if (firstOffset != endOffset) { - break; - } - } else { - if (markBeforDtor != null) { - endOffset= calculateEndOffset(declSpec); - if (firstOffset != endOffset && !isOnSameLine(endOffset, markBeforDtor.getOffset())) { - backup(markBeforDtor); - declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY; - break; - } - } - endOffset= figureEndOffset(declSpec, declarators); - if (lt1 == 0) { - break; - } - if (firstOffset != endOffset) { - if (!isOnSameLine(endOffset, LA(1).getOffset())) { - break; - } - if (declarators.length == 1 && declarators[0] instanceof IASTFunctionDeclarator) { - break; - } - } - } - throwBacktrack(LA(1)); - } - - // no function body - IASTSimpleDeclaration simpleDeclaration = getNodeFactory().newSimpleDeclaration(declSpec); - for (IASTDeclarator declarator : declarators) - simpleDeclaration.addDeclarator(declarator); - - setRange(simpleDeclaration, firstOffset, endOffset); + protected IASTDeclaration declaration(final DeclarationOptions declOption) + throws EndOfFileException, BacktrackException { + switch (LT(1)) { + case IToken.t_asm: + return asmDeclaration(); + case IToken.tSEMI: + IToken semi = consume(); + IASTDeclSpecifier declspec = getNodeFactory().newSimpleDeclSpecifier(); + IASTSimpleDeclaration decl = getNodeFactory().newSimpleDeclaration(declspec); + decl.setDeclSpecifier(declspec); + ((ASTNode) declspec).setOffsetAndLength(semi.getOffset(), 0); + ((ASTNode) decl).setOffsetAndLength(semi.getOffset(), semi.getLength()); + return decl; + } + + return simpleDeclaration(declOption); + } + + private IASTDeclaration simpleDeclaration(final DeclarationOptions declOption) + throws BacktrackException, EndOfFileException { + if (LT(1) == IToken.tLBRACE) + throwBacktrack(LA(1)); + + final int firstOffset = LA(1).getOffset(); + int endOffset = firstOffset; + boolean insertSemi = false; + + IASTDeclSpecifier declSpec = null; + IASTDeclarator dtor = null; + IASTDeclSpecifier altDeclSpec = null; + IASTDeclarator altDtor = null; + IToken markBeforDtor = null; + try { + Decl decl = declSpecifierSequence_initDeclarator(declOption, true); + markBeforDtor = decl.fDtorToken1; + declSpec = decl.fDeclSpec1; + dtor = decl.fDtor1; + altDeclSpec = decl.fDeclSpec2; + altDtor = decl.fDtor2; + } catch (FoundAggregateInitializer lie) { + declSpec = lie.fDeclSpec; + // scalability: don't keep references to tokens, initializer may be large + declarationMark = null; + dtor = addInitializer(lie, declOption); + } catch (BacktrackException e) { + IASTNode node = e.getNodeBeforeProblem(); + if (node instanceof IASTDeclSpecifier) { + IASTSimpleDeclaration d = getNodeFactory().newSimpleDeclaration((IASTDeclSpecifier) node); + setRange(d, node); + throwBacktrack(e.getProblem(), d); + } + throw e; + } + + IASTDeclarator[] declarators = IASTDeclarator.EMPTY_DECLARATOR_ARRAY; + if (dtor != null) { + declarators = new IASTDeclarator[] { dtor }; + while (LTcatchEOF(1) == IToken.tCOMMA) { + consume(); + try { + dtor = initDeclarator(declSpec, declOption); + } catch (FoundAggregateInitializer e) { + // scalability: don't keep references to tokens, initializer may be large + declarationMark = null; + markBeforDtor = null; + dtor = addInitializer(e, declOption); + } + declarators = ArrayUtil.append(IASTDeclarator.class, declarators, dtor); + } + declarators = ArrayUtil.removeNulls(IASTDeclarator.class, declarators); + } + + final int lt1 = LTcatchEOF(1); + switch (lt1) { + case IToken.tEOC: + endOffset = figureEndOffset(declSpec, declarators); + break; + case IToken.tSEMI: + endOffset = consume().getEndOffset(); + break; + case IToken.tLBRACE: + return functionDefinition(firstOffset, declSpec, declarators); + + default: + insertSemi = true; + if (declOption == DeclarationOptions.LOCAL) { + endOffset = figureEndOffset(declSpec, declarators); + if (firstOffset != endOffset) { + break; + } + } else { + if (markBeforDtor != null) { + endOffset = calculateEndOffset(declSpec); + if (firstOffset != endOffset && !isOnSameLine(endOffset, markBeforDtor.getOffset())) { + backup(markBeforDtor); + declarators = IASTDeclarator.EMPTY_DECLARATOR_ARRAY; + break; + } + } + endOffset = figureEndOffset(declSpec, declarators); + if (lt1 == 0) { + break; + } + if (firstOffset != endOffset) { + if (!isOnSameLine(endOffset, LA(1).getOffset())) { + break; + } + if (declarators.length == 1 && declarators[0] instanceof IASTFunctionDeclarator) { + break; + } + } + } + throwBacktrack(LA(1)); + } + + // no function body + IASTSimpleDeclaration simpleDeclaration = getNodeFactory().newSimpleDeclaration(declSpec); + for (IASTDeclarator declarator : declarators) + simpleDeclaration.addDeclarator(declarator); + + setRange(simpleDeclaration, firstOffset, endOffset); if (altDeclSpec != null && altDtor != null) { simpleDeclaration = new CASTAmbiguousSimpleDeclaration(simpleDeclaration, altDeclSpec, altDtor); setRange(simpleDeclaration, firstOffset, endOffset); } - if (insertSemi) { - IASTProblem problem= createProblem(IProblem.MISSING_SEMICOLON, endOffset-1, 1); - throwBacktrack(problem, simpleDeclaration); - } - return simpleDeclaration; - } + if (insertSemi) { + IASTProblem problem = createProblem(IProblem.MISSING_SEMICOLON, endOffset - 1, 1); + throwBacktrack(problem, simpleDeclaration); + } + return simpleDeclaration; + } private IASTDeclaration functionDefinition(int firstOffset, IASTDeclSpecifier declSpec, IASTDeclarator[] declarators) throws BacktrackException, EndOfFileException { if (declarators.length != 1) - throwBacktrack(firstOffset, LA(1).getEndOffset()); + throwBacktrack(firstOffset, LA(1).getEndOffset()); - final IASTDeclarator outerDtor= declarators[0]; - final IASTDeclarator fdtor= ASTQueries.findTypeRelevantDeclarator(outerDtor); + final IASTDeclarator outerDtor = declarators[0]; + final IASTDeclarator fdtor = ASTQueries.findTypeRelevantDeclarator(outerDtor); if (!(fdtor instanceof IASTFunctionDeclarator)) throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); - IASTFunctionDefinition funcDefinition = getNodeFactory().newFunctionDefinition(declSpec, (IASTFunctionDeclarator) fdtor, null); + IASTFunctionDefinition funcDefinition = getNodeFactory().newFunctionDefinition(declSpec, + (IASTFunctionDeclarator) fdtor, null); try { - IASTStatement s= handleFunctionBody(); + IASTStatement s = handleFunctionBody(); funcDefinition.setBody(s); ((ASTNode) funcDefinition).setOffsetAndLength(firstOffset, calculateEndOffset(s) - firstOffset); return funcDefinition; } catch (BacktrackException bt) { - final IASTNode n= bt.getNodeBeforeProblem(); + final IASTNode n = bt.getNodeBeforeProblem(); if (n instanceof IASTCompoundStatement) { funcDefinition.setBody((IASTCompoundStatement) n); ((ASTNode) funcDefinition).setOffsetAndLength(firstOffset, calculateEndOffset(n) - firstOffset); @@ -448,7 +449,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } } - @Override protected void setupTranslationUnit() throws DOMException { translationUnit = getNodeFactory().newTranslationUnit(scanner); @@ -469,31 +469,31 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { @Override protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException { - return expression(ExprKind.eConstant); - } + return expression(ExprKind.eConstant); + } - private IASTExpression expression(final ExprKind kind) throws EndOfFileException, BacktrackException { - final boolean allowComma= kind == ExprKind.eExpression; - boolean allowAssignment= kind != ExprKind.eConstant; + private IASTExpression expression(final ExprKind kind) throws EndOfFileException, BacktrackException { + final boolean allowComma = kind == ExprKind.eExpression; + boolean allowAssignment = kind != ExprKind.eConstant; int lt1; - int conditionCount= 0; - BinaryOperator lastOperator= null; - IASTExpression lastExpression= castExpression(CastExprCtx.eDirectlyInBExpr, null); + int conditionCount = 0; + BinaryOperator lastOperator = null; + IASTExpression lastExpression = castExpression(CastExprCtx.eDirectlyInBExpr, null); loop: while (true) { - lt1= LT(1); + lt1 = LT(1); switch (lt1) { - case IToken.tQUESTION: + case IToken.tQUESTION: conditionCount++; // <logical-or> ? <expression> : <assignment-expression> // Precedence: 25 is lower than precedence of logical or; 0 is lower than precedence of expression - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 25, 0); + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 25, 0); if (LT(2) == IToken.tCOLON) { // Gnu extension: The expression after '?' can be omitted. - consume(); // Consume operator - lastExpression= null; // Next cast expression is just null + consume(); // Consume operator + lastExpression = null; // Next cast expression is just null continue; } - allowAssignment= true; // assignment expressions will be subsumed by the conditional expression + allowAssignment = true; // assignment expressions will be subsumed by the conditional expression break; case IToken.tCOLON: @@ -502,166 +502,169 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { // <logical-or> ? <expression> : <assignment-expression> // Precedence: 0 is lower than precedence of expression; 15 is lower than precedence of assignment; - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 0, 15); - allowAssignment= true; // assignment expressions will be subsumed by the conditional expression - break; + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 0, 15); + allowAssignment = true; // assignment expressions will be subsumed by the conditional expression + break; case IToken.tCOMMA: if (!allowComma && conditionCount == 0) break loop; // Lowest precedence except inside the conditional expression - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 10, 11); - break; - - case IToken.tASSIGN: - case IToken.tSTARASSIGN: - case IToken.tDIVASSIGN: - case IToken.tMODASSIGN: - case IToken.tPLUSASSIGN: - case IToken.tMINUSASSIGN: - case IToken.tSHIFTRASSIGN: - case IToken.tSHIFTLASSIGN: - case IToken.tAMPERASSIGN: - case IToken.tXORASSIGN: - case IToken.tBITORASSIGN: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 10, 11); + break; + + case IToken.tASSIGN: + case IToken.tSTARASSIGN: + case IToken.tDIVASSIGN: + case IToken.tMODASSIGN: + case IToken.tPLUSASSIGN: + case IToken.tMINUSASSIGN: + case IToken.tSHIFTRASSIGN: + case IToken.tSHIFTLASSIGN: + case IToken.tAMPERASSIGN: + case IToken.tXORASSIGN: + case IToken.tBITORASSIGN: if (!allowAssignment && conditionCount == 0) break loop; - // Assignments group right to left - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 21, 20); - break; - - case IToken.tOR: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 30, 31); - break; - case IToken.tAND: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 40, 41); - break; - case IToken.tBITOR: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 50, 51); - break; - case IToken.tXOR: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 60, 61); - break; - case IToken.tAMPER: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 70, 71); - break; - case IToken.tEQUAL: - case IToken.tNOTEQUAL: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 80, 81); - break; - case IToken.tGT: - case IToken.tLT: - case IToken.tLTEQUAL: - case IToken.tGTEQUAL: - case IGCCToken.tMAX: - case IGCCToken.tMIN: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 90, 91); - break; - case IToken.tSHIFTL: - case IToken.tSHIFTR: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 100, 101); - break; - case IToken.tPLUS: - case IToken.tMINUS: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 110, 111); - break; - case IToken.tSTAR: - case IToken.tDIV: - case IToken.tMOD: - lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 120, 121); - break; - default: - break loop; + // Assignments group right to left + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 21, 20); + break; + + case IToken.tOR: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 30, 31); + break; + case IToken.tAND: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 40, 41); + break; + case IToken.tBITOR: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 50, 51); + break; + case IToken.tXOR: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 60, 61); + break; + case IToken.tAMPER: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 70, 71); + break; + case IToken.tEQUAL: + case IToken.tNOTEQUAL: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 80, 81); + break; + case IToken.tGT: + case IToken.tLT: + case IToken.tLTEQUAL: + case IToken.tGTEQUAL: + case IGCCToken.tMAX: + case IGCCToken.tMIN: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 90, 91); + break; + case IToken.tSHIFTL: + case IToken.tSHIFTR: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 100, 101); + break; + case IToken.tPLUS: + case IToken.tMINUS: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 110, 111); + break; + case IToken.tSTAR: + case IToken.tDIV: + case IToken.tMOD: + lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 120, 121); + break; + default: + break loop; } - consume(); // consume operator - lastExpression= castExpression(CastExprCtx.eDirectlyInBExpr, null); // next cast expression + consume(); // consume operator + lastExpression = castExpression(CastExprCtx.eDirectlyInBExpr, null); // next cast expression } - // Check for incomplete conditional expression - if (lt1 != IToken.tEOC && conditionCount > 0) - throwBacktrack(LA(1)); + // Check for incomplete conditional expression + if (lt1 != IToken.tEOC && conditionCount > 0) + throwBacktrack(LA(1)); - return buildExpression(lastOperator, lastExpression); + return buildExpression(lastOperator, lastExpression); + } + + @Override + protected IASTExpression buildBinaryExpression(int operator, IASTExpression expr1, IASTInitializerClause expr2, + int lastOffset) { + IASTBinaryExpression result = getNodeFactory().newBinaryExpression(operator, expr1, (IASTExpression) expr2); + int o = ((ASTNode) expr1).getOffset(); + ((ASTNode) result).setOffsetAndLength(o, lastOffset - o); + return result; } - @Override - protected IASTExpression buildBinaryExpression(int operator, IASTExpression expr1, IASTInitializerClause expr2, int lastOffset) { - IASTBinaryExpression result = getNodeFactory().newBinaryExpression(operator, expr1, (IASTExpression) expr2); - int o = ((ASTNode) expr1).getOffset(); - ((ASTNode) result).setOffsetAndLength(o, lastOffset - o); - return result; - } - - @Override - protected IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException { - switch (LT(1)) { - case IToken.tSTAR: - return unaryExpression(IASTUnaryExpression.op_star, ctx, strat); - case IToken.tAMPER: - return unaryExpression(IASTUnaryExpression.op_amper, ctx, strat); - case IToken.tAND: - return unaryExpression(IASTUnaryExpression.op_labelReference, ctx, strat); - case IToken.tPLUS: - return unaryExpression(IASTUnaryExpression.op_plus, ctx, strat); - case IToken.tMINUS: - return unaryExpression(IASTUnaryExpression.op_minus, ctx, strat); - case IToken.tNOT: - return unaryExpression(IASTUnaryExpression.op_not, ctx, strat); - case IToken.tBITCOMPLEMENT: - return unaryExpression(IASTUnaryExpression.op_tilde, ctx, strat); - case IToken.tINCR: - return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx, strat); - case IToken.tDECR: - return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx, strat); - case IToken.t_sizeof: - return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx, strat); - case IToken.t__Alignof: - case IGCCToken.t___alignof__: - return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx, strat); - default: - return postfixExpression(ctx, strat); - } - } - - private IASTExpression postfixExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException { - IASTExpression firstExpression = null; - switch (LT(1)) { - case IToken.tLPAREN: - // (type-name) { initializer-list } - // (type-name) { initializer-list , } - IToken m = mark(); - try { - int offset = consume().getOffset(); - IASTTypeId t= typeId(DeclarationOptions.TYPEID); - consume(IToken.tRPAREN); - if (LT(1) == IToken.tLBRACE) { - IASTInitializer i = (IASTInitializerList) initClause(); - firstExpression= getNodeFactory().newTypeIdInitializerExpression(t, i); - setRange(firstExpression, offset, calculateEndOffset(i)); - break; - } - } catch (BacktrackException bt) { - } - backup(m); - firstExpression= primaryExpression(ctx, strat); - break; - - default: - firstExpression = primaryExpression(ctx, strat); - break; - } - - IASTExpression secondExpression = null; - for (;;) { - switch (LT(1)) { - case IToken.tLBRACKET: - // array access - consume(); - secondExpression = expression(); - int last; + @Override + protected IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) + throws EndOfFileException, BacktrackException { + switch (LT(1)) { + case IToken.tSTAR: + return unaryExpression(IASTUnaryExpression.op_star, ctx, strat); + case IToken.tAMPER: + return unaryExpression(IASTUnaryExpression.op_amper, ctx, strat); + case IToken.tAND: + return unaryExpression(IASTUnaryExpression.op_labelReference, ctx, strat); + case IToken.tPLUS: + return unaryExpression(IASTUnaryExpression.op_plus, ctx, strat); + case IToken.tMINUS: + return unaryExpression(IASTUnaryExpression.op_minus, ctx, strat); + case IToken.tNOT: + return unaryExpression(IASTUnaryExpression.op_not, ctx, strat); + case IToken.tBITCOMPLEMENT: + return unaryExpression(IASTUnaryExpression.op_tilde, ctx, strat); + case IToken.tINCR: + return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx, strat); + case IToken.tDECR: + return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx, strat); + case IToken.t_sizeof: + return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), + IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx, strat); + case IToken.t__Alignof: + case IGCCToken.t___alignof__: + return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), + IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx, strat); + default: + return postfixExpression(ctx, strat); + } + } + + private IASTExpression postfixExpression(CastExprCtx ctx, ITemplateIdStrategy strat) + throws EndOfFileException, BacktrackException { + IASTExpression firstExpression = null; + switch (LT(1)) { + case IToken.tLPAREN: + // (type-name) { initializer-list } + // (type-name) { initializer-list , } + IToken m = mark(); + try { + int offset = consume().getOffset(); + IASTTypeId t = typeId(DeclarationOptions.TYPEID); + consume(IToken.tRPAREN); + if (LT(1) == IToken.tLBRACE) { + IASTInitializer i = (IASTInitializerList) initClause(); + firstExpression = getNodeFactory().newTypeIdInitializerExpression(t, i); + setRange(firstExpression, offset, calculateEndOffset(i)); + break; + } + } catch (BacktrackException bt) { + } + backup(m); + firstExpression = primaryExpression(ctx, strat); + break; + + default: + firstExpression = primaryExpression(ctx, strat); + break; + } + + IASTExpression secondExpression = null; + for (;;) { + switch (LT(1)) { + case IToken.tLBRACKET: + // array access + consume(); + secondExpression = expression(); + int last; switch (LT(1)) { case IToken.tRBRACKET: last = consume().getEndOffset(); @@ -673,583 +676,587 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { throw backtrack; } - IASTArraySubscriptExpression s = getNodeFactory().newArraySubscriptExpression(firstExpression, secondExpression); - ((ASTNode) s).setOffsetAndLength(((ASTNode) firstExpression).getOffset(), - last - ((ASTNode) firstExpression).getOffset()); - firstExpression = s; - break; - case IToken.tLPAREN: - // function call - int endOffset; - List<IASTExpression> argList= null; - consume(IToken.tLPAREN); - boolean isFirst= true; - while (true) { - final int lt1= LT(1); - if (lt1 == IToken.tRPAREN) { - endOffset= consume().getEndOffset(); - break; - } else if (lt1 == IToken.tEOC) { - endOffset= LA(1).getEndOffset(); - break; - } - if (isFirst) { - isFirst= false; - } else { - consume(IToken.tCOMMA); - } - - IASTExpression expr= expression(ExprKind.eAssignment); - if (argList == null) { - argList= new ArrayList<>(); - } - argList.add(expr); - } + IASTArraySubscriptExpression s = getNodeFactory().newArraySubscriptExpression(firstExpression, + secondExpression); + ((ASTNode) s).setOffsetAndLength(((ASTNode) firstExpression).getOffset(), + last - ((ASTNode) firstExpression).getOffset()); + firstExpression = s; + break; + case IToken.tLPAREN: + // function call + int endOffset; + List<IASTExpression> argList = null; + consume(IToken.tLPAREN); + boolean isFirst = true; + while (true) { + final int lt1 = LT(1); + if (lt1 == IToken.tRPAREN) { + endOffset = consume().getEndOffset(); + break; + } else if (lt1 == IToken.tEOC) { + endOffset = LA(1).getEndOffset(); + break; + } + if (isFirst) { + isFirst = false; + } else { + consume(IToken.tCOMMA); + } + + IASTExpression expr = expression(ExprKind.eAssignment); + if (argList == null) { + argList = new ArrayList<>(); + } + argList.add(expr); + } final IASTExpression[] args; if (argList == null) { - args= IASTExpression.EMPTY_EXPRESSION_ARRAY; + args = IASTExpression.EMPTY_EXPRESSION_ARRAY; } else { - args= argList.toArray(new IASTExpression[argList.size()]); + args = argList.toArray(new IASTExpression[argList.size()]); } IASTFunctionCallExpression f = getNodeFactory().newFunctionCallExpression(firstExpression, args); - firstExpression = setRange(f, firstExpression, endOffset); - break; - case IToken.tINCR: - int offset = consume().getEndOffset(); - firstExpression = buildUnaryExpression( - IASTUnaryExpression.op_postFixIncr, firstExpression, - ((ASTNode) firstExpression).getOffset(), offset); - break; - case IToken.tDECR: - offset = consume().getEndOffset(); - firstExpression = buildUnaryExpression( - IASTUnaryExpression.op_postFixDecr, firstExpression, - ((ASTNode) firstExpression).getOffset(), offset); - break; - case IToken.tDOT: - // member access - IToken dot = consume(); - IASTName name = identifier(); - if (name == null) - throwBacktrack(((ASTNode) firstExpression).getOffset(), - ((ASTNode) firstExpression).getLength() + dot.getLength()); - IASTFieldReference result = getNodeFactory().newFieldReference(name, firstExpression); - result.setIsPointerDereference(false); - ((ASTNode) result).setOffsetAndLength( - ((ASTNode) firstExpression).getOffset(), - calculateEndOffset(name) - ((ASTNode) firstExpression).getOffset()); - firstExpression = result; - break; - case IToken.tARROW: - // member access - IToken arrow = consume(); - name = identifier(); - if (name == null) - throwBacktrack(((ASTNode) firstExpression).getOffset(), - ((ASTNode) firstExpression).getLength() + arrow.getLength()); - result = getNodeFactory().newFieldReference(name, firstExpression); - result.setIsPointerDereference(true); - ((ASTNode) result).setOffsetAndLength( - ((ASTNode) firstExpression).getOffset(), - calculateEndOffset(name) - ((ASTNode) firstExpression).getOffset()); - firstExpression = result; - break; - default: - return firstExpression; - } - } - } - - @Override - protected IASTExpression primaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException { - IToken t = null; - IASTLiteralExpression literalExpression = null; - switch (LT(1)) { - // TO DO: we need more literals... - case IToken.tINTEGER: - t = consume(); - literalExpression = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_integer_constant, t.getImage()); - ((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset()); - return literalExpression; - case IToken.tFLOATINGPT: - t = consume(); - literalExpression = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_float_constant, t.getImage()); - ((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset()); - return literalExpression; - case IToken.tSTRING: - case IToken.tLSTRING: - case IToken.tUTF16STRING: - case IToken.tUTF32STRING: - t = consume(); - literalExpression = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_string_literal, t.getImage()); - ((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset()); - return literalExpression; - case IToken.tCHAR: - case IToken.tLCHAR: - case IToken.tUTF16CHAR: - case IToken.tUTF32CHAR: - t = consume(); - literalExpression = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_char_constant, t.getImage()); - ((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getLength()); - return literalExpression; - case IToken.tLPAREN: - if (supportStatementsInExpressions && LT(2) == IToken.tLBRACE) { - return compoundStatementExpression(); - } - t = consume(); - IASTExpression lhs = expression(ExprKind.eExpression); // instead of expression(), to keep the stack smaller - int finalOffset = 0; - switch (LT(1)) { - case IToken.tRPAREN: - case IToken.tEOC: - finalOffset = consume().getEndOffset(); - break; - default: - throwBacktrack(LA(1)); - } - return buildUnaryExpression(IASTUnaryExpression.op_bracketedPrimary, lhs, t.getOffset(), finalOffset); - case IToken.tIDENTIFIER: - case IToken.tCOMPLETION: - case IToken.tEOC: - int startingOffset = LA(1).getOffset(); - IASTName name = identifier(); - IASTIdExpression idExpression = getNodeFactory().newIdExpression(name); - ((ASTNode) idExpression).setOffsetAndLength((ASTNode) name); - return idExpression; - default: - IToken la = LA(1); - startingOffset = la.getOffset(); - throwBacktrack(startingOffset, la.getLength()); - return null; - } - - } - - - @Override + firstExpression = setRange(f, firstExpression, endOffset); + break; + case IToken.tINCR: + int offset = consume().getEndOffset(); + firstExpression = buildUnaryExpression(IASTUnaryExpression.op_postFixIncr, firstExpression, + ((ASTNode) firstExpression).getOffset(), offset); + break; + case IToken.tDECR: + offset = consume().getEndOffset(); + firstExpression = buildUnaryExpression(IASTUnaryExpression.op_postFixDecr, firstExpression, + ((ASTNode) firstExpression).getOffset(), offset); + break; + case IToken.tDOT: + // member access + IToken dot = consume(); + IASTName name = identifier(); + if (name == null) + throwBacktrack(((ASTNode) firstExpression).getOffset(), + ((ASTNode) firstExpression).getLength() + dot.getLength()); + IASTFieldReference result = getNodeFactory().newFieldReference(name, firstExpression); + result.setIsPointerDereference(false); + ((ASTNode) result).setOffsetAndLength(((ASTNode) firstExpression).getOffset(), + calculateEndOffset(name) - ((ASTNode) firstExpression).getOffset()); + firstExpression = result; + break; + case IToken.tARROW: + // member access + IToken arrow = consume(); + name = identifier(); + if (name == null) + throwBacktrack(((ASTNode) firstExpression).getOffset(), + ((ASTNode) firstExpression).getLength() + arrow.getLength()); + result = getNodeFactory().newFieldReference(name, firstExpression); + result.setIsPointerDereference(true); + ((ASTNode) result).setOffsetAndLength(((ASTNode) firstExpression).getOffset(), + calculateEndOffset(name) - ((ASTNode) firstExpression).getOffset()); + firstExpression = result; + break; + default: + return firstExpression; + } + } + } + + @Override + protected IASTExpression primaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) + throws EndOfFileException, BacktrackException { + IToken t = null; + IASTLiteralExpression literalExpression = null; + switch (LT(1)) { + // TO DO: we need more literals... + case IToken.tINTEGER: + t = consume(); + literalExpression = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_integer_constant, + t.getImage()); + ((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset()); + return literalExpression; + case IToken.tFLOATINGPT: + t = consume(); + literalExpression = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_float_constant, + t.getImage()); + ((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset()); + return literalExpression; + case IToken.tSTRING: + case IToken.tLSTRING: + case IToken.tUTF16STRING: + case IToken.tUTF32STRING: + t = consume(); + literalExpression = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_string_literal, + t.getImage()); + ((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset()); + return literalExpression; + case IToken.tCHAR: + case IToken.tLCHAR: + case IToken.tUTF16CHAR: + case IToken.tUTF32CHAR: + t = consume(); + literalExpression = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_char_constant, + t.getImage()); + ((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getLength()); + return literalExpression; + case IToken.tLPAREN: + if (supportStatementsInExpressions && LT(2) == IToken.tLBRACE) { + return compoundStatementExpression(); + } + t = consume(); + IASTExpression lhs = expression(ExprKind.eExpression); // instead of expression(), to keep the stack smaller + int finalOffset = 0; + switch (LT(1)) { + case IToken.tRPAREN: + case IToken.tEOC: + finalOffset = consume().getEndOffset(); + break; + default: + throwBacktrack(LA(1)); + } + return buildUnaryExpression(IASTUnaryExpression.op_bracketedPrimary, lhs, t.getOffset(), finalOffset); + case IToken.tIDENTIFIER: + case IToken.tCOMPLETION: + case IToken.tEOC: + int startingOffset = LA(1).getOffset(); + IASTName name = identifier(); + IASTIdExpression idExpression = getNodeFactory().newIdExpression(name); + ((ASTNode) idExpression).setOffsetAndLength((ASTNode) name); + return idExpression; + default: + IToken la = LA(1); + startingOffset = la.getOffset(); + throwBacktrack(startingOffset, la.getLength()); + return null; + } + + } + + @Override protected IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException, BacktrackException { - if (!canBeTypeSpecifier()) { - return null; - } - final int offset = mark().getOffset(); - IASTDeclSpecifier declSpecifier = null; - IASTDeclarator declarator = null; - - fPreventKnrCheck++; - try { - Decl decl= declSpecifierSequence_initDeclarator(option, false); - declSpecifier= decl.fDeclSpec1; - declarator= decl.fDtor1; - } catch (FoundAggregateInitializer lie) { - // type-ids have not compound initializers - throwBacktrack(lie.fDeclarator); - } finally { - fPreventKnrCheck--; - } - - IASTTypeId result = getNodeFactory().newTypeId(declSpecifier, declarator); - setRange(result, offset, figureEndOffset(declSpecifier, declarator)); - return result; - } - - /** - * Parse a Pointer Operator. - * - * ptrOperator : "*" (cvQualifier)* | "&" | ::? nestedNameSpecifier "*" - * (cvQualifier)* - * - * @throws BacktrackException to request a backtrack - */ - protected void consumePointerOperators(List<IASTPointerOperator> pointerOps) - throws EndOfFileException, BacktrackException { - for (;;) { - // __attribute__ in-between pointers - __attribute_decl_seq(supportAttributeSpecifiers, false); - - IToken mark = mark(); - IToken last = null; - - boolean isConst = false, isVolatile = false, isRestrict = false; - - if (LT(1) != IToken.tSTAR) { - backup(mark); - break; - } - - last = consume(); - int startOffset = mark.getOffset(); - for (;;) { - IToken t = LA(1); - switch (LT(1)) { - case IToken.t_const: - last = consume(); - isConst = true; - break; - case IToken.t_volatile: - last = consume(); - isVolatile = true; - break; - case IToken.t_restrict: - last = consume(); - isRestrict = true; - break; - } - - if (t == LA(1)) - break; - } - - ICASTPointer po = getNodeFactory().newPointer(); - ((ASTNode) po).setOffsetAndLength(startOffset, last.getEndOffset() - startOffset); - po.setConst(isConst); - po.setVolatile(isVolatile); - po.setRestrict(isRestrict); - pointerOps.add(po); - } - } - - - private final static int INLINE=0x1, CONST=0x2, RESTRICT=0x4, VOLATILE=0x8, - SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100; - - @Override - protected Decl declSpecifierSeq(final DeclarationOptions declOption, ITemplateIdStrategy strat) + if (!canBeTypeSpecifier()) { + return null; + } + final int offset = mark().getOffset(); + IASTDeclSpecifier declSpecifier = null; + IASTDeclarator declarator = null; + + fPreventKnrCheck++; + try { + Decl decl = declSpecifierSequence_initDeclarator(option, false); + declSpecifier = decl.fDeclSpec1; + declarator = decl.fDtor1; + } catch (FoundAggregateInitializer lie) { + // type-ids have not compound initializers + throwBacktrack(lie.fDeclarator); + } finally { + fPreventKnrCheck--; + } + + IASTTypeId result = getNodeFactory().newTypeId(declSpecifier, declarator); + setRange(result, offset, figureEndOffset(declSpecifier, declarator)); + return result; + } + + /** + * Parse a Pointer Operator. + * + * ptrOperator : "*" (cvQualifier)* | "&" | ::? nestedNameSpecifier "*" + * (cvQualifier)* + * + * @throws BacktrackException to request a backtrack + */ + protected void consumePointerOperators(List<IASTPointerOperator> pointerOps) + throws EndOfFileException, BacktrackException { + for (;;) { + // __attribute__ in-between pointers + __attribute_decl_seq(supportAttributeSpecifiers, false); + + IToken mark = mark(); + IToken last = null; + + boolean isConst = false, isVolatile = false, isRestrict = false; + + if (LT(1) != IToken.tSTAR) { + backup(mark); + break; + } + + last = consume(); + int startOffset = mark.getOffset(); + for (;;) { + IToken t = LA(1); + switch (LT(1)) { + case IToken.t_const: + last = consume(); + isConst = true; + break; + case IToken.t_volatile: + last = consume(); + isVolatile = true; + break; + case IToken.t_restrict: + last = consume(); + isRestrict = true; + break; + } + + if (t == LA(1)) + break; + } + + ICASTPointer po = getNodeFactory().newPointer(); + ((ASTNode) po).setOffsetAndLength(startOffset, last.getEndOffset() - startOffset); + po.setConst(isConst); + po.setVolatile(isVolatile); + po.setRestrict(isRestrict); + pointerOps.add(po); + } + } + + private final static int INLINE = 0x1, CONST = 0x2, RESTRICT = 0x4, VOLATILE = 0x8, SHORT = 0x10, UNSIGNED = 0x20, + SIGNED = 0x40, COMPLEX = 0x80, IMAGINARY = 0x100; + + @Override + protected Decl declSpecifierSeq(final DeclarationOptions declOption, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException { - int storageClass= IASTDeclSpecifier.sc_unspecified; - int simpleType= IASTSimpleDeclSpecifier.t_unspecified; - int options= 0; - int isLong= 0; - - IToken returnToken= null; - ICASTDeclSpecifier result= null; - ICASTDeclSpecifier altResult= null; - IASTAlignmentSpecifier[] alignmentSpecifiers = IASTAlignmentSpecifier.EMPTY_ALIGNMENT_SPECIFIER_ARRAY; - List<IASTAttributeSpecifier> attributes = null; - try { - IASTName identifier= null; - IASTExpression typeofExpression= null; - IASTProblem problem= null; - - boolean encounteredRawType= false; - boolean encounteredTypename= false; - - final int offset= LA(1).getOffset(); - int endOffset= offset; - - declSpecifiers: for (;;) { - final int lt1= LTcatchEOF(1); - switch (lt1) { - case 0: // eof - break declSpecifiers; - // storage class specifiers - case IToken.t_auto: - storageClass = IASTDeclSpecifier.sc_auto; - endOffset= consume().getEndOffset(); - break; - case IToken.t_register: - storageClass = IASTDeclSpecifier.sc_register; - endOffset= consume().getEndOffset(); - break; - case IToken.t_static: - storageClass = IASTDeclSpecifier.sc_static; - endOffset= consume().getEndOffset(); - break; - case IToken.t_extern: - storageClass = IASTDeclSpecifier.sc_extern; - endOffset= consume().getEndOffset(); - break; - case IToken.t_typedef: - storageClass = IASTDeclSpecifier.sc_typedef; - endOffset= consume().getEndOffset(); - break; - - // Function Specifier - case IToken.t_inline: - options |= INLINE; - endOffset= consume().getEndOffset(); - break; - - // Type Qualifiers - case IToken.t_const: - options |= CONST; - endOffset= consume().getEndOffset(); - break; - case IToken.t_volatile: - options |= VOLATILE; - endOffset= consume().getEndOffset(); - break; - case IToken.t_restrict: - options |= RESTRICT; - endOffset= consume().getEndOffset(); - break; - - // Type Specifiers - case IToken.t_void: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_void; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_char: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_char; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_short: - if (encounteredTypename) - break declSpecifiers; - options |= SHORT; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_int: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_int; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IGCCToken.t__int128: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_int128; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_long: - if (encounteredTypename) - break declSpecifiers; - isLong++; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_float: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_float; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_double: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_double; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IGCCToken.t__float128: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_float128; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IGCCToken.t_decimal32: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_decimal32; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IGCCToken.t_decimal64: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_decimal64; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IGCCToken.t_decimal128: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_decimal128; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_signed: - if (encounteredTypename) - break declSpecifiers; - options |= SIGNED; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t_unsigned: - if (encounteredTypename) - break declSpecifiers; - options |= UNSIGNED; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t__Bool: - if (encounteredTypename) - break declSpecifiers; - simpleType = IASTSimpleDeclSpecifier.t_bool; - encounteredRawType= true; - endOffset= consume().getEndOffset(); - break; - case IToken.t__Complex: - if (encounteredTypename) - break declSpecifiers; - options |= COMPLEX; - endOffset= consume().getEndOffset(); - break; - case IToken.t__Imaginary: - if (encounteredTypename) - break declSpecifiers; - options |= IMAGINARY; - endOffset= consume().getEndOffset(); - break; - - case IToken.tIDENTIFIER: - case IToken.tCOMPLETION: - case IToken.tEOC: - if (encounteredTypename || encounteredRawType) - break declSpecifiers; - - if ((endOffset != offset || declOption.fAllowEmptySpecifier) && LT(1) != IToken.tCOMPLETION) { - altResult= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); - returnToken= mark(); - } - - identifier = identifier(); - endOffset= calculateEndOffset(identifier); - encounteredTypename= true; - break; - case IToken.t_struct: - case IToken.t_union: - if (encounteredTypename || encounteredRawType) - break declSpecifiers; - try { - result= structOrUnionSpecifier(); - } catch (BacktrackException bt) { - result= elaboratedTypeSpecifier(); - } - endOffset= calculateEndOffset(result); - encounteredTypename= true; - break; - case IToken.t_enum: - if (encounteredTypename || encounteredRawType) - break declSpecifiers; - try { - result= (ICASTEnumerationSpecifier) enumSpecifier(); - } catch (BacktrackException bt) { - if (bt.getNodeBeforeProblem() instanceof ICASTDeclSpecifier) { - result= (ICASTDeclSpecifier) bt.getNodeBeforeProblem(); - problem = bt.getProblem(); - break declSpecifiers; - } else { - result= elaboratedTypeSpecifier(); - } - } - endOffset= calculateEndOffset(result); - encounteredTypename= true; - break; - - case IToken.t__Alignas: - alignmentSpecifiers = ArrayUtil.append(alignmentSpecifiers, alignmentSpecifier()); - break; - - case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec - if (!supportAttributeSpecifiers) - throwBacktrack(LA(1)); - attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(true, false)); - break; - case IGCCToken.t__declspec: // __declspec precedes the identifier - if (identifier != null || !supportDeclspecSpecifiers) - throwBacktrack(LA(1)); - __attribute_decl_seq(false, true); - break; - - case IGCCToken.t_typeof: - if (encounteredRawType || encounteredTypename) - throwBacktrack(LA(1)); - - simpleType= IASTSimpleDeclSpecifier.t_typeof; - consume(IGCCToken.t_typeof); - typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, LA(1).getOffset(), - IASTTypeIdExpression.op_typeof, -1, CastExprCtx.eNotInBExpr, null); - - encounteredTypename= true; - endOffset= calculateEndOffset(typeofExpression); - break; - - default: - if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) { - handleOtherDeclSpecModifier(); - endOffset= LA(1).getOffset(); - break; - } - break declSpecifiers; - } - - if (encounteredRawType && encounteredTypename) - throwBacktrack(LA(1)); - } - - // check for empty specification - if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC && !declOption.fAllowEmptySpecifier) { - if (offset == endOffset) { - throwBacktrack(LA(1)); - } - } - - if (result != null) { - configureDeclSpec(result, storageClass, options); - if ((options & RESTRICT) != 0) { - if (result instanceof ICASTCompositeTypeSpecifier) { - ((ICASTCompositeTypeSpecifier) result).setRestrict(true); - } else if (result instanceof CASTEnumerationSpecifier) { - ((CASTEnumerationSpecifier) result).setRestrict(true); - } else if (result instanceof CASTElaboratedTypeSpecifier) { - ((CASTElaboratedTypeSpecifier) result).setRestrict(true); - } - } - setRange(result, offset, endOffset); - if (problem != null) - throwBacktrack(problem, result); - } else if (identifier != null) { - result= buildNamedTypeSpecifier(identifier, storageClass, options, offset, endOffset); - } else { - result= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); - } - result.setAlignmentSpecifiers(ArrayUtil.trim(alignmentSpecifiers)); + int storageClass = IASTDeclSpecifier.sc_unspecified; + int simpleType = IASTSimpleDeclSpecifier.t_unspecified; + int options = 0; + int isLong = 0; + + IToken returnToken = null; + ICASTDeclSpecifier result = null; + ICASTDeclSpecifier altResult = null; + IASTAlignmentSpecifier[] alignmentSpecifiers = IASTAlignmentSpecifier.EMPTY_ALIGNMENT_SPECIFIER_ARRAY; + List<IASTAttributeSpecifier> attributes = null; + try { + IASTName identifier = null; + IASTExpression typeofExpression = null; + IASTProblem problem = null; + + boolean encounteredRawType = false; + boolean encounteredTypename = false; + + final int offset = LA(1).getOffset(); + int endOffset = offset; + + declSpecifiers: for (;;) { + final int lt1 = LTcatchEOF(1); + switch (lt1) { + case 0: // eof + break declSpecifiers; + // storage class specifiers + case IToken.t_auto: + storageClass = IASTDeclSpecifier.sc_auto; + endOffset = consume().getEndOffset(); + break; + case IToken.t_register: + storageClass = IASTDeclSpecifier.sc_register; + endOffset = consume().getEndOffset(); + break; + case IToken.t_static: + storageClass = IASTDeclSpecifier.sc_static; + endOffset = consume().getEndOffset(); + break; + case IToken.t_extern: + storageClass = IASTDeclSpecifier.sc_extern; + endOffset = consume().getEndOffset(); + break; + case IToken.t_typedef: + storageClass = IASTDeclSpecifier.sc_typedef; + endOffset = consume().getEndOffset(); + break; + + // Function Specifier + case IToken.t_inline: + options |= INLINE; + endOffset = consume().getEndOffset(); + break; + + // Type Qualifiers + case IToken.t_const: + options |= CONST; + endOffset = consume().getEndOffset(); + break; + case IToken.t_volatile: + options |= VOLATILE; + endOffset = consume().getEndOffset(); + break; + case IToken.t_restrict: + options |= RESTRICT; + endOffset = consume().getEndOffset(); + break; + + // Type Specifiers + case IToken.t_void: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_void; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t_char: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_char; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t_short: + if (encounteredTypename) + break declSpecifiers; + options |= SHORT; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t_int: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_int; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IGCCToken.t__int128: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_int128; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t_long: + if (encounteredTypename) + break declSpecifiers; + isLong++; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t_float: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_float; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t_double: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_double; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IGCCToken.t__float128: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_float128; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IGCCToken.t_decimal32: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_decimal32; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IGCCToken.t_decimal64: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_decimal64; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IGCCToken.t_decimal128: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_decimal128; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t_signed: + if (encounteredTypename) + break declSpecifiers; + options |= SIGNED; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t_unsigned: + if (encounteredTypename) + break declSpecifiers; + options |= UNSIGNED; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t__Bool: + if (encounteredTypename) + break declSpecifiers; + simpleType = IASTSimpleDeclSpecifier.t_bool; + encounteredRawType = true; + endOffset = consume().getEndOffset(); + break; + case IToken.t__Complex: + if (encounteredTypename) + break declSpecifiers; + options |= COMPLEX; + endOffset = consume().getEndOffset(); + break; + case IToken.t__Imaginary: + if (encounteredTypename) + break declSpecifiers; + options |= IMAGINARY; + endOffset = consume().getEndOffset(); + break; + + case IToken.tIDENTIFIER: + case IToken.tCOMPLETION: + case IToken.tEOC: + if (encounteredTypename || encounteredRawType) + break declSpecifiers; + + if ((endOffset != offset || declOption.fAllowEmptySpecifier) && LT(1) != IToken.tCOMPLETION) { + altResult = buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, + offset, endOffset); + returnToken = mark(); + } + + identifier = identifier(); + endOffset = calculateEndOffset(identifier); + encounteredTypename = true; + break; + case IToken.t_struct: + case IToken.t_union: + if (encounteredTypename || encounteredRawType) + break declSpecifiers; + try { + result = structOrUnionSpecifier(); + } catch (BacktrackException bt) { + result = elaboratedTypeSpecifier(); + } + endOffset = calculateEndOffset(result); + encounteredTypename = true; + break; + case IToken.t_enum: + if (encounteredTypename || encounteredRawType) + break declSpecifiers; + try { + result = (ICASTEnumerationSpecifier) enumSpecifier(); + } catch (BacktrackException bt) { + if (bt.getNodeBeforeProblem() instanceof ICASTDeclSpecifier) { + result = (ICASTDeclSpecifier) bt.getNodeBeforeProblem(); + problem = bt.getProblem(); + break declSpecifiers; + } else { + result = elaboratedTypeSpecifier(); + } + } + endOffset = calculateEndOffset(result); + encounteredTypename = true; + break; + + case IToken.t__Alignas: + alignmentSpecifiers = ArrayUtil.append(alignmentSpecifiers, alignmentSpecifier()); + break; + + case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec + if (!supportAttributeSpecifiers) + throwBacktrack(LA(1)); + attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(true, false)); + break; + case IGCCToken.t__declspec: // __declspec precedes the identifier + if (identifier != null || !supportDeclspecSpecifiers) + throwBacktrack(LA(1)); + __attribute_decl_seq(false, true); + break; + + case IGCCToken.t_typeof: + if (encounteredRawType || encounteredTypename) + throwBacktrack(LA(1)); + + simpleType = IASTSimpleDeclSpecifier.t_typeof; + consume(IGCCToken.t_typeof); + typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, LA(1).getOffset(), + IASTTypeIdExpression.op_typeof, -1, CastExprCtx.eNotInBExpr, null); + + encounteredTypename = true; + endOffset = calculateEndOffset(typeofExpression); + break; + + default: + if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst + && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) { + handleOtherDeclSpecModifier(); + endOffset = LA(1).getOffset(); + break; + } + break declSpecifiers; + } + + if (encounteredRawType && encounteredTypename) + throwBacktrack(LA(1)); + } + + // check for empty specification + if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC + && !declOption.fAllowEmptySpecifier) { + if (offset == endOffset) { + throwBacktrack(LA(1)); + } + } + + if (result != null) { + configureDeclSpec(result, storageClass, options); + if ((options & RESTRICT) != 0) { + if (result instanceof ICASTCompositeTypeSpecifier) { + ((ICASTCompositeTypeSpecifier) result).setRestrict(true); + } else if (result instanceof CASTEnumerationSpecifier) { + ((CASTEnumerationSpecifier) result).setRestrict(true); + } else if (result instanceof CASTElaboratedTypeSpecifier) { + ((CASTElaboratedTypeSpecifier) result).setRestrict(true); + } + } + setRange(result, offset, endOffset); + if (problem != null) + throwBacktrack(problem, result); + } else if (identifier != null) { + result = buildNamedTypeSpecifier(identifier, storageClass, options, offset, endOffset); + } else { + result = buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, + endOffset); + } + result.setAlignmentSpecifiers(ArrayUtil.trim(alignmentSpecifiers)); addAttributeSpecifiers(attributes, result); endOffset = attributesEndOffset(endOffset, attributes); setRange(result, offset, endOffset); - } catch (BacktrackException e) { - if (returnToken != null) { - backup(returnToken); - result= altResult; - altResult= null; - returnToken= null; - } else { - throw e; - } - } - Decl target= new Decl(); - target.fDeclSpec1= result; - target.fDeclSpec2= altResult; - target.fDtorToken1= returnToken; - return target; - } - - private ICASTTypedefNameSpecifier buildNamedTypeSpecifier(IASTName name, int storageClass, - int options, int offset, int endOffset) { + } catch (BacktrackException e) { + if (returnToken != null) { + backup(returnToken); + result = altResult; + altResult = null; + returnToken = null; + } else { + throw e; + } + } + Decl target = new Decl(); + target.fDeclSpec1 = result; + target.fDeclSpec2 = altResult; + target.fDtorToken1 = returnToken; + return target; + } + + private ICASTTypedefNameSpecifier buildNamedTypeSpecifier(IASTName name, int storageClass, int options, int offset, + int endOffset) { ICASTTypedefNameSpecifier declSpec = getNodeFactory().newTypedefNameSpecifier(name); configureDeclSpec(declSpec, storageClass, options); declSpec.setRestrict((options & RESTRICT) != 0); - ((ASTNode) declSpec).setOffsetAndLength(offset, endOffset - offset); - return declSpec; + ((ASTNode) declSpec).setOffsetAndLength(offset, endOffset - offset); + return declSpec; } - private ICASTSimpleDeclSpecifier buildSimpleDeclSpec(int storageClass, int simpleType, - int options, int isLong, IASTExpression typeofExpression, int offset, int endOffset) { - ICASTSimpleDeclSpecifier declSpec= getNodeFactory().newSimpleDeclSpecifier(); + private ICASTSimpleDeclSpecifier buildSimpleDeclSpec(int storageClass, int simpleType, int options, int isLong, + IASTExpression typeofExpression, int offset, int endOffset) { + ICASTSimpleDeclSpecifier declSpec = getNodeFactory().newSimpleDeclSpecifier(); - configureDeclSpec(declSpec, storageClass, options); + configureDeclSpec(declSpec, storageClass, options); declSpec.setType(simpleType); declSpec.setLong(isLong == 1); declSpec.setLongLong(isLong > 1); @@ -1275,274 +1282,271 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { declSpec.setInline((options & INLINE) != 0); } - /** - * Parse a class/struct/union definition. - * - * classSpecifier : classKey name (baseClause)? "{" (memberSpecification)* - * "}" - * - * @throws BacktrackException to request a backtrack - */ - protected ICASTCompositeTypeSpecifier structOrUnionSpecifier() throws BacktrackException, EndOfFileException { - int classKind = 0; - IToken mark= mark(); - final int offset= mark.getOffset(); - - // class key - switch (LT(1)) { - case IToken.t_struct: - consume(); - classKind = IASTCompositeTypeSpecifier.k_struct; - break; - case IToken.t_union: - consume(); - classKind = IASTCompositeTypeSpecifier.k_union; - break; - default: - throwBacktrack(LA(1)); - return null; // line never reached, hint for the parser. - } - - // if __attribute__ or __declspec occurs after struct/union/class and before the identifier - __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); - - // class name - IASTName name = null; - if (LT(1) == IToken.tIDENTIFIER) { - name = identifier(); - } - - // if __attribute__ or __declspec occurs after struct/union/class identifier and before the { or ; - __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); - - if (LT(1) != IToken.tLBRACE) { - IToken errorPoint = LA(1); - backup(mark); - throwBacktrack(errorPoint); - } - - if (name == null) { - name= getNodeFactory().newName(); - } - ICASTCompositeTypeSpecifier result = getNodeFactory().newCompositeTypeSpecifier(classKind, name); - declarationListInBraces(result, offset, DeclarationOptions.C_MEMBER); - return result; - } - - protected ICASTElaboratedTypeSpecifier elaboratedTypeSpecifier() throws BacktrackException, EndOfFileException { - // this is an elaborated class specifier - IToken t = consume(); - int eck = 0; - - switch (t.getType()) { - case IToken.t_struct: - eck = IASTElaboratedTypeSpecifier.k_struct; - break; - case IToken.t_union: - eck = IASTElaboratedTypeSpecifier.k_union; - break; - case IToken.t_enum: - eck = IASTElaboratedTypeSpecifier.k_enum; - break; - default: - backup(t); - throwBacktrack(t.getOffset(), t.getLength()); - } - - // if __attribute__ or __declspec occurs after struct/union/class and before the identifier - __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); - - IASTName name = identifier(); - ICASTElaboratedTypeSpecifier result = getNodeFactory().newElaboratedTypeSpecifier(eck, name); - ((ASTNode) result).setOffsetAndLength(t.getOffset(), calculateEndOffset(name) - t.getOffset()); - return result; - } - - @Override + /** + * Parse a class/struct/union definition. + * + * classSpecifier : classKey name (baseClause)? "{" (memberSpecification)* + * "}" + * + * @throws BacktrackException to request a backtrack + */ + protected ICASTCompositeTypeSpecifier structOrUnionSpecifier() throws BacktrackException, EndOfFileException { + int classKind = 0; + IToken mark = mark(); + final int offset = mark.getOffset(); + + // class key + switch (LT(1)) { + case IToken.t_struct: + consume(); + classKind = IASTCompositeTypeSpecifier.k_struct; + break; + case IToken.t_union: + consume(); + classKind = IASTCompositeTypeSpecifier.k_union; + break; + default: + throwBacktrack(LA(1)); + return null; // line never reached, hint for the parser. + } + + // if __attribute__ or __declspec occurs after struct/union/class and before the identifier + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + + // class name + IASTName name = null; + if (LT(1) == IToken.tIDENTIFIER) { + name = identifier(); + } + + // if __attribute__ or __declspec occurs after struct/union/class identifier and before the { or ; + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + + if (LT(1) != IToken.tLBRACE) { + IToken errorPoint = LA(1); + backup(mark); + throwBacktrack(errorPoint); + } + + if (name == null) { + name = getNodeFactory().newName(); + } + ICASTCompositeTypeSpecifier result = getNodeFactory().newCompositeTypeSpecifier(classKind, name); + declarationListInBraces(result, offset, DeclarationOptions.C_MEMBER); + return result; + } + + protected ICASTElaboratedTypeSpecifier elaboratedTypeSpecifier() throws BacktrackException, EndOfFileException { + // this is an elaborated class specifier + IToken t = consume(); + int eck = 0; + + switch (t.getType()) { + case IToken.t_struct: + eck = IASTElaboratedTypeSpecifier.k_struct; + break; + case IToken.t_union: + eck = IASTElaboratedTypeSpecifier.k_union; + break; + case IToken.t_enum: + eck = IASTElaboratedTypeSpecifier.k_enum; + break; + default: + backup(t); + throwBacktrack(t.getOffset(), t.getLength()); + } + + // if __attribute__ or __declspec occurs after struct/union/class and before the identifier + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + + IASTName name = identifier(); + ICASTElaboratedTypeSpecifier result = getNodeFactory().newElaboratedTypeSpecifier(eck, name); + ((ASTNode) result).setOffsetAndLength(t.getOffset(), calculateEndOffset(name) - t.getOffset()); + return result; + } + + @Override protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, final DeclarationOptions option) - throws EndOfFileException, BacktrackException, FoundAggregateInitializer { - IASTDeclarator d = declarator(declspec, option); + throws EndOfFileException, BacktrackException, FoundAggregateInitializer { + IASTDeclarator d = declarator(declspec, option); - final int lt1= LTcatchEOF(1); + final int lt1 = LTcatchEOF(1); if (lt1 == IToken.tLBRACE) { if (!(ASTQueries.findTypeRelevantDeclarator(d) instanceof IASTFunctionDeclarator)) { throwBacktrack(LA(1)); } } - if (lt1 == IToken.tASSIGN && LT(2) == IToken.tLBRACE) - throw new FoundAggregateInitializer(declspec, d); - - IASTInitializer i = optionalInitializer(d, option); - if (i != null) { - d.setInitializer(i); - ((ASTNode) d).setLength(calculateEndOffset(i) - ((ASTNode) d).getOffset()); - } - return d; - } - - protected IASTDeclarator declarator(IASTDeclSpecifier declSpec, DeclarationOptions option) throws EndOfFileException, BacktrackException { - final int startingOffset = LA(1).getOffset(); - int endOffset = startingOffset; - - List<IASTPointerOperator> pointerOps = new ArrayList<>(DEFAULT_POINTEROPS_LIST_SIZE); - consumePointerOperators(pointerOps); - if (!pointerOps.isEmpty()) { - endOffset = calculateEndOffset(pointerOps.get(pointerOps.size() - 1)); - } - - // Accept __attribute__ or __declspec between pointer operators and declarator. - List<IASTAttributeSpecifier> attributes = - __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); - - // Look for identifier or nested declarator - final int lt1= LT(1); - if (lt1 == IToken.tIDENTIFIER) { - if (option.fRequireAbstract) - throwBacktrack(LA(1)); - - final IASTName declaratorName = identifier(); - endOffset= calculateEndOffset(declaratorName); - return declarator(pointerOps, attributes, declaratorName, null, startingOffset, - endOffset, option); - } - - if (lt1 == IToken.tLPAREN) { - IASTDeclarator cand1= null; - IToken cand1End= null; - // try an abstract function declarator - if (option.fAllowAbstract) { - final IToken mark= mark(); - try { - cand1= declarator(pointerOps, attributes, getNodeFactory().newName(), null, - startingOffset, endOffset, option); - if (option.fRequireAbstract) - return cand1; - - cand1End= LA(1); - } catch (BacktrackException e) { - } - backup(mark); - } - // try a nested declarator - try { - consume(); - if (LT(1) == IToken.tRPAREN) - throwBacktrack(LA(1)); - - final IASTDeclarator nested= declarator(declSpec, option); - endOffset= consume(IToken.tRPAREN).getEndOffset(); - final IASTDeclarator cand2= declarator(pointerOps, attributes, null, nested, - startingOffset, endOffset, option); - if (cand1 == null || cand1End == null) - return cand2; - final IToken cand2End= LA(1); - if (cand1End == cand2End) { - CASTAmbiguousDeclarator result= new CASTAmbiguousDeclarator(cand1, cand2); - ((ASTNode) result).setOffsetAndLength((ASTNode) cand1); - return result; - } - // use the longer variant - if (cand1End.getOffset() < cand2End.getOffset()) - return cand2; - - } catch (BacktrackException e) { - if (cand1 == null) - throw e; - } - backup(cand1End); - return cand1; - } - - // try abstract declarator - if (!option.fAllowAbstract) { - throwBacktrack(LA(1)); - } - return declarator(pointerOps, attributes, getNodeFactory().newName(), null, startingOffset, - endOffset, option); - } + if (lt1 == IToken.tASSIGN && LT(2) == IToken.tLBRACE) + throw new FoundAggregateInitializer(declspec, d); + + IASTInitializer i = optionalInitializer(d, option); + if (i != null) { + d.setInitializer(i); + ((ASTNode) d).setLength(calculateEndOffset(i) - ((ASTNode) d).getOffset()); + } + return d; + } + + protected IASTDeclarator declarator(IASTDeclSpecifier declSpec, DeclarationOptions option) + throws EndOfFileException, BacktrackException { + final int startingOffset = LA(1).getOffset(); + int endOffset = startingOffset; + + List<IASTPointerOperator> pointerOps = new ArrayList<>(DEFAULT_POINTEROPS_LIST_SIZE); + consumePointerOperators(pointerOps); + if (!pointerOps.isEmpty()) { + endOffset = calculateEndOffset(pointerOps.get(pointerOps.size() - 1)); + } + + // Accept __attribute__ or __declspec between pointer operators and declarator. + List<IASTAttributeSpecifier> attributes = __attribute_decl_seq(supportAttributeSpecifiers, + supportDeclspecSpecifiers); + + // Look for identifier or nested declarator + final int lt1 = LT(1); + if (lt1 == IToken.tIDENTIFIER) { + if (option.fRequireAbstract) + throwBacktrack(LA(1)); + + final IASTName declaratorName = identifier(); + endOffset = calculateEndOffset(declaratorName); + return declarator(pointerOps, attributes, declaratorName, null, startingOffset, endOffset, option); + } + + if (lt1 == IToken.tLPAREN) { + IASTDeclarator cand1 = null; + IToken cand1End = null; + // try an abstract function declarator + if (option.fAllowAbstract) { + final IToken mark = mark(); + try { + cand1 = declarator(pointerOps, attributes, getNodeFactory().newName(), null, startingOffset, + endOffset, option); + if (option.fRequireAbstract) + return cand1; + + cand1End = LA(1); + } catch (BacktrackException e) { + } + backup(mark); + } + // try a nested declarator + try { + consume(); + if (LT(1) == IToken.tRPAREN) + throwBacktrack(LA(1)); + + final IASTDeclarator nested = declarator(declSpec, option); + endOffset = consume(IToken.tRPAREN).getEndOffset(); + final IASTDeclarator cand2 = declarator(pointerOps, attributes, null, nested, startingOffset, endOffset, + option); + if (cand1 == null || cand1End == null) + return cand2; + final IToken cand2End = LA(1); + if (cand1End == cand2End) { + CASTAmbiguousDeclarator result = new CASTAmbiguousDeclarator(cand1, cand2); + ((ASTNode) result).setOffsetAndLength((ASTNode) cand1); + return result; + } + // use the longer variant + if (cand1End.getOffset() < cand2End.getOffset()) + return cand2; + + } catch (BacktrackException e) { + if (cand1 == null) + throw e; + } + backup(cand1End); + return cand1; + } + + // try abstract declarator + if (!option.fAllowAbstract) { + throwBacktrack(LA(1)); + } + return declarator(pointerOps, attributes, getNodeFactory().newName(), null, startingOffset, endOffset, option); + } private IASTDeclarator declarator(final List<IASTPointerOperator> pointerOps, List<IASTAttributeSpecifier> attributes, final IASTName declaratorName, final IASTDeclarator nestedDeclarator, final int startingOffset, int endOffset, final DeclarationOptions option) throws EndOfFileException, BacktrackException { - IASTDeclarator result= null; - int lt1; - loop: while (true) { - lt1= LTcatchEOF(1); - switch (lt1) { - case IToken.tLPAREN: - result= functionDeclarator(isAbstract(declaratorName, nestedDeclarator) - ? DeclarationOptions.PARAMETER : DeclarationOptions.C_PARAMETER_NON_ABSTRACT); - setDeclaratorID(result, declaratorName, nestedDeclarator); - break loop; - - case IToken.tLBRACKET: - result= arrayDeclarator(); - setDeclaratorID(result, declaratorName, nestedDeclarator); - break loop; - - case IToken.tCOLON: - if (!option.fAllowBitField) - throwBacktrack(LA(1)); - - result= bitFieldDeclarator(); - setDeclaratorID(result, declaratorName, nestedDeclarator); - break loop; - - case IGCCToken.t__attribute__: // if __attribute__ is after a declarator - if (!supportAttributeSpecifiers) - throwBacktrack(LA(1)); - attributes = CollectionUtils.merge(attributes, - __attribute_decl_seq(true, supportDeclspecSpecifiers)); - break; - case IGCCToken.t__declspec: - if (!supportDeclspecSpecifiers) - throwBacktrack(LA(1)); - attributes = CollectionUtils.merge(attributes, - __attribute_decl_seq(supportAttributeSpecifiers, true)); - break; - default: - break loop; - } - } - if (lt1 != 0) { - attributes = CollectionUtils.merge(attributes, - __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers)); - } - - if (result == null) { - result= getNodeFactory().newDeclarator(null); - setDeclaratorID(result, declaratorName, nestedDeclarator); - } else { - endOffset= calculateEndOffset(result); - } - - if (lt1 != 0 && LT(1) == IToken.t_asm) { // asm labels bug 226121 - consume(); - endOffset= asmExpression(null).getEndOffset(); - - __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); - } - - for (IASTPointerOperator po : pointerOps) { + IASTDeclarator result = null; + int lt1; + loop: while (true) { + lt1 = LTcatchEOF(1); + switch (lt1) { + case IToken.tLPAREN: + result = functionDeclarator(isAbstract(declaratorName, nestedDeclarator) ? DeclarationOptions.PARAMETER + : DeclarationOptions.C_PARAMETER_NON_ABSTRACT); + setDeclaratorID(result, declaratorName, nestedDeclarator); + break loop; + + case IToken.tLBRACKET: + result = arrayDeclarator(); + setDeclaratorID(result, declaratorName, nestedDeclarator); + break loop; + + case IToken.tCOLON: + if (!option.fAllowBitField) + throwBacktrack(LA(1)); + + result = bitFieldDeclarator(); + setDeclaratorID(result, declaratorName, nestedDeclarator); + break loop; + + case IGCCToken.t__attribute__: // if __attribute__ is after a declarator + if (!supportAttributeSpecifiers) + throwBacktrack(LA(1)); + attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(true, supportDeclspecSpecifiers)); + break; + case IGCCToken.t__declspec: + if (!supportDeclspecSpecifiers) + throwBacktrack(LA(1)); + attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(supportAttributeSpecifiers, true)); + break; + default: + break loop; + } + } + if (lt1 != 0) { + attributes = CollectionUtils.merge(attributes, + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers)); + } + + if (result == null) { + result = getNodeFactory().newDeclarator(null); + setDeclaratorID(result, declaratorName, nestedDeclarator); + } else { + endOffset = calculateEndOffset(result); + } + + if (lt1 != 0 && LT(1) == IToken.t_asm) { // asm labels bug 226121 + consume(); + endOffset = asmExpression(null).getEndOffset(); + + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + } + + for (IASTPointerOperator po : pointerOps) { result.addPointerOperator(po); } - if (attributes != null) { - for (IASTAttributeSpecifier specifier : attributes) { - result.addAttributeSpecifier(specifier); - } - } + if (attributes != null) { + for (IASTAttributeSpecifier specifier : attributes) { + result.addAttributeSpecifier(specifier); + } + } - ((ASTNode) result).setOffsetAndLength(startingOffset, endOffset - startingOffset); - return result; - } + ((ASTNode) result).setOffsetAndLength(startingOffset, endOffset - startingOffset); + return result; + } private boolean isAbstract(IASTName declaratorName, IASTDeclarator nestedDeclarator) { - nestedDeclarator= ASTQueries.findInnermostDeclarator(nestedDeclarator); + nestedDeclarator = ASTQueries.findInnermostDeclarator(nestedDeclarator); if (nestedDeclarator != null) { - declaratorName= nestedDeclarator.getName(); + declaratorName = nestedDeclarator.getName(); } return declaratorName == null || declaratorName.toCharArray().length == 0; } @@ -1556,9 +1560,10 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } } - private IASTDeclarator functionDeclarator(DeclarationOptions paramOption) throws EndOfFileException, BacktrackException { + private IASTDeclarator functionDeclarator(DeclarationOptions paramOption) + throws EndOfFileException, BacktrackException { IToken last = consume(IToken.tLPAREN); - int startOffset= last.getOffset(); + int startOffset = last.getOffset(); // check for K&R C parameters (0 means it's not K&R C) if (fPreventKnrCheck == 0 && supportKnRC) { @@ -1569,7 +1574,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { IASTName[] parmNames = new IASTName[numKnRCParms]; IASTDeclaration[] parmDeclarations = new IASTDeclaration[numKnRCParms]; - boolean seenParameter= false; + boolean seenParameter = false; for (int i = 0; i <= parmNames.length; i++) { switch (LT(1)) { case IToken.tCOMMA: @@ -1594,52 +1599,53 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { // now that the parameter names are parsed, parse the parameter declarations // count for parameter declarations <= count for parameter names. - int endOffset= last.getEndOffset(); + int endOffset = last.getEndOffset(); for (int i = 0; i < numKnRCParms && LT(1) != IToken.tLBRACE; i++) { try { - IASTDeclaration decl= simpleDeclaration(DeclarationOptions.LOCAL); - IASTSimpleDeclaration ok= checkKnrParameterDeclaration(decl, parmNames); + IASTDeclaration decl = simpleDeclaration(DeclarationOptions.LOCAL); + IASTSimpleDeclaration ok = checkKnrParameterDeclaration(decl, parmNames); if (ok != null) { - parmDeclarations[i]= ok; - endOffset= calculateEndOffset(ok); + parmDeclarations[i] = ok; + endOffset = calculateEndOffset(ok); } else { final ASTNode node = (ASTNode) decl; parmDeclarations[i] = createKnRCProblemDeclaration(node.getOffset(), node.getLength()); - endOffset= calculateEndOffset(node); + endOffset = calculateEndOffset(node); } } catch (BacktrackException b) { parmDeclarations[i] = createKnRCProblemDeclaration(b.getOffset(), b.getLength()); - endOffset= b.getOffset() + b.getLength(); + endOffset = b.getOffset() + b.getLength(); } } parmDeclarations = ArrayUtil.removeNulls(IASTDeclaration.class, parmDeclarations); - ICASTKnRFunctionDeclarator functionDecltor = getNodeFactory().newKnRFunctionDeclarator(parmNames, parmDeclarations); - ((ASTNode) functionDecltor).setOffsetAndLength(startOffset, endOffset-startOffset); - return functionDecltor; + ICASTKnRFunctionDeclarator functionDecltor = getNodeFactory().newKnRFunctionDeclarator(parmNames, + parmDeclarations); + ((ASTNode) functionDecltor).setOffsetAndLength(startOffset, endOffset - startOffset); + return functionDecltor; } } finally { fPreventKnrCheck--; } } - boolean seenParameter= false; - boolean encounteredVarArgs= false; - List<IASTParameterDeclaration> parameters= null; - int endOffset= last.getEndOffset(); + boolean seenParameter = false; + boolean encounteredVarArgs = false; + List<IASTParameterDeclaration> parameters = null; + int endOffset = last.getEndOffset(); paramLoop: while (true) { switch (LT(1)) { case IToken.tRPAREN: case IToken.tEOC: - endOffset= consume().getEndOffset(); + endOffset = consume().getEndOffset(); break paramLoop; case IToken.tELLIPSIS: - endOffset= consume().getEndOffset(); + endOffset = consume().getEndOffset(); encounteredVarArgs = true; break; case IToken.tCOMMA: - endOffset= consume().getEndOffset(); + endOffset = consume().getEndOffset(); seenParameter = false; break; default: @@ -1662,22 +1668,22 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { fc.addParameterDeclaration(pd); } } - ((ASTNode) fc).setOffsetAndLength(startOffset, endOffset-startOffset); - return fc; + ((ASTNode) fc).setOffsetAndLength(startOffset, endOffset - startOffset); + return fc; } private IASTSimpleDeclaration checkKnrParameterDeclaration(IASTDeclaration decl, final IASTName[] parmNames) { if (!(decl instanceof IASTSimpleDeclaration)) return null; - IASTSimpleDeclaration declaration= ((IASTSimpleDeclaration) decl); + IASTSimpleDeclaration declaration = ((IASTSimpleDeclaration) decl); IASTDeclarator[] decltors = declaration.getDeclarators(); for (IASTDeclarator decltor : decltors) { boolean decltorOk = false; final char[] nchars = ASTQueries.findInnermostDeclarator(decltor).getName().toCharArray(); for (IASTName parmName : parmNames) { if (CharArrayUtils.equals(nchars, parmName.toCharArray())) { - decltorOk= true; + decltorOk = true; break; } } @@ -1692,7 +1698,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { */ private IASTArrayDeclarator arrayDeclarator() throws EndOfFileException, BacktrackException { ArrayList<IASTArrayModifier> arrayMods = new ArrayList<>(DEFAULT_POINTEROPS_LIST_SIZE); - int start= LA(1).getOffset(); + int start = LA(1).getOffset(); consumeArrayModifiers(arrayMods); if (arrayMods.isEmpty()) throwBacktrack(LA(1)); @@ -1700,104 +1706,103 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { final int endOffset = calculateEndOffset(arrayMods.get(arrayMods.size() - 1)); final IASTArrayDeclarator d = getNodeFactory().newArrayDeclarator(null); for (IASTArrayModifier m : arrayMods) { - d.addArrayModifier(m); - } + d.addArrayModifier(m); + } - ((ASTNode) d).setOffsetAndLength(start, endOffset-start); + ((ASTNode) d).setOffsetAndLength(start, endOffset - start); return d; } - /** * Parses for a bit field declarator starting with the colon */ private IASTFieldDeclarator bitFieldDeclarator() throws EndOfFileException, BacktrackException { - int start= consume(IToken.tCOLON).getOffset(); + int start = consume(IToken.tCOLON).getOffset(); final IASTExpression bitField = constantExpression(); final int endOffset = calculateEndOffset(bitField); - IASTFieldDeclarator d = getNodeFactory().newFieldDeclarator(null, bitField); - d.setBitFieldSize(bitField); + IASTFieldDeclarator d = getNodeFactory().newFieldDeclarator(null, bitField); + d.setBitFieldSize(bitField); - ((ASTNode) d).setOffsetAndLength(start, endOffset-start); + ((ASTNode) d).setOffsetAndLength(start, endOffset - start); return d; } - - @Override + @Override protected IASTName identifier() throws EndOfFileException, BacktrackException { - final IToken t= LA(1); - IASTName n; - switch (t.getType()) { - case IToken.tIDENTIFIER: - consume(); - n = getNodeFactory().newName(t.getCharImage()); - setRange(n, t.getOffset(), t.getEndOffset()); - break; - - case IToken.tCOMPLETION: - case IToken.tEOC: - consume(); - n = getNodeFactory().newName(t.getCharImage()); - setRange(n, t.getOffset(), t.getEndOffset()); - createCompletionNode(t).addName(n); - return n; - - default: - throw backtrack; - } - - return n; - } - - protected void consumeArrayModifiers(List<IASTArrayModifier> arrayMods) throws EndOfFileException, BacktrackException { - while (LT(1) == IToken.tLBRACKET) { - // eat the '[' - int startOffset = consume().getOffset(); - - boolean isStatic = false; - boolean isConst = false; - boolean isRestrict = false; - boolean isVolatile = false; - boolean isVarSized = false; - - outerLoop: do { - switch (LT(1)) { - case IToken.t_static: - isStatic = true; - consume(); - break; - case IToken.t_const: - isConst = true; - consume(); - break; - case IToken.t_volatile: - isVolatile = true; - consume(); - break; - case IToken.t_restrict: - isRestrict = true; - consume(); - break; - case IToken.tSTAR: - isVarSized = true; - consume(); - break outerLoop; - default: - break outerLoop; - } - } while (true); - - IASTExpression exp = null; - - if (LT(1) != IToken.tRBRACKET) { - if (!(isStatic || isRestrict || isConst || isVolatile)) - exp = expression(ExprKind.eAssignment); - else - exp = constantExpression(); - } - int lastOffset; + final IToken t = LA(1); + IASTName n; + switch (t.getType()) { + case IToken.tIDENTIFIER: + consume(); + n = getNodeFactory().newName(t.getCharImage()); + setRange(n, t.getOffset(), t.getEndOffset()); + break; + + case IToken.tCOMPLETION: + case IToken.tEOC: + consume(); + n = getNodeFactory().newName(t.getCharImage()); + setRange(n, t.getOffset(), t.getEndOffset()); + createCompletionNode(t).addName(n); + return n; + + default: + throw backtrack; + } + + return n; + } + + protected void consumeArrayModifiers(List<IASTArrayModifier> arrayMods) + throws EndOfFileException, BacktrackException { + while (LT(1) == IToken.tLBRACKET) { + // eat the '[' + int startOffset = consume().getOffset(); + + boolean isStatic = false; + boolean isConst = false; + boolean isRestrict = false; + boolean isVolatile = false; + boolean isVarSized = false; + + outerLoop: do { + switch (LT(1)) { + case IToken.t_static: + isStatic = true; + consume(); + break; + case IToken.t_const: + isConst = true; + consume(); + break; + case IToken.t_volatile: + isVolatile = true; + consume(); + break; + case IToken.t_restrict: + isRestrict = true; + consume(); + break; + case IToken.tSTAR: + isVarSized = true; + consume(); + break outerLoop; + default: + break outerLoop; + } + } while (true); + + IASTExpression exp = null; + + if (LT(1) != IToken.tRBRACKET) { + if (!(isStatic || isRestrict || isConst || isVolatile)) + exp = expression(ExprKind.eAssignment); + else + exp = constantExpression(); + } + int lastOffset; switch (LT(1)) { case IToken.tRBRACKET: lastOffset = consume().getEndOffset(); @@ -1815,390 +1820,388 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { arrayMod.setVolatile(isVolatile); arrayMod.setRestrict(isRestrict); arrayMod.setVariableSized(isVarSized); - ((ASTNode) arrayMod).setOffsetAndLength(startOffset, lastOffset - startOffset); - arrayMods.add(arrayMod); - } - } - - - protected IASTParameterDeclaration parameterDeclaration(DeclarationOptions option) throws BacktrackException, EndOfFileException { - final IToken current = LA(1); - int startingOffset = current.getOffset(); - if (current.getType() == IToken.tLBRACKET && supportParameterInfoBlock) { - skipBrackets(IToken.tLBRACKET, IToken.tRBRACKET, 0); - } - - IASTDeclSpecifier declSpec = null; - IASTDeclarator declarator = null; - IASTDeclSpecifier altDeclSpec = null; - IASTDeclarator altDeclarator = null; - - try { - fPreventKnrCheck++; - Decl decl= declSpecifierSequence_initDeclarator(option, false); - declSpec= decl.fDeclSpec1; - declarator= decl.fDtor1; - altDeclSpec= decl.fDeclSpec2; - altDeclarator= decl.fDtor2; - } catch (FoundAggregateInitializer lie) { - declSpec= lie.fDeclSpec; - declarator= lie.fDeclarator; - } finally { - fPreventKnrCheck--; - } - - final int length = figureEndOffset(declSpec, declarator) - startingOffset; - IASTParameterDeclaration result = getNodeFactory().newParameterDeclaration(declSpec, declarator); + ((ASTNode) arrayMod).setOffsetAndLength(startOffset, lastOffset - startOffset); + arrayMods.add(arrayMod); + } + } + + protected IASTParameterDeclaration parameterDeclaration(DeclarationOptions option) + throws BacktrackException, EndOfFileException { + final IToken current = LA(1); + int startingOffset = current.getOffset(); + if (current.getType() == IToken.tLBRACKET && supportParameterInfoBlock) { + skipBrackets(IToken.tLBRACKET, IToken.tRBRACKET, 0); + } + + IASTDeclSpecifier declSpec = null; + IASTDeclarator declarator = null; + IASTDeclSpecifier altDeclSpec = null; + IASTDeclarator altDeclarator = null; + + try { + fPreventKnrCheck++; + Decl decl = declSpecifierSequence_initDeclarator(option, false); + declSpec = decl.fDeclSpec1; + declarator = decl.fDtor1; + altDeclSpec = decl.fDeclSpec2; + altDeclarator = decl.fDtor2; + } catch (FoundAggregateInitializer lie) { + declSpec = lie.fDeclSpec; + declarator = lie.fDeclarator; + } finally { + fPreventKnrCheck--; + } + + final int length = figureEndOffset(declSpec, declarator) - startingOffset; + IASTParameterDeclaration result = getNodeFactory().newParameterDeclaration(declSpec, declarator); ((ASTNode) result).setOffsetAndLength(startingOffset, length); - if (altDeclarator != null && altDeclSpec != null) { - IASTParameterDeclaration alt = getNodeFactory().newParameterDeclaration(altDeclSpec, altDeclarator); - ((ASTNode) alt).setOffsetAndLength(startingOffset, length); - // order is important, prefer variant with declspec over the one without - result= new CASTAmbiguousParameterDeclaration(result, alt); - ((ASTNode) result).setOffsetAndLength((ASTNode) alt); - } - return result; - } - - - @Override - protected IASTTranslationUnit getTranslationUnit() { - return translationUnit; - } + if (altDeclarator != null && altDeclSpec != null) { + IASTParameterDeclaration alt = getNodeFactory().newParameterDeclaration(altDeclSpec, altDeclarator); + ((ASTNode) alt).setOffsetAndLength(startingOffset, length); + // order is important, prefer variant with declspec over the one without + result = new CASTAmbiguousParameterDeclaration(result, alt); + ((ASTNode) result).setOffsetAndLength((ASTNode) alt); + } + return result; + } + @Override + protected IASTTranslationUnit getTranslationUnit() { + return translationUnit; + } - @Override + @Override protected IASTStatement statement() throws EndOfFileException, BacktrackException { - switch (LT(1)) { - // labeled statements - case IToken.t_case: - return parseCaseStatement(); - case IToken.t_default: - return parseDefaultStatement(); - // compound statement - case IToken.tLBRACE: - return parseCompoundStatement(); - // selection statement - case IToken.t_if: - return parseIfStatement(); - case IToken.t_switch: - return parseSwitchStatement(); - // iteration statements - case IToken.t_while: - return parseWhileStatement(); - case IToken.t_do: - return parseDoStatement(); - case IToken.t_for: - return parseForStatement(); - // jump statement - case IToken.t_break: - return parseBreakStatement(); - case IToken.t_continue: - return parseContinueStatement(); - case IToken.t_return: - return parseReturnStatement(); - case IToken.t_goto: - return parseGotoStatement(); - case IToken.tSEMI: - return parseNullStatement(); - default: - // can be many things: - // label - if (LT(1) == IToken.tIDENTIFIER && LT(2) == IToken.tCOLON) { - return parseLabelStatement(); - } - - return parseDeclarationOrExpressionStatement(); - } - } - - @Override + switch (LT(1)) { + // labeled statements + case IToken.t_case: + return parseCaseStatement(); + case IToken.t_default: + return parseDefaultStatement(); + // compound statement + case IToken.tLBRACE: + return parseCompoundStatement(); + // selection statement + case IToken.t_if: + return parseIfStatement(); + case IToken.t_switch: + return parseSwitchStatement(); + // iteration statements + case IToken.t_while: + return parseWhileStatement(); + case IToken.t_do: + return parseDoStatement(); + case IToken.t_for: + return parseForStatement(); + // jump statement + case IToken.t_break: + return parseBreakStatement(); + case IToken.t_continue: + return parseContinueStatement(); + case IToken.t_return: + return parseReturnStatement(); + case IToken.t_goto: + return parseGotoStatement(); + case IToken.tSEMI: + return parseNullStatement(); + default: + // can be many things: + // label + if (LT(1) == IToken.tIDENTIFIER && LT(2) == IToken.tCOLON) { + return parseLabelStatement(); + } + + return parseDeclarationOrExpressionStatement(); + } + } + + @Override protected void nullifyTranslationUnit() { - translationUnit = null; - } - - - private int countKnRCParms() { - IToken mark = null; - int parmCount = 0; - boolean previousWasIdentifier = false; - - try { - mark = mark(); - - // starts at the beginning of the parameter list - for (;;) { - if (LT(1) == IToken.tCOMMA) { - consume(); - previousWasIdentifier = false; - } else if (LT(1) == IToken.tIDENTIFIER) { - consume(); - if (previousWasIdentifier) { - backup(mark); - return 0; // i.e. KnR C won't have int f(typedef x) - // char - // x; {} - } - previousWasIdentifier = true; - parmCount++; - } else if (LT(1) == IToken.tRPAREN) { - if (!previousWasIdentifier) { - // if the first token encountered is tRPAREN then it's not K&R C - // the first token when counting K&R C parms is always an identifier - backup(mark); - return 0; - } - consume(); - break; - } else { - backup(mark); - return 0; // i.e. KnR C won't have int f(char) char x; {} - } - } - - // if the next token is a tSEMI then the declaration was a regular - // declaration statement i.e. int f(type_def); - final int lt1= LT(1); - if (lt1 == IToken.tSEMI || lt1 == IToken.tLBRACE) { - backup(mark); - return 0; - } - - // look ahead for the start of the function body, if end of file is - // found then return 0 parameters found (implies not KnR C) - int previous=-1; - while (LT(1) != IToken.tLBRACE) { - // fix for 100104: check if the parameter declaration is a valid one - try { - simpleDeclaration(DeclarationOptions.LOCAL); + translationUnit = null; + } + + private int countKnRCParms() { + IToken mark = null; + int parmCount = 0; + boolean previousWasIdentifier = false; + + try { + mark = mark(); + + // starts at the beginning of the parameter list + for (;;) { + if (LT(1) == IToken.tCOMMA) { + consume(); + previousWasIdentifier = false; + } else if (LT(1) == IToken.tIDENTIFIER) { + consume(); + if (previousWasIdentifier) { + backup(mark); + return 0; // i.e. KnR C won't have int f(typedef x) + // char + // x; {} + } + previousWasIdentifier = true; + parmCount++; + } else if (LT(1) == IToken.tRPAREN) { + if (!previousWasIdentifier) { + // if the first token encountered is tRPAREN then it's not K&R C + // the first token when counting K&R C parms is always an identifier + backup(mark); + return 0; + } + consume(); + break; + } else { + backup(mark); + return 0; // i.e. KnR C won't have int f(char) char x; {} + } + } + + // if the next token is a tSEMI then the declaration was a regular + // declaration statement i.e. int f(type_def); + final int lt1 = LT(1); + if (lt1 == IToken.tSEMI || lt1 == IToken.tLBRACE) { + backup(mark); + return 0; + } + + // look ahead for the start of the function body, if end of file is + // found then return 0 parameters found (implies not KnR C) + int previous = -1; + while (LT(1) != IToken.tLBRACE) { + // fix for 100104: check if the parameter declaration is a valid one + try { + simpleDeclaration(DeclarationOptions.LOCAL); } catch (BacktrackException e) { backup(mark); return 0; } - final IToken t = LA(1); - if (t.getType() == IToken.tEOC) - break; - - final int next = t.hashCode(); - if (next == previous) { // infinite loop detected - break; - } - previous = next; - } - - backup(mark); - return parmCount; - } catch (EndOfFileException eof) { - if (mark != null) - backup(mark); - - return 0; - } - } - - private IASTProblemDeclaration createKnRCProblemDeclaration(int offset, int length) throws EndOfFileException { - IASTProblem p = createProblem(IProblem.SYNTAX_ERROR, offset, length); - IASTProblemDeclaration pd = getNodeFactory().newProblemDeclaration(p); - ((ASTNode) pd).setOffsetAndLength((ASTNode) p); - - // consume until LBRACE is found (to leave off at the function body and - // continue from there) - IToken previous=null; - IToken next=null; - while (LT(1) != IToken.tLBRACE) { - next = consume(); - if (next == previous || next.getType() == IToken.tEOC) { // infinite loop detected - break; - } - previous = next; - } - - return pd; - } - - @Override + final IToken t = LA(1); + if (t.getType() == IToken.tEOC) + break; + + final int next = t.hashCode(); + if (next == previous) { // infinite loop detected + break; + } + previous = next; + } + + backup(mark); + return parmCount; + } catch (EndOfFileException eof) { + if (mark != null) + backup(mark); + + return 0; + } + } + + private IASTProblemDeclaration createKnRCProblemDeclaration(int offset, int length) throws EndOfFileException { + IASTProblem p = createProblem(IProblem.SYNTAX_ERROR, offset, length); + IASTProblemDeclaration pd = getNodeFactory().newProblemDeclaration(p); + ((ASTNode) pd).setOffsetAndLength((ASTNode) p); + + // consume until LBRACE is found (to leave off at the function body and + // continue from there) + IToken previous = null; + IToken next = null; + while (LT(1) != IToken.tLBRACE) { + next = consume(); + if (next == previous || next.getType() == IToken.tEOC) { // infinite loop detected + break; + } + previous = next; + } + + return pd; + } + + @Override protected ASTVisitor createAmbiguityNodeVisitor() { - return new CASTAmbiguityResolver(); - } + return new CASTAmbiguityResolver(); + } - @Override + @Override protected IASTAmbiguousStatement createAmbiguousStatement() { - return new CASTAmbiguousStatement(); - } + return new CASTAmbiguousStatement(); + } - @Override + @Override protected IASTAmbiguousExpression createAmbiguousExpression() { - return new CASTAmbiguousExpression(); - } + return new CASTAmbiguousExpression(); + } @Override - protected IASTAmbiguousExpression createAmbiguousBinaryVsCastExpression(IASTBinaryExpression binary, IASTCastExpression castExpr) { + protected IASTAmbiguousExpression createAmbiguousBinaryVsCastExpression(IASTBinaryExpression binary, + IASTCastExpression castExpr) { return new CASTAmbiguousBinaryVsCastExpression(binary, castExpr); } @Override - protected IASTAmbiguousExpression createAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpr, IASTFunctionCallExpression funcCall) { + protected IASTAmbiguousExpression createAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpr, + IASTFunctionCallExpression funcCall) { return new CASTAmbiguousCastVsFunctionCallExpression(castExpr, funcCall); } - protected IASTStatement parseIfStatement() throws EndOfFileException, BacktrackException { - IASTIfStatement result = null; - IASTIfStatement if_statement = null; - int start = LA(1).getOffset(); - if_loop: while (true) { - int so = consume(IToken.t_if).getOffset(); - consume(IToken.tLPAREN); - // condition - IASTExpression condition= condition(true); - if (LT(1) == IToken.tEOC) { - // Completing in the condition - IASTIfStatement new_if = getNodeFactory().newIfStatement(condition, null, null); - - if (if_statement != null) { - if_statement.setElseClause(new_if); - } - return result != null ? result : new_if; - } - consume(IToken.tRPAREN); - - IASTStatement thenClause = statement(); - IASTIfStatement new_if_statement = getNodeFactory().newIfStatement(null, null, null); - ((ASTNode) new_if_statement).setOffset(so); - if (condition != null) // shouldn't be possible but failure in condition() makes it so - { - new_if_statement.setConditionExpression(condition); - } - if (thenClause != null) { - new_if_statement.setThenClause(thenClause); - ((ASTNode) new_if_statement).setLength(calculateEndOffset(thenClause) - - ((ASTNode) new_if_statement).getOffset()); - } - if (LT(1) == IToken.t_else) { - consume(); - if (LT(1) == IToken.t_if) { - // an else if, don't recurse, just loop and do another if - - if (if_statement != null) { - if_statement.setElseClause(new_if_statement); - ((ASTNode) if_statement).setLength(calculateEndOffset(new_if_statement) - - ((ASTNode) if_statement).getOffset()); - } - if (result == null && if_statement != null) - result = if_statement; - if (result == null) - result = new_if_statement; - - if_statement = new_if_statement; - continue if_loop; - } - IASTStatement elseStatement = statement(); - new_if_statement.setElseClause(elseStatement); - if (if_statement != null) { - if_statement.setElseClause(new_if_statement); - ((ASTNode) if_statement).setLength(calculateEndOffset(new_if_statement) - - ((ASTNode) if_statement).getOffset()); - } else { - if (result == null) - result = new_if_statement; - if_statement = new_if_statement; - } - } else { - if (thenClause != null) - ((ASTNode) new_if_statement).setLength(calculateEndOffset(thenClause) - start); - if (if_statement != null) { - if_statement.setElseClause(new_if_statement); - ((ASTNode) new_if_statement).setLength(calculateEndOffset(new_if_statement) - start); - } - if (result == null && if_statement != null) - result = if_statement; - if (result == null) - result = new_if_statement; - - if_statement = new_if_statement; - } - break if_loop; - } - - reconcileLengths(result); - return result; - } - - - protected IASTStatement parseSwitchStatement() throws EndOfFileException, BacktrackException { - int startOffset; - startOffset = consume().getOffset(); - consume(IToken.tLPAREN); - IASTExpression switch_condition = condition(true); - switch (LT(1)) { - case IToken.tRPAREN: - consume(); - break; - case IToken.tEOC: - break; - default: - throwBacktrack(LA(1)); - } - - IASTStatement switch_body = parseSwitchBody(); - IASTSwitchStatement switch_statement = getNodeFactory().newSwitchStatement(switch_condition, switch_body); - ((ASTNode) switch_statement).setOffsetAndLength(startOffset, - (switch_body != null ? calculateEndOffset(switch_body) : LA(1).getEndOffset()) - startOffset); - return switch_statement; - } - - protected IASTStatement parseForStatement() throws EndOfFileException, BacktrackException { - int startOffset; - startOffset = consume().getOffset(); - consume(IToken.tLPAREN); - IASTStatement init = initStatement(); - IASTExpression for_condition = null; - switch (LT(1)) { - case IToken.tSEMI: - case IToken.tEOC: - break; - default: - for_condition = condition(false); - } - switch (LT(1)) { - case IToken.tSEMI: - consume(); - break; - case IToken.tEOC: - break; - default: - throw backtrack; - } - IASTExpression iterationExpression = null; - switch (LT(1)) { - case IToken.tRPAREN: - case IToken.tEOC: - break; - default: - iterationExpression = expression(); - } - switch (LT(1)) { - case IToken.tRPAREN: - consume(); - break; - case IToken.tEOC: - break; - default: - throw backtrack; - } - - IASTForStatement for_statement = getNodeFactory().newForStatement(init, for_condition, iterationExpression, null); - if (LT(1) != IToken.tEOC) { - IASTStatement for_body = statement(); - ((ASTNode) for_statement).setOffsetAndLength(startOffset, calculateEndOffset(for_body) - startOffset); - for_statement.setBody(for_body); - } - return for_statement; - } + protected IASTStatement parseIfStatement() throws EndOfFileException, BacktrackException { + IASTIfStatement result = null; + IASTIfStatement if_statement = null; + int start = LA(1).getOffset(); + if_loop: while (true) { + int so = consume(IToken.t_if).getOffset(); + consume(IToken.tLPAREN); + // condition + IASTExpression condition = condition(true); + if (LT(1) == IToken.tEOC) { + // Completing in the condition + IASTIfStatement new_if = getNodeFactory().newIfStatement(condition, null, null); + + if (if_statement != null) { + if_statement.setElseClause(new_if); + } + return result != null ? result : new_if; + } + consume(IToken.tRPAREN); + + IASTStatement thenClause = statement(); + IASTIfStatement new_if_statement = getNodeFactory().newIfStatement(null, null, null); + ((ASTNode) new_if_statement).setOffset(so); + if (condition != null) // shouldn't be possible but failure in condition() makes it so + { + new_if_statement.setConditionExpression(condition); + } + if (thenClause != null) { + new_if_statement.setThenClause(thenClause); + ((ASTNode) new_if_statement) + .setLength(calculateEndOffset(thenClause) - ((ASTNode) new_if_statement).getOffset()); + } + if (LT(1) == IToken.t_else) { + consume(); + if (LT(1) == IToken.t_if) { + // an else if, don't recurse, just loop and do another if + + if (if_statement != null) { + if_statement.setElseClause(new_if_statement); + ((ASTNode) if_statement) + .setLength(calculateEndOffset(new_if_statement) - ((ASTNode) if_statement).getOffset()); + } + if (result == null && if_statement != null) + result = if_statement; + if (result == null) + result = new_if_statement; + + if_statement = new_if_statement; + continue if_loop; + } + IASTStatement elseStatement = statement(); + new_if_statement.setElseClause(elseStatement); + if (if_statement != null) { + if_statement.setElseClause(new_if_statement); + ((ASTNode) if_statement) + .setLength(calculateEndOffset(new_if_statement) - ((ASTNode) if_statement).getOffset()); + } else { + if (result == null) + result = new_if_statement; + if_statement = new_if_statement; + } + } else { + if (thenClause != null) + ((ASTNode) new_if_statement).setLength(calculateEndOffset(thenClause) - start); + if (if_statement != null) { + if_statement.setElseClause(new_if_statement); + ((ASTNode) new_if_statement).setLength(calculateEndOffset(new_if_statement) - start); + } + if (result == null && if_statement != null) + result = if_statement; + if (result == null) + result = new_if_statement; + + if_statement = new_if_statement; + } + break if_loop; + } + + reconcileLengths(result); + return result; + } + + protected IASTStatement parseSwitchStatement() throws EndOfFileException, BacktrackException { + int startOffset; + startOffset = consume().getOffset(); + consume(IToken.tLPAREN); + IASTExpression switch_condition = condition(true); + switch (LT(1)) { + case IToken.tRPAREN: + consume(); + break; + case IToken.tEOC: + break; + default: + throwBacktrack(LA(1)); + } + + IASTStatement switch_body = parseSwitchBody(); + IASTSwitchStatement switch_statement = getNodeFactory().newSwitchStatement(switch_condition, switch_body); + ((ASTNode) switch_statement).setOffsetAndLength(startOffset, + (switch_body != null ? calculateEndOffset(switch_body) : LA(1).getEndOffset()) - startOffset); + return switch_statement; + } + + protected IASTStatement parseForStatement() throws EndOfFileException, BacktrackException { + int startOffset; + startOffset = consume().getOffset(); + consume(IToken.tLPAREN); + IASTStatement init = initStatement(); + IASTExpression for_condition = null; + switch (LT(1)) { + case IToken.tSEMI: + case IToken.tEOC: + break; + default: + for_condition = condition(false); + } + switch (LT(1)) { + case IToken.tSEMI: + consume(); + break; + case IToken.tEOC: + break; + default: + throw backtrack; + } + IASTExpression iterationExpression = null; + switch (LT(1)) { + case IToken.tRPAREN: + case IToken.tEOC: + break; + default: + iterationExpression = expression(); + } + switch (LT(1)) { + case IToken.tRPAREN: + consume(); + break; + case IToken.tEOC: + break; + default: + throw backtrack; + } + + IASTForStatement for_statement = getNodeFactory().newForStatement(init, for_condition, iterationExpression, + null); + if (LT(1) != IToken.tEOC) { + IASTStatement for_body = statement(); + ((ASTNode) for_statement).setOffsetAndLength(startOffset, calculateEndOffset(for_body) - startOffset); + for_statement.setBody(for_body); + } + return for_statement; + } @Override - protected IASTExpression expressionWithOptionalTrailingEllipsis() throws BacktrackException, - EndOfFileException { + protected IASTExpression expressionWithOptionalTrailingEllipsis() throws BacktrackException, EndOfFileException { // No pack expansions in C. return expression(); } |