mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Simplification of binary expression parsing, bug 294029.
This commit is contained in:
parent
2b793aaf12
commit
18c73ee0f5
4 changed files with 705 additions and 501 deletions
|
@ -7080,4 +7080,27 @@ public class AST2Tests extends AST2BaseTest {
|
|||
assertEquals(1, ff.getParameters().length);
|
||||
}
|
||||
}
|
||||
|
||||
// void f() {
|
||||
// int a=
|
||||
public void testLargeExpression_294029() throws Exception {
|
||||
// when running the test in a suite, it cannot handle more than 200 parenthesis.
|
||||
// run as a single test it does > 600.
|
||||
sValidateCopy= false;
|
||||
StringBuilder buf= new StringBuilder();
|
||||
buf.append(getAboveComment());
|
||||
final int depth= 200;
|
||||
for (int i = 0; i < depth; i++) {
|
||||
buf.append('(');
|
||||
}
|
||||
buf.append('1');
|
||||
for (int i = 0; i < depth; i++) {
|
||||
buf.append(")+1");
|
||||
}
|
||||
buf.append(";}");
|
||||
String code= buf.toString();
|
||||
for(ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu = parseAndCheckBindings(code, lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.INodeFactory;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
|
||||
import org.eclipse.cdt.core.dom.parser.IBuiltinBindingsProvider;
|
||||
|
@ -176,8 +177,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected IToken declarationMark;
|
||||
protected IToken nextToken;
|
||||
protected IToken lastTokenFromScanner;
|
||||
protected boolean onTopInTemplateArgs= false;
|
||||
protected boolean inBinaryExpression= true;
|
||||
|
||||
protected boolean isCancelled = false;
|
||||
protected boolean parsePassed = true;
|
||||
|
@ -881,69 +880,329 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return expression();
|
||||
}
|
||||
|
||||
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
|
||||
IToken la = LA(1);
|
||||
int startingOffset = la.getOffset();
|
||||
IASTExpression assignmentExpression = assignmentExpression();
|
||||
if (LT(1) != IToken.tCOMMA)
|
||||
return assignmentExpression;
|
||||
/**
|
||||
* Models a cast expression followed by an operator. Can be linked into a chain.
|
||||
* This is done right to left, such that a tree of variants can be built.
|
||||
*/
|
||||
protected static class CastExpressionOp {
|
||||
final CastExpressionOp fLeft;
|
||||
final IASTExpression fExpression;
|
||||
final int fOperatorToken;
|
||||
final int fLeftPrecedence;
|
||||
final int fRightPrecedence;
|
||||
|
||||
IASTExpressionList expressionList = nodeFactory.newExpressionList();
|
||||
((ASTNode) expressionList).setOffset(startingOffset);
|
||||
expressionList.addExpression(assignmentExpression);
|
||||
|
||||
int lastOffset = 0;
|
||||
while (LT(1) == IToken.tCOMMA) {
|
||||
consume();
|
||||
IASTExpression secondExpression = assignmentExpression();
|
||||
expressionList.addExpression(secondExpression);
|
||||
lastOffset = calculateEndOffset(secondExpression);
|
||||
public CastExpressionOp(CastExpressionOp left, IASTExpression expression, int operatorToken, int leftPrecedence, int rightPrecedence) {
|
||||
fLeft= left;
|
||||
fExpression= expression;
|
||||
fOperatorToken= operatorToken;
|
||||
fLeftPrecedence= leftPrecedence;
|
||||
fRightPrecedence= rightPrecedence;
|
||||
}
|
||||
((ASTNode) expressionList).setLength(lastOffset - startingOffset);
|
||||
return expressionList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to temporarily store a sequence of operator followed by expression.
|
||||
*/
|
||||
private static final class OpCastExpressionStack {
|
||||
private IASTExpression fExpressions[]= new IASTExpression[128];
|
||||
private int fPrecedenceAndTokens[]= new int[256];
|
||||
private int fPos=-1;
|
||||
|
||||
protected abstract IASTExpression assignmentExpression()
|
||||
throws BacktrackException, EndOfFileException;
|
||||
boolean isEmpty() {
|
||||
return fPos<0;
|
||||
}
|
||||
|
||||
protected IASTExpression relationalExpression() throws BacktrackException, EndOfFileException {
|
||||
IASTExpression result= shiftExpression();
|
||||
for (;;) {
|
||||
int operator;
|
||||
switch (LT(1)) {
|
||||
public IASTExpression getExpression() {
|
||||
return fExpressions[fPos];
|
||||
}
|
||||
|
||||
public int getLeftPrecedence() {
|
||||
return fPrecedenceAndTokens[2*fPos];
|
||||
}
|
||||
|
||||
public int getOperatorToken() {
|
||||
return fPrecedenceAndTokens[2*fPos+1];
|
||||
}
|
||||
|
||||
public void push(int leftPrecedence, int operatorToken, IASTExpression trailing) {
|
||||
final int pos= ++fPos;
|
||||
if (pos == fExpressions.length) {
|
||||
IASTExpression newExpressions[]= new IASTExpression[pos*2];
|
||||
int newPrecedenceAndTokens[]= new int[pos*4];
|
||||
System.arraycopy(fExpressions, 0, newExpressions, 0, pos);
|
||||
System.arraycopy(fPrecedenceAndTokens, 0, newPrecedenceAndTokens, 0, 2*pos);
|
||||
fExpressions= newExpressions;
|
||||
fPrecedenceAndTokens= newPrecedenceAndTokens;
|
||||
}
|
||||
|
||||
fExpressions[pos]= trailing;
|
||||
fPrecedenceAndTokens[2*pos]= leftPrecedence;
|
||||
fPrecedenceAndTokens[2*pos+1]= operatorToken;
|
||||
}
|
||||
|
||||
public void pop() {
|
||||
--fPos;
|
||||
}
|
||||
}
|
||||
|
||||
protected final IASTExpression buildExpression(CastExpressionOp exprOp1, IASTExpression expr) throws BacktrackException {
|
||||
if (exprOp1 == null)
|
||||
return expr;
|
||||
|
||||
// exprOp1 exprOp2 expr
|
||||
CastExpressionOp exprOp2= exprOp1;
|
||||
exprOp1= exprOp1.fLeft;
|
||||
OpCastExpressionStack stack= null;
|
||||
|
||||
while (exprOp1 != null) {
|
||||
if (exprOp1.fRightPrecedence < exprOp2.fLeftPrecedence) {
|
||||
// (exprOp2 expr) -> expr2
|
||||
expr= buildExpression(exprOp2.fExpression, exprOp2.fOperatorToken, expr, stack);
|
||||
if (stack != null) {
|
||||
while (!stack.isEmpty() && exprOp1.fRightPrecedence < stack.getLeftPrecedence()) {
|
||||
final int opToken= stack.getOperatorToken();
|
||||
final IASTExpression expr2= stack.getExpression();
|
||||
stack.pop();
|
||||
expr= buildExpression(expr, opToken, expr2, stack);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// expr(Op2 expr) -> expr | op2 expr on stack
|
||||
if (stack == null) {
|
||||
stack= new OpCastExpressionStack();
|
||||
}
|
||||
stack.push(exprOp2.fLeftPrecedence, exprOp2.fOperatorToken, expr);
|
||||
expr= exprOp2.fExpression;
|
||||
}
|
||||
exprOp2= exprOp1;
|
||||
exprOp1= exprOp1.fLeft;
|
||||
}
|
||||
|
||||
// (exprOp2 expr) -> expr2
|
||||
expr= buildExpression(exprOp2.fExpression, exprOp2.fOperatorToken, expr, stack);
|
||||
if (stack != null) {
|
||||
while (!stack.isEmpty()) {
|
||||
final int opToken= stack.getOperatorToken();
|
||||
final IASTExpression expr2= stack.getExpression();
|
||||
stack.pop();
|
||||
expr= buildExpression(expr, opToken, expr2, stack);
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
private IASTExpression buildExpression(IASTExpression left, int token, IASTExpression right, OpCastExpressionStack stack) throws BacktrackException {
|
||||
int op, unaryOp=0;
|
||||
switch(token) {
|
||||
case IToken.tQUESTION:
|
||||
if (stack == null || stack.isEmpty() || stack.getOperatorToken() != IToken.tCOLON) {
|
||||
assert false;
|
||||
ASTNode node= (ASTNode) left;
|
||||
throwBacktrack(node.getOffset(), node.getLength());
|
||||
return null; // Will never be reached.
|
||||
}
|
||||
IASTExpression negative= stack.getExpression();
|
||||
stack.pop();
|
||||
IASTConditionalExpression conditionalEx = nodeFactory.newConditionalExpession(left, right, negative);
|
||||
setRange(conditionalEx, left);
|
||||
if (negative != null) {
|
||||
adjustLength(conditionalEx, negative);
|
||||
}
|
||||
return conditionalEx;
|
||||
|
||||
case IToken.tCOMMA:
|
||||
IASTExpressionList list;
|
||||
if (left instanceof IASTExpressionList) {
|
||||
list= (IASTExpressionList) left;
|
||||
} else {
|
||||
list= nodeFactory.newExpressionList();
|
||||
list.addExpression(left);
|
||||
setRange(list, left);
|
||||
}
|
||||
list.addExpression(right);
|
||||
adjustLength(list, right);
|
||||
return list;
|
||||
|
||||
case IToken.tASSIGN:
|
||||
op= IASTBinaryExpression.op_assign;
|
||||
break;
|
||||
case IToken.tSTARASSIGN:
|
||||
op= IASTBinaryExpression.op_multiplyAssign;
|
||||
break;
|
||||
case IToken.tDIVASSIGN:
|
||||
op= IASTBinaryExpression.op_divideAssign;
|
||||
break;
|
||||
case IToken.tMODASSIGN:
|
||||
op= IASTBinaryExpression.op_moduloAssign;
|
||||
break;
|
||||
case IToken.tPLUSASSIGN:
|
||||
op= IASTBinaryExpression.op_plusAssign;
|
||||
break;
|
||||
case IToken.tMINUSASSIGN:
|
||||
op= IASTBinaryExpression.op_minusAssign;
|
||||
break;
|
||||
case IToken.tSHIFTRASSIGN:
|
||||
op= IASTBinaryExpression.op_shiftRightAssign;
|
||||
break;
|
||||
case IToken.tSHIFTLASSIGN:
|
||||
op= IASTBinaryExpression.op_shiftLeftAssign;
|
||||
break;
|
||||
case IToken.tAMPERASSIGN:
|
||||
op= IASTBinaryExpression.op_binaryAndAssign;
|
||||
break;
|
||||
case IToken.tXORASSIGN:
|
||||
op= IASTBinaryExpression.op_binaryXorAssign;
|
||||
break;
|
||||
case IToken.tBITORASSIGN:
|
||||
op= IASTBinaryExpression.op_binaryOrAssign;
|
||||
break;
|
||||
case IToken.tOR:
|
||||
op= IASTBinaryExpression.op_logicalOr;
|
||||
break;
|
||||
case IToken.tAND:
|
||||
op= IASTBinaryExpression.op_logicalAnd;
|
||||
break;
|
||||
case IToken.tBITOR:
|
||||
op= IASTBinaryExpression.op_binaryOr;
|
||||
break;
|
||||
case IToken.tXOR:
|
||||
op= IASTBinaryExpression.op_binaryXor;
|
||||
break;
|
||||
case IToken.tAMPER:
|
||||
op= IASTBinaryExpression.op_binaryAnd;
|
||||
unaryOp= IASTUnaryExpression.op_amper;
|
||||
break;
|
||||
case IToken.tEQUAL:
|
||||
op= IASTBinaryExpression.op_equals;
|
||||
break;
|
||||
case IToken.tNOTEQUAL:
|
||||
op= IASTBinaryExpression.op_notequals;
|
||||
break;
|
||||
case IToken.tGT:
|
||||
if (onTopInTemplateArgs)
|
||||
return result;
|
||||
operator= IASTBinaryExpression.op_greaterThan;
|
||||
op= IASTBinaryExpression.op_greaterThan;
|
||||
break;
|
||||
case IToken.tLT:
|
||||
operator = IASTBinaryExpression.op_lessThan;
|
||||
op= IASTBinaryExpression.op_lessThan;
|
||||
break;
|
||||
case IToken.tLTEQUAL:
|
||||
operator = IASTBinaryExpression.op_lessEqual;
|
||||
op= IASTBinaryExpression.op_lessEqual;
|
||||
break;
|
||||
case IToken.tGTEQUAL:
|
||||
operator = IASTBinaryExpression.op_greaterEqual;
|
||||
op= IASTBinaryExpression.op_greaterEqual;
|
||||
break;
|
||||
case IGCCToken.tMAX:
|
||||
operator = IASTBinaryExpression.op_max;
|
||||
op= IASTBinaryExpression.op_max;
|
||||
break;
|
||||
case IGCCToken.tMIN:
|
||||
operator = IASTBinaryExpression.op_min;
|
||||
op= IASTBinaryExpression.op_min;
|
||||
break;
|
||||
case IToken.tSHIFTL:
|
||||
op= IASTBinaryExpression.op_shiftLeft;
|
||||
break;
|
||||
case IToken.tSHIFTR:
|
||||
op= IASTBinaryExpression.op_shiftRight;
|
||||
break;
|
||||
case IToken.tPLUS:
|
||||
op= IASTBinaryExpression.op_plus;
|
||||
unaryOp= IASTUnaryExpression.op_plus;
|
||||
break;
|
||||
case IToken.tMINUS:
|
||||
op= IASTBinaryExpression.op_minus;
|
||||
unaryOp= IASTUnaryExpression.op_minus;
|
||||
break;
|
||||
case IToken.tSTAR:
|
||||
op= IASTBinaryExpression.op_multiply;
|
||||
unaryOp= IASTUnaryExpression.op_star;
|
||||
break;
|
||||
case IToken.tDIV:
|
||||
op= IASTBinaryExpression.op_divide;
|
||||
break;
|
||||
case IToken.tMOD:
|
||||
op= IASTBinaryExpression.op_modulo;
|
||||
break;
|
||||
case IToken.tDOTSTAR:
|
||||
op = IASTBinaryExpression.op_pmdot;
|
||||
break;
|
||||
case IToken.tARROWSTAR:
|
||||
op = IASTBinaryExpression.op_pmarrow;
|
||||
break;
|
||||
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
consume();
|
||||
IASTExpression rhs= shiftExpression();
|
||||
result = buildBinaryExpression(operator, result, rhs, calculateEndOffset(rhs));
|
||||
}
|
||||
assert false;
|
||||
ASTNode node= (ASTNode) left;
|
||||
throwBacktrack(node.getOffset(), node.getLength());
|
||||
return null;
|
||||
}
|
||||
|
||||
CastAmbiguityMarker lca= null;
|
||||
CastAmbiguityMarker rca= null;
|
||||
if (left instanceof CastAmbiguityMarker) {
|
||||
lca= (CastAmbiguityMarker) left;
|
||||
left= lca.getExpression();
|
||||
assert !(left instanceof CastAmbiguityMarker);
|
||||
}
|
||||
if (right instanceof CastAmbiguityMarker) {
|
||||
rca= (CastAmbiguityMarker) right;
|
||||
right= rca.getExpression();
|
||||
assert !(right instanceof CastAmbiguityMarker);
|
||||
}
|
||||
|
||||
IASTExpression result= buildBinaryExpression(op, left, right, calculateEndOffset(right));
|
||||
|
||||
if (lca != null) {
|
||||
assert unaryOp != 0;
|
||||
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result,
|
||||
lca.getTypeIdForCast(), unaryOp, lca.getUnaryOperatorOffset());
|
||||
}
|
||||
|
||||
return rca == null ? result : rca.updateExpression(result);
|
||||
}
|
||||
|
||||
protected abstract IASTExpression expression() throws BacktrackException, EndOfFileException;
|
||||
protected abstract IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException;
|
||||
protected abstract IASTExpression constantExpression() throws BacktrackException, EndOfFileException;
|
||||
protected abstract IASTExpression unaryExpression(boolean inBinary) throws BacktrackException, EndOfFileException;
|
||||
protected abstract IASTExpression primaryExpression() throws BacktrackException, EndOfFileException;
|
||||
protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException;
|
||||
|
||||
protected IASTExpression castExpression() throws EndOfFileException, BacktrackException {
|
||||
private final static class CastAmbiguityMarker extends ASTNode implements IASTExpression {
|
||||
private IASTExpression fExpression;
|
||||
private final IASTTypeId fTypeIdForCast;
|
||||
private final int fUnaryOperatorOffset;
|
||||
|
||||
CastAmbiguityMarker(IASTExpression unary, IASTTypeId typeIdForCast, int unaryOperatorOffset) {
|
||||
fExpression= unary;
|
||||
fTypeIdForCast= typeIdForCast;
|
||||
fUnaryOperatorOffset= unaryOperatorOffset;
|
||||
}
|
||||
|
||||
public CastAmbiguityMarker updateExpression(IASTExpression expression) {
|
||||
fExpression= expression;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IASTExpression getExpression() {
|
||||
return fExpression;
|
||||
}
|
||||
|
||||
public IASTTypeId getTypeIdForCast() {
|
||||
return fTypeIdForCast;
|
||||
}
|
||||
|
||||
public int getUnaryOperatorOffset() {
|
||||
return fUnaryOperatorOffset;
|
||||
}
|
||||
|
||||
public IASTExpression copy() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public IType getExpressionType() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
protected final IASTExpression castExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException {
|
||||
if (LT(1) == IToken.tLPAREN) {
|
||||
final IToken mark= mark();
|
||||
final int startingOffset= mark.getOffset();
|
||||
|
@ -957,12 +1216,12 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
// ambiguity with unary operator
|
||||
case IToken.tPLUS: case IToken.tMINUS:
|
||||
case IToken.tSTAR: case IToken.tAMPER:
|
||||
final int operatorOffset = LA(1).getOffset();
|
||||
IToken markEnd= mark();
|
||||
backup(mark);
|
||||
try {
|
||||
IASTExpression unary= unaryExpression();
|
||||
fTypeIdForCastAmbiguity= typeId;
|
||||
return unary;
|
||||
IASTExpression unary= unaryExpression(false);
|
||||
return new CastAmbiguityMarker(unary, typeId, operatorOffset);
|
||||
} catch (BacktrackException bt) {
|
||||
backup(markEnd);
|
||||
unaryFailed= true;
|
||||
|
@ -971,25 +1230,30 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
try {
|
||||
boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN;
|
||||
IASTExpression rhs= castExpression();
|
||||
IASTExpression rhs= castExpression(inBinaryExpression);
|
||||
|
||||
CastAmbiguityMarker ca= null;
|
||||
if (rhs instanceof CastAmbiguityMarker) {
|
||||
ca= (CastAmbiguityMarker) rhs;
|
||||
rhs= ca.getExpression();
|
||||
assert !(rhs instanceof CastAmbiguityMarker);
|
||||
}
|
||||
IASTCastExpression result= buildCastExpression(IASTCastExpression.op_cast, typeId, rhs, startingOffset, calculateEndOffset(rhs));
|
||||
if (!unaryFailed && couldBeFunctionCall && rhs instanceof IASTCastExpression == false) {
|
||||
IToken markEnd= mark();
|
||||
final IASTTypeId typeidForCastAmbiguity= fTypeIdForCastAmbiguity;
|
||||
backup(mark);
|
||||
try {
|
||||
IASTExpression expr= primaryExpression();
|
||||
IASTFunctionCallExpression fcall = nodeFactory.newFunctionCallExpression(expr, null);
|
||||
IASTAmbiguousExpression ambiguity = createAmbiguousCastVsFunctionCallExpression(result, fcall);
|
||||
((ASTNode) ambiguity).setOffsetAndLength((ASTNode) result);
|
||||
return ambiguity;
|
||||
return ca == null ? ambiguity : ca.updateExpression(ambiguity);
|
||||
} catch (BacktrackException bt) {
|
||||
} finally {
|
||||
backup(markEnd);
|
||||
fTypeIdForCastAmbiguity= typeidForCastAmbiguity;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return ca == null ? result : ca.updateExpression(result);
|
||||
} catch (BacktrackException b) {
|
||||
if (unaryFailed)
|
||||
throw b;
|
||||
|
@ -997,12 +1261,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
backup(mark);
|
||||
}
|
||||
return unaryExpression();
|
||||
return unaryExpression(inBinaryExpression);
|
||||
}
|
||||
|
||||
protected abstract IASTExpression unaryExpression() throws BacktrackException, EndOfFileException;
|
||||
protected abstract IASTExpression primaryExpression() throws BacktrackException, EndOfFileException;
|
||||
|
||||
protected abstract IASTTranslationUnit getTranslationUnit();
|
||||
|
||||
protected abstract void setupTranslationUnit() throws Exception;
|
||||
|
@ -1109,112 +1370,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
parent.addDeclaration(declaration);
|
||||
}
|
||||
|
||||
protected IASTExpression assignmentOperatorExpression(int kind,
|
||||
IASTExpression lhs) throws EndOfFileException, BacktrackException {
|
||||
consume();
|
||||
IASTExpression rhs = assignmentExpression();
|
||||
return buildBinaryExpression(kind, lhs, rhs, calculateEndOffset(rhs));
|
||||
}
|
||||
|
||||
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
|
||||
return conditionalExpression();
|
||||
}
|
||||
|
||||
protected IASTExpression logicalOrExpression() throws BacktrackException, EndOfFileException {
|
||||
IASTExpression firstExpression = logicalAndExpression();
|
||||
while (LT(1) == IToken.tOR) {
|
||||
if (shallRejectLogicalOperator()) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
|
||||
consume();
|
||||
IASTExpression secondExpression = logicalAndExpression();
|
||||
firstExpression = buildBinaryExpression(
|
||||
IASTBinaryExpression.op_logicalOr, firstExpression,
|
||||
secondExpression, calculateEndOffset(secondExpression));
|
||||
}
|
||||
return firstExpression;
|
||||
}
|
||||
|
||||
protected boolean shallRejectLogicalOperator() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected IASTExpression logicalAndExpression() throws BacktrackException, EndOfFileException {
|
||||
IASTExpression firstExpression = inclusiveOrExpression();
|
||||
while (LT(1) == IToken.tAND) {
|
||||
if (shallRejectLogicalOperator()) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
|
||||
consume();
|
||||
IASTExpression secondExpression = inclusiveOrExpression();
|
||||
firstExpression = buildBinaryExpression(
|
||||
IASTBinaryExpression.op_logicalAnd, firstExpression,
|
||||
secondExpression, calculateEndOffset(secondExpression));
|
||||
}
|
||||
return firstExpression;
|
||||
}
|
||||
|
||||
protected IASTExpression inclusiveOrExpression() throws BacktrackException, EndOfFileException {
|
||||
IASTExpression firstExpression = exclusiveOrExpression();
|
||||
while (LT(1) == IToken.tBITOR) {
|
||||
consume();
|
||||
IASTExpression secondExpression = exclusiveOrExpression();
|
||||
firstExpression = buildBinaryExpression(
|
||||
IASTBinaryExpression.op_binaryOr, firstExpression,
|
||||
secondExpression, calculateEndOffset(secondExpression));
|
||||
}
|
||||
return firstExpression;
|
||||
}
|
||||
|
||||
protected IASTExpression exclusiveOrExpression() throws BacktrackException, EndOfFileException {
|
||||
IASTExpression firstExpression = andExpression();
|
||||
while (LT(1) == IToken.tXOR) {
|
||||
consume();
|
||||
IASTExpression secondExpression = andExpression();
|
||||
firstExpression = buildBinaryExpression(
|
||||
IASTBinaryExpression.op_binaryXor, firstExpression,
|
||||
secondExpression, calculateEndOffset(secondExpression));
|
||||
}
|
||||
return firstExpression;
|
||||
}
|
||||
|
||||
protected IASTExpression andExpression() throws EndOfFileException, BacktrackException {
|
||||
IASTExpression firstExpression = equalityExpression();
|
||||
while (LT(1) == IToken.tAMPER) {
|
||||
final int offset= consume().getOffset();
|
||||
final IASTTypeId typeid= fTypeIdForCastAmbiguity; fTypeIdForCastAmbiguity= null;
|
||||
IASTExpression secondExpression = equalityExpression();
|
||||
firstExpression = buildBinaryExpression(
|
||||
IASTBinaryExpression.op_binaryAnd, firstExpression,
|
||||
secondExpression, calculateEndOffset(secondExpression));
|
||||
if (typeid != null) {
|
||||
firstExpression = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) firstExpression, typeid, IASTUnaryExpression.op_amper, offset);
|
||||
}
|
||||
}
|
||||
return firstExpression;
|
||||
}
|
||||
|
||||
protected IASTExpression equalityExpression() throws EndOfFileException, BacktrackException {
|
||||
IASTExpression firstExpression = relationalExpression();
|
||||
for (;;) {
|
||||
switch (LT(1)) {
|
||||
case IToken.tEQUAL:
|
||||
case IToken.tNOTEQUAL:
|
||||
IToken t = consume();
|
||||
int operator = ((t.getType() == IToken.tEQUAL) ? IASTBinaryExpression.op_equals : IASTBinaryExpression.op_notequals);
|
||||
IASTExpression secondExpression = relationalExpression();
|
||||
firstExpression = buildBinaryExpression(operator,
|
||||
firstExpression, secondExpression,
|
||||
calculateEndOffset(secondExpression));
|
||||
break;
|
||||
default:
|
||||
return firstExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected IASTExpression buildBinaryExpression(int operator, IASTExpression expr1, IASTExpression expr2, int lastOffset) {
|
||||
IASTBinaryExpression result = nodeFactory.newBinaryExpression(operator, expr1, expr2);
|
||||
int o = ((ASTNode) expr1).getOffset();
|
||||
|
@ -1222,84 +1377,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return result;
|
||||
}
|
||||
|
||||
protected IASTExpression shiftExpression() throws BacktrackException, EndOfFileException {
|
||||
IASTExpression firstExpression = additiveExpression();
|
||||
for (;;) {
|
||||
switch (LT(1)) {
|
||||
case IToken.tSHIFTL:
|
||||
case IToken.tSHIFTR:
|
||||
IToken t = consume();
|
||||
int operator = t.getType() == IToken.tSHIFTL ? IASTBinaryExpression.op_shiftLeft : IASTBinaryExpression.op_shiftRight;
|
||||
IASTExpression secondExpression = additiveExpression();
|
||||
firstExpression = buildBinaryExpression(operator,
|
||||
firstExpression, secondExpression,
|
||||
calculateEndOffset(secondExpression));
|
||||
break;
|
||||
default:
|
||||
return firstExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected IASTExpression additiveExpression() throws BacktrackException, EndOfFileException {
|
||||
IASTExpression result= multiplicativeExpression();
|
||||
for (;;) {
|
||||
int operator;
|
||||
int unaryOperator;
|
||||
switch (LT(1)) {
|
||||
case IToken.tPLUS:
|
||||
operator= IASTBinaryExpression.op_plus;
|
||||
unaryOperator= IASTUnaryExpression.op_plus;
|
||||
break;
|
||||
case IToken.tMINUS:
|
||||
operator= IASTBinaryExpression.op_minus;
|
||||
unaryOperator= IASTUnaryExpression.op_minus;
|
||||
break;
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
final int offset= consume().getOffset();
|
||||
final IASTTypeId typeid= fTypeIdForCastAmbiguity; fTypeIdForCastAmbiguity= null;
|
||||
IASTExpression secondExpression = multiplicativeExpression();
|
||||
result = buildBinaryExpression(operator, result, secondExpression, calculateEndOffset(secondExpression));
|
||||
if (typeid != null) {
|
||||
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result, typeid, unaryOperator, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected IASTExpression multiplicativeExpression() throws BacktrackException, EndOfFileException {
|
||||
inBinaryExpression= true;
|
||||
fTypeIdForCastAmbiguity= null;
|
||||
IASTExpression result= pmExpression();
|
||||
for (;;) {
|
||||
int operator;
|
||||
switch (LT(1)) {
|
||||
case IToken.tSTAR:
|
||||
operator = IASTBinaryExpression.op_multiply;
|
||||
break;
|
||||
case IToken.tDIV:
|
||||
operator = IASTBinaryExpression.op_divide;
|
||||
break;
|
||||
case IToken.tMOD:
|
||||
operator = IASTBinaryExpression.op_modulo;
|
||||
break;
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
final int offset= consume().getOffset();
|
||||
final IASTTypeId typeid= fTypeIdForCastAmbiguity; fTypeIdForCastAmbiguity= null;
|
||||
IASTExpression secondExpression= pmExpression();
|
||||
result= buildBinaryExpression(operator, result, secondExpression, calculateEndOffset(secondExpression));
|
||||
if (typeid != null) {
|
||||
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result, typeid, IASTUnaryExpression.op_star, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract IASTExpression pmExpression() throws EndOfFileException, BacktrackException;
|
||||
|
||||
|
||||
private IASTExpression createCastVsBinaryExpressionAmbiguity(IASTBinaryExpression expr, final IASTTypeId typeid, int unaryOperator, int unaryOpOffset) {
|
||||
IASTUnaryExpression unary= nodeFactory.newUnaryExpression(unaryOperator, null);
|
||||
((ASTNode) unary).setOffset(unaryOpOffset);
|
||||
|
@ -1309,40 +1386,16 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return result;
|
||||
}
|
||||
|
||||
protected IASTExpression conditionalExpression() throws BacktrackException, EndOfFileException {
|
||||
IASTExpression firstExpression = logicalOrExpression();
|
||||
if (LT(1) == IToken.tQUESTION) {
|
||||
if (shallRejectLogicalOperator()) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
|
||||
consume();
|
||||
IASTExpression secondExpression= null;
|
||||
if (LT(1) != IToken.tCOLON) {
|
||||
secondExpression = expression();
|
||||
}
|
||||
IASTExpression thirdExpression = null;
|
||||
|
||||
if (LT(1) != IToken.tEOC) {
|
||||
consume(IToken.tCOLON);
|
||||
thirdExpression = assignmentExpression();
|
||||
}
|
||||
|
||||
IASTConditionalExpression result = nodeFactory.newConditionalExpession(firstExpression, secondExpression, thirdExpression);
|
||||
if (thirdExpression != null) {
|
||||
((ASTNode) result).setOffsetAndLength(((ASTNode) firstExpression)
|
||||
.getOffset(), calculateEndOffset(thirdExpression)
|
||||
- ((ASTNode) firstExpression).getOffset());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return firstExpression;
|
||||
}
|
||||
|
||||
protected IASTExpression unarayExpression(int operator) throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression unarayExpression(int operator, boolean inBinary) throws EndOfFileException, BacktrackException {
|
||||
final IToken operatorToken= consume();
|
||||
final IASTExpression operand= castExpression();
|
||||
IASTExpression operand= castExpression(inBinary);
|
||||
|
||||
CastAmbiguityMarker ca= null;
|
||||
if (operand instanceof CastAmbiguityMarker) {
|
||||
ca= (CastAmbiguityMarker) operand;
|
||||
operand= ca.getExpression();
|
||||
assert !(operand instanceof CastAmbiguityMarker);
|
||||
}
|
||||
|
||||
if (operator == IASTUnaryExpression.op_star && operand instanceof IASTLiteralExpression) {
|
||||
IASTLiteralExpression lit= (IASTLiteralExpression) operand;
|
||||
|
@ -1356,7 +1409,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
}
|
||||
|
||||
return buildUnaryExpression(operator, operand, operatorToken.getOffset(), calculateEndOffset(operand));
|
||||
IASTExpression result= buildUnaryExpression(operator, operand, operatorToken.getOffset(), calculateEndOffset(operand));
|
||||
return ca == null ? result : ca.updateExpression(result);
|
||||
}
|
||||
|
||||
protected IASTExpression buildUnaryExpression(int operator, IASTExpression operand, int offset, int lastOffset) {
|
||||
|
@ -2131,7 +2185,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
|
||||
protected IASTExpression parseTypeidInParenthesisOrUnaryExpression(boolean exprIsLimitedToParenthesis,
|
||||
int offset, int typeExprKind, int unaryExprKind) throws BacktrackException, EndOfFileException {
|
||||
int offset, int typeExprKind, int unaryExprKind, boolean inBinary) throws BacktrackException, EndOfFileException {
|
||||
IASTTypeId typeid;
|
||||
IASTExpression expr= null;
|
||||
IToken typeidLA= null;
|
||||
|
@ -2184,6 +2238,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
typeid= null;
|
||||
}
|
||||
|
||||
CastAmbiguityMarker ca= null;
|
||||
backup(mark);
|
||||
try {
|
||||
if (exprIsLimitedToParenthesis) {
|
||||
|
@ -2191,7 +2246,12 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
expr= expression();
|
||||
endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
||||
} else {
|
||||
expr= unaryExpression();
|
||||
expr= unaryExpression(inBinary);
|
||||
if (expr instanceof CastAmbiguityMarker) {
|
||||
ca= (CastAmbiguityMarker) expr;
|
||||
expr= ca.getExpression();
|
||||
assert !(expr instanceof CastAmbiguityMarker);
|
||||
}
|
||||
endOffset2= calculateEndOffset(expr);
|
||||
}
|
||||
} catch (BacktrackException bte) {
|
||||
|
@ -2211,6 +2271,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
|
||||
IASTExpression result2= buildUnaryExpression(unaryExprKind, expr, offset, endOffset2);
|
||||
if (ca != null)
|
||||
result2= ca.updateExpression(result2);
|
||||
|
||||
if (result1 == null)
|
||||
return result2;
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ 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.IASTConditionalExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
|
@ -445,73 +444,160 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
|
||||
return expression(true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException {
|
||||
IASTExpression conditionalExpression = conditionalExpression();
|
||||
// if the condition not taken, try assignment operators
|
||||
if (conditionalExpression instanceof IASTConditionalExpression)
|
||||
return conditionalExpression;
|
||||
switch (LT(1)) {
|
||||
return expression(false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
|
||||
return expression(false, false);
|
||||
}
|
||||
|
||||
private IASTExpression expression(boolean allowComma, boolean allowAssignment) throws BacktrackException, EndOfFileException {
|
||||
int lt1;
|
||||
int conditionCount= 0;
|
||||
CastExpressionOp lastComponent= null;
|
||||
IASTExpression lastExpression= castExpression(true);
|
||||
loop: while(true) {
|
||||
lt1= LT(1);
|
||||
switch(lt1) {
|
||||
case IToken.tQUESTION:
|
||||
conditionCount++;
|
||||
// <logical-or> ? <expression> : <assignment-expression>
|
||||
// Precedence: 25 is lower than precedence of logical or; 1 is lower than precedence of expression
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 25, 1);
|
||||
if (LT(2) == IToken.tCOLON) {
|
||||
// Gnu extension: The expression after '?' can be omitted.
|
||||
consume(); // Consume operator
|
||||
lastExpression= null; // Next cast expression is just null
|
||||
continue;
|
||||
}
|
||||
allowAssignment= true; // assignment expressions will be subsumed by the conditional expression
|
||||
break;
|
||||
|
||||
case IToken.tCOLON:
|
||||
if (--conditionCount < 0)
|
||||
break loop;
|
||||
|
||||
// <logical-or> ? <expression> : <assignment-expression>
|
||||
// Precedence: 0 is lower than precedence of expression; 15 is lower than precedence of assignment;
|
||||
lastComponent= new CastExpressionOp(lastComponent, 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
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 10, 11);
|
||||
break;
|
||||
|
||||
case IToken.tASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_assign, conditionalExpression);
|
||||
case IToken.tSTARASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_multiplyAssign, conditionalExpression);
|
||||
case IToken.tDIVASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_divideAssign, conditionalExpression);
|
||||
case IToken.tMODASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_moduloAssign, conditionalExpression);
|
||||
case IToken.tPLUSASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_plusAssign, conditionalExpression);
|
||||
case IToken.tMINUSASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_minusAssign, conditionalExpression);
|
||||
case IToken.tSHIFTRASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_shiftRightAssign, conditionalExpression);
|
||||
case IToken.tSHIFTLASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_shiftLeftAssign, conditionalExpression);
|
||||
case IToken.tAMPERASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_binaryAndAssign, conditionalExpression);
|
||||
case IToken.tXORASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_binaryXorAssign, conditionalExpression);
|
||||
case IToken.tBITORASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_binaryOrAssign, conditionalExpression);
|
||||
if (!allowAssignment && conditionCount == 0)
|
||||
break loop;
|
||||
// Assignments group right to left
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 21, 20);
|
||||
break;
|
||||
|
||||
case IToken.tOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 30, 31);
|
||||
break;
|
||||
case IToken.tAND:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 40, 41);
|
||||
break;
|
||||
case IToken.tBITOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 50, 51);
|
||||
break;
|
||||
case IToken.tXOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 60, 61);
|
||||
break;
|
||||
case IToken.tAMPER:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 70, 71);
|
||||
break;
|
||||
case IToken.tEQUAL:
|
||||
case IToken.tNOTEQUAL:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 80, 81);
|
||||
break;
|
||||
case IToken.tGT:
|
||||
case IToken.tLT:
|
||||
case IToken.tLTEQUAL:
|
||||
case IToken.tGTEQUAL:
|
||||
case IGCCToken.tMAX:
|
||||
case IGCCToken.tMIN:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 90, 91);
|
||||
break;
|
||||
case IToken.tSHIFTL:
|
||||
case IToken.tSHIFTR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 100, 101);
|
||||
break;
|
||||
case IToken.tPLUS:
|
||||
case IToken.tMINUS:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 110, 111);
|
||||
break;
|
||||
case IToken.tSTAR:
|
||||
case IToken.tDIV:
|
||||
case IToken.tMOD:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 120, 121);
|
||||
break;
|
||||
default:
|
||||
break loop;
|
||||
}
|
||||
return conditionalExpression;
|
||||
|
||||
consume(); // consume operator
|
||||
lastExpression= castExpression(true); // next cast expression
|
||||
}
|
||||
|
||||
// Check for incomplete conditional expression
|
||||
if (lt1 != IToken.tEOC && conditionCount > 0)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
return buildExpression(lastComponent, lastExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression pmExpression() throws BacktrackException, EndOfFileException {
|
||||
return castExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression unaryExpression() throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression unaryExpression(boolean inBinary) throws EndOfFileException, BacktrackException {
|
||||
switch (LT(1)) {
|
||||
case IToken.tSTAR:
|
||||
return unarayExpression(IASTUnaryExpression.op_star);
|
||||
return unarayExpression(IASTUnaryExpression.op_star, inBinary);
|
||||
case IToken.tAMPER:
|
||||
return unarayExpression(IASTUnaryExpression.op_amper);
|
||||
return unarayExpression(IASTUnaryExpression.op_amper, inBinary);
|
||||
case IToken.tPLUS:
|
||||
return unarayExpression(IASTUnaryExpression.op_plus);
|
||||
return unarayExpression(IASTUnaryExpression.op_plus, inBinary);
|
||||
case IToken.tMINUS:
|
||||
return unarayExpression(IASTUnaryExpression.op_minus);
|
||||
return unarayExpression(IASTUnaryExpression.op_minus, inBinary);
|
||||
case IToken.tNOT:
|
||||
return unarayExpression(IASTUnaryExpression.op_not);
|
||||
return unarayExpression(IASTUnaryExpression.op_not, inBinary);
|
||||
case IToken.tBITCOMPLEMENT:
|
||||
return unarayExpression(IASTUnaryExpression.op_tilde);
|
||||
return unarayExpression(IASTUnaryExpression.op_tilde, inBinary);
|
||||
case IToken.tINCR:
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixIncr);
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixIncr, inBinary);
|
||||
case IToken.tDECR:
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixDecr);
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixDecr, inBinary);
|
||||
case IToken.t_sizeof:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof);
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, inBinary);
|
||||
case IGCCToken.t_typeof:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof);
|
||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, inBinary);
|
||||
case IGCCToken.t___alignof__:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf);
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, inBinary);
|
||||
default:
|
||||
return postfixExpression();
|
||||
}
|
||||
|
@ -669,7 +755,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return compoundStatementExpression();
|
||||
}
|
||||
t = consume();
|
||||
IASTExpression lhs = expression();
|
||||
IASTExpression lhs = expression(true, true); // instead of expression(), to keep the stack smaller
|
||||
int finalOffset = 0;
|
||||
switch (LT(1)) {
|
||||
case IToken.tRPAREN:
|
||||
|
@ -998,14 +1084,9 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (encounteredRawType || encounteredTypename)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
final boolean wasInBinary= inBinaryExpression;
|
||||
try {
|
||||
inBinaryExpression= false;
|
||||
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof);
|
||||
} finally {
|
||||
inBinaryExpression= wasInBinary;
|
||||
}
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, false);
|
||||
|
||||
encounteredTypename= true;
|
||||
endOffset= calculateEndOffset(typeofExpression);
|
||||
break;
|
||||
|
|
|
@ -27,7 +27,6 @@ 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.IASTConditionalExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
|
@ -61,7 +60,6 @@ import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
|||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
|
@ -156,6 +154,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
private char[] currentClassName;
|
||||
|
||||
private final ICPPNodeFactory nodeFactory;
|
||||
private boolean fInTemplateParameterList;
|
||||
|
||||
public GNUCPPSourceParser(IScanner scanner, ParserMode mode,
|
||||
IParserLogService log, ICPPParserExtensionConfiguration config) {
|
||||
|
@ -316,8 +315,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
IToken secondMark = mark();
|
||||
consume(IToken.tLT);
|
||||
final boolean wasOnTop= onTopInTemplateArgs;
|
||||
onTopInTemplateArgs= true;
|
||||
try {
|
||||
// bug 229062: content assist after '<' needs to prefer to backtrack here
|
||||
if (rejectLogicalOperatorInTemplateID == 1) {
|
||||
|
@ -342,8 +339,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
} catch (BacktrackException bt) {
|
||||
backup(secondMark);
|
||||
return templateName;
|
||||
} finally {
|
||||
onTopInTemplateArgs= wasOnTop;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,7 +470,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
throw backtrack;
|
||||
|
||||
backup(argStart);
|
||||
IASTExpression expression = assignmentExpression();
|
||||
IASTExpression expression = expression(false, true, true);
|
||||
if (expression instanceof IASTIdExpression) {
|
||||
if (mark() != typeIdEnd)
|
||||
throw backtrack;
|
||||
|
@ -496,7 +491,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
} else {
|
||||
// not a type-id - try as expression
|
||||
backup(argStart);
|
||||
IASTExpression expression = assignmentExpression();
|
||||
IASTExpression expression = expression(false, true, true);
|
||||
list.add(expression);
|
||||
}
|
||||
|
||||
|
@ -570,89 +565,165 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression expression() throws EndOfFileException, BacktrackException {
|
||||
final boolean wasOnTop= onTopInTemplateArgs;
|
||||
onTopInTemplateArgs= false;
|
||||
try {
|
||||
return super.expression();
|
||||
} finally {
|
||||
onTopInTemplateArgs= wasOnTop;
|
||||
}
|
||||
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
|
||||
return expression(true, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shallRejectLogicalOperator() {
|
||||
return onTopInTemplateArgs && rejectLogicalOperatorInTemplateID > 0;
|
||||
protected IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException {
|
||||
return expression(false, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression constantExpression() throws EndOfFileException, BacktrackException {
|
||||
final boolean wasOnTop= onTopInTemplateArgs;
|
||||
onTopInTemplateArgs= false;
|
||||
try {
|
||||
return super.constantExpression();
|
||||
} finally {
|
||||
onTopInTemplateArgs= wasOnTop;
|
||||
}
|
||||
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
|
||||
return expression(false, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression assignmentExpression() throws EndOfFileException,
|
||||
BacktrackException {
|
||||
if (LT(1) == IToken.t_throw) {
|
||||
private IASTExpression expression(boolean allowComma, boolean allowAssignment, boolean onTopOfTemplateArgs) throws EndOfFileException, BacktrackException {
|
||||
if (allowAssignment && LT(1) == IToken.t_throw) {
|
||||
return throwExpression();
|
||||
}
|
||||
|
||||
// if this is a conditional expression, return right away.
|
||||
IASTExpression conditionalExpression = conditionalExpression();
|
||||
if (conditionalExpression instanceof IASTConditionalExpression)
|
||||
return conditionalExpression;
|
||||
int lt1;
|
||||
int conditionCount= 0;
|
||||
CastExpressionOp lastComponent= null;
|
||||
IASTExpression expr= castExpression(true);
|
||||
|
||||
loop: while(true) {
|
||||
// typically after a binary operator there cannot be a throw expression
|
||||
boolean allowThrow= false;
|
||||
lt1= LT(1);
|
||||
switch(lt1) {
|
||||
case IToken.tQUESTION:
|
||||
conditionCount++;
|
||||
// <logical-or> ? <expression> : <assignment-expression>
|
||||
// Precedence: 25 is lower than precedence of logical or; 1 is lower than precedence of expression
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 25, 1);
|
||||
if (LT(2) == IToken.tCOLON) {
|
||||
// Gnu extension: The expression after '?' can be omitted.
|
||||
consume(); // Consume operator
|
||||
expr= null; // Next cast expression is just null
|
||||
continue;
|
||||
}
|
||||
allowAssignment= true; // assignment expressions will be subsumed by the conditional expression
|
||||
allowThrow= true;
|
||||
break;
|
||||
|
||||
case IToken.tCOLON:
|
||||
if (--conditionCount < 0)
|
||||
break loop;
|
||||
|
||||
// <logical-or> ? <expression> : <assignment-expression>
|
||||
// Precedence: 0 is lower than precedence of expression; 15 is lower than precedence of assignment;
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 0, 15);
|
||||
allowAssignment= true; // assignment expressions will be subsumed by the conditional expression
|
||||
allowThrow= true;
|
||||
break;
|
||||
|
||||
case IToken.tCOMMA:
|
||||
allowThrow= true;
|
||||
if (!allowComma && conditionCount == 0)
|
||||
break loop;
|
||||
// Lowest precedence except inside the conditional expression
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 10, 11);
|
||||
break;
|
||||
|
||||
switch (LT(1)) {
|
||||
case IToken.tASSIGN:
|
||||
return assignmentOperatorExpression(IASTBinaryExpression.op_assign,
|
||||
conditionalExpression);
|
||||
case IToken.tSTARASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_multiplyAssign,
|
||||
conditionalExpression);
|
||||
case IToken.tDIVASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_divideAssign, conditionalExpression);
|
||||
case IToken.tMODASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_moduloAssign, conditionalExpression);
|
||||
case IToken.tPLUSASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_plusAssign, conditionalExpression);
|
||||
case IToken.tMINUSASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_minusAssign, conditionalExpression);
|
||||
case IToken.tSHIFTRASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_shiftRightAssign,
|
||||
conditionalExpression);
|
||||
case IToken.tSHIFTLASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_shiftLeftAssign,
|
||||
conditionalExpression);
|
||||
case IToken.tAMPERASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_binaryAndAssign,
|
||||
conditionalExpression);
|
||||
case IToken.tXORASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_binaryXorAssign,
|
||||
conditionalExpression);
|
||||
case IToken.tBITORASSIGN:
|
||||
return assignmentOperatorExpression(
|
||||
IASTBinaryExpression.op_binaryOrAssign,
|
||||
conditionalExpression);
|
||||
if (!allowAssignment && conditionCount == 0)
|
||||
break loop;
|
||||
// Assignments group right to left
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 21, 20);
|
||||
break;
|
||||
|
||||
case IToken.tOR:
|
||||
if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
return conditionalExpression;
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 30, 31);
|
||||
break;
|
||||
case IToken.tAND:
|
||||
if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 40, 41);
|
||||
break;
|
||||
case IToken.tBITOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 50, 51);
|
||||
break;
|
||||
case IToken.tXOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 60, 61);
|
||||
break;
|
||||
case IToken.tAMPER:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 70, 71);
|
||||
break;
|
||||
case IToken.tEQUAL:
|
||||
case IToken.tNOTEQUAL:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 80, 81);
|
||||
break;
|
||||
case IToken.tGT:
|
||||
if (onTopOfTemplateArgs)
|
||||
break loop;
|
||||
//$FALL-THROUGH$
|
||||
case IToken.tLT:
|
||||
case IToken.tLTEQUAL:
|
||||
case IToken.tGTEQUAL:
|
||||
case IGCCToken.tMAX:
|
||||
case IGCCToken.tMIN:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 90, 91);
|
||||
break;
|
||||
case IToken.tSHIFTL:
|
||||
case IToken.tSHIFTR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 100, 101);
|
||||
break;
|
||||
case IToken.tPLUS:
|
||||
case IToken.tMINUS:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 110, 111);
|
||||
break;
|
||||
case IToken.tSTAR:
|
||||
case IToken.tDIV:
|
||||
case IToken.tMOD:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 120, 121);
|
||||
break;
|
||||
case IToken.tDOTSTAR:
|
||||
case IToken.tARROWSTAR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 130, 131);
|
||||
break;
|
||||
default:
|
||||
break loop;
|
||||
}
|
||||
|
||||
protected IASTExpression throwExpression() throws EndOfFileException, BacktrackException {
|
||||
consume(); // consume operator
|
||||
if (allowThrow && LT(1) == IToken.t_throw) {
|
||||
expr= throwExpression();
|
||||
switch (LT(1)) {
|
||||
case IToken.tCOLON:
|
||||
case IToken.tCOMMA:
|
||||
break;
|
||||
default:
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
expr= castExpression(true); // next cast expression
|
||||
}
|
||||
|
||||
// Check for incomplete conditional expression
|
||||
if (lt1 != IToken.tEOC && conditionCount > 0)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
return buildExpression(lastComponent, expr);
|
||||
}
|
||||
|
||||
private IASTExpression throwExpression() throws EndOfFileException, BacktrackException {
|
||||
IToken throwToken = consume();
|
||||
IASTExpression throwExpression = null;
|
||||
try {
|
||||
|
@ -667,34 +738,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
throwExpression, throwToken.getOffset(), o); // fix for 95225
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression pmExpression() throws EndOfFileException, BacktrackException {
|
||||
IASTExpression firstExpression = castExpression();
|
||||
for (;;) {
|
||||
switch (LT(1)) {
|
||||
case IToken.tDOTSTAR:
|
||||
case IToken.tARROWSTAR:
|
||||
IToken t = consume();
|
||||
IASTExpression secondExpression = castExpression();
|
||||
int operator = 0;
|
||||
switch (t.getType()) {
|
||||
case IToken.tDOTSTAR:
|
||||
operator = ICPPASTBinaryExpression.op_pmdot;
|
||||
break;
|
||||
case IToken.tARROWSTAR:
|
||||
operator = ICPPASTBinaryExpression.op_pmarrow;
|
||||
break;
|
||||
}
|
||||
firstExpression = buildBinaryExpression(operator,
|
||||
firstExpression, secondExpression,
|
||||
calculateEndOffset(secondExpression));
|
||||
break;
|
||||
default:
|
||||
return firstExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected IASTExpression deleteExpression() throws EndOfFileException, BacktrackException {
|
||||
int startingOffset = LA(1).getOffset();
|
||||
boolean global = false;
|
||||
|
@ -713,7 +756,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
consume(IToken.tRBRACKET);
|
||||
vectored = true;
|
||||
}
|
||||
IASTExpression castExpression = castExpression();
|
||||
IASTExpression castExpression = castExpression(false);
|
||||
ICPPASTDeleteExpression deleteExpression = nodeFactory.newDeleteExpression(castExpression);
|
||||
((ASTNode) deleteExpression).setOffsetAndLength(startingOffset, calculateEndOffset(castExpression) - startingOffset);
|
||||
deleteExpression.setIsGlobal(global);
|
||||
|
@ -855,24 +898,24 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
|
||||
@Override
|
||||
protected IASTExpression unaryExpression() throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression unaryExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException {
|
||||
switch (LT(1)) {
|
||||
case IToken.tSTAR:
|
||||
return unarayExpression(IASTUnaryExpression.op_star);
|
||||
return unarayExpression(IASTUnaryExpression.op_star, inBinaryExpression);
|
||||
case IToken.tAMPER:
|
||||
return unarayExpression(IASTUnaryExpression.op_amper);
|
||||
return unarayExpression(IASTUnaryExpression.op_amper, inBinaryExpression);
|
||||
case IToken.tPLUS:
|
||||
return unarayExpression(IASTUnaryExpression.op_plus);
|
||||
return unarayExpression(IASTUnaryExpression.op_plus, inBinaryExpression);
|
||||
case IToken.tMINUS:
|
||||
return unarayExpression(IASTUnaryExpression.op_minus);
|
||||
return unarayExpression(IASTUnaryExpression.op_minus, inBinaryExpression);
|
||||
case IToken.tNOT:
|
||||
return unarayExpression(IASTUnaryExpression.op_not);
|
||||
return unarayExpression(IASTUnaryExpression.op_not, inBinaryExpression);
|
||||
case IToken.tBITCOMPLEMENT:
|
||||
return unarayExpression(IASTUnaryExpression.op_tilde);
|
||||
return unarayExpression(IASTUnaryExpression.op_tilde, inBinaryExpression);
|
||||
case IToken.tINCR:
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixIncr);
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixIncr, inBinaryExpression);
|
||||
case IToken.tDECR:
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixDecr);
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixDecr, inBinaryExpression);
|
||||
case IToken.t_new:
|
||||
return newExpression();
|
||||
case IToken.t_delete:
|
||||
|
@ -884,23 +927,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.t_delete:
|
||||
return deleteExpression();
|
||||
default:
|
||||
return postfixExpression();
|
||||
return postfixExpression(inBinaryExpression);
|
||||
}
|
||||
case IToken.t_sizeof:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof);
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, inBinaryExpression);
|
||||
case IGCCToken.t_typeof:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof);
|
||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, inBinaryExpression);
|
||||
case IGCCToken.t___alignof__:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf);
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, inBinaryExpression);
|
||||
default:
|
||||
return postfixExpression();
|
||||
return postfixExpression(inBinaryExpression);
|
||||
}
|
||||
}
|
||||
|
||||
protected IASTExpression postfixExpression() throws EndOfFileException, BacktrackException {
|
||||
private IASTExpression postfixExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException {
|
||||
IASTExpression firstExpression = null;
|
||||
boolean isTemplate = false;
|
||||
|
||||
|
@ -989,7 +1032,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
break;
|
||||
case IToken.t_typeid:
|
||||
int so = consume().getOffset();
|
||||
firstExpression= parseTypeidInParenthesisOrUnaryExpression(true, so, ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid);
|
||||
firstExpression = parseTypeidInParenthesisOrUnaryExpression(true, so,
|
||||
ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid, inBinaryExpression);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1191,7 +1235,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
t = consume();
|
||||
int finalOffset= 0;
|
||||
IASTExpression lhs= expression();
|
||||
IASTExpression lhs= expression(true, true, false); // instead of expression(), to keep the stack smaller
|
||||
switch (LT(1)) {
|
||||
case IToken.tRPAREN:
|
||||
case IToken.tEOC:
|
||||
|
@ -1421,15 +1465,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return templateSpecialization;
|
||||
}
|
||||
|
||||
final boolean wasOnTop= onTopInTemplateArgs;
|
||||
onTopInTemplateArgs= true;
|
||||
List<ICPPASTTemplateParameter> parms;
|
||||
try {
|
||||
parms = templateParameterList();
|
||||
List<ICPPASTTemplateParameter> parms= templateParameterList();
|
||||
consume(IToken.tGT);
|
||||
} finally {
|
||||
onTopInTemplateArgs= wasOnTop;
|
||||
}
|
||||
IASTDeclaration d = declaration(option);
|
||||
ICPPASTTemplateDeclaration templateDecl = nodeFactory.newTemplateDeclaration(d);
|
||||
((ASTNode) templateDecl).setOffsetAndLength(firstToken.getOffset(), calculateEndOffset(d) - firstToken.getOffset());
|
||||
|
@ -1526,8 +1563,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
consume();
|
||||
continue;
|
||||
} else {
|
||||
boolean inTParList= fInTemplateParameterList;
|
||||
try {
|
||||
fInTemplateParameterList= true;
|
||||
ICPPASTParameterDeclaration parm = parameterDeclaration();
|
||||
returnValue.add(parm);
|
||||
} finally {
|
||||
fInTemplateParameterList= inTParList;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2182,14 +2225,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (encounteredRawType || encounteredTypename)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
final boolean wasInBinary= inBinaryExpression;
|
||||
try {
|
||||
inBinaryExpression= false;
|
||||
typeofExpression= parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof);
|
||||
} finally {
|
||||
inBinaryExpression= wasInBinary;
|
||||
}
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, false);
|
||||
|
||||
encounteredTypename= true;
|
||||
endOffset= calculateEndOffset(typeofExpression);
|
||||
|
@ -2617,7 +2654,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
// if we get this far, it means that we did not
|
||||
// try this now instead
|
||||
// assignmentExpression
|
||||
IASTExpression assignmentExpression = assignmentExpression();
|
||||
IASTExpression assignmentExpression = expression(false, true, fInTemplateParameterList);
|
||||
if (inAggregateInitializer && skipTrivialExpressionsInAggregateInitializers) {
|
||||
if (!ASTQueries.canContainName(assignmentExpression))
|
||||
return null;
|
||||
|
|
Loading…
Add table
Reference in a new issue