mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +02:00
C++0x: Right angle brackets, bug 261268.
This commit is contained in:
parent
aca23fae0e
commit
f40c0fc481
10 changed files with 539 additions and 353 deletions
|
@ -4395,7 +4395,8 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
|||
// X<(1>2)> x2; // OK
|
||||
// template<class T> class Y { };
|
||||
// Y< X<1> > x3; // OK
|
||||
// Y<X<6>> 1> > x4; // OK: Y< X< (6>>1) > >
|
||||
// // with C++0x this is no longer valid:
|
||||
// // Y<X<6>> 1> > x4; // OK: Y< X< (6>>1) > >
|
||||
public void test14_2s3() throws Exception {
|
||||
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||
|
@ -4245,4 +4246,58 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// template<typename T> class CT {};
|
||||
// template<int I> class CTI {};
|
||||
//
|
||||
// int test() {
|
||||
// int a;
|
||||
// CT<CT<int>> x;
|
||||
// a= 1 >> 2;
|
||||
// return a;
|
||||
// }
|
||||
public void testClosingAngleBrackets1_261268() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// template<typename T> class CT {};
|
||||
// template<int I> class CTI {};
|
||||
//
|
||||
// int test() {
|
||||
// int a;
|
||||
// a= 1 > > 3; // must be syntax error
|
||||
// return a;
|
||||
// }
|
||||
public void testClosingAngleBrackets2_261268() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
IASTTranslationUnit tu = parse(code, ParserLanguage.CPP, true, false);
|
||||
IASTFunctionDefinition fdef= getDeclaration(tu, 2);
|
||||
IASTProblemStatement p1= getStatement(fdef, 1);
|
||||
}
|
||||
|
||||
// template<typename T> class CT {};
|
||||
// typedef int TInt;
|
||||
// int test() {
|
||||
// int a;
|
||||
// CT<CT<TInt>> x; // declaration
|
||||
// int y= a<a<a>> a; // binary expression
|
||||
// a<a<a>> a; // binary expression via ambiguity
|
||||
// y= a < a >> (1+2); // binary expression
|
||||
// a < a >> (1+2); // binary expression via ambiguity
|
||||
// }
|
||||
public void testClosingAngleBracketsAmbiguity_261268() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// #define OPASSIGN(x) x##=
|
||||
// int test() {
|
||||
// int a=1;
|
||||
// a OPASSIGN(>>) 1;
|
||||
// }
|
||||
public void testTokenPasteShiftROperaotr_261268() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
|
|||
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.IASTDeclarationStatement;
|
||||
|
@ -33,6 +34,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||
|
@ -5434,6 +5436,59 @@ public class AST2Tests extends AST2BaseTest {
|
|||
}
|
||||
}
|
||||
|
||||
// int a,b;
|
||||
// void test() {
|
||||
|
||||
// 1+2+3 // 1,2,+,3,+
|
||||
// a=b=1 // a,b,1,=,=
|
||||
// 0, a= 1 ? 2,3 : b= 4, 5 // 0,a,1,2,3,,,b,4,=,?,=,5,,
|
||||
// 1 ? 2 ? 3 : 4 ? 5 : 6 : 7 // 1,2,3,4,5,6,?,?,7,?
|
||||
public void testBinaryExpressionBinding() throws Exception {
|
||||
StringBuffer[] input= getContents(2);
|
||||
String code= input[0].toString();
|
||||
String[] samples= input[1].toString().split("\n");
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
for (String s : samples) {
|
||||
final String[] io= s.split("//");
|
||||
final String exprStr = io[0].trim();
|
||||
final IASTTranslationUnit tu= parse(code + exprStr + ";}", lang);
|
||||
final IASTFunctionDefinition fdef= getDeclaration(tu, 1);
|
||||
IASTExpression expr= getExpressionOfStatement(fdef, 0);
|
||||
assertEquals("expr: " + exprStr, io[1].trim(), polnishNotation(expr));
|
||||
assertEquals(exprStr, expr.getRawSignature());
|
||||
checkOffsets(exprStr, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// int a,b;
|
||||
// void test(int a=
|
||||
|
||||
// 1+2+3 // 1,2,+,3,+
|
||||
// a=b=1 // a,b,1,=,=
|
||||
// 1 ? 2,3 : b= 4 // 1,2,3,,,b,4,=,?
|
||||
// 1 ? 2 ? 3 : 4 ? 5 : 6 : 7 // 1,2,3,4,5,6,?,?,7,?
|
||||
public void testConstantExpressionBinding() throws Exception {
|
||||
StringBuffer[] input= getContents(2);
|
||||
String code= input[0].toString();
|
||||
String[] samples= input[1].toString().split("\n");
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
for (String s : samples) {
|
||||
final String[] io= s.split("//");
|
||||
final String exprStr = io[0].trim();
|
||||
final IASTTranslationUnit tu= parse(code + exprStr + "){}", lang);
|
||||
final IASTFunctionDefinition fdef= getDeclaration(tu, 1);
|
||||
IASTFunctionDeclarator fdtor= fdef.getDeclarator();
|
||||
IASTParameterDeclaration pdecl= (IASTParameterDeclaration) fdtor.getChildren()[1];
|
||||
IASTExpression expr= ((IASTInitializerExpression) pdecl.getDeclarator().getInitializer()).getExpression();
|
||||
assertEquals("expr: " + exprStr, io[1].trim(), polnishNotation(expr));
|
||||
assertEquals(exprStr, expr.getRawSignature());
|
||||
checkOffsets(exprStr, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkOffsets(String exprStr, IASTExpression expr) {
|
||||
if (expr instanceof IASTBinaryExpression) {
|
||||
IASTBinaryExpression bexpr= (IASTBinaryExpression) expr;
|
||||
|
@ -5484,7 +5539,24 @@ public class AST2Tests extends AST2BaseTest {
|
|||
}
|
||||
|
||||
private void polnishNotation(IASTExpression expr, StringBuilder buf) {
|
||||
if (expr instanceof IASTBinaryExpression) {
|
||||
if (expr instanceof IASTConditionalExpression) {
|
||||
IASTConditionalExpression bexpr= (IASTConditionalExpression) expr;
|
||||
polnishNotation(bexpr.getLogicalConditionExpression(), buf);
|
||||
buf.append(',');
|
||||
polnishNotation(bexpr.getPositiveResultExpression(), buf);
|
||||
buf.append(',');
|
||||
polnishNotation(bexpr.getNegativeResultExpression(), buf);
|
||||
buf.append(',');
|
||||
buf.append('?');
|
||||
} else if (expr instanceof IASTExpressionList) {
|
||||
IASTExpressionList bexpr= (IASTExpressionList) expr;
|
||||
IASTExpression[] args = bexpr.getExpressions();
|
||||
for (IASTExpression e : args) {
|
||||
polnishNotation(e, buf);
|
||||
buf.append(',');
|
||||
}
|
||||
buf.append(',');
|
||||
} else if (expr instanceof IASTBinaryExpression) {
|
||||
IASTBinaryExpression bexpr= (IASTBinaryExpression) expr;
|
||||
polnishNotation(bexpr.getOperand1(), buf);
|
||||
buf.append(',');
|
||||
|
|
|
@ -68,12 +68,11 @@ public interface IScanner {
|
|||
public void setContentAssistMode(int offset);
|
||||
|
||||
/**
|
||||
* Method has no effect.
|
||||
* Instructs the scanner to split tokens of kind {@link IToken#tSHIFTR} into two tokens of
|
||||
* kind {@link IToken#tGT_in_SHIFTR}.
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
* @since 4.0
|
||||
*/
|
||||
@Deprecated
|
||||
public void setScanComments(boolean val);
|
||||
public void setSplitShiftROperator(boolean val);
|
||||
|
||||
/**
|
||||
* Turns on/off creation of image locations.
|
||||
|
@ -106,4 +105,10 @@ public interface IScanner {
|
|||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
public int getCodeBranchNesting();
|
||||
|
||||
/**
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setScanComments(boolean val);
|
||||
}
|
||||
|
|
|
@ -94,7 +94,11 @@ public interface IToken {
|
|||
int tDOT = 50;
|
||||
int tDIVASSIGN = 51;
|
||||
int tDIV = 52;
|
||||
|
||||
/**
|
||||
* @see IScanner#setSplitShiftROperator(boolean)
|
||||
* @since 5.2
|
||||
*/
|
||||
int tGT_in_SHIFTR= 53;
|
||||
/** @deprecated use {@link #tAND} */ @Deprecated int t_and = 54;
|
||||
/** @deprecated use {@link #tAMPERASSIGN} */ @Deprecated int t_and_eq = 55;
|
||||
int t_asm = 56;
|
||||
|
|
|
@ -147,6 +147,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return PROCESS_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about the context in which a cast-expression is parsed:
|
||||
* in a binary expression, in a binary expression in a template-id, or elsewhere.
|
||||
*/
|
||||
protected static enum CastExprCtx {eBExpr, eBExprInTmplID, eNotBExpr}
|
||||
protected static enum ExprKind {eExpression, eAssignment, eConstant}
|
||||
|
||||
protected static final int DEFAULT_DESIGNATOR_LIST_SIZE = 4;
|
||||
protected static int parseCount = 0;
|
||||
|
@ -184,7 +191,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected BacktrackException backtrack = new BacktrackException();
|
||||
|
||||
protected ASTCompletionNode completionNode;
|
||||
protected IASTTypeId fTypeIdForCastAmbiguity;
|
||||
|
||||
private final INodeFactory nodeFactory;
|
||||
private boolean fActiveCode= true;
|
||||
|
@ -269,12 +275,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
|
||||
private final IToken nextToken(boolean skipInactive) throws EndOfFileException {
|
||||
IToken t= nextToken;
|
||||
if (t == null) {
|
||||
t= fetchToken(skipInactive);
|
||||
}
|
||||
nextToken= t;
|
||||
return t;
|
||||
final IToken t= nextToken;
|
||||
if (t != null)
|
||||
return t;
|
||||
|
||||
final IToken tn= fetchToken(skipInactive);
|
||||
nextToken= tn;
|
||||
return tn;
|
||||
}
|
||||
|
||||
private final IToken lookaheadToken(int i, boolean skipInactive) throws EndOfFileException {
|
||||
|
@ -457,6 +464,18 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the type of the next token matches, it is consumed and returned. Otherwise a
|
||||
* {@link BacktrackException} will be thrown.
|
||||
*/
|
||||
protected final IToken consume(int type1, int type2) throws EndOfFileException, BacktrackException {
|
||||
final IToken result= consume();
|
||||
final int lt1 = result.getType();
|
||||
if (lt1 != type1 && lt1 != type2)
|
||||
throwBacktrack(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume the next token available only if the type is as specified. In case we reached the end of
|
||||
* completion, no token is consumed and the eoc-token returned.
|
||||
|
@ -884,125 +903,71 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
* 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;
|
||||
protected static class BinaryOperator {
|
||||
final int fOperatorToken;
|
||||
final int fLeftPrecedence;
|
||||
final int fRightPrecedence;
|
||||
BinaryOperator fNext;
|
||||
IASTExpression fExpression;
|
||||
final CastAmbiguityMarker fAmbiguityMarker;
|
||||
|
||||
public CastExpressionOp(CastExpressionOp left, IASTExpression expression, int operatorToken, int leftPrecedence, int rightPrecedence) {
|
||||
fLeft= left;
|
||||
fExpression= expression;
|
||||
public BinaryOperator(BinaryOperator left, IASTExpression expression, int operatorToken, int leftPrecedence, int rightPrecedence) {
|
||||
fNext= left;
|
||||
fOperatorToken= operatorToken;
|
||||
fLeftPrecedence= leftPrecedence;
|
||||
fRightPrecedence= rightPrecedence;
|
||||
if (expression instanceof CastAmbiguityMarker) {
|
||||
fAmbiguityMarker= (CastAmbiguityMarker) expression;
|
||||
fExpression= fAmbiguityMarker.fExpression;
|
||||
fAmbiguityMarker.fExpression= null;
|
||||
} else {
|
||||
fExpression= expression;
|
||||
fAmbiguityMarker= null;
|
||||
}
|
||||
}
|
||||
|
||||
public IASTExpression exchange(IASTExpression expr) {
|
||||
IASTExpression e= fExpression;
|
||||
fExpression= expr;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
protected final IASTExpression buildExpression(BinaryOperator leftChain, IASTExpression expr) throws BacktrackException {
|
||||
BinaryOperator rightChain= null;
|
||||
for (;;) {
|
||||
if (leftChain == null) {
|
||||
if (rightChain == null)
|
||||
return expr;
|
||||
|
||||
expr= buildExpression(expr, rightChain);
|
||||
rightChain= rightChain.fNext;
|
||||
} else if (rightChain != null && leftChain.fRightPrecedence < rightChain.fLeftPrecedence) {
|
||||
expr= buildExpression(expr, rightChain);
|
||||
rightChain= rightChain.fNext;
|
||||
} else {
|
||||
BinaryOperator op= leftChain;
|
||||
leftChain= leftChain.fNext;
|
||||
expr= op.exchange(expr);
|
||||
op.fNext= rightChain;
|
||||
rightChain= op;
|
||||
}
|
||||
|
||||
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) {
|
||||
private IASTExpression buildExpression(IASTExpression left, BinaryOperator operator) throws BacktrackException {
|
||||
int op, unaryOp= 0;
|
||||
final IASTExpression right= operator.fExpression;
|
||||
switch(operator.fOperatorToken) {
|
||||
case IToken.tQUESTION:
|
||||
if (stack == null || stack.isEmpty() || stack.getOperatorToken() != IToken.tCOLON) {
|
||||
if (operator.fNext == null || operator.fNext.fOperatorToken != 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();
|
||||
IASTExpression negative= operator.fNext.fExpression;
|
||||
operator.fNext= operator.fNext.fNext;
|
||||
IASTConditionalExpression conditionalEx = nodeFactory.newConditionalExpession(left, right, negative);
|
||||
setRange(conditionalEx, left);
|
||||
if (negative != null) {
|
||||
|
@ -1134,35 +1099,20 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
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) {
|
||||
final CastAmbiguityMarker am = operator.fAmbiguityMarker;
|
||||
if (am != null) {
|
||||
assert unaryOp != 0;
|
||||
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result,
|
||||
lca.getTypeIdForCast(), unaryOp, lca.getUnaryOperatorOffset());
|
||||
am.getTypeIdForCast(), unaryOp, am.getUnaryOperatorOffset());
|
||||
}
|
||||
|
||||
return rca == null ? result : rca.updateExpression(result);
|
||||
return 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 IASTExpression unaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException;
|
||||
protected abstract IASTExpression primaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException;
|
||||
protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException;
|
||||
|
||||
private final static class CastAmbiguityMarker extends ASTNode implements IASTExpression {
|
||||
|
@ -1202,7 +1152,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
}
|
||||
|
||||
protected final IASTExpression castExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException {
|
||||
protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
if (LT(1) == IToken.tLPAREN) {
|
||||
final IToken mark= mark();
|
||||
final int startingOffset= mark.getOffset();
|
||||
|
@ -1211,7 +1161,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
if (typeId != null && LT(1) == IToken.tRPAREN) {
|
||||
consume();
|
||||
boolean unaryFailed= false;
|
||||
if (inBinaryExpression) {
|
||||
if (ctx != CastExprCtx.eNotBExpr) {
|
||||
switch (LT(1)){
|
||||
// ambiguity with unary operator
|
||||
case IToken.tPLUS: case IToken.tMINUS:
|
||||
|
@ -1220,7 +1170,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
IToken markEnd= mark();
|
||||
backup(mark);
|
||||
try {
|
||||
IASTExpression unary= unaryExpression(false);
|
||||
IASTExpression unary= unaryExpression(CastExprCtx.eNotBExpr);
|
||||
return new CastAmbiguityMarker(unary, typeId, operatorOffset);
|
||||
} catch (BacktrackException bt) {
|
||||
backup(markEnd);
|
||||
|
@ -1230,7 +1180,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
try {
|
||||
boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN;
|
||||
IASTExpression rhs= castExpression(inBinaryExpression);
|
||||
IASTExpression rhs= castExpression(ctx);
|
||||
|
||||
CastAmbiguityMarker ca= null;
|
||||
if (rhs instanceof CastAmbiguityMarker) {
|
||||
|
@ -1243,7 +1193,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
IToken markEnd= mark();
|
||||
backup(mark);
|
||||
try {
|
||||
IASTExpression expr= primaryExpression();
|
||||
IASTExpression expr= primaryExpression(ctx);
|
||||
IASTFunctionCallExpression fcall = nodeFactory.newFunctionCallExpression(expr, null);
|
||||
IASTAmbiguousExpression ambiguity = createAmbiguousCastVsFunctionCallExpression(result, fcall);
|
||||
((ASTNode) ambiguity).setOffsetAndLength((ASTNode) result);
|
||||
|
@ -1261,7 +1211,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
backup(mark);
|
||||
}
|
||||
return unaryExpression(inBinaryExpression);
|
||||
return unaryExpression(ctx);
|
||||
}
|
||||
|
||||
protected abstract IASTTranslationUnit getTranslationUnit();
|
||||
|
@ -1386,9 +1336,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return result;
|
||||
}
|
||||
|
||||
protected IASTExpression unarayExpression(int operator, boolean inBinary) throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression unaryExpression(int operator, CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
final IToken operatorToken= consume();
|
||||
IASTExpression operand= castExpression(inBinary);
|
||||
IASTExpression operand= castExpression(ctx);
|
||||
|
||||
CastAmbiguityMarker ca= null;
|
||||
if (operand instanceof CastAmbiguityMarker) {
|
||||
|
@ -2185,7 +2135,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
|
||||
protected IASTExpression parseTypeidInParenthesisOrUnaryExpression(boolean exprIsLimitedToParenthesis,
|
||||
int offset, int typeExprKind, int unaryExprKind, boolean inBinary) throws BacktrackException, EndOfFileException {
|
||||
int offset, int typeExprKind, int unaryExprKind, CastExprCtx ctx) throws BacktrackException, EndOfFileException {
|
||||
IASTTypeId typeid;
|
||||
IASTExpression expr= null;
|
||||
IToken typeidLA= null;
|
||||
|
@ -2246,7 +2196,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
expr= expression();
|
||||
endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
||||
} else {
|
||||
expr= unaryExpression(inBinary);
|
||||
expr= unaryExpression(ctx);
|
||||
if (expr instanceof CastAmbiguityMarker) {
|
||||
ca= (CastAmbiguityMarker) expr;
|
||||
expr= ca.getExpression();
|
||||
|
|
|
@ -145,7 +145,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
protected IASTInitializer cInitializerClause(boolean inAggregate) throws EndOfFileException, BacktrackException {
|
||||
final int offset = LA(1).getOffset();
|
||||
if (LT(1) != IToken.tLBRACE) {
|
||||
IASTExpression assignmentExpression= assignmentExpression();
|
||||
IASTExpression assignmentExpression= expression(ExprKind.eAssignment);
|
||||
if (inAggregate && skipTrivialExpressionsInAggregateInitializers) {
|
||||
if (!ASTQueries.canContainName(assignmentExpression))
|
||||
return null;
|
||||
|
@ -446,32 +446,29 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
@Override
|
||||
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
|
||||
return expression(true, true);
|
||||
return expression(ExprKind.eExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException {
|
||||
return expression(false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
|
||||
return expression(false, false);
|
||||
return expression(ExprKind.eConstant);
|
||||
}
|
||||
|
||||
private IASTExpression expression(boolean allowComma, boolean allowAssignment) throws BacktrackException, EndOfFileException {
|
||||
private IASTExpression expression(final ExprKind kind) throws EndOfFileException, BacktrackException {
|
||||
final boolean allowComma= kind==ExprKind.eExpression;
|
||||
boolean allowAssignment= kind !=ExprKind.eConstant;
|
||||
int lt1;
|
||||
int conditionCount= 0;
|
||||
CastExpressionOp lastComponent= null;
|
||||
IASTExpression lastExpression= castExpression(true);
|
||||
BinaryOperator lastOperator= null;
|
||||
IASTExpression lastExpression= castExpression(CastExprCtx.eBExpr);
|
||||
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);
|
||||
// Precedence: 25 is lower than precedence of logical or; 0 is lower than precedence of expression
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 25, 0);
|
||||
if (LT(2) == IToken.tCOLON) {
|
||||
// Gnu extension: The expression after '?' can be omitted.
|
||||
consume(); // Consume operator
|
||||
|
@ -487,7 +484,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
// <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);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 0, 15);
|
||||
allowAssignment= true; // assignment expressions will be subsumed by the conditional expression
|
||||
break;
|
||||
|
||||
|
@ -495,7 +492,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (!allowComma && conditionCount == 0)
|
||||
break loop;
|
||||
// Lowest precedence except inside the conditional expression
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 10, 11);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 10, 11);
|
||||
break;
|
||||
|
||||
case IToken.tASSIGN:
|
||||
|
@ -512,27 +509,27 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (!allowAssignment && conditionCount == 0)
|
||||
break loop;
|
||||
// Assignments group right to left
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 21, 20);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 21, 20);
|
||||
break;
|
||||
|
||||
case IToken.tOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 30, 31);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 30, 31);
|
||||
break;
|
||||
case IToken.tAND:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 40, 41);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 40, 41);
|
||||
break;
|
||||
case IToken.tBITOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 50, 51);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 50, 51);
|
||||
break;
|
||||
case IToken.tXOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 60, 61);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 60, 61);
|
||||
break;
|
||||
case IToken.tAMPER:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 70, 71);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 70, 71);
|
||||
break;
|
||||
case IToken.tEQUAL:
|
||||
case IToken.tNOTEQUAL:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 80, 81);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 80, 81);
|
||||
break;
|
||||
case IToken.tGT:
|
||||
case IToken.tLT:
|
||||
|
@ -540,70 +537,70 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.tGTEQUAL:
|
||||
case IGCCToken.tMAX:
|
||||
case IGCCToken.tMIN:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 90, 91);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 90, 91);
|
||||
break;
|
||||
case IToken.tSHIFTL:
|
||||
case IToken.tSHIFTR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 100, 101);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 100, 101);
|
||||
break;
|
||||
case IToken.tPLUS:
|
||||
case IToken.tMINUS:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 110, 111);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 110, 111);
|
||||
break;
|
||||
case IToken.tSTAR:
|
||||
case IToken.tDIV:
|
||||
case IToken.tMOD:
|
||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 120, 121);
|
||||
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 120, 121);
|
||||
break;
|
||||
default:
|
||||
break loop;
|
||||
}
|
||||
|
||||
consume(); // consume operator
|
||||
lastExpression= castExpression(true); // next cast expression
|
||||
consume(); // consume operator
|
||||
lastExpression= castExpression(CastExprCtx.eBExpr); // next cast expression
|
||||
}
|
||||
|
||||
// Check for incomplete conditional expression
|
||||
if (lt1 != IToken.tEOC && conditionCount > 0)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
return buildExpression(lastComponent, lastExpression);
|
||||
return buildExpression(lastOperator, lastExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression unaryExpression(boolean inBinary) throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression unaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
switch (LT(1)) {
|
||||
case IToken.tSTAR:
|
||||
return unarayExpression(IASTUnaryExpression.op_star, inBinary);
|
||||
return unaryExpression(IASTUnaryExpression.op_star, ctx);
|
||||
case IToken.tAMPER:
|
||||
return unarayExpression(IASTUnaryExpression.op_amper, inBinary);
|
||||
return unaryExpression(IASTUnaryExpression.op_amper, ctx);
|
||||
case IToken.tPLUS:
|
||||
return unarayExpression(IASTUnaryExpression.op_plus, inBinary);
|
||||
return unaryExpression(IASTUnaryExpression.op_plus, ctx);
|
||||
case IToken.tMINUS:
|
||||
return unarayExpression(IASTUnaryExpression.op_minus, inBinary);
|
||||
return unaryExpression(IASTUnaryExpression.op_minus, ctx);
|
||||
case IToken.tNOT:
|
||||
return unarayExpression(IASTUnaryExpression.op_not, inBinary);
|
||||
return unaryExpression(IASTUnaryExpression.op_not, ctx);
|
||||
case IToken.tBITCOMPLEMENT:
|
||||
return unarayExpression(IASTUnaryExpression.op_tilde, inBinary);
|
||||
return unaryExpression(IASTUnaryExpression.op_tilde, ctx);
|
||||
case IToken.tINCR:
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixIncr, inBinary);
|
||||
return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx);
|
||||
case IToken.tDECR:
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixDecr, inBinary);
|
||||
return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx);
|
||||
case IToken.t_sizeof:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, inBinary);
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx);
|
||||
case IGCCToken.t_typeof:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, inBinary);
|
||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, ctx);
|
||||
case IGCCToken.t___alignof__:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, inBinary);
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx);
|
||||
default:
|
||||
return postfixExpression();
|
||||
return postfixExpression(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
protected IASTExpression postfixExpression() throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression postfixExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
IASTExpression firstExpression = null;
|
||||
switch (LT(1)) {
|
||||
case IToken.tLPAREN:
|
||||
|
@ -625,11 +622,11 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
} catch (BacktrackException bt) {
|
||||
}
|
||||
backup(m);
|
||||
firstExpression= primaryExpression();
|
||||
firstExpression= primaryExpression(ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
firstExpression = primaryExpression();
|
||||
firstExpression = primaryExpression(ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -719,7 +716,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression primaryExpression() throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression primaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
IToken t = null;
|
||||
IASTLiteralExpression literalExpression = null;
|
||||
switch (LT(1)) {
|
||||
|
@ -755,7 +752,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return compoundStatementExpression();
|
||||
}
|
||||
t = consume();
|
||||
IASTExpression lhs = expression(true, true); // instead of expression(), to keep the stack smaller
|
||||
IASTExpression lhs = expression(ExprKind.eExpression); // instead of expression(), to keep the stack smaller
|
||||
int finalOffset = 0;
|
||||
switch (LT(1)) {
|
||||
case IToken.tRPAREN:
|
||||
|
@ -1085,7 +1082,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
throwBacktrack(LA(1));
|
||||
|
||||
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, false);
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, CastExprCtx.eNotBExpr);
|
||||
|
||||
encounteredTypename= true;
|
||||
endOffset= calculateEndOffset(typeofExpression);
|
||||
|
@ -1705,7 +1702,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
if (LT(1) != IToken.tRBRACKET) {
|
||||
if (!(isStatic || isRestrict || isConst || isVolatile))
|
||||
exp = assignmentExpression();
|
||||
exp = expression(ExprKind.eAssignment);
|
||||
else
|
||||
exp = constantExpression();
|
||||
}
|
||||
|
|
|
@ -150,7 +150,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
protected ICPPASTTranslationUnit translationUnit;
|
||||
|
||||
private int functionBodyCount= 0;
|
||||
private int rejectLogicalOperatorInTemplateID= 0;
|
||||
private char[] currentClassName;
|
||||
|
||||
private final ICPPNodeFactory nodeFactory;
|
||||
|
@ -181,6 +180,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
functionCallCanBeLValue= true;
|
||||
this.index= index;
|
||||
this.nodeFactory = CPPNodeFactory.getDefault();
|
||||
scanner.setSplitShiftROperator(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -195,15 +195,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
throw backtrack;
|
||||
}
|
||||
|
||||
protected IASTName idExpression() throws EndOfFileException, BacktrackException {
|
||||
try {
|
||||
rejectLogicalOperatorInTemplateID++;
|
||||
return qualifiedName();
|
||||
} finally {
|
||||
rejectLogicalOperatorInTemplateID--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a name.
|
||||
* name ::= ("::")? name2 ("::" name2)*
|
||||
|
@ -211,7 +202,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
*
|
||||
* @throws BacktrackException request a backtrack
|
||||
*/
|
||||
private IASTName qualifiedName() throws BacktrackException, EndOfFileException {
|
||||
private IASTName qualifiedName(CastExprCtx ctx) throws BacktrackException, EndOfFileException {
|
||||
ICPPASTQualifiedName qname= null;
|
||||
IASTName name= null;
|
||||
final int offset= LA(1).getOffset();
|
||||
|
@ -261,7 +252,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
haveName= true;
|
||||
name= addTemplateArguments(name);
|
||||
name= addTemplateArguments(name, ctx);
|
||||
endOffset= calculateEndOffset(name);
|
||||
if (qname != null) {
|
||||
qname.addName(name);
|
||||
|
@ -309,24 +300,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return name;
|
||||
}
|
||||
|
||||
private IASTName addTemplateArguments(IASTName templateName) throws EndOfFileException, BacktrackException {
|
||||
if (!canBeTemplateArguments())
|
||||
return templateName;
|
||||
private IASTName addTemplateArguments(IASTName templateName, CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
boolean isAmbiguous= false;
|
||||
switch(canBeTemplateArguments(ctx)) {
|
||||
case -1:
|
||||
return templateName;
|
||||
case 0:
|
||||
isAmbiguous= true;
|
||||
break;
|
||||
}
|
||||
|
||||
IToken secondMark = mark();
|
||||
consume(IToken.tLT);
|
||||
try {
|
||||
// bug 229062: content assist after '<' needs to prefer to backtrack here
|
||||
if (rejectLogicalOperatorInTemplateID == 1) {
|
||||
final int lt1= LT(1);
|
||||
if (lt1 == IToken.tCOMPLETION || lt1 == IToken.tEOC) {
|
||||
throw backtrack;
|
||||
}
|
||||
}
|
||||
|
||||
List<IASTNode> list = templateArgumentList();
|
||||
List<IASTNode> list = templateArgumentList(isAmbiguous);
|
||||
IToken end= LA(1);
|
||||
switch(end.getType()) {
|
||||
case IToken.tGT_in_SHIFTR:
|
||||
case IToken.tGT:
|
||||
consume();
|
||||
break;
|
||||
|
@ -360,34 +350,109 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
/**
|
||||
* Makes a fast check whether there could be template arguments.
|
||||
*/
|
||||
private boolean canBeTemplateArguments() throws EndOfFileException, BacktrackException {
|
||||
private int canBeTemplateArguments(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
if (LTcatchEOF(1) != IToken.tLT)
|
||||
return false;
|
||||
|
||||
return -1;
|
||||
|
||||
final IToken mark= mark();
|
||||
try {
|
||||
consume();
|
||||
int nk= 0;
|
||||
int depth= 0;
|
||||
int angleDepth= 0;
|
||||
int limit= 100;
|
||||
int limit= 10000;
|
||||
|
||||
while(--limit > 0) {
|
||||
switch(consume().getType()) {
|
||||
case IToken.tEOC:
|
||||
case IToken.tCOMPLETION:
|
||||
return true;
|
||||
return ctx == CastExprCtx.eNotBExpr ? 0 : -1;
|
||||
|
||||
case IToken.tLT:
|
||||
if (nk == 0) {
|
||||
angleDepth++;
|
||||
}
|
||||
break;
|
||||
case IToken.tGT_in_SHIFTR:
|
||||
case IToken.tGT:
|
||||
if (nk == 0) {
|
||||
if (--angleDepth < 0) {
|
||||
final int lt1= LTcatchEOF(1);
|
||||
return (lt1 != IToken.tINTEGER && lt1 != IToken.tFLOATINGPT);
|
||||
if (ctx == CastExprCtx.eNotBExpr)
|
||||
return 1;
|
||||
|
||||
int lt1= LTcatchEOF(1);
|
||||
if (lt1 == IToken.tGT_in_SHIFTR) {
|
||||
if (ctx != CastExprCtx.eBExprInTmplID)
|
||||
return -1;
|
||||
// do the same check for the enclosing template
|
||||
lt1= LTcatchEOF(2);
|
||||
}
|
||||
switch(lt1) {
|
||||
// can be some cast-expression or continuation after template-id
|
||||
case IToken.tCOLONCOLON: // CT<int>::member
|
||||
case IToken.tLPAREN: // ft<int>(args)
|
||||
return 0;
|
||||
// end of an expression
|
||||
// unary expression
|
||||
case IToken.tMINUS:
|
||||
case IToken.tPLUS:
|
||||
case IToken.tAMPER:
|
||||
case IToken.tSTAR:
|
||||
case IToken.tNOT:
|
||||
case IToken.tBITCOMPLEMENT:
|
||||
case IToken.tINCR:
|
||||
case IToken.tDECR:
|
||||
case IToken.t_new:
|
||||
case IToken.t_delete:
|
||||
case IToken.t_sizeof:
|
||||
case IGCCToken.t_typeof:
|
||||
case IGCCToken.t___alignof__:
|
||||
// postfix expression
|
||||
case IToken.t_typename:
|
||||
case IToken.t_char:
|
||||
case IToken.t_wchar_t:
|
||||
case IToken.t_bool:
|
||||
case IToken.t_short:
|
||||
case IToken.t_int:
|
||||
case IToken.t_long:
|
||||
case IToken.t_signed:
|
||||
case IToken.t_unsigned:
|
||||
case IToken.t_float:
|
||||
case IToken.t_double:
|
||||
case IToken.t_dynamic_cast:
|
||||
case IToken.t_static_cast:
|
||||
case IToken.t_reinterpret_cast:
|
||||
case IToken.t_const_cast:
|
||||
case IToken.t_typeid:
|
||||
// primary expression
|
||||
case IToken.tINTEGER:
|
||||
case IToken.tFLOATINGPT:
|
||||
case IToken.tSTRING:
|
||||
case IToken.tLSTRING:
|
||||
case IToken.tUTF16STRING:
|
||||
case IToken.tUTF32STRING:
|
||||
case IToken.tCHAR:
|
||||
case IToken.tLCHAR:
|
||||
case IToken.tUTF16CHAR:
|
||||
case IToken.tUTF32CHAR:
|
||||
case IToken.t_false:
|
||||
case IToken.t_true:
|
||||
case IToken.t_this:
|
||||
case IToken.tIDENTIFIER:
|
||||
case IToken.t_operator:
|
||||
case IToken.tCOMPLETION:
|
||||
return -1;
|
||||
// ending an expression
|
||||
case IToken.tSEMI:
|
||||
case IToken.tCOMMA:
|
||||
case IToken.tRBRACE:
|
||||
case IToken.tRBRACKET:
|
||||
case IToken.tRPAREN:
|
||||
return 1;
|
||||
// don't know
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -426,31 +491,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.tLBRACE:
|
||||
case IToken.tRBRACE:
|
||||
if (nk == 0) {
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return 0;
|
||||
} finally {
|
||||
backup(mark);
|
||||
}
|
||||
}
|
||||
|
||||
private List<IASTNode> templateArgumentList() throws EndOfFileException, BacktrackException {
|
||||
private List<IASTNode> templateArgumentList(boolean isAmbiguous) throws EndOfFileException, BacktrackException {
|
||||
IToken start = LA(1);
|
||||
int startingOffset = start.getOffset();
|
||||
int endOffset = 0;
|
||||
start = null;
|
||||
List<IASTNode> list = new ArrayList<IASTNode>();
|
||||
final BinaryExprCtx exprCtx = isAmbiguous ? BinaryExprCtx.eAmbigTmplID : BinaryExprCtx.eTmplID;
|
||||
|
||||
boolean failed = false;
|
||||
|
||||
while (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
|
||||
int lt1= LT(1);
|
||||
while (lt1 != IToken.tGT && lt1 != IToken.tGT_in_SHIFTR && lt1 != IToken.tEOC) {
|
||||
IToken argStart = mark();
|
||||
IASTTypeId typeId = typeId(DeclarationOptions.TYPEID);
|
||||
|
||||
if(typeId != null && (LT(1)==IToken.tCOMMA || LT(1)==IToken.tGT || LT(1)==IToken.tEOC)) {
|
||||
lt1 = LT(1);
|
||||
if(typeId != null && (lt1==IToken.tCOMMA || lt1==IToken.tGT || lt1 == IToken.tGT_in_SHIFTR || lt1==IToken.tEOC)) {
|
||||
// potentially a type-id - check for id-expression ambiguity
|
||||
IToken typeIdEnd= mark();
|
||||
try {
|
||||
|
@ -470,7 +537,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
throw backtrack;
|
||||
|
||||
backup(argStart);
|
||||
IASTExpression expression = expression(false, true, true);
|
||||
IASTExpression expression = expression(ExprKind.eAssignment, exprCtx);
|
||||
if (expression instanceof IASTIdExpression) {
|
||||
if (mark() != typeIdEnd)
|
||||
throw backtrack;
|
||||
|
@ -491,13 +558,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
} else {
|
||||
// not a type-id - try as expression
|
||||
backup(argStart);
|
||||
IASTExpression expression = expression(false, true, true);
|
||||
IASTExpression expression = expression(ExprKind.eAssignment, exprCtx);
|
||||
list.add(expression);
|
||||
}
|
||||
|
||||
if (LT(1) == IToken.tCOMMA) {
|
||||
lt1= LT(1);
|
||||
if (lt1 == IToken.tCOMMA) {
|
||||
consume();
|
||||
} else if (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
|
||||
lt1= LT(1);
|
||||
} else if (lt1 != IToken.tGT && lt1 != IToken.tGT_in_SHIFTR && lt1 != IToken.tEOC) {
|
||||
failed = true;
|
||||
endOffset = LA(1).getEndOffset();
|
||||
break;
|
||||
|
@ -539,6 +608,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
op= OverloadableOperator.valueOf(t);
|
||||
}
|
||||
break;
|
||||
case IToken.tGT_in_SHIFTR:
|
||||
consume();
|
||||
endOffset= consume(IToken.tGT_in_SHIFTR).getEndOffset();
|
||||
op= OverloadableOperator.SHIFTR;
|
||||
break;
|
||||
default:
|
||||
op= OverloadableOperator.valueOf(LA(1));
|
||||
if (op != null) {
|
||||
|
@ -564,30 +638,36 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information for the parser, whether a binary expression is parsed in the context of a
|
||||
* template-id an ambiguous template-id (one where the '<' could be a greater sign) or
|
||||
* else where.
|
||||
*/
|
||||
private enum BinaryExprCtx {eTmplID, eAmbigTmplID, eNoTmplID}
|
||||
|
||||
@Override
|
||||
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
|
||||
return expression(true, true, false);
|
||||
return expression(ExprKind.eExpression, BinaryExprCtx.eNoTmplID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException {
|
||||
return expression(false, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
|
||||
return expression(false, false, false);
|
||||
return expression(ExprKind.eConstant, BinaryExprCtx.eNoTmplID);
|
||||
}
|
||||
|
||||
private IASTExpression expression(boolean allowComma, boolean allowAssignment, boolean onTopOfTemplateArgs) throws EndOfFileException, BacktrackException {
|
||||
private IASTExpression expression(final ExprKind kind, final BinaryExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
final boolean allowComma= kind==ExprKind.eExpression;
|
||||
boolean allowAssignment= kind !=ExprKind.eConstant;
|
||||
final CastExprCtx castCtx= ctx == BinaryExprCtx.eNoTmplID ? CastExprCtx.eBExpr : CastExprCtx.eBExprInTmplID;
|
||||
|
||||
if (allowAssignment && LT(1) == IToken.t_throw) {
|
||||
return throwExpression();
|
||||
}
|
||||
|
||||
int lt1;
|
||||
int conditionCount= 0;
|
||||
CastExpressionOp lastComponent= null;
|
||||
IASTExpression expr= castExpression(true);
|
||||
BinaryOperator lastOperator= null;
|
||||
IASTExpression expr= castExpression(castCtx);
|
||||
|
||||
loop: while(true) {
|
||||
// typically after a binary operator there cannot be a throw expression
|
||||
|
@ -595,13 +675,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
lt1= LT(1);
|
||||
switch(lt1) {
|
||||
case IToken.tQUESTION:
|
||||
if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) {
|
||||
if (ctx == BinaryExprCtx.eAmbigTmplID) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
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);
|
||||
// Precedence: 25 is lower than precedence of logical or; 0 is lower than precedence of expression
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 25, 0);
|
||||
if (LT(2) == IToken.tCOLON) {
|
||||
// Gnu extension: The expression after '?' can be omitted.
|
||||
consume(); // Consume operator
|
||||
|
@ -618,7 +698,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
// <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);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 0, 15);
|
||||
allowAssignment= true; // assignment expressions will be subsumed by the conditional expression
|
||||
allowThrow= true;
|
||||
break;
|
||||
|
@ -628,7 +708,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (!allowComma && conditionCount == 0)
|
||||
break loop;
|
||||
// Lowest precedence except inside the conditional expression
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 10, 11);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 10, 11);
|
||||
break;
|
||||
|
||||
case IToken.tASSIGN:
|
||||
|
@ -645,36 +725,36 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (!allowAssignment && conditionCount == 0)
|
||||
break loop;
|
||||
// Assignments group right to left
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 21, 20);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 21, 20);
|
||||
break;
|
||||
|
||||
case IToken.tOR:
|
||||
if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) {
|
||||
if (ctx == BinaryExprCtx.eAmbigTmplID) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 30, 31);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 30, 31);
|
||||
break;
|
||||
case IToken.tAND:
|
||||
if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) {
|
||||
if (ctx == BinaryExprCtx.eAmbigTmplID) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 40, 41);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 40, 41);
|
||||
break;
|
||||
case IToken.tBITOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 50, 51);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 50, 51);
|
||||
break;
|
||||
case IToken.tXOR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 60, 61);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 60, 61);
|
||||
break;
|
||||
case IToken.tAMPER:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 70, 71);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 70, 71);
|
||||
break;
|
||||
case IToken.tEQUAL:
|
||||
case IToken.tNOTEQUAL:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 80, 81);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 80, 81);
|
||||
break;
|
||||
case IToken.tGT:
|
||||
if (onTopOfTemplateArgs)
|
||||
if (ctx != BinaryExprCtx.eNoTmplID)
|
||||
break loop;
|
||||
//$FALL-THROUGH$
|
||||
case IToken.tLT:
|
||||
|
@ -682,24 +762,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.tGTEQUAL:
|
||||
case IGCCToken.tMAX:
|
||||
case IGCCToken.tMIN:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 90, 91);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 90, 91);
|
||||
break;
|
||||
case IToken.tSHIFTL:
|
||||
case IToken.tGT_in_SHIFTR:
|
||||
if (ctx != BinaryExprCtx.eNoTmplID)
|
||||
break loop;
|
||||
if (LT(2) != IToken.tGT_in_SHIFTR) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
lt1= IToken.tSHIFTR; // convert back
|
||||
consume(); // consume the extra token
|
||||
//$FALL-THROUGH$
|
||||
case IToken.tSHIFTL:
|
||||
case IToken.tSHIFTR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 100, 101);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 100, 101);
|
||||
break;
|
||||
case IToken.tPLUS:
|
||||
case IToken.tMINUS:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 110, 111);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 110, 111);
|
||||
break;
|
||||
case IToken.tSTAR:
|
||||
case IToken.tDIV:
|
||||
case IToken.tMOD:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 120, 121);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 120, 121);
|
||||
break;
|
||||
case IToken.tDOTSTAR:
|
||||
case IToken.tARROWSTAR:
|
||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 130, 131);
|
||||
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 130, 131);
|
||||
break;
|
||||
default:
|
||||
break loop;
|
||||
|
@ -716,14 +805,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
break loop;
|
||||
}
|
||||
}
|
||||
expr= castExpression(true); // next cast expression
|
||||
expr= castExpression(castCtx); // next cast expression
|
||||
}
|
||||
|
||||
// Check for incomplete conditional expression
|
||||
if (lt1 != IToken.tEOC && conditionCount > 0)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
return buildExpression(lastComponent, expr);
|
||||
return buildExpression(lastOperator, expr);
|
||||
}
|
||||
|
||||
private IASTExpression throwExpression() throws EndOfFileException, BacktrackException {
|
||||
|
@ -759,7 +848,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
consume(IToken.tRBRACKET);
|
||||
vectored = true;
|
||||
}
|
||||
IASTExpression castExpression = castExpression(false);
|
||||
IASTExpression castExpression = castExpression(CastExprCtx.eNotBExpr);
|
||||
ICPPASTDeleteExpression deleteExpression = nodeFactory.newDeleteExpression(castExpression);
|
||||
((ASTNode) deleteExpression).setOffsetAndLength(startingOffset, calculateEndOffset(castExpression) - startingOffset);
|
||||
deleteExpression.setIsGlobal(global);
|
||||
|
@ -901,24 +990,24 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
|
||||
@Override
|
||||
protected IASTExpression unaryExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression unaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
switch (LT(1)) {
|
||||
case IToken.tSTAR:
|
||||
return unarayExpression(IASTUnaryExpression.op_star, inBinaryExpression);
|
||||
return unaryExpression(IASTUnaryExpression.op_star, ctx);
|
||||
case IToken.tAMPER:
|
||||
return unarayExpression(IASTUnaryExpression.op_amper, inBinaryExpression);
|
||||
return unaryExpression(IASTUnaryExpression.op_amper, ctx);
|
||||
case IToken.tPLUS:
|
||||
return unarayExpression(IASTUnaryExpression.op_plus, inBinaryExpression);
|
||||
return unaryExpression(IASTUnaryExpression.op_plus, ctx);
|
||||
case IToken.tMINUS:
|
||||
return unarayExpression(IASTUnaryExpression.op_minus, inBinaryExpression);
|
||||
return unaryExpression(IASTUnaryExpression.op_minus, ctx);
|
||||
case IToken.tNOT:
|
||||
return unarayExpression(IASTUnaryExpression.op_not, inBinaryExpression);
|
||||
return unaryExpression(IASTUnaryExpression.op_not, ctx);
|
||||
case IToken.tBITCOMPLEMENT:
|
||||
return unarayExpression(IASTUnaryExpression.op_tilde, inBinaryExpression);
|
||||
return unaryExpression(IASTUnaryExpression.op_tilde, ctx);
|
||||
case IToken.tINCR:
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixIncr, inBinaryExpression);
|
||||
return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx);
|
||||
case IToken.tDECR:
|
||||
return unarayExpression(IASTUnaryExpression.op_prefixDecr, inBinaryExpression);
|
||||
return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx);
|
||||
case IToken.t_new:
|
||||
return newExpression();
|
||||
case IToken.t_delete:
|
||||
|
@ -930,23 +1019,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.t_delete:
|
||||
return deleteExpression();
|
||||
default:
|
||||
return postfixExpression(inBinaryExpression);
|
||||
return postfixExpression(ctx);
|
||||
}
|
||||
case IToken.t_sizeof:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, inBinaryExpression);
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx);
|
||||
case IGCCToken.t_typeof:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, inBinaryExpression);
|
||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, ctx);
|
||||
case IGCCToken.t___alignof__:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, inBinaryExpression);
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx);
|
||||
default:
|
||||
return postfixExpression(inBinaryExpression);
|
||||
return postfixExpression(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
private IASTExpression postfixExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException {
|
||||
private IASTExpression postfixExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
IASTExpression firstExpression = null;
|
||||
boolean isTemplate = false;
|
||||
|
||||
|
@ -970,7 +1059,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
} catch (BacktrackException bt) {
|
||||
}
|
||||
backup(m);
|
||||
firstExpression= primaryExpression();
|
||||
firstExpression= primaryExpression(ctx);
|
||||
break;
|
||||
|
||||
case IToken.t_typename:
|
||||
|
@ -981,7 +1070,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
consume();
|
||||
templateTokenConsumed = true;
|
||||
}
|
||||
IASTName name = idExpression();
|
||||
IASTName name = qualifiedName(CastExprCtx.eNotBExpr); // treat as not in binary to force template arguments
|
||||
if (LT(1) != IToken.tLPAREN) {
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
|
@ -1036,11 +1125,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.t_typeid:
|
||||
int so = consume().getOffset();
|
||||
firstExpression = parseTypeidInParenthesisOrUnaryExpression(true, so,
|
||||
ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid, inBinaryExpression);
|
||||
ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid, ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
firstExpression = primaryExpression();
|
||||
firstExpression = primaryExpression(ctx);
|
||||
break;
|
||||
}
|
||||
IASTExpression secondExpression = null;
|
||||
|
@ -1107,7 +1196,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
isTemplate = true;
|
||||
}
|
||||
|
||||
IASTName name = idExpression();
|
||||
IASTName name = qualifiedName(ctx);
|
||||
|
||||
if (name == null)
|
||||
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
||||
|
@ -1130,7 +1219,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
isTemplate = true;
|
||||
}
|
||||
|
||||
name = idExpression();
|
||||
name = qualifiedName(ctx);
|
||||
|
||||
if (name == null)
|
||||
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
||||
|
@ -1185,7 +1274,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
|
||||
@Override
|
||||
protected IASTExpression primaryExpression() throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression primaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
IToken t = null;
|
||||
IASTLiteralExpression literalExpression = null;
|
||||
switch (LT(1)) {
|
||||
|
@ -1238,7 +1327,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
t = consume();
|
||||
int finalOffset= 0;
|
||||
IASTExpression lhs= expression(true, true, false); // instead of expression(), to keep the stack smaller
|
||||
IASTExpression lhs= expression(ExprKind.eExpression, BinaryExprCtx.eNoTmplID); // instead of expression(), to keep the stack smaller
|
||||
switch (LT(1)) {
|
||||
case IToken.tRPAREN:
|
||||
case IToken.tEOC:
|
||||
|
@ -1253,7 +1342,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.t_operator:
|
||||
case IToken.tCOMPLETION:
|
||||
case IToken.tBITCOMPLEMENT: {
|
||||
IASTName name = idExpression();
|
||||
IASTName name = qualifiedName(ctx);
|
||||
IASTIdExpression idExpression = nodeFactory.newIdExpression(name);
|
||||
((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset()
|
||||
+ ((ASTNode) name).getLength() - ((ASTNode) name).getOffset());
|
||||
|
@ -1320,7 +1409,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.tIDENTIFIER:
|
||||
case IToken.tCOLONCOLON:
|
||||
case IToken.tCOMPLETION:
|
||||
name = qualifiedName();
|
||||
name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||
break;
|
||||
default:
|
||||
throwBacktrack(offset, endOffset - offset);
|
||||
|
@ -1351,7 +1440,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
consume();
|
||||
}
|
||||
|
||||
IASTName name = idExpression();
|
||||
IASTName name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||
int end;
|
||||
switch (LT(1)) {
|
||||
case IToken.tSEMI:
|
||||
|
@ -1469,7 +1558,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
List<ICPPASTTemplateParameter> parms= templateParameterList();
|
||||
consume(IToken.tGT);
|
||||
consume(IToken.tGT, IToken.tGT_in_SHIFTR);
|
||||
IASTDeclaration d = declaration(option);
|
||||
ICPPASTTemplateDeclaration templateDecl = nodeFactory.newTemplateDeclaration(d);
|
||||
((ASTNode) templateDecl).setOffsetAndLength(firstToken.getOffset(), calculateEndOffset(d) - firstToken.getOffset());
|
||||
|
@ -1503,7 +1592,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
for (;;) {
|
||||
final int lt1= LT(1);
|
||||
if (lt1 == IToken.tGT || lt1 == IToken.tEOC)
|
||||
if (lt1 == IToken.tGT || lt1 == IToken.tEOC || lt1 == IToken.tGT_in_SHIFTR)
|
||||
return returnValue;
|
||||
if (lt1 == IToken.t_class || lt1 == IToken.t_typename) {
|
||||
IToken startingToken = LA(1);
|
||||
|
@ -1537,7 +1626,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
consume(IToken.tLT);
|
||||
|
||||
List<ICPPASTTemplateParameter> subResult = templateParameterList();
|
||||
consume(IToken.tGT);
|
||||
consume(IToken.tGT, IToken.tGT_in_SHIFTR);
|
||||
int last = consume(IToken.t_class).getEndOffset();
|
||||
IASTName identifierName = null;
|
||||
IASTExpression optionalExpression = null;
|
||||
|
@ -1547,7 +1636,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
last = calculateEndOffset(identifierName);
|
||||
if (LT(1) == IToken.tASSIGN) { // optional = type-id
|
||||
consume();
|
||||
optionalExpression = primaryExpression();
|
||||
optionalExpression = primaryExpression(CastExprCtx.eNotBExpr);
|
||||
last = calculateEndOffset(optionalExpression);
|
||||
}
|
||||
} else
|
||||
|
@ -1690,7 +1779,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return null;
|
||||
}
|
||||
|
||||
IASTName qualifiedName= qualifiedName();
|
||||
IASTName qualifiedName= qualifiedName(CastExprCtx.eNotBExpr);
|
||||
endOffset = consume(IToken.tSEMI).getEndOffset();
|
||||
|
||||
ICPPASTNamespaceAlias alias = nodeFactory.newNamespaceAlias(name, qualifiedName);
|
||||
|
@ -1892,7 +1981,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
consume();
|
||||
ctorLoop: for (;;) {
|
||||
int offset= LA(1).getOffset();
|
||||
IASTName name = qualifiedName();
|
||||
IASTName name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||
|
||||
int endOffset;
|
||||
IASTExpression expressionList = null;
|
||||
|
@ -2161,7 +2250,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (encounteredTypename || encounteredRawType)
|
||||
break declSpecifiers;
|
||||
consume();
|
||||
identifier= qualifiedName();
|
||||
identifier= qualifiedName(CastExprCtx.eNotBExpr);
|
||||
endOffset= calculateEndOffset(identifier);
|
||||
isTypename = true;
|
||||
encounteredTypename= true;
|
||||
|
@ -2180,7 +2269,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
}
|
||||
|
||||
identifier= qualifiedName();
|
||||
identifier= qualifiedName(CastExprCtx.eNotBExpr);
|
||||
if (identifier.getLookupKey().length == 0 && LT(1) != IToken.tEOC)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
|
@ -2235,7 +2324,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
throwBacktrack(LA(1));
|
||||
|
||||
typeofExpression= parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, false);
|
||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, CastExprCtx.eNotBExpr);
|
||||
|
||||
encounteredTypename= true;
|
||||
endOffset= calculateEndOffset(typeofExpression);
|
||||
|
@ -2374,7 +2463,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
// if __attribute__ or __declspec occurs after struct/union/class and before the identifier
|
||||
__attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers);
|
||||
|
||||
IASTName name = qualifiedName();
|
||||
IASTName name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||
|
||||
ICPPASTElaboratedTypeSpecifier elaboratedTypeSpec = nodeFactory.newElaboratedTypeSpecifier(eck, name);
|
||||
((ASTNode) elaboratedTypeSpec).setOffsetAndLength(t.getOffset(), calculateEndOffset(name) - t.getOffset());
|
||||
|
@ -2628,51 +2717,50 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
|
||||
protected IASTInitializer initializerClause(boolean inAggregateInitializer) throws EndOfFileException, BacktrackException {
|
||||
if (LT(1) == IToken.tLBRACE) {
|
||||
int startingOffset = consume().getOffset();
|
||||
protected IASTInitializer initializerClause(boolean inAggregateInitializer) throws EndOfFileException,
|
||||
BacktrackException {
|
||||
if (LT(1) == IToken.tLBRACE) {
|
||||
int startingOffset = consume().getOffset();
|
||||
|
||||
IASTInitializerList result = nodeFactory.newInitializerList();
|
||||
((ASTNode) result).setOffset(startingOffset);
|
||||
IASTInitializerList result = nodeFactory.newInitializerList();
|
||||
((ASTNode) result).setOffset(startingOffset);
|
||||
|
||||
if (LT(1) == (IToken.tRBRACE)) {
|
||||
int l = consume().getEndOffset();
|
||||
((ASTNode) result).setLength(l - startingOffset);
|
||||
return result;
|
||||
}
|
||||
if (LT(1) == (IToken.tRBRACE)) {
|
||||
int endOffset = consume().getEndOffset();
|
||||
setRange(result, startingOffset, endOffset);
|
||||
return result;
|
||||
}
|
||||
|
||||
// otherwise it is a list of initializer clauses
|
||||
// otherwise it is a list of initializer clauses
|
||||
for (;;) {
|
||||
if (LT(1) == IToken.tRBRACE)
|
||||
break;
|
||||
|
||||
for (;;) {
|
||||
if (LT(1) == IToken.tRBRACE)
|
||||
break;
|
||||
// clause may be null, add to initializer anyways, such that the
|
||||
// actual size can be computed.
|
||||
IASTInitializer clause = initializerClause(true);
|
||||
result.addInitializer(clause);
|
||||
if (LT(1) == IToken.tRBRACE || LT(1) == IToken.tEOC)
|
||||
break;
|
||||
consume(IToken.tCOMMA);
|
||||
}
|
||||
int endOffset = consume().getEndOffset(); // tRBRACE
|
||||
setRange(result, startingOffset, endOffset);
|
||||
return result;
|
||||
}
|
||||
|
||||
// clause may be null, add to initializer anyways, such that the
|
||||
// actual size can be computed.
|
||||
IASTInitializer clause = initializerClause(true);
|
||||
result.addInitializer(clause);
|
||||
if (LT(1) == IToken.tRBRACE || LT(1) == IToken.tEOC)
|
||||
break;
|
||||
consume(IToken.tCOMMA);
|
||||
}
|
||||
int l = consume().getEndOffset(); // tRBRACE
|
||||
((ASTNode) result).setLength(l - startingOffset);
|
||||
return result;
|
||||
}
|
||||
// no brace, so try an assignment expression
|
||||
final BinaryExprCtx ctx = fInTemplateParameterList ? BinaryExprCtx.eTmplID : BinaryExprCtx.eNoTmplID;
|
||||
IASTExpression assignmentExpression = expression(ExprKind.eAssignment, ctx);
|
||||
if (inAggregateInitializer && skipTrivialExpressionsInAggregateInitializers) {
|
||||
if (!ASTQueries.canContainName(assignmentExpression))
|
||||
return null;
|
||||
}
|
||||
|
||||
// if we get this far, it means that we did not
|
||||
// try this now instead
|
||||
// assignmentExpression
|
||||
IASTExpression assignmentExpression = expression(false, true, fInTemplateParameterList);
|
||||
if (inAggregateInitializer && skipTrivialExpressionsInAggregateInitializers) {
|
||||
if (!ASTQueries.canContainName(assignmentExpression))
|
||||
return null;
|
||||
}
|
||||
|
||||
IASTInitializerExpression result = nodeFactory.newInitializerExpression(assignmentExpression);
|
||||
((ASTNode) result).setOffsetAndLength(((ASTNode) assignmentExpression));
|
||||
return result;
|
||||
}
|
||||
IASTInitializerExpression result = nodeFactory.newInitializerExpression(assignmentExpression);
|
||||
setRange(result, assignmentExpression);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -2684,7 +2772,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
IASTDeclSpecifier declSpecifier = null;
|
||||
IASTDeclarator declarator = null;
|
||||
|
||||
rejectLogicalOperatorInTemplateID++;
|
||||
try {
|
||||
Decl decl= declSpecifierSequence_initDeclarator(option, false);
|
||||
declSpecifier= decl.fDeclSpec1;
|
||||
|
@ -2694,9 +2781,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return null;
|
||||
} catch (BacktrackException bt) {
|
||||
return null;
|
||||
} finally {
|
||||
rejectLogicalOperatorInTemplateID--;
|
||||
}
|
||||
}
|
||||
IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator);
|
||||
setRange(result, offset, figureEndOffset(declSpecifier, declarator));
|
||||
return result;
|
||||
|
@ -2744,7 +2829,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (option.fRequireAbstract)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
final IASTName declaratorName= qualifiedName();
|
||||
final IASTName declaratorName= qualifiedName(CastExprCtx.eNotBExpr);
|
||||
endOffset= calculateEndOffset(declaratorName);
|
||||
return declarator(pointerOps, declaratorName, null, startingOffset, endOffset, strategy, option);
|
||||
}
|
||||
|
@ -2860,7 +2945,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
if (coloncolon != 0) {
|
||||
try {
|
||||
name= qualifiedName();
|
||||
name= qualifiedName(CastExprCtx.eNotBExpr);
|
||||
if (name.getLookupKey().length != 0) {
|
||||
backup(mark);
|
||||
return;
|
||||
|
@ -3167,7 +3252,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
// class name
|
||||
IASTName name = null;
|
||||
if (LT(1) == IToken.tIDENTIFIER)
|
||||
name = qualifiedName();
|
||||
name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||
else
|
||||
name = nodeFactory.newName();
|
||||
|
||||
|
@ -3253,7 +3338,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.tIDENTIFIER:
|
||||
case IToken.tCOMPLETION:
|
||||
// to get templates right we need to use the class as the scope
|
||||
name = qualifiedName();
|
||||
name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||
endOffset= calculateEndOffset(name);
|
||||
break;
|
||||
case IToken.tCOMMA:
|
||||
|
|
|
@ -171,6 +171,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
|
||||
private int fContentAssistLimit= -1;
|
||||
private boolean fHandledCompletion= false;
|
||||
private boolean fSplitShiftRightOperator= false;
|
||||
|
||||
// state information
|
||||
private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<PreprocessorMacro>(512);
|
||||
|
@ -238,6 +239,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
}
|
||||
|
||||
public void setSplitShiftROperator(boolean val) {
|
||||
fSplitShiftRightOperator= val;
|
||||
}
|
||||
|
||||
public void setComputeImageLocations(boolean val) {
|
||||
fLexOptions.fCreateImageLocations= val;
|
||||
|
@ -442,7 +446,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the next token from the preprocessor without concatenating string literals.
|
||||
* Returns the next token from the preprocessor without concatenating string literals
|
||||
* and also without splitting the shift-right operator.
|
||||
*/
|
||||
private Token fetchToken() throws OffsetLimitReachedException {
|
||||
if (fIsFirstFetchToken) {
|
||||
|
@ -537,7 +542,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
case IToken.tLSTRING:
|
||||
case IToken.tUTF16STRING:
|
||||
case IToken.tUTF32STRING:
|
||||
|
||||
StringType st = StringType.fromToken(tt1);
|
||||
Token t2;
|
||||
StringBuffer buf= null;
|
||||
|
@ -580,6 +584,18 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
image[image.length - 1]= '"';
|
||||
t1= new TokenWithImage(st.getTokenValue(), null, t1.getOffset(), endOffset, image);
|
||||
}
|
||||
break;
|
||||
|
||||
case IToken.tSHIFTR:
|
||||
if (fSplitShiftRightOperator) {
|
||||
int offset= t1.getOffset();
|
||||
endOffset= t1.getEndOffset();
|
||||
|
||||
t1.setType(IToken.tGT_in_SHIFTR);
|
||||
t1.setOffset(offset, offset+1);
|
||||
t2= new Token(IToken.tGT_in_SHIFTR, t1.fSource, offset+1, endOffset);
|
||||
pushbackToken(t2);
|
||||
}
|
||||
}
|
||||
|
||||
if (fLastToken != null) {
|
||||
|
|
|
@ -112,6 +112,7 @@ public class TokenUtil {
|
|||
case IToken.tSHIFTRASSIGN: return Keywords.cpSHIFTRASSIGN;
|
||||
case IToken.tSHIFTR: return Keywords.cpSHIFTR;
|
||||
case IToken.tGTEQUAL: return Keywords.cpGTEQUAL;
|
||||
case IToken.tGT_in_SHIFTR:
|
||||
case IToken.tGT: return Keywords.cpGT;
|
||||
case IToken.tSHIFTLASSIGN: return Keywords.cpSHIFTLASSIGN;
|
||||
case IToken.tELLIPSIS: return Keywords.cpELLIPSIS;
|
||||
|
|
Loading…
Add table
Reference in a new issue