Skip to content

Commit

Permalink
CPPSourceParser
Browse files Browse the repository at this point in the history
  • Loading branch information
TheShermanTanker committed Feb 19, 2023
1 parent 7200ad3 commit 7833735
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationListOwner;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
Expand All @@ -30,7 +29,6 @@
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
Expand All @@ -40,15 +38,13 @@
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNullStatement;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
Expand Down Expand Up @@ -84,8 +80,6 @@ public abstract class AbstractSourceCodeParser implements ISourceCodeParser {
protected final INodeFactory nodeFactory;
protected final IBuiltinBindingsProvider builtinBindingsProvider;

protected boolean lvalueCanBeCall = false;

protected boolean passing = true;
protected boolean cancelled = false;
protected IToken declarationMark;
Expand Down Expand Up @@ -204,6 +198,9 @@ protected abstract IASTAmbiguousExpression createAmbiguousCastVsMethodCallExpres

protected abstract IASTTypeId typeID(DeclarationOptions option) throws EndOfFileException, BacktrackException;

protected abstract IASTStatement parseDeclarationOrExpressionStatement(
List<IASTAttributeSpecifier> attributeSpecifiers) throws EndOfFileException, BacktrackException;

// Methods for parsing a type-id and an expression with an optional trailing ellipsis.
// The optional trailing ellipsis can only appear in C++ code, and only the C++ parser
// allows it, but being able to invoke this from here allows reusing more productions
Expand Down Expand Up @@ -899,109 +896,6 @@ protected IASTStatement parseDeclarationOrExpressionStatement() throws EndOfFile
return parseDeclarationOrExpressionStatement(null);
}

protected IASTStatement parseDeclarationOrExpressionStatement(List<IASTAttributeSpecifier> attributeSpecifiers)
throws EndOfFileException, BacktrackException {
// First attempt to parse an expressionStatement
// Note: the method style cast ambiguity is handled in expression
// Since it only happens when we are in a statement
IToken mark = mark();
IASTExpressionStatement expressionStatement = null;
IToken afterExpression = null;
boolean foundSemicolon = false;
try {
IASTExpression expression = expression();
expressionStatement = nodeFactory.newExpressionStatement(expression);
addAttributeSpecifiers(attributeSpecifiers, expressionStatement);
setRange(expressionStatement, expression);
afterExpression = lookahead();

IToken semi = consumeOrEndOfCompletion(IToken.tSEMI);
foundSemicolon = true;
adjustEndOffset(expressionStatement, semi.getEndOffset());
afterExpression = lookahead();
} catch (BacktrackException b) {
}

backup(mark);

// Now attempt to parse a declarationStatement
IASTDeclarationStatement declarationStatement = null;
try {
IASTDeclaration d = declaration(DeclarationOptions.LOCAL);
if (d instanceof IASTAttributeOwner) {
addAttributeSpecifiers(attributeSpecifiers, (IASTAttributeOwner) d);
}
declarationStatement = nodeFactory.newDeclarationStatement(d);
setRange(declarationStatement, d);
} catch (BacktrackException exception) {
IASTNode node = exception.getNodeBeforeProblem();
final boolean isProblemDecl = node instanceof IASTDeclaration;
if (expressionStatement == null
|| (!foundSemicolon && isProblemDecl && node.contains(expressionStatement))) {
if (isProblemDecl) {
declarationStatement = nodeFactory.newDeclarationStatement((IASTDeclaration) node);
exception.initialize(exception.getProblem(), setRange(declarationStatement, node));
}
throw exception;
}
}

if (declarationStatement == null) {
backup(afterExpression);
if (foundSemicolon)
return expressionStatement;

throwBacktrack(createProblem(IProblem.MISSING_SEMICOLON, calculateEndOffset(expressionStatement) - 1, 1),
expressionStatement);
return null; // Hint for java-compiler
}

if (expressionStatement == null || !foundSemicolon) {
return declarationStatement;
}

// At this point we know we have an ambiguity.
// Attempt to resolve some ambiguities that are easy to detect.

// A * B = C; // A*B cannot be a lvalue.
// foo() = x; // foo() cannot be a lvalue in C, in C++ it can.
if (expressionStatement.getExpression() instanceof IASTBinaryExpression) {
IASTBinaryExpression exp = (IASTBinaryExpression) expressionStatement.getExpression();
if (exp.getOperator() == IASTBinaryExpression.op_assign) {
IASTExpression left = exp.getOperand1();
if (left instanceof IASTBinaryExpression
&& ((IASTBinaryExpression) left).getOperator() == IASTBinaryExpression.op_multiply) {
return declarationStatement;
}
if (left instanceof IASTFunctionCallExpression && !lvalueCanBeCall) {
return declarationStatement;
}
}
}

final IASTDeclaration declaration = declarationStatement.getDeclaration();
if (declaration instanceof IASTSimpleDeclaration) {
final IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) declaration;
IASTDeclSpecifier declspec = simpleDecl.getDeclSpecifier();
if (declspec instanceof IASTNamedTypeSpecifier) {
final IASTDeclarator[] declarators = simpleDecl.getDeclarators();

// x;
// can be parsed as a named declaration specifier without a declarator
if (declarators.length == 0) {
backup(afterExpression);
return expressionStatement;
}
}
}

