1
0
Fork 0
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:
Markus Schorn 2009-11-12 17:45:31 +00:00
parent 2b793aaf12
commit 18c73ee0f5
4 changed files with 705 additions and 501 deletions

View file

@ -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);
}
}
}

View file

@ -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);
public CastExpressionOp(CastExpressionOp left, IASTExpression expression, int operatorToken, int leftPrecedence, int rightPrecedence) {
fLeft= left;
fExpression= expression;
fOperatorToken= operatorToken;
fLeftPrecedence= leftPrecedence;
fRightPrecedence= rightPrecedence;
}
}
/**
* 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;
boolean isEmpty() {
return fPos<0;
}
int lastOffset = 0;
while (LT(1) == IToken.tCOMMA) {
consume();
IASTExpression secondExpression = assignmentExpression();
expressionList.addExpression(secondExpression);
lastOffset = calculateEndOffset(secondExpression);
}
((ASTNode) expressionList).setLength(lastOffset - startingOffset);
return expressionList;
}
public IASTExpression getExpression() {
return fExpressions[fPos];
}
public int getLeftPrecedence() {
return fPrecedenceAndTokens[2*fPos];
}
protected abstract IASTExpression assignmentExpression()
throws BacktrackException, EndOfFileException;
public int getOperatorToken() {
return fPrecedenceAndTokens[2*fPos+1];
}
protected IASTExpression relationalExpression() throws BacktrackException, EndOfFileException {
IASTExpression result= shiftExpression();
for (;;) {
int operator;
switch (LT(1)) {
case IToken.tGT:
if (onTopInTemplateArgs)
return result;
operator= IASTBinaryExpression.op_greaterThan;
break;
case IToken.tLT:
operator = IASTBinaryExpression.op_lessThan;
break;
case IToken.tLTEQUAL:
operator = IASTBinaryExpression.op_lessEqual;
break;
case IToken.tGTEQUAL:
operator = IASTBinaryExpression.op_greaterEqual;
break;
case IGCCToken.tMAX:
operator = IASTBinaryExpression.op_max;
break;
case IGCCToken.tMIN:
operator = IASTBinaryExpression.op_min;
break;
default:
return result;
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);
}
consume();
IASTExpression rhs= shiftExpression();
result = buildBinaryExpression(operator, result, rhs, calculateEndOffset(rhs));
}
}
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:
op= IASTBinaryExpression.op_greaterThan;
break;
case IToken.tLT:
op= IASTBinaryExpression.op_lessThan;
break;
case IToken.tLTEQUAL:
op= IASTBinaryExpression.op_lessEqual;
break;
case IToken.tGTEQUAL:
op= IASTBinaryExpression.op_greaterEqual;
break;
case IGCCToken.tMAX:
op= IASTBinaryExpression.op_max;
break;
case IGCCToken.tMIN:
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:
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;
private final static class CastAmbiguityMarker extends ASTNode implements IASTExpression {
private IASTExpression fExpression;
private final IASTTypeId fTypeIdForCast;
private final int fUnaryOperatorOffset;
protected IASTExpression castExpression() throws EndOfFileException, BacktrackException {
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,41 +1386,17 @@ 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;
switch(lit.getKind()) {
@ -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;

View file

@ -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;
@ -444,74 +443,161 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
}
}
}
@Override
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
return expression(true, true);
}
@Override
@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)) {
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);
}
return conditionalExpression;
return expression(false, true);
}
@Override
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
return expression(false, false);
}
@Override
protected IASTExpression pmExpression() throws BacktrackException, EndOfFileException {
return castExpression();
}
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:
case IToken.tSTARASSIGN:
case IToken.tDIVASSIGN:
case IToken.tMODASSIGN:
case IToken.tPLUSASSIGN:
case IToken.tMINUSASSIGN:
case IToken.tSHIFTRASSIGN:
case IToken.tSHIFTLASSIGN:
case IToken.tAMPERASSIGN:
case IToken.tXORASSIGN:
case IToken.tBITORASSIGN:
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;
}
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 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;
}
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, false);
encounteredTypename= true;
endOffset= calculateEndOffset(typeofExpression);
break;

View file

@ -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,9 +339,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} catch (BacktrackException bt) {
backup(secondMark);
return templateName;
} finally {
onTopInTemplateArgs= wasOnTop;
}
}
}
private ICPPASTTemplateId buildTemplateID(IASTName templateName, int endOffset, List<IASTNode> args) {
@ -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);
}
@ -569,90 +564,166 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return name;
}
@Override
protected IASTExpression expression() throws EndOfFileException, BacktrackException {
final boolean wasOnTop= onTopInTemplateArgs;
onTopInTemplateArgs= false;
try {
return super.expression();
} finally {
onTopInTemplateArgs= wasOnTop;
@Override
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
return expression(true, true, false);
}
@Override
protected IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException {
return expression(false, true, false);
}
@Override
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
return expression(false, false, false);
}
private IASTExpression expression(boolean allowComma, boolean allowAssignment, boolean onTopOfTemplateArgs) throws EndOfFileException, BacktrackException {
if (allowAssignment && LT(1) == IToken.t_throw) {
return throwExpression();
}
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;
case IToken.tASSIGN:
case IToken.tSTARASSIGN:
case IToken.tDIVASSIGN:
case IToken.tMODASSIGN:
case IToken.tPLUSASSIGN:
case IToken.tMINUSASSIGN:
case IToken.tSHIFTRASSIGN:
case IToken.tSHIFTLASSIGN:
case IToken.tAMPERASSIGN:
case IToken.tXORASSIGN:
case IToken.tBITORASSIGN:
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));
}
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;
}
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);
}
@Override
protected boolean shallRejectLogicalOperator() {
return onTopInTemplateArgs && rejectLogicalOperatorInTemplateID > 0;
}
@Override
protected IASTExpression constantExpression() throws EndOfFileException, BacktrackException {
final boolean wasOnTop= onTopInTemplateArgs;
onTopInTemplateArgs= false;
try {
return super.constantExpression();
} finally {
onTopInTemplateArgs= wasOnTop;
}
}
@Override
protected IASTExpression assignmentExpression() throws EndOfFileException,
BacktrackException {
if (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;
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);
}
return conditionalExpression;
}
protected IASTExpression throwExpression() throws EndOfFileException, BacktrackException {
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();
consume(IToken.tGT);
} finally {
onTopInTemplateArgs= wasOnTop;
}
List<ICPPASTTemplateParameter> parms= templateParameterList();
consume(IToken.tGT);
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 {
ICPPASTParameterDeclaration parm = parameterDeclaration();
returnValue.add(parm);
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;
}
typeofExpression= parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
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;