mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-25 01:45:33 +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
|
// X<(1>2)> x2; // OK
|
||||||
// template<class T> class Y { };
|
// template<class T> class Y { };
|
||||||
// Y< X<1> > x3; // OK
|
// 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 {
|
public void test14_2s3() throws Exception {
|
||||||
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
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.IASTIdExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
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.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||||
|
@ -4245,4 +4246,58 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
final String code= getAboveComment();
|
final String code= getAboveComment();
|
||||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
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.IASTCastExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
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.IASTDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
|
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.IASTDoStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
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.IASTExpressionStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
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) {
|
private void checkOffsets(String exprStr, IASTExpression expr) {
|
||||||
if (expr instanceof IASTBinaryExpression) {
|
if (expr instanceof IASTBinaryExpression) {
|
||||||
IASTBinaryExpression bexpr= (IASTBinaryExpression) expr;
|
IASTBinaryExpression bexpr= (IASTBinaryExpression) expr;
|
||||||
|
@ -5484,7 +5539,24 @@ public class AST2Tests extends AST2BaseTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void polnishNotation(IASTExpression expr, StringBuilder buf) {
|
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;
|
IASTBinaryExpression bexpr= (IASTBinaryExpression) expr;
|
||||||
polnishNotation(bexpr.getOperand1(), buf);
|
polnishNotation(bexpr.getOperand1(), buf);
|
||||||
buf.append(',');
|
buf.append(',');
|
||||||
|
|
|
@ -68,12 +68,11 @@ public interface IScanner {
|
||||||
public void setContentAssistMode(int offset);
|
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.
|
* @noreference This method is not intended to be referenced by clients.
|
||||||
* @since 4.0
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
public void setSplitShiftROperator(boolean val);
|
||||||
public void setScanComments(boolean val);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turns on/off creation of image locations.
|
* 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.
|
* @noreference This method is not intended to be referenced by clients.
|
||||||
*/
|
*/
|
||||||
public int getCodeBranchNesting();
|
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 tDOT = 50;
|
||||||
int tDIVASSIGN = 51;
|
int tDIVASSIGN = 51;
|
||||||
int tDIV = 52;
|
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 #tAND} */ @Deprecated int t_and = 54;
|
||||||
/** @deprecated use {@link #tAMPERASSIGN} */ @Deprecated int t_and_eq = 55;
|
/** @deprecated use {@link #tAMPERASSIGN} */ @Deprecated int t_and_eq = 55;
|
||||||
int t_asm = 56;
|
int t_asm = 56;
|
||||||
|
|
|
@ -147,6 +147,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
return PROCESS_CONTINUE;
|
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 final int DEFAULT_DESIGNATOR_LIST_SIZE = 4;
|
||||||
protected static int parseCount = 0;
|
protected static int parseCount = 0;
|
||||||
|
@ -184,7 +191,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
protected BacktrackException backtrack = new BacktrackException();
|
protected BacktrackException backtrack = new BacktrackException();
|
||||||
|
|
||||||
protected ASTCompletionNode completionNode;
|
protected ASTCompletionNode completionNode;
|
||||||
protected IASTTypeId fTypeIdForCastAmbiguity;
|
|
||||||
|
|
||||||
private final INodeFactory nodeFactory;
|
private final INodeFactory nodeFactory;
|
||||||
private boolean fActiveCode= true;
|
private boolean fActiveCode= true;
|
||||||
|
@ -269,12 +275,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final IToken nextToken(boolean skipInactive) throws EndOfFileException {
|
private final IToken nextToken(boolean skipInactive) throws EndOfFileException {
|
||||||
IToken t= nextToken;
|
final IToken t= nextToken;
|
||||||
if (t == null) {
|
if (t != null)
|
||||||
t= fetchToken(skipInactive);
|
return t;
|
||||||
}
|
|
||||||
nextToken= t;
|
final IToken tn= fetchToken(skipInactive);
|
||||||
return t;
|
nextToken= tn;
|
||||||
|
return tn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final IToken lookaheadToken(int i, boolean skipInactive) throws EndOfFileException {
|
private final IToken lookaheadToken(int i, boolean skipInactive) throws EndOfFileException {
|
||||||
|
@ -457,6 +464,18 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
return result;
|
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
|
* 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.
|
* 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.
|
* 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.
|
* This is done right to left, such that a tree of variants can be built.
|
||||||
*/
|
*/
|
||||||
protected static class CastExpressionOp {
|
protected static class BinaryOperator {
|
||||||
final CastExpressionOp fLeft;
|
|
||||||
final IASTExpression fExpression;
|
|
||||||
final int fOperatorToken;
|
final int fOperatorToken;
|
||||||
final int fLeftPrecedence;
|
final int fLeftPrecedence;
|
||||||
final int fRightPrecedence;
|
final int fRightPrecedence;
|
||||||
|
BinaryOperator fNext;
|
||||||
|
IASTExpression fExpression;
|
||||||
|
final CastAmbiguityMarker fAmbiguityMarker;
|
||||||
|
|
||||||
public CastExpressionOp(CastExpressionOp left, IASTExpression expression, int operatorToken, int leftPrecedence, int rightPrecedence) {
|
public BinaryOperator(BinaryOperator left, IASTExpression expression, int operatorToken, int leftPrecedence, int rightPrecedence) {
|
||||||
fLeft= left;
|
fNext= left;
|
||||||
fExpression= expression;
|
|
||||||
fOperatorToken= operatorToken;
|
fOperatorToken= operatorToken;
|
||||||
fLeftPrecedence= leftPrecedence;
|
fLeftPrecedence= leftPrecedence;
|
||||||
fRightPrecedence= rightPrecedence;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected final IASTExpression buildExpression(BinaryOperator leftChain, IASTExpression expr) throws BacktrackException {
|
||||||
* Helper class to temporarily store a sequence of operator followed by expression.
|
BinaryOperator rightChain= null;
|
||||||
*/
|
for (;;) {
|
||||||
private static final class OpCastExpressionStack {
|
if (leftChain == null) {
|
||||||
private IASTExpression fExpressions[]= new IASTExpression[128];
|
if (rightChain == null)
|
||||||
private int fPrecedenceAndTokens[]= new int[256];
|
return expr;
|
||||||
private int fPos=-1;
|
|
||||||
|
expr= buildExpression(expr, rightChain);
|
||||||
boolean isEmpty() {
|
rightChain= rightChain.fNext;
|
||||||
return fPos<0;
|
} else if (rightChain != null && leftChain.fRightPrecedence < rightChain.fLeftPrecedence) {
|
||||||
}
|
expr= buildExpression(expr, rightChain);
|
||||||
|
rightChain= rightChain.fNext;
|
||||||
public IASTExpression getExpression() {
|
} else {
|
||||||
return fExpressions[fPos];
|
BinaryOperator op= leftChain;
|
||||||
}
|
leftChain= leftChain.fNext;
|
||||||
|
expr= op.exchange(expr);
|
||||||
public int getLeftPrecedence() {
|
op.fNext= rightChain;
|
||||||
return fPrecedenceAndTokens[2*fPos];
|
rightChain= op;
|
||||||
}
|
|
||||||
|
|
||||||
public int getOperatorToken() {
|
|
||||||
return fPrecedenceAndTokens[2*fPos+1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void push(int leftPrecedence, int operatorToken, IASTExpression trailing) {
|
|
||||||
final int pos= ++fPos;
|
|
||||||
if (pos == fExpressions.length) {
|
|
||||||
IASTExpression newExpressions[]= new IASTExpression[pos*2];
|
|
||||||
int newPrecedenceAndTokens[]= new int[pos*4];
|
|
||||||
System.arraycopy(fExpressions, 0, newExpressions, 0, pos);
|
|
||||||
System.arraycopy(fPrecedenceAndTokens, 0, newPrecedenceAndTokens, 0, 2*pos);
|
|
||||||
fExpressions= newExpressions;
|
|
||||||
fPrecedenceAndTokens= newPrecedenceAndTokens;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fExpressions[pos]= trailing;
|
|
||||||
fPrecedenceAndTokens[2*pos]= leftPrecedence;
|
|
||||||
fPrecedenceAndTokens[2*pos+1]= operatorToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pop() {
|
|
||||||
--fPos;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final IASTExpression buildExpression(CastExpressionOp exprOp1, IASTExpression expr) throws BacktrackException {
|
private IASTExpression buildExpression(IASTExpression left, BinaryOperator operator) throws BacktrackException {
|
||||||
if (exprOp1 == null)
|
int op, unaryOp= 0;
|
||||||
return expr;
|
final IASTExpression right= operator.fExpression;
|
||||||
|
switch(operator.fOperatorToken) {
|
||||||
// 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:
|
case IToken.tQUESTION:
|
||||||
if (stack == null || stack.isEmpty() || stack.getOperatorToken() != IToken.tCOLON) {
|
if (operator.fNext == null || operator.fNext.fOperatorToken != IToken.tCOLON) {
|
||||||
assert false;
|
assert false;
|
||||||
ASTNode node= (ASTNode) left;
|
ASTNode node= (ASTNode) left;
|
||||||
throwBacktrack(node.getOffset(), node.getLength());
|
throwBacktrack(node.getOffset(), node.getLength());
|
||||||
return null; // Will never be reached.
|
return null; // Will never be reached.
|
||||||
}
|
}
|
||||||
IASTExpression negative= stack.getExpression();
|
IASTExpression negative= operator.fNext.fExpression;
|
||||||
stack.pop();
|
operator.fNext= operator.fNext.fNext;
|
||||||
IASTConditionalExpression conditionalEx = nodeFactory.newConditionalExpession(left, right, negative);
|
IASTConditionalExpression conditionalEx = nodeFactory.newConditionalExpession(left, right, negative);
|
||||||
setRange(conditionalEx, left);
|
setRange(conditionalEx, left);
|
||||||
if (negative != null) {
|
if (negative != null) {
|
||||||
|
@ -1134,35 +1099,20 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
return null;
|
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));
|
IASTExpression result= buildBinaryExpression(op, left, right, calculateEndOffset(right));
|
||||||
|
final CastAmbiguityMarker am = operator.fAmbiguityMarker;
|
||||||
if (lca != null) {
|
if (am != null) {
|
||||||
assert unaryOp != 0;
|
assert unaryOp != 0;
|
||||||
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result,
|
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result,
|
||||||
lca.getTypeIdForCast(), unaryOp, lca.getUnaryOperatorOffset());
|
am.getTypeIdForCast(), unaryOp, am.getUnaryOperatorOffset());
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
return rca == null ? result : rca.updateExpression(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract IASTExpression expression() throws BacktrackException, EndOfFileException;
|
protected abstract IASTExpression expression() throws BacktrackException, EndOfFileException;
|
||||||
protected abstract IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException;
|
|
||||||
protected abstract IASTExpression constantExpression() throws BacktrackException, EndOfFileException;
|
protected abstract IASTExpression constantExpression() throws BacktrackException, EndOfFileException;
|
||||||
protected abstract IASTExpression unaryExpression(boolean inBinary) throws BacktrackException, EndOfFileException;
|
protected abstract IASTExpression unaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException;
|
||||||
protected abstract IASTExpression primaryExpression() throws BacktrackException, EndOfFileException;
|
protected abstract IASTExpression primaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException;
|
||||||
protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException;
|
protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException;
|
||||||
|
|
||||||
private final static class CastAmbiguityMarker extends ASTNode implements IASTExpression {
|
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) {
|
if (LT(1) == IToken.tLPAREN) {
|
||||||
final IToken mark= mark();
|
final IToken mark= mark();
|
||||||
final int startingOffset= mark.getOffset();
|
final int startingOffset= mark.getOffset();
|
||||||
|
@ -1211,7 +1161,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
if (typeId != null && LT(1) == IToken.tRPAREN) {
|
if (typeId != null && LT(1) == IToken.tRPAREN) {
|
||||||
consume();
|
consume();
|
||||||
boolean unaryFailed= false;
|
boolean unaryFailed= false;
|
||||||
if (inBinaryExpression) {
|
if (ctx != CastExprCtx.eNotBExpr) {
|
||||||
switch (LT(1)){
|
switch (LT(1)){
|
||||||
// ambiguity with unary operator
|
// ambiguity with unary operator
|
||||||
case IToken.tPLUS: case IToken.tMINUS:
|
case IToken.tPLUS: case IToken.tMINUS:
|
||||||
|
@ -1220,7 +1170,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
IToken markEnd= mark();
|
IToken markEnd= mark();
|
||||||
backup(mark);
|
backup(mark);
|
||||||
try {
|
try {
|
||||||
IASTExpression unary= unaryExpression(false);
|
IASTExpression unary= unaryExpression(CastExprCtx.eNotBExpr);
|
||||||
return new CastAmbiguityMarker(unary, typeId, operatorOffset);
|
return new CastAmbiguityMarker(unary, typeId, operatorOffset);
|
||||||
} catch (BacktrackException bt) {
|
} catch (BacktrackException bt) {
|
||||||
backup(markEnd);
|
backup(markEnd);
|
||||||
|
@ -1230,7 +1180,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN;
|
boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN;
|
||||||
IASTExpression rhs= castExpression(inBinaryExpression);
|
IASTExpression rhs= castExpression(ctx);
|
||||||
|
|
||||||
CastAmbiguityMarker ca= null;
|
CastAmbiguityMarker ca= null;
|
||||||
if (rhs instanceof CastAmbiguityMarker) {
|
if (rhs instanceof CastAmbiguityMarker) {
|
||||||
|
@ -1243,7 +1193,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
IToken markEnd= mark();
|
IToken markEnd= mark();
|
||||||
backup(mark);
|
backup(mark);
|
||||||
try {
|
try {
|
||||||
IASTExpression expr= primaryExpression();
|
IASTExpression expr= primaryExpression(ctx);
|
||||||
IASTFunctionCallExpression fcall = nodeFactory.newFunctionCallExpression(expr, null);
|
IASTFunctionCallExpression fcall = nodeFactory.newFunctionCallExpression(expr, null);
|
||||||
IASTAmbiguousExpression ambiguity = createAmbiguousCastVsFunctionCallExpression(result, fcall);
|
IASTAmbiguousExpression ambiguity = createAmbiguousCastVsFunctionCallExpression(result, fcall);
|
||||||
((ASTNode) ambiguity).setOffsetAndLength((ASTNode) result);
|
((ASTNode) ambiguity).setOffsetAndLength((ASTNode) result);
|
||||||
|
@ -1261,7 +1211,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
backup(mark);
|
backup(mark);
|
||||||
}
|
}
|
||||||
return unaryExpression(inBinaryExpression);
|
return unaryExpression(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract IASTTranslationUnit getTranslationUnit();
|
protected abstract IASTTranslationUnit getTranslationUnit();
|
||||||
|
@ -1386,9 +1336,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
return result;
|
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();
|
final IToken operatorToken= consume();
|
||||||
IASTExpression operand= castExpression(inBinary);
|
IASTExpression operand= castExpression(ctx);
|
||||||
|
|
||||||
CastAmbiguityMarker ca= null;
|
CastAmbiguityMarker ca= null;
|
||||||
if (operand instanceof CastAmbiguityMarker) {
|
if (operand instanceof CastAmbiguityMarker) {
|
||||||
|
@ -2185,7 +2135,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IASTExpression parseTypeidInParenthesisOrUnaryExpression(boolean exprIsLimitedToParenthesis,
|
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;
|
IASTTypeId typeid;
|
||||||
IASTExpression expr= null;
|
IASTExpression expr= null;
|
||||||
IToken typeidLA= null;
|
IToken typeidLA= null;
|
||||||
|
@ -2246,7 +2196,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
expr= expression();
|
expr= expression();
|
||||||
endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
||||||
} else {
|
} else {
|
||||||
expr= unaryExpression(inBinary);
|
expr= unaryExpression(ctx);
|
||||||
if (expr instanceof CastAmbiguityMarker) {
|
if (expr instanceof CastAmbiguityMarker) {
|
||||||
ca= (CastAmbiguityMarker) expr;
|
ca= (CastAmbiguityMarker) expr;
|
||||||
expr= ca.getExpression();
|
expr= ca.getExpression();
|
||||||
|
|
|
@ -145,7 +145,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
protected IASTInitializer cInitializerClause(boolean inAggregate) throws EndOfFileException, BacktrackException {
|
protected IASTInitializer cInitializerClause(boolean inAggregate) throws EndOfFileException, BacktrackException {
|
||||||
final int offset = LA(1).getOffset();
|
final int offset = LA(1).getOffset();
|
||||||
if (LT(1) != IToken.tLBRACE) {
|
if (LT(1) != IToken.tLBRACE) {
|
||||||
IASTExpression assignmentExpression= assignmentExpression();
|
IASTExpression assignmentExpression= expression(ExprKind.eAssignment);
|
||||||
if (inAggregate && skipTrivialExpressionsInAggregateInitializers) {
|
if (inAggregate && skipTrivialExpressionsInAggregateInitializers) {
|
||||||
if (!ASTQueries.canContainName(assignmentExpression))
|
if (!ASTQueries.canContainName(assignmentExpression))
|
||||||
return null;
|
return null;
|
||||||
|
@ -446,32 +446,29 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
|
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
|
@Override
|
||||||
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
|
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 lt1;
|
||||||
int conditionCount= 0;
|
int conditionCount= 0;
|
||||||
CastExpressionOp lastComponent= null;
|
BinaryOperator lastOperator= null;
|
||||||
IASTExpression lastExpression= castExpression(true);
|
IASTExpression lastExpression= castExpression(CastExprCtx.eBExpr);
|
||||||
loop: while(true) {
|
loop: while(true) {
|
||||||
lt1= LT(1);
|
lt1= LT(1);
|
||||||
switch(lt1) {
|
switch(lt1) {
|
||||||
case IToken.tQUESTION:
|
case IToken.tQUESTION:
|
||||||
conditionCount++;
|
conditionCount++;
|
||||||
// <logical-or> ? <expression> : <assignment-expression>
|
// <logical-or> ? <expression> : <assignment-expression>
|
||||||
// Precedence: 25 is lower than precedence of logical or; 1 is lower than precedence of expression
|
// Precedence: 25 is lower than precedence of logical or; 0 is lower than precedence of expression
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 25, 1);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 25, 0);
|
||||||
if (LT(2) == IToken.tCOLON) {
|
if (LT(2) == IToken.tCOLON) {
|
||||||
// Gnu extension: The expression after '?' can be omitted.
|
// Gnu extension: The expression after '?' can be omitted.
|
||||||
consume(); // Consume operator
|
consume(); // Consume operator
|
||||||
|
@ -487,7 +484,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
|
|
||||||
// <logical-or> ? <expression> : <assignment-expression>
|
// <logical-or> ? <expression> : <assignment-expression>
|
||||||
// Precedence: 0 is lower than precedence of expression; 15 is lower than precedence of assignment;
|
// 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
|
allowAssignment= true; // assignment expressions will be subsumed by the conditional expression
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -495,7 +492,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
if (!allowComma && conditionCount == 0)
|
if (!allowComma && conditionCount == 0)
|
||||||
break loop;
|
break loop;
|
||||||
// Lowest precedence except inside the conditional expression
|
// Lowest precedence except inside the conditional expression
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 10, 11);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 10, 11);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IToken.tASSIGN:
|
case IToken.tASSIGN:
|
||||||
|
@ -512,27 +509,27 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
if (!allowAssignment && conditionCount == 0)
|
if (!allowAssignment && conditionCount == 0)
|
||||||
break loop;
|
break loop;
|
||||||
// Assignments group right to left
|
// Assignments group right to left
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 21, 20);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 21, 20);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IToken.tOR:
|
case IToken.tOR:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 30, 31);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 30, 31);
|
||||||
break;
|
break;
|
||||||
case IToken.tAND:
|
case IToken.tAND:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 40, 41);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 40, 41);
|
||||||
break;
|
break;
|
||||||
case IToken.tBITOR:
|
case IToken.tBITOR:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 50, 51);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 50, 51);
|
||||||
break;
|
break;
|
||||||
case IToken.tXOR:
|
case IToken.tXOR:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 60, 61);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 60, 61);
|
||||||
break;
|
break;
|
||||||
case IToken.tAMPER:
|
case IToken.tAMPER:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 70, 71);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 70, 71);
|
||||||
break;
|
break;
|
||||||
case IToken.tEQUAL:
|
case IToken.tEQUAL:
|
||||||
case IToken.tNOTEQUAL:
|
case IToken.tNOTEQUAL:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 80, 81);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 80, 81);
|
||||||
break;
|
break;
|
||||||
case IToken.tGT:
|
case IToken.tGT:
|
||||||
case IToken.tLT:
|
case IToken.tLT:
|
||||||
|
@ -540,70 +537,70 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.tGTEQUAL:
|
case IToken.tGTEQUAL:
|
||||||
case IGCCToken.tMAX:
|
case IGCCToken.tMAX:
|
||||||
case IGCCToken.tMIN:
|
case IGCCToken.tMIN:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 90, 91);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 90, 91);
|
||||||
break;
|
break;
|
||||||
case IToken.tSHIFTL:
|
case IToken.tSHIFTL:
|
||||||
case IToken.tSHIFTR:
|
case IToken.tSHIFTR:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 100, 101);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 100, 101);
|
||||||
break;
|
break;
|
||||||
case IToken.tPLUS:
|
case IToken.tPLUS:
|
||||||
case IToken.tMINUS:
|
case IToken.tMINUS:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 110, 111);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 110, 111);
|
||||||
break;
|
break;
|
||||||
case IToken.tSTAR:
|
case IToken.tSTAR:
|
||||||
case IToken.tDIV:
|
case IToken.tDIV:
|
||||||
case IToken.tMOD:
|
case IToken.tMOD:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 120, 121);
|
lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 120, 121);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break loop;
|
break loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
consume(); // consume operator
|
consume(); // consume operator
|
||||||
lastExpression= castExpression(true); // next cast expression
|
lastExpression= castExpression(CastExprCtx.eBExpr); // next cast expression
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for incomplete conditional expression
|
// Check for incomplete conditional expression
|
||||||
if (lt1 != IToken.tEOC && conditionCount > 0)
|
if (lt1 != IToken.tEOC && conditionCount > 0)
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
|
|
||||||
return buildExpression(lastComponent, lastExpression);
|
return buildExpression(lastOperator, lastExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IASTExpression unaryExpression(boolean inBinary) throws EndOfFileException, BacktrackException {
|
protected IASTExpression unaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
case IToken.tSTAR:
|
case IToken.tSTAR:
|
||||||
return unarayExpression(IASTUnaryExpression.op_star, inBinary);
|
return unaryExpression(IASTUnaryExpression.op_star, ctx);
|
||||||
case IToken.tAMPER:
|
case IToken.tAMPER:
|
||||||
return unarayExpression(IASTUnaryExpression.op_amper, inBinary);
|
return unaryExpression(IASTUnaryExpression.op_amper, ctx);
|
||||||
case IToken.tPLUS:
|
case IToken.tPLUS:
|
||||||
return unarayExpression(IASTUnaryExpression.op_plus, inBinary);
|
return unaryExpression(IASTUnaryExpression.op_plus, ctx);
|
||||||
case IToken.tMINUS:
|
case IToken.tMINUS:
|
||||||
return unarayExpression(IASTUnaryExpression.op_minus, inBinary);
|
return unaryExpression(IASTUnaryExpression.op_minus, ctx);
|
||||||
case IToken.tNOT:
|
case IToken.tNOT:
|
||||||
return unarayExpression(IASTUnaryExpression.op_not, inBinary);
|
return unaryExpression(IASTUnaryExpression.op_not, ctx);
|
||||||
case IToken.tBITCOMPLEMENT:
|
case IToken.tBITCOMPLEMENT:
|
||||||
return unarayExpression(IASTUnaryExpression.op_tilde, inBinary);
|
return unaryExpression(IASTUnaryExpression.op_tilde, ctx);
|
||||||
case IToken.tINCR:
|
case IToken.tINCR:
|
||||||
return unarayExpression(IASTUnaryExpression.op_prefixIncr, inBinary);
|
return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx);
|
||||||
case IToken.tDECR:
|
case IToken.tDECR:
|
||||||
return unarayExpression(IASTUnaryExpression.op_prefixDecr, inBinary);
|
return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx);
|
||||||
case IToken.t_sizeof:
|
case IToken.t_sizeof:
|
||||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, inBinary);
|
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx);
|
||||||
case IGCCToken.t_typeof:
|
case IGCCToken.t_typeof:
|
||||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, inBinary);
|
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, ctx);
|
||||||
case IGCCToken.t___alignof__:
|
case IGCCToken.t___alignof__:
|
||||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, inBinary);
|
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx);
|
||||||
default:
|
default:
|
||||||
return postfixExpression();
|
return postfixExpression(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IASTExpression postfixExpression() throws EndOfFileException, BacktrackException {
|
protected IASTExpression postfixExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||||
IASTExpression firstExpression = null;
|
IASTExpression firstExpression = null;
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
case IToken.tLPAREN:
|
case IToken.tLPAREN:
|
||||||
|
@ -625,11 +622,11 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
} catch (BacktrackException bt) {
|
} catch (BacktrackException bt) {
|
||||||
}
|
}
|
||||||
backup(m);
|
backup(m);
|
||||||
firstExpression= primaryExpression();
|
firstExpression= primaryExpression(ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
firstExpression = primaryExpression();
|
firstExpression = primaryExpression(ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,7 +716,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IASTExpression primaryExpression() throws EndOfFileException, BacktrackException {
|
protected IASTExpression primaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||||
IToken t = null;
|
IToken t = null;
|
||||||
IASTLiteralExpression literalExpression = null;
|
IASTLiteralExpression literalExpression = null;
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
|
@ -755,7 +752,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return compoundStatementExpression();
|
return compoundStatementExpression();
|
||||||
}
|
}
|
||||||
t = consume();
|
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;
|
int finalOffset = 0;
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
case IToken.tRPAREN:
|
case IToken.tRPAREN:
|
||||||
|
@ -1085,7 +1082,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
|
|
||||||
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, false);
|
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, CastExprCtx.eNotBExpr);
|
||||||
|
|
||||||
encounteredTypename= true;
|
encounteredTypename= true;
|
||||||
endOffset= calculateEndOffset(typeofExpression);
|
endOffset= calculateEndOffset(typeofExpression);
|
||||||
|
@ -1705,7 +1702,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
|
|
||||||
if (LT(1) != IToken.tRBRACKET) {
|
if (LT(1) != IToken.tRBRACKET) {
|
||||||
if (!(isStatic || isRestrict || isConst || isVolatile))
|
if (!(isStatic || isRestrict || isConst || isVolatile))
|
||||||
exp = assignmentExpression();
|
exp = expression(ExprKind.eAssignment);
|
||||||
else
|
else
|
||||||
exp = constantExpression();
|
exp = constantExpression();
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
protected ICPPASTTranslationUnit translationUnit;
|
protected ICPPASTTranslationUnit translationUnit;
|
||||||
|
|
||||||
private int functionBodyCount= 0;
|
private int functionBodyCount= 0;
|
||||||
private int rejectLogicalOperatorInTemplateID= 0;
|
|
||||||
private char[] currentClassName;
|
private char[] currentClassName;
|
||||||
|
|
||||||
private final ICPPNodeFactory nodeFactory;
|
private final ICPPNodeFactory nodeFactory;
|
||||||
|
@ -181,6 +180,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
functionCallCanBeLValue= true;
|
functionCallCanBeLValue= true;
|
||||||
this.index= index;
|
this.index= index;
|
||||||
this.nodeFactory = CPPNodeFactory.getDefault();
|
this.nodeFactory = CPPNodeFactory.getDefault();
|
||||||
|
scanner.setSplitShiftROperator(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -195,15 +195,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
throw backtrack;
|
throw backtrack;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IASTName idExpression() throws EndOfFileException, BacktrackException {
|
|
||||||
try {
|
|
||||||
rejectLogicalOperatorInTemplateID++;
|
|
||||||
return qualifiedName();
|
|
||||||
} finally {
|
|
||||||
rejectLogicalOperatorInTemplateID--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a name.
|
* Parse a name.
|
||||||
* name ::= ("::")? name2 ("::" name2)*
|
* name ::= ("::")? name2 ("::" name2)*
|
||||||
|
@ -211,7 +202,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
*
|
*
|
||||||
* @throws BacktrackException request a backtrack
|
* @throws BacktrackException request a backtrack
|
||||||
*/
|
*/
|
||||||
private IASTName qualifiedName() throws BacktrackException, EndOfFileException {
|
private IASTName qualifiedName(CastExprCtx ctx) throws BacktrackException, EndOfFileException {
|
||||||
ICPPASTQualifiedName qname= null;
|
ICPPASTQualifiedName qname= null;
|
||||||
IASTName name= null;
|
IASTName name= null;
|
||||||
final int offset= LA(1).getOffset();
|
final int offset= LA(1).getOffset();
|
||||||
|
@ -261,7 +252,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
haveName= true;
|
haveName= true;
|
||||||
name= addTemplateArguments(name);
|
name= addTemplateArguments(name, ctx);
|
||||||
endOffset= calculateEndOffset(name);
|
endOffset= calculateEndOffset(name);
|
||||||
if (qname != null) {
|
if (qname != null) {
|
||||||
qname.addName(name);
|
qname.addName(name);
|
||||||
|
@ -309,24 +300,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IASTName addTemplateArguments(IASTName templateName) throws EndOfFileException, BacktrackException {
|
private IASTName addTemplateArguments(IASTName templateName, CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||||
if (!canBeTemplateArguments())
|
boolean isAmbiguous= false;
|
||||||
return templateName;
|
switch(canBeTemplateArguments(ctx)) {
|
||||||
|
case -1:
|
||||||
|
return templateName;
|
||||||
|
case 0:
|
||||||
|
isAmbiguous= true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
IToken secondMark = mark();
|
IToken secondMark = mark();
|
||||||
consume(IToken.tLT);
|
consume(IToken.tLT);
|
||||||
try {
|
try {
|
||||||
// bug 229062: content assist after '<' needs to prefer to backtrack here
|
List<IASTNode> list = templateArgumentList(isAmbiguous);
|
||||||
if (rejectLogicalOperatorInTemplateID == 1) {
|
|
||||||
final int lt1= LT(1);
|
|
||||||
if (lt1 == IToken.tCOMPLETION || lt1 == IToken.tEOC) {
|
|
||||||
throw backtrack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IASTNode> list = templateArgumentList();
|
|
||||||
IToken end= LA(1);
|
IToken end= LA(1);
|
||||||
switch(end.getType()) {
|
switch(end.getType()) {
|
||||||
|
case IToken.tGT_in_SHIFTR:
|
||||||
case IToken.tGT:
|
case IToken.tGT:
|
||||||
consume();
|
consume();
|
||||||
break;
|
break;
|
||||||
|
@ -360,34 +350,109 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
/**
|
/**
|
||||||
* Makes a fast check whether there could be template arguments.
|
* 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)
|
if (LTcatchEOF(1) != IToken.tLT)
|
||||||
return false;
|
return -1;
|
||||||
|
|
||||||
final IToken mark= mark();
|
final IToken mark= mark();
|
||||||
try {
|
try {
|
||||||
consume();
|
consume();
|
||||||
int nk= 0;
|
int nk= 0;
|
||||||
int depth= 0;
|
int depth= 0;
|
||||||
int angleDepth= 0;
|
int angleDepth= 0;
|
||||||
int limit= 100;
|
int limit= 10000;
|
||||||
|
|
||||||
while(--limit > 0) {
|
while(--limit > 0) {
|
||||||
switch(consume().getType()) {
|
switch(consume().getType()) {
|
||||||
case IToken.tEOC:
|
case IToken.tEOC:
|
||||||
case IToken.tCOMPLETION:
|
case IToken.tCOMPLETION:
|
||||||
return true;
|
return ctx == CastExprCtx.eNotBExpr ? 0 : -1;
|
||||||
|
|
||||||
case IToken.tLT:
|
case IToken.tLT:
|
||||||
if (nk == 0) {
|
if (nk == 0) {
|
||||||
angleDepth++;
|
angleDepth++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case IToken.tGT_in_SHIFTR:
|
||||||
case IToken.tGT:
|
case IToken.tGT:
|
||||||
if (nk == 0) {
|
if (nk == 0) {
|
||||||
if (--angleDepth < 0) {
|
if (--angleDepth < 0) {
|
||||||
final int lt1= LTcatchEOF(1);
|
if (ctx == CastExprCtx.eNotBExpr)
|
||||||
return (lt1 != IToken.tINTEGER && lt1 != IToken.tFLOATINGPT);
|
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;
|
break;
|
||||||
|
@ -426,31 +491,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.tLBRACE:
|
case IToken.tLBRACE:
|
||||||
case IToken.tRBRACE:
|
case IToken.tRBRACE:
|
||||||
if (nk == 0) {
|
if (nk == 0) {
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return 0;
|
||||||
} finally {
|
} finally {
|
||||||
backup(mark);
|
backup(mark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IASTNode> templateArgumentList() throws EndOfFileException, BacktrackException {
|
private List<IASTNode> templateArgumentList(boolean isAmbiguous) throws EndOfFileException, BacktrackException {
|
||||||
IToken start = LA(1);
|
IToken start = LA(1);
|
||||||
int startingOffset = start.getOffset();
|
int startingOffset = start.getOffset();
|
||||||
int endOffset = 0;
|
int endOffset = 0;
|
||||||
start = null;
|
start = null;
|
||||||
List<IASTNode> list = new ArrayList<IASTNode>();
|
List<IASTNode> list = new ArrayList<IASTNode>();
|
||||||
|
final BinaryExprCtx exprCtx = isAmbiguous ? BinaryExprCtx.eAmbigTmplID : BinaryExprCtx.eTmplID;
|
||||||
|
|
||||||
boolean failed = false;
|
boolean failed = false;
|
||||||
|
int lt1= LT(1);
|
||||||
while (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
|
while (lt1 != IToken.tGT && lt1 != IToken.tGT_in_SHIFTR && lt1 != IToken.tEOC) {
|
||||||
IToken argStart = mark();
|
IToken argStart = mark();
|
||||||
IASTTypeId typeId = typeId(DeclarationOptions.TYPEID);
|
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
|
// potentially a type-id - check for id-expression ambiguity
|
||||||
IToken typeIdEnd= mark();
|
IToken typeIdEnd= mark();
|
||||||
try {
|
try {
|
||||||
|
@ -470,7 +537,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
throw backtrack;
|
throw backtrack;
|
||||||
|
|
||||||
backup(argStart);
|
backup(argStart);
|
||||||
IASTExpression expression = expression(false, true, true);
|
IASTExpression expression = expression(ExprKind.eAssignment, exprCtx);
|
||||||
if (expression instanceof IASTIdExpression) {
|
if (expression instanceof IASTIdExpression) {
|
||||||
if (mark() != typeIdEnd)
|
if (mark() != typeIdEnd)
|
||||||
throw backtrack;
|
throw backtrack;
|
||||||
|
@ -491,13 +558,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
} else {
|
} else {
|
||||||
// not a type-id - try as expression
|
// not a type-id - try as expression
|
||||||
backup(argStart);
|
backup(argStart);
|
||||||
IASTExpression expression = expression(false, true, true);
|
IASTExpression expression = expression(ExprKind.eAssignment, exprCtx);
|
||||||
list.add(expression);
|
list.add(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LT(1) == IToken.tCOMMA) {
|
lt1= LT(1);
|
||||||
|
if (lt1 == IToken.tCOMMA) {
|
||||||
consume();
|
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;
|
failed = true;
|
||||||
endOffset = LA(1).getEndOffset();
|
endOffset = LA(1).getEndOffset();
|
||||||
break;
|
break;
|
||||||
|
@ -539,6 +608,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
op= OverloadableOperator.valueOf(t);
|
op= OverloadableOperator.valueOf(t);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case IToken.tGT_in_SHIFTR:
|
||||||
|
consume();
|
||||||
|
endOffset= consume(IToken.tGT_in_SHIFTR).getEndOffset();
|
||||||
|
op= OverloadableOperator.SHIFTR;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
op= OverloadableOperator.valueOf(LA(1));
|
op= OverloadableOperator.valueOf(LA(1));
|
||||||
if (op != null) {
|
if (op != null) {
|
||||||
|
@ -564,30 +638,36 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return name;
|
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
|
@Override
|
||||||
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
|
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
|
@Override
|
||||||
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
|
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) {
|
if (allowAssignment && LT(1) == IToken.t_throw) {
|
||||||
return throwExpression();
|
return throwExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
int lt1;
|
int lt1;
|
||||||
int conditionCount= 0;
|
int conditionCount= 0;
|
||||||
CastExpressionOp lastComponent= null;
|
BinaryOperator lastOperator= null;
|
||||||
IASTExpression expr= castExpression(true);
|
IASTExpression expr= castExpression(castCtx);
|
||||||
|
|
||||||
loop: while(true) {
|
loop: while(true) {
|
||||||
// typically after a binary operator there cannot be a throw expression
|
// typically after a binary operator there cannot be a throw expression
|
||||||
|
@ -595,13 +675,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
lt1= LT(1);
|
lt1= LT(1);
|
||||||
switch(lt1) {
|
switch(lt1) {
|
||||||
case IToken.tQUESTION:
|
case IToken.tQUESTION:
|
||||||
if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) {
|
if (ctx == BinaryExprCtx.eAmbigTmplID) {
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
}
|
}
|
||||||
conditionCount++;
|
conditionCount++;
|
||||||
// <logical-or> ? <expression> : <assignment-expression>
|
// <logical-or> ? <expression> : <assignment-expression>
|
||||||
// Precedence: 25 is lower than precedence of logical or; 1 is lower than precedence of expression
|
// Precedence: 25 is lower than precedence of logical or; 0 is lower than precedence of expression
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 25, 1);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 25, 0);
|
||||||
if (LT(2) == IToken.tCOLON) {
|
if (LT(2) == IToken.tCOLON) {
|
||||||
// Gnu extension: The expression after '?' can be omitted.
|
// Gnu extension: The expression after '?' can be omitted.
|
||||||
consume(); // Consume operator
|
consume(); // Consume operator
|
||||||
|
@ -618,7 +698,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
|
|
||||||
// <logical-or> ? <expression> : <assignment-expression>
|
// <logical-or> ? <expression> : <assignment-expression>
|
||||||
// Precedence: 0 is lower than precedence of expression; 15 is lower than precedence of assignment;
|
// 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
|
allowAssignment= true; // assignment expressions will be subsumed by the conditional expression
|
||||||
allowThrow= true;
|
allowThrow= true;
|
||||||
break;
|
break;
|
||||||
|
@ -628,7 +708,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
if (!allowComma && conditionCount == 0)
|
if (!allowComma && conditionCount == 0)
|
||||||
break loop;
|
break loop;
|
||||||
// Lowest precedence except inside the conditional expression
|
// Lowest precedence except inside the conditional expression
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 10, 11);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 10, 11);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IToken.tASSIGN:
|
case IToken.tASSIGN:
|
||||||
|
@ -645,36 +725,36 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
if (!allowAssignment && conditionCount == 0)
|
if (!allowAssignment && conditionCount == 0)
|
||||||
break loop;
|
break loop;
|
||||||
// Assignments group right to left
|
// Assignments group right to left
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 21, 20);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 21, 20);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IToken.tOR:
|
case IToken.tOR:
|
||||||
if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) {
|
if (ctx == BinaryExprCtx.eAmbigTmplID) {
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
}
|
}
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 30, 31);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 30, 31);
|
||||||
break;
|
break;
|
||||||
case IToken.tAND:
|
case IToken.tAND:
|
||||||
if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) {
|
if (ctx == BinaryExprCtx.eAmbigTmplID) {
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
}
|
}
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 40, 41);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 40, 41);
|
||||||
break;
|
break;
|
||||||
case IToken.tBITOR:
|
case IToken.tBITOR:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 50, 51);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 50, 51);
|
||||||
break;
|
break;
|
||||||
case IToken.tXOR:
|
case IToken.tXOR:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 60, 61);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 60, 61);
|
||||||
break;
|
break;
|
||||||
case IToken.tAMPER:
|
case IToken.tAMPER:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 70, 71);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 70, 71);
|
||||||
break;
|
break;
|
||||||
case IToken.tEQUAL:
|
case IToken.tEQUAL:
|
||||||
case IToken.tNOTEQUAL:
|
case IToken.tNOTEQUAL:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 80, 81);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 80, 81);
|
||||||
break;
|
break;
|
||||||
case IToken.tGT:
|
case IToken.tGT:
|
||||||
if (onTopOfTemplateArgs)
|
if (ctx != BinaryExprCtx.eNoTmplID)
|
||||||
break loop;
|
break loop;
|
||||||
//$FALL-THROUGH$
|
//$FALL-THROUGH$
|
||||||
case IToken.tLT:
|
case IToken.tLT:
|
||||||
|
@ -682,24 +762,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.tGTEQUAL:
|
case IToken.tGTEQUAL:
|
||||||
case IGCCToken.tMAX:
|
case IGCCToken.tMAX:
|
||||||
case IGCCToken.tMIN:
|
case IGCCToken.tMIN:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 90, 91);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 90, 91);
|
||||||
break;
|
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:
|
case IToken.tSHIFTR:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 100, 101);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 100, 101);
|
||||||
break;
|
break;
|
||||||
case IToken.tPLUS:
|
case IToken.tPLUS:
|
||||||
case IToken.tMINUS:
|
case IToken.tMINUS:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 110, 111);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 110, 111);
|
||||||
break;
|
break;
|
||||||
case IToken.tSTAR:
|
case IToken.tSTAR:
|
||||||
case IToken.tDIV:
|
case IToken.tDIV:
|
||||||
case IToken.tMOD:
|
case IToken.tMOD:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 120, 121);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 120, 121);
|
||||||
break;
|
break;
|
||||||
case IToken.tDOTSTAR:
|
case IToken.tDOTSTAR:
|
||||||
case IToken.tARROWSTAR:
|
case IToken.tARROWSTAR:
|
||||||
lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 130, 131);
|
lastOperator= new BinaryOperator(lastOperator, expr, lt1, 130, 131);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break loop;
|
break loop;
|
||||||
|
@ -716,14 +805,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
break loop;
|
break loop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr= castExpression(true); // next cast expression
|
expr= castExpression(castCtx); // next cast expression
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for incomplete conditional expression
|
// Check for incomplete conditional expression
|
||||||
if (lt1 != IToken.tEOC && conditionCount > 0)
|
if (lt1 != IToken.tEOC && conditionCount > 0)
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
|
|
||||||
return buildExpression(lastComponent, expr);
|
return buildExpression(lastOperator, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IASTExpression throwExpression() throws EndOfFileException, BacktrackException {
|
private IASTExpression throwExpression() throws EndOfFileException, BacktrackException {
|
||||||
|
@ -759,7 +848,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
consume(IToken.tRBRACKET);
|
consume(IToken.tRBRACKET);
|
||||||
vectored = true;
|
vectored = true;
|
||||||
}
|
}
|
||||||
IASTExpression castExpression = castExpression(false);
|
IASTExpression castExpression = castExpression(CastExprCtx.eNotBExpr);
|
||||||
ICPPASTDeleteExpression deleteExpression = nodeFactory.newDeleteExpression(castExpression);
|
ICPPASTDeleteExpression deleteExpression = nodeFactory.newDeleteExpression(castExpression);
|
||||||
((ASTNode) deleteExpression).setOffsetAndLength(startingOffset, calculateEndOffset(castExpression) - startingOffset);
|
((ASTNode) deleteExpression).setOffsetAndLength(startingOffset, calculateEndOffset(castExpression) - startingOffset);
|
||||||
deleteExpression.setIsGlobal(global);
|
deleteExpression.setIsGlobal(global);
|
||||||
|
@ -901,24 +990,24 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IASTExpression unaryExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException {
|
protected IASTExpression unaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
case IToken.tSTAR:
|
case IToken.tSTAR:
|
||||||
return unarayExpression(IASTUnaryExpression.op_star, inBinaryExpression);
|
return unaryExpression(IASTUnaryExpression.op_star, ctx);
|
||||||
case IToken.tAMPER:
|
case IToken.tAMPER:
|
||||||
return unarayExpression(IASTUnaryExpression.op_amper, inBinaryExpression);
|
return unaryExpression(IASTUnaryExpression.op_amper, ctx);
|
||||||
case IToken.tPLUS:
|
case IToken.tPLUS:
|
||||||
return unarayExpression(IASTUnaryExpression.op_plus, inBinaryExpression);
|
return unaryExpression(IASTUnaryExpression.op_plus, ctx);
|
||||||
case IToken.tMINUS:
|
case IToken.tMINUS:
|
||||||
return unarayExpression(IASTUnaryExpression.op_minus, inBinaryExpression);
|
return unaryExpression(IASTUnaryExpression.op_minus, ctx);
|
||||||
case IToken.tNOT:
|
case IToken.tNOT:
|
||||||
return unarayExpression(IASTUnaryExpression.op_not, inBinaryExpression);
|
return unaryExpression(IASTUnaryExpression.op_not, ctx);
|
||||||
case IToken.tBITCOMPLEMENT:
|
case IToken.tBITCOMPLEMENT:
|
||||||
return unarayExpression(IASTUnaryExpression.op_tilde, inBinaryExpression);
|
return unaryExpression(IASTUnaryExpression.op_tilde, ctx);
|
||||||
case IToken.tINCR:
|
case IToken.tINCR:
|
||||||
return unarayExpression(IASTUnaryExpression.op_prefixIncr, inBinaryExpression);
|
return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx);
|
||||||
case IToken.tDECR:
|
case IToken.tDECR:
|
||||||
return unarayExpression(IASTUnaryExpression.op_prefixDecr, inBinaryExpression);
|
return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx);
|
||||||
case IToken.t_new:
|
case IToken.t_new:
|
||||||
return newExpression();
|
return newExpression();
|
||||||
case IToken.t_delete:
|
case IToken.t_delete:
|
||||||
|
@ -930,23 +1019,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.t_delete:
|
case IToken.t_delete:
|
||||||
return deleteExpression();
|
return deleteExpression();
|
||||||
default:
|
default:
|
||||||
return postfixExpression(inBinaryExpression);
|
return postfixExpression(ctx);
|
||||||
}
|
}
|
||||||
case IToken.t_sizeof:
|
case IToken.t_sizeof:
|
||||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, inBinaryExpression);
|
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx);
|
||||||
case IGCCToken.t_typeof:
|
case IGCCToken.t_typeof:
|
||||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, inBinaryExpression);
|
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, ctx);
|
||||||
case IGCCToken.t___alignof__:
|
case IGCCToken.t___alignof__:
|
||||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, inBinaryExpression);
|
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx);
|
||||||
default:
|
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;
|
IASTExpression firstExpression = null;
|
||||||
boolean isTemplate = false;
|
boolean isTemplate = false;
|
||||||
|
|
||||||
|
@ -970,7 +1059,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
} catch (BacktrackException bt) {
|
} catch (BacktrackException bt) {
|
||||||
}
|
}
|
||||||
backup(m);
|
backup(m);
|
||||||
firstExpression= primaryExpression();
|
firstExpression= primaryExpression(ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IToken.t_typename:
|
case IToken.t_typename:
|
||||||
|
@ -981,7 +1070,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
consume();
|
consume();
|
||||||
templateTokenConsumed = true;
|
templateTokenConsumed = true;
|
||||||
}
|
}
|
||||||
IASTName name = idExpression();
|
IASTName name = qualifiedName(CastExprCtx.eNotBExpr); // treat as not in binary to force template arguments
|
||||||
if (LT(1) != IToken.tLPAREN) {
|
if (LT(1) != IToken.tLPAREN) {
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
}
|
}
|
||||||
|
@ -1036,11 +1125,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.t_typeid:
|
case IToken.t_typeid:
|
||||||
int so = consume().getOffset();
|
int so = consume().getOffset();
|
||||||
firstExpression = parseTypeidInParenthesisOrUnaryExpression(true, so,
|
firstExpression = parseTypeidInParenthesisOrUnaryExpression(true, so,
|
||||||
ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid, inBinaryExpression);
|
ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid, ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
firstExpression = primaryExpression();
|
firstExpression = primaryExpression(ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
IASTExpression secondExpression = null;
|
IASTExpression secondExpression = null;
|
||||||
|
@ -1107,7 +1196,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
isTemplate = true;
|
isTemplate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTName name = idExpression();
|
IASTName name = qualifiedName(ctx);
|
||||||
|
|
||||||
if (name == null)
|
if (name == null)
|
||||||
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
||||||
|
@ -1130,7 +1219,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
isTemplate = true;
|
isTemplate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = idExpression();
|
name = qualifiedName(ctx);
|
||||||
|
|
||||||
if (name == null)
|
if (name == null)
|
||||||
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
throwBacktrack(((ASTNode) firstExpression).getOffset(),
|
||||||
|
@ -1185,7 +1274,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IASTExpression primaryExpression() throws EndOfFileException, BacktrackException {
|
protected IASTExpression primaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||||
IToken t = null;
|
IToken t = null;
|
||||||
IASTLiteralExpression literalExpression = null;
|
IASTLiteralExpression literalExpression = null;
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
|
@ -1238,7 +1327,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
t = consume();
|
t = consume();
|
||||||
int finalOffset= 0;
|
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)) {
|
switch (LT(1)) {
|
||||||
case IToken.tRPAREN:
|
case IToken.tRPAREN:
|
||||||
case IToken.tEOC:
|
case IToken.tEOC:
|
||||||
|
@ -1253,7 +1342,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.t_operator:
|
case IToken.t_operator:
|
||||||
case IToken.tCOMPLETION:
|
case IToken.tCOMPLETION:
|
||||||
case IToken.tBITCOMPLEMENT: {
|
case IToken.tBITCOMPLEMENT: {
|
||||||
IASTName name = idExpression();
|
IASTName name = qualifiedName(ctx);
|
||||||
IASTIdExpression idExpression = nodeFactory.newIdExpression(name);
|
IASTIdExpression idExpression = nodeFactory.newIdExpression(name);
|
||||||
((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset()
|
((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset()
|
||||||
+ ((ASTNode) name).getLength() - ((ASTNode) name).getOffset());
|
+ ((ASTNode) name).getLength() - ((ASTNode) name).getOffset());
|
||||||
|
@ -1320,7 +1409,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.tIDENTIFIER:
|
case IToken.tIDENTIFIER:
|
||||||
case IToken.tCOLONCOLON:
|
case IToken.tCOLONCOLON:
|
||||||
case IToken.tCOMPLETION:
|
case IToken.tCOMPLETION:
|
||||||
name = qualifiedName();
|
name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throwBacktrack(offset, endOffset - offset);
|
throwBacktrack(offset, endOffset - offset);
|
||||||
|
@ -1351,7 +1440,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
consume();
|
consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTName name = idExpression();
|
IASTName name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
int end;
|
int end;
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
case IToken.tSEMI:
|
case IToken.tSEMI:
|
||||||
|
@ -1469,7 +1558,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ICPPASTTemplateParameter> parms= templateParameterList();
|
List<ICPPASTTemplateParameter> parms= templateParameterList();
|
||||||
consume(IToken.tGT);
|
consume(IToken.tGT, IToken.tGT_in_SHIFTR);
|
||||||
IASTDeclaration d = declaration(option);
|
IASTDeclaration d = declaration(option);
|
||||||
ICPPASTTemplateDeclaration templateDecl = nodeFactory.newTemplateDeclaration(d);
|
ICPPASTTemplateDeclaration templateDecl = nodeFactory.newTemplateDeclaration(d);
|
||||||
((ASTNode) templateDecl).setOffsetAndLength(firstToken.getOffset(), calculateEndOffset(d) - firstToken.getOffset());
|
((ASTNode) templateDecl).setOffsetAndLength(firstToken.getOffset(), calculateEndOffset(d) - firstToken.getOffset());
|
||||||
|
@ -1503,7 +1592,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
final int lt1= LT(1);
|
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;
|
return returnValue;
|
||||||
if (lt1 == IToken.t_class || lt1 == IToken.t_typename) {
|
if (lt1 == IToken.t_class || lt1 == IToken.t_typename) {
|
||||||
IToken startingToken = LA(1);
|
IToken startingToken = LA(1);
|
||||||
|
@ -1537,7 +1626,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
consume(IToken.tLT);
|
consume(IToken.tLT);
|
||||||
|
|
||||||
List<ICPPASTTemplateParameter> subResult = templateParameterList();
|
List<ICPPASTTemplateParameter> subResult = templateParameterList();
|
||||||
consume(IToken.tGT);
|
consume(IToken.tGT, IToken.tGT_in_SHIFTR);
|
||||||
int last = consume(IToken.t_class).getEndOffset();
|
int last = consume(IToken.t_class).getEndOffset();
|
||||||
IASTName identifierName = null;
|
IASTName identifierName = null;
|
||||||
IASTExpression optionalExpression = null;
|
IASTExpression optionalExpression = null;
|
||||||
|
@ -1547,7 +1636,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
last = calculateEndOffset(identifierName);
|
last = calculateEndOffset(identifierName);
|
||||||
if (LT(1) == IToken.tASSIGN) { // optional = type-id
|
if (LT(1) == IToken.tASSIGN) { // optional = type-id
|
||||||
consume();
|
consume();
|
||||||
optionalExpression = primaryExpression();
|
optionalExpression = primaryExpression(CastExprCtx.eNotBExpr);
|
||||||
last = calculateEndOffset(optionalExpression);
|
last = calculateEndOffset(optionalExpression);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -1690,7 +1779,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTName qualifiedName= qualifiedName();
|
IASTName qualifiedName= qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
endOffset = consume(IToken.tSEMI).getEndOffset();
|
endOffset = consume(IToken.tSEMI).getEndOffset();
|
||||||
|
|
||||||
ICPPASTNamespaceAlias alias = nodeFactory.newNamespaceAlias(name, qualifiedName);
|
ICPPASTNamespaceAlias alias = nodeFactory.newNamespaceAlias(name, qualifiedName);
|
||||||
|
@ -1892,7 +1981,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
consume();
|
consume();
|
||||||
ctorLoop: for (;;) {
|
ctorLoop: for (;;) {
|
||||||
int offset= LA(1).getOffset();
|
int offset= LA(1).getOffset();
|
||||||
IASTName name = qualifiedName();
|
IASTName name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
|
|
||||||
int endOffset;
|
int endOffset;
|
||||||
IASTExpression expressionList = null;
|
IASTExpression expressionList = null;
|
||||||
|
@ -2161,7 +2250,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
if (encounteredTypename || encounteredRawType)
|
if (encounteredTypename || encounteredRawType)
|
||||||
break declSpecifiers;
|
break declSpecifiers;
|
||||||
consume();
|
consume();
|
||||||
identifier= qualifiedName();
|
identifier= qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
endOffset= calculateEndOffset(identifier);
|
endOffset= calculateEndOffset(identifier);
|
||||||
isTypename = true;
|
isTypename = true;
|
||||||
encounteredTypename= 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)
|
if (identifier.getLookupKey().length == 0 && LT(1) != IToken.tEOC)
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
|
|
||||||
|
@ -2235,7 +2324,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
|
|
||||||
typeofExpression= parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
typeofExpression= parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, false);
|
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, CastExprCtx.eNotBExpr);
|
||||||
|
|
||||||
encounteredTypename= true;
|
encounteredTypename= true;
|
||||||
endOffset= calculateEndOffset(typeofExpression);
|
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
|
// if __attribute__ or __declspec occurs after struct/union/class and before the identifier
|
||||||
__attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers);
|
__attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers);
|
||||||
|
|
||||||
IASTName name = qualifiedName();
|
IASTName name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
|
|
||||||
ICPPASTElaboratedTypeSpecifier elaboratedTypeSpec = nodeFactory.newElaboratedTypeSpecifier(eck, name);
|
ICPPASTElaboratedTypeSpecifier elaboratedTypeSpec = nodeFactory.newElaboratedTypeSpecifier(eck, name);
|
||||||
((ASTNode) elaboratedTypeSpec).setOffsetAndLength(t.getOffset(), calculateEndOffset(name) - t.getOffset());
|
((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 {
|
protected IASTInitializer initializerClause(boolean inAggregateInitializer) throws EndOfFileException,
|
||||||
if (LT(1) == IToken.tLBRACE) {
|
BacktrackException {
|
||||||
int startingOffset = consume().getOffset();
|
if (LT(1) == IToken.tLBRACE) {
|
||||||
|
int startingOffset = consume().getOffset();
|
||||||
|
|
||||||
IASTInitializerList result = nodeFactory.newInitializerList();
|
IASTInitializerList result = nodeFactory.newInitializerList();
|
||||||
((ASTNode) result).setOffset(startingOffset);
|
((ASTNode) result).setOffset(startingOffset);
|
||||||
|
|
||||||
if (LT(1) == (IToken.tRBRACE)) {
|
if (LT(1) == (IToken.tRBRACE)) {
|
||||||
int l = consume().getEndOffset();
|
int endOffset = consume().getEndOffset();
|
||||||
((ASTNode) result).setLength(l - startingOffset);
|
setRange(result, startingOffset, endOffset);
|
||||||
return result;
|
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 (;;) {
|
// clause may be null, add to initializer anyways, such that the
|
||||||
if (LT(1) == IToken.tRBRACE)
|
// actual size can be computed.
|
||||||
break;
|
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
|
// no brace, so try an assignment expression
|
||||||
// actual size can be computed.
|
final BinaryExprCtx ctx = fInTemplateParameterList ? BinaryExprCtx.eTmplID : BinaryExprCtx.eNoTmplID;
|
||||||
IASTInitializer clause = initializerClause(true);
|
IASTExpression assignmentExpression = expression(ExprKind.eAssignment, ctx);
|
||||||
result.addInitializer(clause);
|
if (inAggregateInitializer && skipTrivialExpressionsInAggregateInitializers) {
|
||||||
if (LT(1) == IToken.tRBRACE || LT(1) == IToken.tEOC)
|
if (!ASTQueries.canContainName(assignmentExpression))
|
||||||
break;
|
return null;
|
||||||
consume(IToken.tCOMMA);
|
}
|
||||||
}
|
|
||||||
int l = consume().getEndOffset(); // tRBRACE
|
|
||||||
((ASTNode) result).setLength(l - startingOffset);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we get this far, it means that we did not
|
IASTInitializerExpression result = nodeFactory.newInitializerExpression(assignmentExpression);
|
||||||
// try this now instead
|
setRange(result, assignmentExpression);
|
||||||
// assignmentExpression
|
return result;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2684,7 +2772,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
IASTDeclSpecifier declSpecifier = null;
|
IASTDeclSpecifier declSpecifier = null;
|
||||||
IASTDeclarator declarator = null;
|
IASTDeclarator declarator = null;
|
||||||
|
|
||||||
rejectLogicalOperatorInTemplateID++;
|
|
||||||
try {
|
try {
|
||||||
Decl decl= declSpecifierSequence_initDeclarator(option, false);
|
Decl decl= declSpecifierSequence_initDeclarator(option, false);
|
||||||
declSpecifier= decl.fDeclSpec1;
|
declSpecifier= decl.fDeclSpec1;
|
||||||
|
@ -2694,9 +2781,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return null;
|
return null;
|
||||||
} catch (BacktrackException bt) {
|
} catch (BacktrackException bt) {
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
}
|
||||||
rejectLogicalOperatorInTemplateID--;
|
|
||||||
}
|
|
||||||
IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator);
|
IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator);
|
||||||
setRange(result, offset, figureEndOffset(declSpecifier, declarator));
|
setRange(result, offset, figureEndOffset(declSpecifier, declarator));
|
||||||
return result;
|
return result;
|
||||||
|
@ -2744,7 +2829,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
if (option.fRequireAbstract)
|
if (option.fRequireAbstract)
|
||||||
throwBacktrack(LA(1));
|
throwBacktrack(LA(1));
|
||||||
|
|
||||||
final IASTName declaratorName= qualifiedName();
|
final IASTName declaratorName= qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
endOffset= calculateEndOffset(declaratorName);
|
endOffset= calculateEndOffset(declaratorName);
|
||||||
return declarator(pointerOps, declaratorName, null, startingOffset, endOffset, strategy, option);
|
return declarator(pointerOps, declaratorName, null, startingOffset, endOffset, strategy, option);
|
||||||
}
|
}
|
||||||
|
@ -2860,7 +2945,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
if (coloncolon != 0) {
|
if (coloncolon != 0) {
|
||||||
try {
|
try {
|
||||||
name= qualifiedName();
|
name= qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
if (name.getLookupKey().length != 0) {
|
if (name.getLookupKey().length != 0) {
|
||||||
backup(mark);
|
backup(mark);
|
||||||
return;
|
return;
|
||||||
|
@ -3167,7 +3252,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
// class name
|
// class name
|
||||||
IASTName name = null;
|
IASTName name = null;
|
||||||
if (LT(1) == IToken.tIDENTIFIER)
|
if (LT(1) == IToken.tIDENTIFIER)
|
||||||
name = qualifiedName();
|
name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
else
|
else
|
||||||
name = nodeFactory.newName();
|
name = nodeFactory.newName();
|
||||||
|
|
||||||
|
@ -3253,7 +3338,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.tIDENTIFIER:
|
case IToken.tIDENTIFIER:
|
||||||
case IToken.tCOMPLETION:
|
case IToken.tCOMPLETION:
|
||||||
// to get templates right we need to use the class as the scope
|
// to get templates right we need to use the class as the scope
|
||||||
name = qualifiedName();
|
name = qualifiedName(CastExprCtx.eNotBExpr);
|
||||||
endOffset= calculateEndOffset(name);
|
endOffset= calculateEndOffset(name);
|
||||||
break;
|
break;
|
||||||
case IToken.tCOMMA:
|
case IToken.tCOMMA:
|
||||||
|
|
|
@ -171,6 +171,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
|
|
||||||
private int fContentAssistLimit= -1;
|
private int fContentAssistLimit= -1;
|
||||||
private boolean fHandledCompletion= false;
|
private boolean fHandledCompletion= false;
|
||||||
|
private boolean fSplitShiftRightOperator= false;
|
||||||
|
|
||||||
// state information
|
// state information
|
||||||
private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<PreprocessorMacro>(512);
|
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) {
|
public void setComputeImageLocations(boolean val) {
|
||||||
fLexOptions.fCreateImageLocations= 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 {
|
private Token fetchToken() throws OffsetLimitReachedException {
|
||||||
if (fIsFirstFetchToken) {
|
if (fIsFirstFetchToken) {
|
||||||
|
@ -537,7 +542,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
case IToken.tLSTRING:
|
case IToken.tLSTRING:
|
||||||
case IToken.tUTF16STRING:
|
case IToken.tUTF16STRING:
|
||||||
case IToken.tUTF32STRING:
|
case IToken.tUTF32STRING:
|
||||||
|
|
||||||
StringType st = StringType.fromToken(tt1);
|
StringType st = StringType.fromToken(tt1);
|
||||||
Token t2;
|
Token t2;
|
||||||
StringBuffer buf= null;
|
StringBuffer buf= null;
|
||||||
|
@ -580,6 +584,18 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
||||||
image[image.length - 1]= '"';
|
image[image.length - 1]= '"';
|
||||||
t1= new TokenWithImage(st.getTokenValue(), null, t1.getOffset(), endOffset, image);
|
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) {
|
if (fLastToken != null) {
|
||||||
|
|
|
@ -112,6 +112,7 @@ public class TokenUtil {
|
||||||
case IToken.tSHIFTRASSIGN: return Keywords.cpSHIFTRASSIGN;
|
case IToken.tSHIFTRASSIGN: return Keywords.cpSHIFTRASSIGN;
|
||||||
case IToken.tSHIFTR: return Keywords.cpSHIFTR;
|
case IToken.tSHIFTR: return Keywords.cpSHIFTR;
|
||||||
case IToken.tGTEQUAL: return Keywords.cpGTEQUAL;
|
case IToken.tGTEQUAL: return Keywords.cpGTEQUAL;
|
||||||
|
case IToken.tGT_in_SHIFTR:
|
||||||
case IToken.tGT: return Keywords.cpGT;
|
case IToken.tGT: return Keywords.cpGT;
|
||||||
case IToken.tSHIFTLASSIGN: return Keywords.cpSHIFTLASSIGN;
|
case IToken.tSHIFTLASSIGN: return Keywords.cpSHIFTLASSIGN;
|
||||||
case IToken.tELLIPSIS: return Keywords.cpELLIPSIS;
|
case IToken.tELLIPSIS: return Keywords.cpELLIPSIS;
|
||||||
|
|
Loading…
Add table
Reference in a new issue