// create and return ambiguity node
IASTAmbiguousStatement statement = createAmbiguousStatement();
statement.addStatement(expressionStatement);
statement.addStatement(declarationStatement);
return setRange(statement, declarationStatement);
}

protected IASTStatement parseNullStatement() throws EndOfFileException, BacktrackException {
IToken t = consume(); // tSEMI

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTAttributeOwner;
import org.eclipse.cdt.core.dom.ast.IASTAttributeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
Expand All @@ -32,6 +35,7 @@
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
Expand Down Expand Up @@ -240,6 +244,110 @@ protected IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy st
}
}

@Override
protected IASTStatement parseDeclarationOrExpressionStatement(List<IASTAttributeSpecifier> attributeSpecifiers)
throws EndOfFileException, BacktrackException {
// First attempt to parse an expressionStatement
// Note: the method style cast ambiguity is handled in expression
// Since it only happens when we are in a statement
IToken mark = mark();
IASTExpressionStatement expressionStatement = null;
IToken afterExpression = null;
boolean foundSemicolon = false;
try {
IASTExpression expression = expression();
expressionStatement = nodeFactory.newExpressionStatement(expression);
addAttributeSpecifiers(attributeSpecifiers, expressionStatement);
setRange(expressionStatement, expression);
afterExpression = lookahead();

IToken semi = consumeOrEndOfCompletion(IToken.tSEMI);
foundSemicolon = true;
adjustEndOffset(expressionStatement, semi.getEndOffset());
afterExpression = lookahead();
} catch (BacktrackException b) {
}

backup(mark);

// Now attempt to parse a declarationStatement
IASTDeclarationStatement declarationStatement = null;
try {
IASTDeclaration d = declaration(DeclarationOptions.LOCAL);
if (d instanceof IASTAttributeOwner) {
addAttributeSpecifiers(attributeSpecifiers, (IASTAttributeOwner) d);
}
declarationStatement = nodeFactory.newDeclarationStatement(d);
setRange(declarationStatement, d);
} catch (BacktrackException exception) {
IASTNode node = exception.getNodeBeforeProblem();
final boolean isProblemDecl = node instanceof IASTDeclaration;
if (expressionStatement == null
|| (!foundSemicolon && isProblemDecl && node.contains(expressionStatement))) {
if (isProblemDecl) {
declarationStatement = nodeFactory.newDeclarationStatement((IASTDeclaration) node);
exception.initialize(exception.getProblem(), setRange(declarationStatement, node));
}
throw exception;
}
}

if (declarationStatement == null) {
backup(afterExpression);
if (foundSemicolon)
return expressionStatement;

throwBacktrack(createProblem(IProblem.MISSING_SEMICOLON, calculateEndOffset(expressionStatement) - 1, 1),
expressionStatement);
return null; // Hint for java-compiler
}

if (expressionStatement == null || !foundSemicolon) {
return declarationStatement;
}

// At this point we know we have an ambiguity.
// Attempt to resolve some ambiguities that are easy to detect.

// A * B = C; // A*B cannot be a lvalue.
// foo() = x; // foo() cannot be an lvalue in C.
if (expressionStatement.getExpression() instanceof IASTBinaryExpression) {
IASTBinaryExpression exp = (IASTBinaryExpression) expressionStatement.getExpression();
if (exp.getOperator() == IASTBinaryExpression.op_assign) {
IASTExpression left = exp.getOperand1();
if (left instanceof IASTBinaryExpression
&& ((IASTBinaryExpression) left).getOperator() == IASTBinaryExpression.op_multiply) {
return declarationStatement;
}
if (left instanceof IASTFunctionCallExpression) {
return declarationStatement;
}
}
}

final IASTDeclaration declaration = declarationStatement.getDeclaration();
if (declaration instanceof IASTSimpleDeclaration) {
final IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) declaration;
IASTDeclSpecifier declspec = simpleDecl.getDeclSpecifier();
if (declspec instanceof IASTNamedTypeSpecifier) {
final IASTDeclarator[] declarators = simpleDecl.getDeclarators();

// x;
// can be parsed as a named declaration specifier without a declarator
if (declarators.length == 0) {
backup(afterExpression);
return expressionStatement;
}
}
}

// create and return ambiguity node
IASTAmbiguousStatement statement = createAmbiguousStatement();
statement.addStatement(expressionStatement);
statement.addStatement(declarationStatement);
return setRange(statement, declarationStatement);
}

@Override
protected IASTExpression expressionWithOptionalTrailingEllipsis() throws BacktrackException, EndOfFileException {
return expression();
Expand Down
Loading

0 comments on commit 7833735

Please sign in to comment.