1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

cleaned up and commented the code in AbstractGNUSourceCodeParser.parseDeclarationOrExpressionStatement()

This commit is contained in:
Mike Kucera 2008-01-31 16:50:44 +00:00
parent bb44d4020d
commit 20a43f994b

View file

@ -1474,16 +1474,15 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected abstract IASTCastExpression createCastExpression(); protected abstract IASTCastExpression createCastExpression();
/** /**
* @return * There are many ambiguities in C and C++ between expressions and declarations.
* @throws EndOfFileException * This method will attempt to parse a statement as both an expression and a declaration,
* @throws BacktrackException * if both parses succeed then an ambiguity node is returned.
*/ */
protected IASTStatement parseDeclarationOrExpressionStatement() protected IASTStatement parseDeclarationOrExpressionStatement() throws EndOfFileException, BacktrackException {
throws EndOfFileException, BacktrackException { // First attempt to parse an expressionStatement
// expressionStatement // Note: the function style cast ambiguity is handled in expression
// Note: the function style cast ambiguity is handled in
// expression
// Since it only happens when we are in a statement // Since it only happens when we are in a statement
IToken mark = mark(); IToken mark = mark();
IASTExpressionStatement expressionStatement = null; IASTExpressionStatement expressionStatement = null;
@ -1497,14 +1496,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
lastTokenOfExpression = consume(IToken.tSEMI); lastTokenOfExpression = consume(IToken.tSEMI);
expressionStatement = createExpressionStatement(); expressionStatement = createExpressionStatement();
expressionStatement.setExpression(expression); expressionStatement.setExpression(expression);
((ASTNode) expressionStatement).setOffsetAndLength( ((ASTNode) expressionStatement).setOffsetAndLength(mark.getOffset(), lastTokenOfExpression.getEndOffset() - mark.getOffset());
mark.getOffset(), lastTokenOfExpression.getEndOffset() - mark.getOffset());
} catch (BacktrackException b) { } catch (BacktrackException b) {
} }
backup(mark); backup(mark);
// declarationStatement // Now attempt to parse a declarationStatement
IASTDeclarationStatement ds = null; IASTDeclarationStatement ds = null;
try { try {
IASTDeclaration d = declaration(); IASTDeclaration d = declaration();
@ -1516,6 +1514,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
backup(mark); backup(mark);
} }
// if not ambiguous then return the appropriate node
if (expressionStatement == null && ds != null) { if (expressionStatement == null && ds != null) {
return ds; return ds;
} }
@ -1526,35 +1525,33 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
} }
return expressionStatement; return expressionStatement;
} }
if (expressionStatement == null && ds == null) if (expressionStatement == null && ds == null)
throwBacktrack(savedBt); throwBacktrack(savedBt);
// resolve ambiguities
// At this point we know we have an ambiguity.
// Attempt to resolve some ambiguities that are easy to detect.
// A * B = C; // A * B = C;
// foo() = x;
// These can get parsed as expressions but the lvalue doesn't make sense
if (expressionStatement.getExpression() instanceof IASTBinaryExpression) { if (expressionStatement.getExpression() instanceof IASTBinaryExpression) {
IASTBinaryExpression exp = (IASTBinaryExpression) expressionStatement.getExpression(); IASTBinaryExpression exp = (IASTBinaryExpression) expressionStatement.getExpression();
if (exp.getOperator() == IASTBinaryExpression.op_assign) { if (exp.getOperator() == IASTBinaryExpression.op_assign) {
IASTExpression lhs = exp.getOperand1(); IASTExpression lhs = exp.getOperand1();
if (lhs instanceof IASTBinaryExpression if (lhs instanceof IASTBinaryExpression
&& ((IASTBinaryExpression) lhs).getOperator() == IASTBinaryExpression.op_multiply) { && ((IASTBinaryExpression) lhs).getOperator() == IASTBinaryExpression.op_multiply) {
return ds; return ds;
} }
if (lhs instanceof IASTFunctionCallExpression) { if (lhs instanceof IASTFunctionCallExpression) {
// lvalue - makes no sense
return ds; return ds;
} }
} }
} }
// x = y; // default to int // x = y; // implicit int
// valid @ Translation Unit scope // valid at Translation Unit scope but not valid as a statement in a function body
// but not valid as a statement in a function body if(isImplicitInt(ds.getDeclaration())) {
if (ds.getDeclaration() instanceof IASTSimpleDeclaration
&& ((IASTSimpleDeclaration) ds.getDeclaration())
.getDeclSpecifier() instanceof IASTSimpleDeclSpecifier
&& ((IASTSimpleDeclSpecifier) ((IASTSimpleDeclaration) ds
.getDeclaration()).getDeclSpecifier()).getType() == IASTSimpleDeclSpecifier.t_unspecified) {
backup(mark); backup(mark);
while (true) { while (true) {
if (consume() == lastTokenOfExpression) if (consume() == lastTokenOfExpression)
@ -1564,39 +1561,31 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
return expressionStatement; return expressionStatement;
} }
if (ds.getDeclaration() instanceof IASTAmbiguousDeclaration ) // generalization of the previous check for implicit int
{ if (ds.getDeclaration() instanceof IASTAmbiguousDeclaration ) {
IASTAmbiguousDeclaration amb = (IASTAmbiguousDeclaration) ds.getDeclaration(); IASTAmbiguousDeclaration amb = (IASTAmbiguousDeclaration) ds.getDeclaration();
IASTDeclaration [] ambDs = amb.getDeclarations(); boolean allImplicitInt = true;
int ambCount = 0; for(IASTDeclaration ambD : amb.getDeclarations()) {
for( int i = 0; i < ambDs.length; ++i ) if(!isImplicitInt(ambD)) {
{ allImplicitInt = false;
if (ambDs[i] instanceof IASTSimpleDeclaration break;
&& ((IASTSimpleDeclaration) ambDs[i]) }
.getDeclSpecifier() instanceof IASTSimpleDeclSpecifier
&& ((IASTSimpleDeclSpecifier) ((IASTSimpleDeclaration) ambDs[i]).getDeclSpecifier()).getType() == IASTSimpleDeclSpecifier.t_unspecified) {
++ambCount;
}
} }
if ( ambCount == ambDs.length ) if(allImplicitInt) {
{
backup(mark); backup(mark);
while (true) { while (true) {
if (consume() == lastTokenOfExpression) if (consume() == lastTokenOfExpression)
break; break;
} }
return expressionStatement; return expressionStatement;
} }
} }
if (ds.getDeclaration() instanceof IASTSimpleDeclaration // x;
&& ((IASTSimpleDeclaration) ds.getDeclaration()) // a single identifier can be parsed as a named declaration specifier without a declarator
.getDeclSpecifier() instanceof IASTNamedTypeSpecifier) if(ds.getDeclaration() instanceof IASTSimpleDeclaration &&
((IASTSimpleDeclaration) ds.getDeclaration()).getDeclSpecifier() instanceof IASTNamedTypeSpecifier) {
{ final IASTDeclarator[] declarators = ((IASTSimpleDeclaration) ds.getDeclaration()).getDeclarators();
final IASTDeclarator[] declarators = ((IASTSimpleDeclaration) ds
.getDeclaration()).getDeclarators();
if (declarators.length == 0 if (declarators.length == 0
|| (declarators.length == 1 && (declarators[0].getName() || (declarators.length == 1 && (declarators[0].getName()
.toCharArray().length == 0 && declarators[0] .toCharArray().length == 0 && declarators[0]
@ -1611,6 +1600,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
} }
} }
// create and return ambiguity node
IASTAmbiguousStatement statement = createAmbiguousStatement(); IASTAmbiguousStatement statement = createAmbiguousStatement();
statement.addStatement(ds); statement.addStatement(ds);
statement.addStatement(expressionStatement); statement.addStatement(expressionStatement);
@ -1618,6 +1608,23 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
return statement; return statement;
} }
/**
* Returns true if the given declaration has unspecified type,
* in this case the type defaults to int and is know as "implicit int".
*/
protected static boolean isImplicitInt(IASTDeclaration declaration) {
if(declaration instanceof IASTSimpleDeclaration) {
IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration)declaration).getDeclSpecifier();
if(declSpec instanceof IASTSimpleDeclSpecifier &&
((IASTSimpleDeclSpecifier)declSpec).getType() == IASTSimpleDeclSpecifier.t_unspecified) {
return true;
}
}
return false;
}
protected abstract IASTAmbiguousStatement createAmbiguousStatement(); protected abstract IASTAmbiguousStatement createAmbiguousStatement();
/** /**