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:
parent
bb44d4020d
commit
20a43f994b
1 changed files with 52 additions and 45 deletions
|
@ -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();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue