diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 19847fb3245..3e9246f1efa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -1045,77 +1045,101 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { /** * @param flags * input flags that are used to make our decision - * @return whether or not this looks like a a declarator follows + * @throws FoundDeclaratorException * @throws * @throws EndOfFileException * we could encounter EOF while looking ahead */ - protected boolean lookAheadForDeclarator(Flags flags) { + protected void lookAheadForDeclarator(Flags flags) throws FoundDeclaratorException { if (flags.typeId) - return false; + return; IToken mark = null; try { mark = mark(); } catch (EndOfFileException eof) { - return false; + return; + } + try + { + if( LT(1) == IToken.tIDENTIFIER && LT(2) == IToken.tIDENTIFIER ) + return; + } + catch( EndOfFileException eof ) + { + backup( mark ); + return; } try { IASTDeclarator d = initDeclarator(); IToken la = LA(1); backup(mark); if (la == null || la.getType() == IToken.tEOC) - return false; + return; final ASTNode n = ((ASTNode) d); final int length = n.getLength(); final int offset = n.getOffset(); if (length == 0) - return false; + return; if (flags.parm) { ASTNode name = (ASTNode) d.getName(); if (name.getOffset() == offset && name.getLength() == length) - return false; + return; if (d.getInitializer() != null) { ASTNode init = (ASTNode) d.getInitializer(); if (name.getOffset() == offset && n.getOffset() + n.getLength() == init .getOffset() + init.getLength()) - return false; + return; } switch (la.getType()) { case IToken.tCOMMA: case IToken.tRPAREN: - return true; + throw new FoundDeclaratorException( d, la ); default: - return false; + return; } } - return checkTokenVsDeclarator(la, d); + checkTokenVsDeclarator(la, d); + return; } catch (BacktrackException bte) { backup(mark); - return false; + return; } catch (EndOfFileException e) { backup(mark); - return false; + return; } } - protected boolean checkTokenVsDeclarator(IToken la, IASTDeclarator d) { + protected void checkTokenVsDeclarator(IToken la, IASTDeclarator d) throws FoundDeclaratorException { switch (la.getType()) { case IToken.tCOMMA: case IToken.tLBRACE: - return true; + throw new FoundDeclaratorException( d, la ); case IToken.tSEMI: if (d instanceof IASTFieldDeclarator) - return false; - return true; + return; + throw new FoundDeclaratorException( d, la ); default: - return false; + return; } } + public static class FoundDeclaratorException extends Exception + { + public final IASTDeclarator declarator; + public final IToken currToken; + public IASTDeclSpecifier declSpec; + + public FoundDeclaratorException( IASTDeclarator d, IToken t ) + { + this.declarator = d; + this.currToken =t; + } + } + public static class Flags { private boolean encounteredTypename = false; 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 d9a387655cc..363c82a4a9b 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 @@ -440,11 +440,22 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { firstToken = null; // necessary for scalability - IASTDeclSpecifier declSpec = declSpecifierSeq(false, false); - + IASTDeclSpecifier declSpec; IASTDeclarator [] declarators = new IASTDeclarator[2]; + boolean skipAhead = false; + try { + declSpec = declSpecifierSeq(false, false); + } catch (FoundDeclaratorException e) { + skipAhead = true; + declSpec = e.declSpec; + declarators = (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, e.declarator ); + backup( e.currToken ); + } + + if (LT(1) != IToken.tSEMI) { - declarators = (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, initDeclarator()); + if( ! skipAhead ) + declarators = (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, initDeclarator()); while (LT(1) == IToken.tCOMMA) { consume(IToken.tCOMMA); @@ -1211,7 +1222,12 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { IASTDeclarator declarator = null; try { - declSpecifier = declSpecifierSeq(false, true); + try + { + declSpecifier = declSpecifierSeq(false, true); + } catch (FoundDeclaratorException e) { + throwBacktrack( e.currToken ); + } declarator = declarator(); } catch (BacktrackException bt) { backup(mark); @@ -1313,7 +1329,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } protected IASTDeclSpecifier declSpecifierSeq(boolean parm, boolean forTypeId) - throws BacktrackException, EndOfFileException { + throws BacktrackException, EndOfFileException, FoundDeclaratorException { Flags flags = new Flags(parm,forTypeId); int startingOffset = LA(1).getOffset(); @@ -1447,10 +1463,43 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { if (flags.haveEncounteredTypename()) { break declSpecifiers; } - if (lookAheadForDeclarator(flags)) { - break declSpecifiers; - } + + try { + lookAheadForDeclarator(flags); + } catch (FoundDeclaratorException e) { + ICASTSimpleDeclSpecifier declSpec = null; + if (typeofExpression != null) { + declSpec = createGCCSimpleTypeSpecifier(); + ((IGCCASTSimpleDeclSpecifier) declSpec) + .setTypeofExpression(typeofExpression); + typeofExpression.setParent(declSpec); + typeofExpression + .setPropertyInParent(IGCCASTSimpleDeclSpecifier.TYPEOF_EXPRESSION); + } else { + declSpec = createSimpleTypeSpecifier(); + } + + declSpec.setConst(isConst); + declSpec.setRestrict(isRestrict); + declSpec.setVolatile(isVolatile); + declSpec.setInline(isInline); + declSpec.setStorageClass(storageClass); + declSpec.setType(simpleType); + declSpec.setLong(isLong); + declSpec.setLongLong(isLongLong); + declSpec.setUnsigned(isUnsigned); + declSpec.setSigned(isSigned); + declSpec.setShort(isShort); + if( typeofExpression != null && last == null ){ + ((ASTNode)declSpec).setOffsetAndLength( (ASTNode)typeofExpression ); + } else { + ((ASTNode) declSpec).setOffsetAndLength(startingOffset, + (last != null) ? last.getEndOffset() - startingOffset : 0); + } + e.declSpec = declSpec; + throw e; + } identifier = identifier(); last = identifier; isIdentifier = true; @@ -1746,20 +1795,15 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { BacktrackException { IASTDeclarator d = declarator(); - try { - // astFactory.constructExpressions(constructInitializers); - IASTInitializer i = optionalCInitializer(); - if (i != null) { - d.setInitializer(i); - i.setParent(d); - i.setPropertyInParent(IASTDeclarator.INITIALIZER); + IASTInitializer i = optionalCInitializer(); + if (i != null) { + d.setInitializer(i); + i.setParent(d); + i.setPropertyInParent(IASTDeclarator.INITIALIZER); ((ASTNode) d).setLength(calculateEndOffset(i) - ((ASTNode) d).getOffset()); - } - return d; - } finally { - // astFactory.constructExpressions(true); } + return d; } protected IASTDeclarator declarator() throws EndOfFileException, @@ -2179,7 +2223,16 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { throws BacktrackException, EndOfFileException { IToken current = LA(1); int startingOffset = current.getOffset(); - IASTDeclSpecifier declSpec = declSpecifierSeq(true, false); + + IASTDeclSpecifier declSpec = null; + try + { + declSpec = declSpecifierSeq(true, false); + } + catch( FoundDeclaratorException fd ) + { + declSpec = fd.declSpec; + } IASTDeclarator declarator = null; if (LT(1) != IToken.tSEMI) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index e057f4f03da..aecf6b8e76f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -944,7 +944,12 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { IASTDeclarator declarator = null; try { - declSpecifier = declSpecifierSeq(true, true); + try { + declSpecifier = declSpecifierSeq(true, true); + } + catch (FoundDeclaratorException e) { + throwBacktrack( mark ); + } if (LT(1) != IToken.tEOC) declarator = declarator(SimpleDeclarationStrategy.TRY_FUNCTION, forNewExpression); @@ -2821,12 +2826,25 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { throwBacktrack(firstOffset, firstToken.getLength()); firstToken = null; // necessary for scalability - ICPPASTDeclSpecifier declSpec = declSpecifierSeq(false, false); + IASTDeclSpecifier declSpec; IASTDeclarator[] declarators = new IASTDeclarator[2]; - if (LT(1) != IToken.tSEMI && LT(1) != IToken.tEOC) { + boolean tryAgain = false; + try { + declSpec = declSpecifierSeq(false, false); + } catch (FoundDeclaratorException e) { + tryAgain = true; + declSpec = e.declSpec; declarators = (IASTDeclarator[]) ArrayUtil - .append(IASTDeclarator.class, declarators, - initDeclarator(strategy)); + .append(IASTDeclarator.class, declarators, + e.declarator); + backup( e.currToken ); + } + + if (LT(1) != IToken.tSEMI && LT(1) != IToken.tEOC) { + if( !tryAgain ) + declarators = (IASTDeclarator[]) ArrayUtil + .append(IASTDeclarator.class, declarators, + initDeclarator(strategy)); while (LT(1) == IToken.tCOMMA) { consume(IToken.tCOMMA); declarators = (IASTDeclarator[]) ArrayUtil.append( @@ -3085,7 +3103,12 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { protected ICPPASTParameterDeclaration parameterDeclaration() throws BacktrackException, EndOfFileException { IToken current = LA(1); - IASTDeclSpecifier declSpec = declSpecifierSeq(true, false); + IASTDeclSpecifier declSpec = null; + try { + declSpec = declSpecifierSeq(true, false); + } catch (FoundDeclaratorException e) { + throwBacktrack( e.currToken ); + } IASTDeclarator declarator = null; if (LT(1) != IToken.tSEMI) declarator = initDeclarator(SimpleDeclarationStrategy.TRY_FUNCTION); @@ -3135,9 +3158,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * @return TODO * @throws BacktrackException * request a backtrack + * @throws FoundDeclaratorException */ protected ICPPASTDeclSpecifier declSpecifierSeq(boolean parm, - boolean forTypeId) throws BacktrackException, EndOfFileException { + boolean forTypeId) throws BacktrackException, EndOfFileException, FoundDeclaratorException { IToken firstToken = LA(1); Flags flags = new Flags(parm, false, forTypeId); IToken last = null; @@ -3307,8 +3331,54 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (flags.haveEncounteredTypename()) break declSpecifiers; - if (lookAheadForDeclarator(flags)) - break declSpecifiers; + try + { + lookAheadForDeclarator(flags); + } + catch( FoundDeclaratorException fde ) + { + ICPPASTSimpleDeclSpecifier simpleDeclSpec = null; + if (isLongLong || typeofExpression != null) { + simpleDeclSpec = createGPPSimpleDeclSpecifier(); + ((IGPPASTSimpleDeclSpecifier) simpleDeclSpec) + .setLongLong(isLongLong); + if (typeofExpression != null) { + ((IGPPASTSimpleDeclSpecifier) simpleDeclSpec) + .setTypeofExpression(typeofExpression); + typeofExpression.setParent(simpleDeclSpec); + typeofExpression + .setPropertyInParent(IGPPASTSimpleDeclSpecifier.TYPEOF_EXPRESSION); + } + } else + simpleDeclSpec = createSimpleDeclSpecifier(); + + if( last == null && typeofExpression != null ){ + ((ASTNode) simpleDeclSpec).setOffsetAndLength((ASTNode) typeofExpression); + } else { + int l = last != null ? last.getEndOffset() - firstToken.getOffset() : 0; + ((ASTNode) simpleDeclSpec) + .setOffsetAndLength(firstToken.getOffset(), l); + } + simpleDeclSpec.setConst(isConst); + simpleDeclSpec.setVolatile(isVolatile); + if (simpleDeclSpec instanceof IGPPASTDeclSpecifier) + ((IGPPASTDeclSpecifier) simpleDeclSpec).setRestrict(isRestrict); + + simpleDeclSpec.setFriend(isFriend); + simpleDeclSpec.setInline(isInline); + simpleDeclSpec.setStorageClass(storageClass); + simpleDeclSpec.setVirtual(isVirtual); + simpleDeclSpec.setExplicit(isExplicit); + + simpleDeclSpec.setType(simpleType); + simpleDeclSpec.setLong(isLong); + simpleDeclSpec.setShort(isShort); + simpleDeclSpec.setUnsigned(isUnsigned); + simpleDeclSpec.setSigned(isSigned); + fde.declSpec = simpleDeclSpec; + throw fde; + + } duple = name(); last = duple.getLastToken(); @@ -3561,7 +3631,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { ((ASTNode) d).setLength(calculateEndOffset(initializer) - ((ASTNode) d).getOffset()); } - return d; } @@ -3745,34 +3814,39 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { for (;;) { switch (LT(1)) { case IToken.tLPAREN: + IToken markityMark = mark(); + boolean success = false; + try + { + consume( IToken.tLPAREN ); + expression(); + consume( IToken.tRPAREN ); + success = true; + backup( markityMark ); + } + catch( BacktrackException bte ) + { + backup( markityMark ); + } + catch( EndOfFileException eof ) + { + backup( markityMark ); + } + if( success ) + { + switch( LT(1) ) + { + case IToken.tSEMI: + case IToken.tCOMMA: + break overallLoop; + } + } - // boolean failed = false; - // - // // temporary fix for initializer/function declaration - // // ambiguity - // if (!LA(2).looksLikeExpression() - // && strategy != SimpleDeclarationStrategy.TRY_VARIABLE) { - // if (LT(2) == IToken.tIDENTIFIER) { - // IToken newMark = mark(); - // consume(IToken.tLPAREN); - // try { - // name(); - // // TODO - we need to lookup/resolve this name - // // see if its a type ... - // // if it is a type, failed = false - // // else failed = true - // failed = false; - // } catch (BacktrackException b) { - // failed = true; - // } - // - // backup(newMark); - // } - // } - if ((!LA(2).looksLikeExpression() - && strategy != SimpleDeclarationStrategy.TRY_VARIABLE - // && !failed - && !forNewTypeId)) { + if( strategy == SimpleDeclarationStrategy.TRY_VARIABLE ) + break overallLoop; + + + if (!LA(2).looksLikeExpression()&& !forNewTypeId) { // parameterDeclarationClause isFunction = true; // TODO need to create a temporary scope object here @@ -5239,13 +5313,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return result; } - protected boolean checkTokenVsDeclarator(IToken la, IASTDeclarator d) { + protected void checkTokenVsDeclarator(IToken la, IASTDeclarator d) throws FoundDeclaratorException { switch (la.getType()) { case IToken.tCOLON: case IToken.t_try: - return true; + throw new FoundDeclaratorException( d, la ); default: - return super.checkTokenVsDeclarator(la, d); + super.checkTokenVsDeclarator(la, d); } }