1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Parser tests using CPreprocessor

This commit is contained in:
Markus Schorn 2007-11-06 16:53:51 +00:00
parent e0ba2b4f84
commit 981ddadee0
29 changed files with 1110 additions and 525 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* Copyright (c) 2005, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
*
* Contributors:
* Rational Software - initial implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
@ -724,9 +725,14 @@ public class ASTSignatureUtil {
private static String getLiteralExpression( IASTLiteralExpression expression ){
StringBuffer result = new StringBuffer();
if (expression.getKind() == IASTLiteralExpression.lk_string_literal) result.append("\""); //$NON-NLS-1$
result.append(expression.toString());
if (expression.getKind() == IASTLiteralExpression.lk_string_literal) result.append("\""); //$NON-NLS-1$
if (expression.getKind() == IASTLiteralExpression.lk_string_literal) {
// mstodo- support for old scanner
if (result.length() == 0 || result.charAt(0) != '"') {
result.insert(0, '"');
result.append('"');
}
}
return result.toString();
}

View file

@ -24,6 +24,16 @@ public interface IASTFileLocation extends IASTNodeLocation {
*/
public String getFileName();
/**
* Returns the offset within the file where this location starts.
*/
public int getNodeOffset();
/**
* Returns the length of this location in terms of characters.
*/
public int getNodeLength();
/**
* Get the starting line number. Locations obtained via the index do not have line numbers
* and return <code>0</code>.

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2005 IBM Corporation and others.
* Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,6 +7,7 @@
*
* Contributors:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
@ -26,14 +27,26 @@ public interface IASTMacroExpansion extends IASTNodeLocation {
*/
public IASTPreprocessorMacroDefinition getMacroDefinition();
/**
* Returns an offset within the macro-expansion. The offset can be used to compare
* nodes within the same macro-expansion. However, it does not serve as an offset
* into a file.
*/
public int getNodeOffset();
/**
* Returns the length of this location. The length can be used to compare this location
* with others from within the same macro-expansion. However, the length does not neccessarily
* relate to a length in terms of characters.
*/
public int getNodeLength();
/**
* The source locations for for the macro expansion. These are the locations
* where the expansion in question occured and was replaced.
* where the expansion in question occurred and was replaced.
*
* @return
* @deprecated use {@link IASTNodeLocation#asFileLocation()}.
*/
public IASTNodeLocation[] getExpansionLocations();
}

View file

@ -19,24 +19,17 @@ package org.eclipse.cdt.core.dom.ast;
public interface IASTNodeLocation {
/**
* This is the offset into the actual source location that this node starts
* at.
*
* @return
* This is the offset within either the file or a macro-expansion.
*/
public int getNodeOffset();
/**
* This is the length of the node contained in this location.
*
* @return
* This is the length of the node within the file or macro-expansion.
*/
public int getNodeLength();
/**
* Return a file location that best maps into this location.
*
* @return
*/
public IASTFileLocation asFileLocation();

View file

@ -14,13 +14,14 @@ package org.eclipse.cdt.core.dom.ast;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.core.runtime.IAdaptable;
/**
* The translation unit represents a compilable unit of source.
*
* @author Doug Schaefer
*/
public interface IASTTranslationUnit extends IASTNode {
public interface IASTTranslationUnit extends IASTNode, IAdaptable {
/**
* <code>OWNED_DECLARATION</code> represents the relationship between an <code>IASTTranslationUnit</code> and
@ -115,12 +116,25 @@ public interface IASTTranslationUnit extends IASTNode {
public IASTName[] getReferences(IBinding binding);
/**
* @param offset
* Returns an array of locations. This is a sequence of file locations and macro-expansion locations.
* @param offset sequence number as stored in the ast nodes.
* @param length
* @return
* @return and array of locations.
*/
public IASTNodeLocation[] getLocationInfo(int offset, int length);
/**
* Returns the smallest file location, that encloses the given global range. In case the range
* spans over multiple files, the files are mapped to include statements until all of them are
* found in the same file. So the resulting location contains the include directives that actually
* cause the range to be part of the AST.
* @param offset sequence number as stored in the ASTNodes.
* @param length
* @return a file location
* @since 5.0
*/
public IASTFileLocation getMappedFileLocation(int offset, int length);
/**
* Select the node in the treet that best fits the offset/length/file path.
*
@ -173,6 +187,7 @@ public interface IASTTranslationUnit extends IASTNode {
*
* @param locations A range of node locations
* @return A String signature.
* @deprecated was never fully implemented.
*/
public String getUnpreprocessedSignature(IASTNodeLocation[] locations);
@ -187,6 +202,7 @@ public interface IASTTranslationUnit extends IASTNode {
*
* @param nodeLocations <code>IASTNodeLocation</code>s to flatten
* @return null if not possible, otherwise, a file location representing where the macros are.
* @deprecated use {@link #getMappedFileLocation(int, int)}
*/
public IASTFileLocation flattenLocationsToFile( IASTNodeLocation [] nodeLocations );

View file

@ -85,7 +85,7 @@ public class CharArrayIntMap extends CharTable {
*/
public void putAll(CharArrayIntMap map) {
resize(size() + map.size());
for(int i=0; i<map.currEntry; i++) {
for(int i=0; i<=map.currEntry; i++) {
put(map.keyTable[i], map.valueTable[i]);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2006 IBM Corporation and others.
* Copyright (c) 2005, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -17,6 +17,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
/**
* @author jcamelon
@ -88,8 +89,19 @@ public abstract class ASTNode implements IASTNode {
}
public String getRawSignature() {
return getTranslationUnit().getUnpreprocessedSignature(
getNodeLocations());
final IASTFileLocation floc= getFileLocation();
final IASTTranslationUnit ast = getTranslationUnit();
if (floc != null && ast != null) {
ILocationResolver lr= (ILocationResolver) ast.getAdapter(ILocationResolver.class);
if (lr != null) {
return new String(lr.getUnpreprocessedSignature(getFileLocation()));
}
else {
// mstodo- support for old location map
return ast.getUnpreprocessedSignature(getNodeLocations());
}
}
return ""; //$NON-NLS-1$
}
public String getContainingFilename() {
@ -100,8 +112,16 @@ public abstract class ASTNode implements IASTNode {
if( fileLocation != null )
return fileLocation;
IASTTranslationUnit ast = getTranslationUnit();
if (ast != null)
fileLocation = ast.flattenLocationsToFile( getNodeLocations() );
if (ast != null) {
ILocationResolver lr= (ILocationResolver) ast.getAdapter(ILocationResolver.class);
if (lr != null) {
fileLocation= lr.getMappedFileLocation(offset, length);
}
else {
// support for old location map
fileLocation= ast.flattenLocationsToFile(getNodeLocations());
}
}
return fileLocation;
}

View file

@ -1420,7 +1420,14 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
BacktrackException {
IToken first = consume(); // t_asm
consume(IToken.tLPAREN);
String assembly = consume(IToken.tSTRING).getImage();
char[] assemblyChars = consume(IToken.tSTRING).getCharImage();
String assembly;
if (assemblyChars.length > 2 && assemblyChars[0] == '"') {
assembly= new String(assemblyChars, 1, assemblyChars.length-2);
}
else {
assembly= new String(assemblyChars);
}
consume(IToken.tRPAREN);
int lastOffset = consume(IToken.tSEMI).getEndOffset();

View file

@ -391,8 +391,25 @@ public class CASTTranslationUnit extends CASTNode implements
*
* @see org.eclipse.cdt.core.dom.ast.IASTTranslationUnit#getNodeForLocation(org.eclipse.cdt.core.dom.ast.IASTNodeLocation)
*/
public IASTNode selectNodeForLocation(String path, int realOffset,
int realLength) {
public IASTNode selectNodeForLocation(String path, int realOffset, int realLength) {
if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) {
org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver;
IASTNode result= null;
int start= r2.getSequenceNumberForFileOffset(path, realOffset);
if (start >= 0) {
int length= realLength < 1 ? 0 :
r2.getSequenceNumberForFileOffset(path, realOffset+realLength-1) + 1 - start;
result= r2.findSurroundingPreprocessorNode(start, length);
if (result == null) {
CFindNodeForOffsetAction nodeFinder = new CFindNodeForOffsetAction(start, length);
accept(nodeFinder);
result = nodeFinder.getNode();
}
}
return result;
}
// mstodo- support for old location resolver
IASTNode node = null;
ASTPreprocessorSelectionResult result = null;
int globalOffset = 0;
@ -480,17 +497,6 @@ public class CASTTranslationUnit extends CASTNode implements
resolver.setRootNode( this );
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#finalize()
*/
protected void finalize() throws Throwable {
if (resolver != null)
resolver.cleanup();
super.finalize();
}
/*
* (non-Javadoc)
*
@ -552,6 +558,14 @@ public class CASTTranslationUnit extends CASTNode implements
return true;
}
public IASTFileLocation getMappedFileLocation(int offset, int length) {
if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) {
org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver;
return r2.getMappedFileLocation(offset, length);
}
return flattenLocationsToFile(getLocationInfo(offset, length));
}
public IASTFileLocation flattenLocationsToFile(IASTNodeLocation[] nodeLocations) {
if( resolver == null )
return null;
@ -590,6 +604,11 @@ public class CASTTranslationUnit extends CASTNode implements
}
public IASTComment[] getComments() {
if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) {
org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver;
return r2.getComments();
}
// support for old location resolver
return comments;
}
@ -597,4 +616,10 @@ public class CASTTranslationUnit extends CASTNode implements
this.comments = comments;
}
public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(resolver.getClass())) {
return resolver;
}
return null;
}
}

View file

@ -382,6 +382,24 @@ public class CPPASTTranslationUnit extends CPPASTNode implements
public IASTNode selectNodeForLocation(String path, int realOffset, int realLength) {
if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) {
org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver;
IASTNode result= null;
int start= r2.getSequenceNumberForFileOffset(path, realOffset);
if (start >= 0) {
int length= realLength < 1 ? 0 :
r2.getSequenceNumberForFileOffset(path, realOffset+realLength-1) + 1 - start;
result= r2.findSurroundingPreprocessorNode(start, length);
if (result == null) {
CPPFindNodeForOffsetAction nodeFinder = new CPPFindNodeForOffsetAction(start, length);
accept(nodeFinder);
result = nodeFinder.getNode();
}
}
return result;
}
// mstodo- support for old location resolver
IASTNode node = null;
ASTPreprocessorSelectionResult result = null;
int globalOffset = 0;
@ -491,6 +509,14 @@ public class CPPASTTranslationUnit extends CPPASTNode implements
return true;
}
public IASTFileLocation getMappedFileLocation(int offset, int length) {
if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) {
org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver;
return r2.getMappedFileLocation(offset, length);
}
return flattenLocationsToFile(getLocationInfo(offset, length));
}
public IASTFileLocation flattenLocationsToFile(IASTNodeLocation[] nodeLocations) {
if( resolver == null )
return null;
@ -542,6 +568,11 @@ public class CPPASTTranslationUnit extends CPPASTNode implements
}
public IASTComment[] getComments() {
if (resolver instanceof org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) {
org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver r2= (org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver) resolver;
return r2.getComments();
}
// support for old location resolver
return comments;
}
@ -549,4 +580,10 @@ public class CPPASTTranslationUnit extends CPPASTNode implements
this.comments = comments;
}
public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(resolver.getClass())) {
return resolver;
}
return null;
}
}

View file

@ -2523,21 +2523,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
result.setValue(duple.toString());
ITokenDuple[] segments = duple.getSegments();
int startingValue = 0;
if (segments.length > 0 && segments[0] instanceof IToken
&& ((IToken) segments[0]).getType() == IToken.tCOLONCOLON) {
if (segments.length > 0) {
final ITokenDuple firstSeg= segments[0];
final IToken firstToken= firstSeg.getFirstToken();
if (firstToken.getType() == IToken.tCOLONCOLON) {
if (firstToken == firstSeg.getLastToken() && firstSeg.getTemplateIdArgLists() == null) {
++startingValue;
result.setFullyQualified(true);
}
}
}
for (int i = startingValue; i < segments.length; ++i) {
IASTName subName = null;
// take each name and add it to the result
if (segments[i] instanceof IToken) {
subName = createName((IToken) segments[i]);
} else if (segments[i].getTemplateIdArgLists() == null)
subName = createName(segments[i]);
else
final ITokenDuple seg= segments[i];
if (seg.getTemplateIdArgLists() == null) {
final IToken firstToken= seg.getFirstToken();
if (firstToken == seg.getLastToken()) {
subName= createName(firstToken);
}
else {
subName = createName(seg);
}
}
else {
// templateID
subName = createTemplateID(segments[i]);
}
if (i == segments.length - 1 && duple instanceof OperatorTokenDuple) {
// make sure the last segment is an OperatorName/ConversionName

View file

@ -16,6 +16,7 @@ import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionStyleMacroParameter;
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
@ -37,6 +38,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
/**
@ -51,10 +53,18 @@ abstract class ASTPreprocessorNode extends ASTNode {
setLength(endNumber-startNumber);
}
protected String getSource(int offset, int length) {
final IASTTranslationUnit tu= getTranslationUnit();
IASTNodeLocation[] loc=tu.getLocationInfo(offset, length);
return tu.getUnpreprocessedSignature(loc);
protected char[] getSource(int offset, int length) {
final IASTTranslationUnit ast= getTranslationUnit();
if (ast != null) {
ILocationResolver lr= (ILocationResolver) ast.getAdapter(ILocationResolver.class);
if (lr != null) {
final IASTFileLocation loc= lr.getMappedFileLocation(offset, length);
if (loc != null) {
return lr.getUnpreprocessedSignature(loc);
}
}
}
return CharArrayUtils.EMPTY;
}
public IASTNodeLocation[] getNodeLocations() {
@ -99,6 +109,13 @@ abstract class ASTPreprocessorNode extends ASTNode {
}
return super.getRawSignature();
}
/**
* Returns a subnode surrounding the given range or this.
*/
IASTNode findSurroundingNode(int sequenceNumber, int length) {
return this;
}
}
@ -111,7 +128,7 @@ class ASTComment extends ASTPreprocessorNode implements IASTComment {
}
public char[] getComment() {
return getSource(getOffset(), getLength()).toCharArray();
return getSource(getOffset(), getLength());
}
public boolean isBlockComment() {
@ -138,7 +155,7 @@ abstract class ASTDirectiveWithCondition extends ASTPreprocessorNode {
}
public String getConditionString() {
return getSource(fConditionOffset, getOffset() + getLength() - fConditionOffset);
return new String(getSource(fConditionOffset, getOffset() + getLength() - fConditionOffset));
}
public char[] getCondition() {
@ -208,7 +225,7 @@ class ASTPragma extends ASTDirectiveWithCondition implements IASTPreprocessorPra
}
class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreprocessorIncludeStatement {
private final IASTName fName;
private final ASTPreprocessorName fName;
private final String fPath;
private final boolean fIsActive;
private final boolean fIsResolved;
@ -243,6 +260,15 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
public boolean isSystemInclude() {
return fIsSystemInclude;
}
IASTNode findSurroundingNode(int sequenceNumber, int length) {
final int nameSequencNumber= fName.getOffset();
final int nameEndSequencNumber= nameSequencNumber + fName.getLength();
if (nameSequencNumber <= sequenceNumber && sequenceNumber+length <= nameEndSequencNumber) {
return fName;
}
return this;
}
}
class ASTMacro extends ASTPreprocessorNode implements IASTPreprocessorObjectStyleMacroDefinition {
@ -282,6 +308,15 @@ class ASTMacro extends ASTPreprocessorNode implements IASTPreprocessorObjectStyl
return (fName == n) ? r_definition : r_unclear;
}
IASTNode findSurroundingNode(int sequenceNumber, int length) {
final int nameSequencNumber= fName.getOffset();
final int nameEndSequencNumber= nameSequencNumber + fName.getLength();
if (nameSequencNumber <= sequenceNumber && sequenceNumber+length <= nameEndSequencNumber) {
return fName;
}
return this;
}
public void setExpansion(String exp) {assert false;}
public void setName(IASTName name) {assert false;}
}
@ -333,7 +368,7 @@ class ASTFunctionMacro extends ASTMacro implements IASTPreprocessorFunctionStyle
class ASTUndef extends ASTPreprocessorNode implements IASTPreprocessorUndefStatement {
private final IASTName fName;
private final ASTPreprocessorName fName;
public ASTUndef(IASTTranslationUnit parent, char[] name, int startNumber, int nameNumber, int nameEndNumber, IBinding binding) {
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, nameEndNumber);
fName= new ASTPreprocessorName(this, IASTPreprocessorUndefStatement.MACRO_NAME, nameNumber, nameEndNumber, name, binding);
@ -342,6 +377,15 @@ class ASTUndef extends ASTPreprocessorNode implements IASTPreprocessorUndefState
public IASTName getMacroName() {
return fName;
}
IASTNode findSurroundingNode(int sequenceNumber, int length) {
final int nameSequencNumber= fName.getOffset();
final int nameEndSequencNumber= nameSequencNumber + fName.getLength();
if (nameSequencNumber <= sequenceNumber && sequenceNumber+length <= nameEndSequencNumber) {
return fName;
}
return this;
}
}
class ASTInclusionNode implements IASTInclusionNode {
@ -381,11 +425,11 @@ class DependencyTree extends ASTInclusionNode implements IDependencyTree {
}
class ASTFileLocation implements IASTFileLocation {
private FileLocationCtx fLocationCtx;
private LocationCtxFile fLocationCtx;
private int fOffset;
private int fLength;
public ASTFileLocation(FileLocationCtx fileLocationCtx, int startOffset, int length) {
public ASTFileLocation(LocationCtxFile fileLocationCtx, int startOffset, int length) {
fLocationCtx= fileLocationCtx;
fOffset= startOffset;
fLength= length;
@ -419,6 +463,48 @@ class ASTFileLocation implements IASTFileLocation {
public char[] getSource() {
return fLocationCtx.getSource(fOffset, fLength);
}
public String toString() {
return getFileName() + "[" + fOffset + "," + (fOffset+fLength) + ")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
}
}
class ASTMacroExpansionLocation implements IASTMacroExpansion {
private LocationCtxMacroExpansion fContext;
private int fOffset;
private int fLength;
public ASTMacroExpansionLocation(LocationCtxMacroExpansion macroExpansionCtx, int offset, int length) {
fContext= macroExpansionCtx;
fOffset= offset;
fLength= length;
}
public IASTNodeLocation[] getExpansionLocations() {
final IASTFileLocation fl= asFileLocation();
return fl == null ? new IASTNodeLocation[0] : new IASTNodeLocation[] {fl};
}
public IASTPreprocessorMacroDefinition getMacroDefinition() {
return fContext.getMacroDefinition();
}
public IASTFileLocation asFileLocation() {
return ((LocationCtxContainer) fContext.getParent()).createFileLocation(fContext.fOffsetInParent, fContext.fEndOffsetInParent-fContext.fOffsetInParent);
}
public int getNodeLength() {
return fLength;
}
public int getNodeOffset() {
return fOffset;
}
public String toString() {
return fContext.getMacroDefinition().getName().toString() + "[" + fOffset + "," + (fOffset+fLength) + ")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
}
}
class ASTFileLocationForBuiltins implements IASTFileLocation {

View file

@ -40,6 +40,7 @@ import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.ast.IASTFactory;
import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
@ -51,14 +52,6 @@ import org.eclipse.cdt.internal.core.parser.scanner2.ScannerUtility;
* you should be using the {@link IScanner} interface.
* @since 5.0
*/
/**
* @since 5.0
*
*/
/**
* @since 5.0
*
*/
public class CPreprocessor implements ILexerLog, IScanner {
public static final String PROP_VALUE = "CPreprocessor"; //$NON-NLS-1$
@ -118,7 +111,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
StringBuffer buffer = new StringBuffer("\""); //$NON-NLS-1$
buffer.append(getCurrentFilename());
buffer.append('\"');
return new ImageToken(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
}
};
final private DynamicStyleMacro __DATE__= new DynamicStyleMacro("__DATE__".toCharArray()) { //$NON-NLS-1$
@ -137,7 +130,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
buffer.append(" "); //$NON-NLS-1$
buffer.append(cal.get(Calendar.YEAR));
buffer.append("\""); //$NON-NLS-1$
return new ImageToken(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
}
};
@ -157,14 +150,14 @@ public class CPreprocessor implements ILexerLog, IScanner {
buffer.append(":"); //$NON-NLS-1$
append(buffer, cal.get(Calendar.SECOND));
buffer.append("\""); //$NON-NLS-1$
return new ImageToken(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
return new TokenWithImage(IToken.tSTRING, null, 0, 0, buffer.toString().toCharArray());
}
};
final private DynamicStyleMacro __LINE__ = new DynamicStyleMacro("__LINE__".toCharArray()) { //$NON-NLS-1$
public Token execute() {
int lineNumber= fLocationMap.getCurrentLineNumber(fCurrentContext.currentLexerToken().getOffset());
return new ImageToken(IToken.tINTEGER, null, 0, 0, Long.toString(lineNumber).toCharArray());
return new TokenWithImage(IToken.tINTEGER, null, 0, 0, Long.toString(lineNumber).toCharArray());
}
};
@ -240,6 +233,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
}
public void setContentAssistMode(int offset) {
fContentAssistLimit= offset;
fRootLexer.setContentAssistMode(offset);
}
@ -441,8 +435,17 @@ public class CPreprocessor implements ILexerLog, IScanner {
if (fContentAssistLimit < 0) {
throw new EndOfFileException();
}
t1= new SimpleToken(IToken.tEOC, null, fContentAssistLimit, fContentAssistLimit);
int useType= IToken.tCOMPLETION;
if (fLastToken != null) {
final int lt= fLastToken.getType();
if (lt == IToken.tCOMPLETION || lt == IToken.tEOC) {
useType= IToken.tEOC;
}
}
int sequenceNumber= fLocationMap.getSequenceNumberForOffset(fContentAssistLimit);
t1= new Token(useType, null, sequenceNumber, sequenceNumber);
break;
case IToken.tSTRING:
case IToken.tLSTRING:
boolean isWide= tt1 == IToken.tLSTRING;
@ -480,7 +483,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
image[++off]= '"';
buf.getChars(0, buf.length(), image, ++off);
image[image.length-1]= '"';
t1= new ImageToken((isWide ? IToken.tLSTRING : IToken.tSTRING), null, t1.getOffset(), endOffset, image);
t1= new TokenWithImage((isWide ? IToken.tLSTRING : IToken.tSTRING), null, t1.getOffset(), endOffset, image);
}
}
@ -653,7 +656,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
if (isHex && !hasExponent) {
continue;
}
if (isFloat && !isHex && !hasExponent && pos+1 >= image.length) {
if (isFloat && !isHex && !hasExponent && pos+1 <= image.length) {
switch (image[pos+1]) {
case '+': case '-':
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
@ -841,14 +844,13 @@ public class CPreprocessor implements ILexerLog, IScanner {
// we have an identifier
final char[] name = ident.getCharImage();
final int type = fPPKeywords.get(name);
int endOffset;
int condEndOffset;
switch (type) {
case IPreprocessorDirective.ppImport:
case IPreprocessorDirective.ppInclude:
if (fExpandingMacro) {
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, startOffset, endOffset);
condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, startOffset, condEndOffset);
}
else {
executeInclude(lexer, startOffset, false, true);
@ -879,35 +881,33 @@ public class CPreprocessor implements ILexerLog, IScanner {
break;
case IPreprocessorDirective.ppElse:
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELSE)) {
fLocationMap.encounterPoundElse(startOffset, endOffset, false);
fLocationMap.encounterPoundElse(startOffset, ident.getEndOffset(), false);
skipOverConditionalCode(lexer, false);
}
else {
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, endOffset);
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, ident.getEndOffset());
}
break;
case IPreprocessorDirective.ppElif:
int condOffset= lexer.nextToken().getOffset();
int condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
int endOffset= lexer.currentToken().getEndOffset();
if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELIF)) {
fLocationMap.encounterPoundElif(startOffset, condOffset, condEndOffset, endOffset, false);
skipOverConditionalCode(lexer, false);
}
else {
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, endOffset);
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, condEndOffset);
}
break;
case IPreprocessorDirective.ppEndif:
condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
if (fCurrentContext.changeBranch(ScannerContext.BRANCH_END)) {
fLocationMap.encounterPoundEndIf(startOffset, condEndOffset);
fLocationMap.encounterPoundEndIf(startOffset, ident.getEndOffset());
}
else {
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, endOffset);
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, startOffset, ident.getEndOffset());
}
break;
case IPreprocessorDirective.ppWarning:
@ -932,9 +932,9 @@ public class CPreprocessor implements ILexerLog, IScanner {
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
break;
default:
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, startOffset, endOffset);
handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE, name, startOffset, condEndOffset);
break;
}
}
@ -962,8 +962,13 @@ public class CPreprocessor implements ILexerLog, IScanner {
case Lexer.tQUOTE_HEADER_NAME:
image= header.getCharImage();
if (image.length <= 2) {
headerName= CharArrayUtils.EMPTY;
}
else {
headerName= new char[image.length-2];
System.arraycopy(image, 1, headerName, 0, headerName.length);
}
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
break;
@ -1011,7 +1016,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
if (headerName == null || headerName.length==0) {
if (active) {
handleProblem(IProblem.PREPROCESSOR_INVALID_DIRECTIVE,
lexer.getInputChars(poundOffset, endOffset), poundOffset, endOffset);
lexer.getInputChars(poundOffset, endOffset), poundOffset, nameEndOffset);
}
return;
}
@ -1032,7 +1037,7 @@ public class CPreprocessor implements ILexerLog, IScanner {
}
}
else {
handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, headerName, poundOffset, endOffset);
handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, headerName, poundOffset, nameEndOffset);
}
}
else {
@ -1240,16 +1245,15 @@ public class CPreprocessor implements ILexerLog, IScanner {
break;
case IPreprocessorDirective.ppElse:
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
if (fCurrentContext.changeBranch(ScannerContext.BRANCH_ELSE)) {
boolean isActive= nesting == 0 && takeElseBranch;
fLocationMap.encounterPoundElse(pound.getOffset(), endOffset, isActive);
fLocationMap.encounterPoundElse(pound.getOffset(), ident.getEndOffset(), isActive);
if (isActive) {
return;
}
}
else {
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), endOffset);
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), ident.getEndOffset());
}
break;
case IPreprocessorDirective.ppElif:
@ -1286,16 +1290,15 @@ public class CPreprocessor implements ILexerLog, IScanner {
break;
case IPreprocessorDirective.ppEndif:
lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
endOffset= lexer.currentToken().getEndOffset();
if (fCurrentContext.changeBranch(ScannerContext.BRANCH_END)) {
fLocationMap.encounterPoundEndIf(pound.getOffset(), endOffset);
fLocationMap.encounterPoundEndIf(pound.getOffset(), ident.getEndOffset());
if (nesting == 0) {
return;
}
--nesting;
}
else {
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), endOffset);
handleProblem(IProblem.PREPROCESSOR_UNBALANCE_CONDITION, name, pound.getOffset(), ident.getEndOffset());
}
break;
default:

View file

@ -272,7 +272,7 @@ class ExpressionEvaluator {
private void consume() {
fTokens= (Token) fTokens.getNext();
if (fTokens == null) {
fTokens= new SimpleToken(Lexer.tEND_OF_INPUT, null, 0, 0);
fTokens= new Token(Lexer.tEND_OF_INPUT, null, 0, 0);
}
}

View file

@ -12,7 +12,10 @@
package org.eclipse.cdt.internal.core.parser.scanner;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
@ -59,34 +62,67 @@ public interface ILocationResolver extends org.eclipse.cdt.internal.core.parser.
*/
IASTProblem[] getScannerProblems();
/**
* Returns the comments encountered.
*/
IASTComment[] getComments();
/**
* @see IASTTranslationUnit#getFilePath()
*/
public String getTranslationUnitPath();
String getTranslationUnitPath();
/**
* @see IASTTranslationUnit#getContainingFilename()
* mstodo- scanner removal should be renamed
*/
public String getContainingFilename(int offset);
String getContainingFilename(int sequenceNumber);
/**
* @see IASTTranslationUnit#getDependencyTree()
*/
public IDependencyTree getDependencyTree();
IDependencyTree getDependencyTree();
/**
* Returns explicit and implicit references for a macro.
*/
public IASTName[] getReferences(IMacroBinding binding);
IASTName[] getReferences(IMacroBinding binding);
/**
* Returns the definition for a macro.
*/
public IASTName[] getDeclarations(IMacroBinding binding);
IASTName[] getDeclarations(IMacroBinding binding);
/**
* Returns the comments encountered.
* Returns the smallest file location, that encloses the given global range. In case the range
* spans over multiple files, the files are mapped to include statements until all of them are
* found in the same file. So the resulting location contains the include directives that actually
* cause the range to be part of the AST.
* @param offset sequence number as stored in the ASTNodes.
* @param length
*/
IASTComment[] getComments();
IASTFileLocation getMappedFileLocation(int offset, int length);
/**
* @see IASTTranslationUnit#getLocationInfo(int, int).
*/
IASTNodeLocation[] getLocations(int sequenceNumber, int length);
/**
* Returns the sequence-number for the given file-path and offset, or <code>-1</code> if this file
* is not part of the translation-unit.
* @param filePath a file path or <code>null</code> to specify the root of the translation unit.
* @param fileOffset an offset into the source of the file.
*/
int getSequenceNumberForFileOffset(String filePath, int fileOffset);
/**
* @see IASTTranslationUnit#getUnpreprocessedSignature(IASTFileLocation).
*/
char[] getUnpreprocessedSignature(IASTFileLocation loc);
/**
* Returns a preprocessor node surrounding the given range, or <code>null</code>.
*/
IASTNode findSurroundingPreprocessorNode(int sequenceNumber, int length);
}

View file

@ -96,7 +96,7 @@ final public class Lexer {
fOptions= options;
fLog= log;
fSource= source;
fToken= new SimpleToken(tBEFORE_INPUT, source, start, start);
fToken= new Token(tBEFORE_INPUT, source, start, start);
nextCharPhase3();
}
@ -601,20 +601,25 @@ final public class Lexer {
}
private Token newToken(int kind, int offset) {
return new SimpleToken(kind, fSource, offset, fOffset);
return new Token(kind, fSource, offset, fOffset);
}
private Token newDigraphToken(int kind, int offset) {
return new DigraphToken(kind, fSource, offset, fOffset);
return new TokenForDigraph(kind, fSource, offset, fOffset);
}
private Token newToken(int kind, int offset, int imageLength) {
private Token newToken(final int kind, final int offset, final int imageLength) {
final int endOffset= fOffset;
int sourceLen= endOffset-offset;
final int sourceLen= endOffset-offset;
char[] image;
if (sourceLen != imageLength) {
return new ImageToken(kind, fSource, offset, endOffset, getCharImage(offset, endOffset, imageLength));
image= getCharImage(offset, endOffset, imageLength);
}
return new SourceImageToken(kind, fSource, offset, endOffset, fInput);
else {
image= new char[imageLength];
System.arraycopy(fInput, offset, image, 0, imageLength);
}
return new TokenWithImage(kind, fSource, offset, endOffset, image);
}
private void handleProblem(int problemID, char[] arg, int offset) {

View file

@ -11,8 +11,8 @@
package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Collection;
import java.util.Collections;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
@ -22,15 +22,24 @@ import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
* @since 5.0
*/
abstract class LocationCtx implements ILocationCtx {
final ContainerLocationCtx fParent;
final LocationCtxContainer fParent;
/**
* The first sequence number used by this context.
*/
final int fSequenceNumber;
final int fParentOffset;
final int fParentEndOffset;
/**
* The offset of the denotation of this context in the parent's source. This is no sequence number.
*/
final int fOffsetInParent;
/**
* The end-offset of the denotation of this context in the parent's source. This is no sequence number.
*/
final int fEndOffsetInParent;
public LocationCtx(ContainerLocationCtx parent, int parentOffset, int parentEndOffset, int sequenceNumber) {
public LocationCtx(LocationCtxContainer parent, int parentOffset, int parentEndOffset, int sequenceNumber) {
fParent= parent;
fParentOffset= parentOffset;
fParentEndOffset= parentEndOffset;
fOffsetInParent= parentOffset;
fEndOffsetInParent= parentEndOffset;
fSequenceNumber= sequenceNumber;
if (parent != null) {
parent.addChild(this);
@ -77,7 +86,7 @@ abstract class LocationCtx implements ILocationCtx {
* Returns the minimal context containing the specified range, assuming that it is contained in
* this context.
*/
public LocationCtx ctxForNumberRange(int sequenceNumber, int length) {
public LocationCtx findSurroundingContext(int sequenceNumber, int length) {
return this;
}
@ -85,17 +94,23 @@ abstract class LocationCtx implements ILocationCtx {
* Returns the minimal file location containing the specified sequence number range, assuming
* that it is contained in this context.
*/
public IASTFileLocation fileLocationForNumberRange(int sequenceNumber, int length) {
return fParent.fileLocationForOffsetRange(fParentOffset, fParentEndOffset-fParentOffset);
public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
return fParent.createMappedFileLocation(fOffsetInParent, fEndOffsetInParent-fOffsetInParent);
}
/**
* Returns the file location containing the specified offset range in this context.
*/
public IASTFileLocation fileLocationForOffsetRange(int parentOffset, int length) {
return fParent.fileLocationForOffsetRange(fParentOffset, fParentEndOffset-fParentOffset);
public IASTFileLocation createMappedFileLocation(int offset, int length) {
return fParent.createMappedFileLocation(fOffsetInParent, fEndOffsetInParent-fOffsetInParent);
}
/**
* Returns the sequence of file locations spanning the given range.
* Assumes that the range starts within this context.
*/
public abstract boolean collectLocations(int sequenceNumber, int length, ArrayList sofar);
/**
* Support for the dependency tree, add inclusion statements found in this context.
*/
@ -108,228 +123,8 @@ abstract class LocationCtx implements ILocationCtx {
public ASTInclusionStatement getInclusionStatement() {
return null;
}
}
class ContainerLocationCtx extends LocationCtx {
private int fChildSequenceLength;
private ArrayList fChildren;
private char[] fSource;
private int[] fLineOffsets;
public ContainerLocationCtx(ContainerLocationCtx parent, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber) {
super(parent, parentOffset, parentEndOffset, sequenceNumber);
fSource= source;
}
public void addChild(LocationCtx locationCtx) {
if (fChildren == null) {
fChildren= new ArrayList();
}
fChildren.add(locationCtx);
}
public char[] getSource(int offset, int length) {
offset= Math.max(0, Math.min(offset, fSource.length));
length= Math.max(0, Math.min(length, fSource.length-offset));
char[] result= new char[length];
System.arraycopy(fSource, offset, result, 0, length);
return result;
}
public final int getSequenceLength() {
return fSource.length + fChildSequenceLength;
}
public final int getSequenceNumberForOffset(int offset, boolean checkChildren) {
int result= fSequenceNumber + fChildSequenceLength + offset;
if (checkChildren && fChildren != null) {
for (int i= fChildren.size()-1; i >= 0; i--) {
final LocationCtx child= (LocationCtx) fChildren.get(i);
if (child.fParentEndOffset > offset) { // child was inserted behind the offset, adjust sequence number
result-= child.getSequenceLength();
}
else {
return result;
}
}
}
return result;
}
public void addChildSequenceLength(int childLength) {
fChildSequenceLength+= childLength;
}
public final LocationCtx ctxForNumberRange(int sequenceNumber, int length) {
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber);
if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) {
return child.ctxForNumberRange(sequenceNumber, length);
}
return this;
}
public IASTFileLocation fileLocationForNumberRange(int sequenceNumber, int length) {
// try to delegate to a child.
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber);
if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) {
if (testEnd == sequenceNumber || findChildLessOrEqualThan(testEnd) == child) {
return child.fileLocationForNumberRange(sequenceNumber, length);
}
}
return super.fileLocationForNumberRange(sequenceNumber, length);
}
final LocationCtx findChildLessOrEqualThan(final int sequenceNumber) {
if (fChildren == null) {
return null;
}
int upper= fChildren.size();
int lower= 0;
while (upper > lower) {
int middle= (upper+lower)/2;
LocationCtx child= (LocationCtx) fChildren.get(middle);
if (child.fSequenceNumber <= sequenceNumber) {
lower= middle+1;
}
else {
upper= middle;
}
}
if (lower > 0) {
return (LocationCtx) fChildren.get(lower-1);
}
return null;
}
public void getInclusions(ArrayList result) {
if (fChildren != null) {
for (Iterator iterator = fChildren.iterator(); iterator.hasNext();) {
LocationCtx ctx= (LocationCtx) iterator.next();
if (ctx.getInclusionStatement() != null) {
result.add(new ASTInclusionNode(ctx));
}
else {
ctx.getInclusions(result);
}
}
}
}
public int getLineNumber(int offset) {
if (fLineOffsets == null) {
fLineOffsets= computeLineOffsets();
}
int idx= Arrays.binarySearch(fLineOffsets, offset);
if (idx < 0) {
return -idx;
}
return idx+1;
}
private int[] computeLineOffsets() {
ArrayList offsets= new ArrayList();
for (int i = 0; i < fSource.length; i++) {
if (fSource[i] == '\n') {
offsets.add(new Integer(i));
}
}
int[] result= new int[offsets.size()];
for (int i = 0; i < result.length; i++) {
result[i]= ((Integer) offsets.get(i)).intValue();
}
return result;
}
}
class FileLocationCtx extends ContainerLocationCtx {
private final String fFilename;
private final ASTInclusionStatement fASTInclude;
public FileLocationCtx(ContainerLocationCtx parent, String filename, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber, ASTInclusionStatement inclusionStatement) {
super(parent, source, parentOffset, parentEndOffset, sequenceNumber);
fFilename= new String(filename);
fASTInclude= inclusionStatement;
}
public final void addChildSequenceLength(int childLength) {
super.addChildSequenceLength(childLength);
if (fASTInclude != null) {
fASTInclude.setLength(fASTInclude.getLength()+childLength);
}
}
public final String getFilePath() {
return fFilename;
}
public IASTFileLocation fileLocationForNumberRange(int sequenceNumber, int length) {
// try to delegate to a child.
final int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
final int sequenceEnd= sequenceNumber+length;
final LocationCtx child1= findChildLessOrEqualThan(sequenceNumber);
final LocationCtx child2= testEnd == sequenceNumber ? child1 : findChildLessOrEqualThan(testEnd);
if (child1 == child2 && child1 != null && child1.fSequenceNumber + child1.getSequenceLength() > testEnd) {
return child1.fileLocationForNumberRange(sequenceNumber, length);
}
// handle here
int startOffset;
int endOffset;
if (child1 == null) {
startOffset= sequenceNumber-fSequenceNumber;
}
else {
int childSequenceEnd= child1.fSequenceNumber + child1.getSequenceLength();
if (sequenceNumber < childSequenceEnd) {
startOffset= child1.fParentOffset;
}
else { // start beyond child1
startOffset= child1.fParentEndOffset + sequenceNumber-childSequenceEnd;
}
}
if (child2 == null) {
endOffset= sequenceEnd-fSequenceNumber;
}
else {
int childSequenceEnd= child2.fSequenceNumber + child2.getSequenceLength();
if (childSequenceEnd < sequenceEnd) { // beyond child2
endOffset= child2.fParentEndOffset+sequenceEnd-childSequenceEnd;
}
else {
endOffset= child2.fParentEndOffset;
}
}
return new ASTFileLocation(this, startOffset, endOffset-startOffset);
}
public IASTFileLocation fileLocationForOffsetRange(int offset, int length) {
return new ASTFileLocation(this, offset, length);
}
public ASTInclusionStatement getInclusionStatement() {
return fASTInclude;
public Collection getChildren() {
return Collections.EMPTY_SET;
}
}
class MacroExpansionCtx extends LocationCtx {
private final int fLength;
public MacroExpansionCtx(ContainerLocationCtx parent, int parentOffset, int parentEndOffset,
int sequenceNumber, int length, ImageLocationInfo[] imageLocations, ASTPreprocessorName expansion) {
super(parent, parentOffset, parentEndOffset, sequenceNumber);
fLength= length;
}
public int getSequenceLength() {
return fLength;
}
// mstodo- image locations
}

View file

@ -0,0 +1,220 @@
/*******************************************************************************
* Copyright (c) 2007 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
/**
* Base class for all location contexts that can contain children.
* <p>
* @since 5.0
*/
class LocationCtxContainer extends LocationCtx {
/**
* The total length of all children in terms of sequence numbers.
*/
private int fChildSequenceLength;
private ArrayList fChildren;
private char[] fSource;
private int[] fLineOffsets;
public LocationCtxContainer(LocationCtxContainer parent, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber) {
super(parent, parentOffset, parentEndOffset, sequenceNumber);
fSource= source;
}
public Collection getChildren() {
return fChildren == null ? Collections.EMPTY_LIST : fChildren;
}
public void addChild(LocationCtx locationCtx) {
if (fChildren == null) {
fChildren= new ArrayList();
}
fChildren.add(locationCtx);
}
public char[] getSource(int offset, int length) {
offset= Math.max(0, Math.min(offset, fSource.length));
length= Math.max(0, Math.min(length, fSource.length-offset));
char[] result= new char[length];
System.arraycopy(fSource, offset, result, 0, length);
return result;
}
public final int getSequenceLength() {
return fSource.length + fChildSequenceLength;
}
public final int getSequenceNumberForOffset(int offset, boolean checkChildren) {
int result= fSequenceNumber + fChildSequenceLength + offset;
if (checkChildren && fChildren != null) {
for (int i= fChildren.size()-1; i >= 0; i--) {
final LocationCtx child= (LocationCtx) fChildren.get(i);
if (child.fEndOffsetInParent > offset) { // child was inserted behind the offset, adjust sequence number
result-= child.getSequenceLength();
}
else {
return result;
}
}
}
return result;
}
public void addChildSequenceLength(int childLength) {
fChildSequenceLength+= childLength;
}
public final LocationCtx findSurroundingContext(int sequenceNumber, int length) {
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber);
if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) {
return child.findSurroundingContext(sequenceNumber, length);
}
return this;
}
public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
// try to delegate to a child.
int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
final LocationCtx child= findChildLessOrEqualThan(sequenceNumber);
if (child != null && child.fSequenceNumber+child.getSequenceLength() > testEnd) {
return child.findMappedFileLocation(sequenceNumber, length);
}
return super.findMappedFileLocation(sequenceNumber, length);
}
public boolean collectLocations(int sequenceNumber, final int length, ArrayList locations) {
final int endSequenceNumber= sequenceNumber+length;
if (fChildren != null) {
int childIdx= Math.max(0, findChildIdxLessOrEqualThan(sequenceNumber));
for (; childIdx < fChildren.size(); childIdx++) {
final LocationCtx child= (LocationCtx) fChildren.get(childIdx);
// create the location between start and the child
if (sequenceNumber < child.fSequenceNumber) {
// compute offset backwards from the child's offset
final int offset= child.fEndOffsetInParent - (child.fSequenceNumber - sequenceNumber);
// it the child is not affected, we are done.
if (endSequenceNumber <= child.fSequenceNumber) {
addFileLocation(offset, endSequenceNumber-sequenceNumber, locations);
return true;
}
addFileLocation(offset, child.fOffsetInParent-offset, locations);
sequenceNumber= child.fSequenceNumber;
}
// let the child create locations
final int childEndSequenceNumber= child.fSequenceNumber + child.getSequenceLength();
if (sequenceNumber < childEndSequenceNumber) {
if (child.collectLocations(sequenceNumber, endSequenceNumber-sequenceNumber, locations)) {
return true;
}
sequenceNumber= childEndSequenceNumber;
}
}
}
// create the location after the last child.
final int myEndNumber = fSequenceNumber + getSequenceLength();
final int offset= fSource.length - (myEndNumber - sequenceNumber);
if (endSequenceNumber <= myEndNumber) {
addFileLocation(offset, endSequenceNumber-sequenceNumber, locations);
return true;
}
addFileLocation(offset, fSource.length-offset, locations);
return false;
}
private ArrayList addFileLocation(int offset, int length, ArrayList sofar) {
IASTFileLocation loc= createFileLocation(offset, length);
if (loc != null) {
sofar.add(loc);
}
return sofar;
}
ASTFileLocation createFileLocation(int start, int length) {
return null;
}
final int findChildIdxLessOrEqualThan(int sequenceNumber) {
if (fChildren == null) {
return -1;
}
int upper= fChildren.size();
int lower= 0;
while (upper > lower) {
int middle= (upper+lower)/2;
LocationCtx child= (LocationCtx) fChildren.get(middle);
if (child.fSequenceNumber <= sequenceNumber) {
lower= middle+1;
}
else {
upper= middle;
}
}
return lower-1;
}
final LocationCtx findChildLessOrEqualThan(final int sequenceNumber) {
final int idx= findChildIdxLessOrEqualThan(sequenceNumber);
return idx >= 0 ? (LocationCtx) fChildren.get(idx) : null;
}
public void getInclusions(ArrayList result) {
if (fChildren != null) {
for (Iterator iterator = fChildren.iterator(); iterator.hasNext();) {
LocationCtx ctx= (LocationCtx) iterator.next();
if (ctx.getInclusionStatement() != null) {
result.add(new ASTInclusionNode(ctx));
}
else {
ctx.getInclusions(result);
}
}
}
}
public int getLineNumber(int offset) {
if (fLineOffsets == null) {
fLineOffsets= computeLineOffsets();
}
int idx= Arrays.binarySearch(fLineOffsets, offset);
if (idx < 0) {
return -idx;
}
return idx+1;
}
private int[] computeLineOffsets() {
ArrayList offsets= new ArrayList();
for (int i = 0; i < fSource.length; i++) {
if (fSource[i] == '\n') {
offsets.add(new Integer(i));
}
}
int[] result= new int[offsets.size()];
for (int i = 0; i < result.length; i++) {
result[i]= ((Integer) offsets.get(i)).intValue();
}
return result;
}
}

View file

@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright (c) 2007 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
/**
* A location context representing a file.
* @since 5.0
*/
class LocationCtxFile extends LocationCtxContainer {
private final String fFilename;
private final ASTInclusionStatement fASTInclude;
public LocationCtxFile(LocationCtxContainer parent, String filename, char[] source, int parentOffset, int parentEndOffset, int sequenceNumber, ASTInclusionStatement inclusionStatement) {
super(parent, source, parentOffset, parentEndOffset, sequenceNumber);
fFilename= new String(filename);
fASTInclude= inclusionStatement;
}
public final void addChildSequenceLength(int childLength) {
super.addChildSequenceLength(childLength);
if (fASTInclude != null) {
fASTInclude.setLength(fASTInclude.getLength()+childLength);
}
}
public final String getFilePath() {
return fFilename;
}
public IASTFileLocation findMappedFileLocation(int sequenceNumber, int length) {
// try to delegate to a child.
final int testEnd= length > 1 ? sequenceNumber+length-1 : sequenceNumber;
final int sequenceEnd= sequenceNumber+length;
final LocationCtx child1= findChildLessOrEqualThan(sequenceNumber);
final LocationCtx child2= testEnd == sequenceNumber ? child1 : findChildLessOrEqualThan(testEnd);
if (child1 == child2 && child1 != null && child1.fSequenceNumber + child1.getSequenceLength() > testEnd) {
return child1.findMappedFileLocation(sequenceNumber, length);
}
// handle here
int startOffset;
int endOffset;
if (child1 == null) {
startOffset= sequenceNumber-fSequenceNumber;
}
else {
int childSequenceEnd= child1.fSequenceNumber + child1.getSequenceLength();
if (sequenceNumber < childSequenceEnd) {
startOffset= child1.fOffsetInParent;
}
else { // start beyond child1
startOffset= child1.fEndOffsetInParent + sequenceNumber-childSequenceEnd;
}
}
if (child2 == null) {
endOffset= sequenceEnd-fSequenceNumber;
}
else {
int childSequenceEnd= child2.fSequenceNumber + child2.getSequenceLength();
if (childSequenceEnd < sequenceEnd) { // beyond child2
endOffset= child2.fEndOffsetInParent+sequenceEnd-childSequenceEnd;
}
else {
endOffset= child2.fEndOffsetInParent;
}
}
return new ASTFileLocation(this, startOffset, endOffset-startOffset);
}
public IASTFileLocation createMappedFileLocation(int offset, int length) {
return new ASTFileLocation(this, offset, length);
}
public ASTInclusionStatement getInclusionStatement() {
return fASTInclude;
}
ASTFileLocation createFileLocation(int start, int length) {
return new ASTFileLocation(this, start, length);
}
}

View file

@ -0,0 +1,57 @@
/*******************************************************************************
* Copyright (c) 2007 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
/**
* A location context representing macro expansions.
* @since 5.0
*/
class LocationCtxMacroExpansion extends LocationCtx {
private final LocationMap fLocationMap;
private final int fLength;
private ASTMacroReferenceName fName;
public LocationCtxMacroExpansion(LocationMap map, LocationCtxContainer parent, int parentOffset, int parentEndOffset,
int sequenceNumber, int length, ImageLocationInfo[] imageLocations, ASTMacroReferenceName expansion) {
super(parent, parentOffset, parentEndOffset, sequenceNumber);
fLocationMap= map;
fLength= length;
fName= expansion;
}
public int getSequenceLength() {
return fLength;
}
public boolean collectLocations(int start, int length, ArrayList locations) {
final int offset= start-fSequenceNumber;
assert offset >= 0 && length >= 0;
if (offset+length <= fLength) {
locations.add(new ASTMacroExpansionLocation(this, offset, length));
return true;
}
locations.add(new ASTMacroExpansionLocation(this, offset, fLength-offset));
return false;
}
public IASTPreprocessorMacroDefinition getMacroDefinition() {
return fLocationMap.getMacroDefinition((IMacroBinding) fName.getBinding());
}
}

View file

@ -13,11 +13,13 @@ package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
@ -44,7 +46,7 @@ public class LocationMap implements ILocationResolver {
private ArrayList fProblems= new ArrayList();
private ArrayList fComments= new ArrayList();
private ArrayList fBuiltinMacros= new ArrayList();
private IdentityHashMap fMacroExpansions= new IdentityHashMap();
private IdentityHashMap fMacroReferences= new IdentityHashMap();
private LocationCtx fRootContext= null;
private LocationCtx fCurrentContext= null;
@ -81,7 +83,7 @@ public class LocationMap implements ILocationResolver {
public ILocationCtx pushTranslationUnit(String filename, char[] buffer) {
assert fCurrentContext == null;
fTranslationUnitPath= filename;
fRootContext= fCurrentContext= new FileLocationCtx(null, filename, buffer, 0, 0, 0, null);
fRootContext= fCurrentContext= new LocationCtxFile(null, filename, buffer, 0, 0, 0, null);
fLastChildInsertionOffset= 0;
return fCurrentContext;
}
@ -93,9 +95,9 @@ public class LocationMap implements ILocationResolver {
* @param isMacroFile whether the context is used for running the preprocessor, only.
*/
public ILocationCtx pushPreInclusion(char[] buffer, int offset, boolean isMacroFile) {
assert fCurrentContext instanceof ContainerLocationCtx;
assert fCurrentContext instanceof LocationCtxContainer;
int sequenceNumber= getSequenceNumberForOffset(offset);
fCurrentContext= new ContainerLocationCtx((ContainerLocationCtx) fCurrentContext, buffer, offset, offset, sequenceNumber);
fCurrentContext= new LocationCtxContainer((LocationCtxContainer) fCurrentContext, buffer, offset, offset, sequenceNumber);
fLastChildInsertionOffset= 0;
return fCurrentContext;
}
@ -112,7 +114,7 @@ public class LocationMap implements ILocationResolver {
*/
public ILocationCtx pushInclusion(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
char[] buffer, String filename, char[] name, boolean userInclude) {
assert fCurrentContext instanceof ContainerLocationCtx;
assert fCurrentContext instanceof LocationCtxContainer;
int startNumber= getSequenceNumberForOffset(startOffset);
int nameNumber= getSequenceNumberForOffset(nameOffset);
int nameEndNumber= getSequenceNumberForOffset(nameEndOffset);
@ -120,7 +122,7 @@ public class LocationMap implements ILocationResolver {
final ASTInclusionStatement inclusionStatement=
new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, name, filename, userInclude, true);
fDirectives.add(inclusionStatement);
fCurrentContext= new FileLocationCtx((ContainerLocationCtx) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement);
fCurrentContext= new LocationCtxFile((LocationCtxContainer) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement);
fLastChildInsertionOffset= 0;
return fCurrentContext;
}
@ -146,7 +148,7 @@ public class LocationMap implements ILocationResolver {
*/
public ILocationCtx pushMacroExpansion(int nameOffset, int nameEndOffset, int endOffset, int contextLength,
IMacroBinding macro, IASTName[] implicitMacroReferences, ImageLocationInfo[] imageLocations) {
assert fCurrentContext instanceof ContainerLocationCtx;
assert fCurrentContext instanceof LocationCtxContainer;
int nameNumber= getSequenceNumberForOffset(nameOffset);
int nameEndNumber= getSequenceNumberForOffset(nameEndOffset);
@ -156,22 +158,22 @@ public class LocationMap implements ILocationResolver {
for (int i = 0; i < implicitMacroReferences.length; i++) {
ASTMacroReferenceName name = (ASTMacroReferenceName) implicitMacroReferences[i];
name.setOffsetAndLength(nameNumber, length);
addExpansion((IMacroBinding) name.getBinding(), name);
addMacroReference((IMacroBinding) name.getBinding(), name);
}
ASTMacroReferenceName expansion= new ASTMacroReferenceName(fTranslationUnit, nameNumber, nameEndNumber, macro, null);
addExpansion(macro, expansion);
addMacroReference(macro, expansion);
fCurrentContext= new MacroExpansionCtx((ContainerLocationCtx) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, expansion);
fCurrentContext= new LocationCtxMacroExpansion(this, (LocationCtxContainer) fCurrentContext, nameOffset, endOffset, endNumber, contextLength, imageLocations, expansion);
fLastChildInsertionOffset= 0;
return fCurrentContext;
}
private void addExpansion(IMacroBinding macro, ASTPreprocessorName name) {
List list= (List) fMacroExpansions.get(macro);
private void addMacroReference(IMacroBinding macro, IASTName name) {
List list= (List) fMacroReferences.get(macro);
if (list == null) {
list= new ArrayList();
fMacroExpansions.put(macro, list);
fMacroReferences.put(macro, list);
}
list.add(name);
}
@ -186,7 +188,7 @@ public class LocationMap implements ILocationResolver {
final LocationCtx parent= (LocationCtx) fCurrentContext.getParent();
if (parent != null) {
fCurrentContext= parent;
fLastChildInsertionOffset= child.fParentEndOffset;
fLastChildInsertionOffset= child.fEndOffsetInParent;
parent.addChildSequenceLength(child.getSequenceLength());
}
}
@ -206,7 +208,7 @@ public class LocationMap implements ILocationResolver {
startOffset= getSequenceNumberForOffset(startOffset);
nameOffset= getSequenceNumberForOffset(nameOffset);
nameEndOffset= getSequenceNumberForOffset(nameEndOffset);
// endOffset= getSequenceNumberForOffset(endOffset);
// not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
fDirectives.add(new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset, nameEndOffset, name, filename, userInclude, active));
}
@ -247,7 +249,7 @@ public class LocationMap implements ILocationResolver {
startOffset= getSequenceNumberForOffset(startOffset);
condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
// compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
// not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
fDirectives.add(new ASTError(fTranslationUnit, startOffset, condOffset, condEndOffset));
}
@ -255,7 +257,7 @@ public class LocationMap implements ILocationResolver {
startOffset= getSequenceNumberForOffset(startOffset);
condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
// compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
// not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
fDirectives.add(new ASTPragma(fTranslationUnit, startOffset, condOffset, condEndOffset));
}
@ -263,7 +265,7 @@ public class LocationMap implements ILocationResolver {
startOffset= getSequenceNumberForOffset(startOffset);
condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
// compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
// not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
fDirectives.add(new ASTIfdef(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive));
}
@ -271,7 +273,7 @@ public class LocationMap implements ILocationResolver {
startOffset= getSequenceNumberForOffset(startOffset);
condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
// compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
// not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
fDirectives.add(new ASTIfndef(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive));
}
@ -279,7 +281,7 @@ public class LocationMap implements ILocationResolver {
startOffset= getSequenceNumberForOffset(startOffset);
condOffset= getSequenceNumberForOffset(condOffset);
condEndOffset= getSequenceNumberForOffset(condEndOffset);
// compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
// not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
fDirectives.add(new ASTIf(fTranslationUnit, startOffset, condOffset, condEndOffset, isActive));
}
@ -303,8 +305,10 @@ public class LocationMap implements ILocationResolver {
startOffset= getSequenceNumberForOffset(startOffset);
nameOffset= getSequenceNumberForOffset(nameOffset);
nameEndOffset= getSequenceNumberForOffset(nameEndOffset);
// endOffset= getSequenceNumberForOffset(endOffset);
fDirectives.add(new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, definition));
// not using endOffset, compatible with 4.0: endOffset= getSequenceNumberForOffset(endOffset);
final ASTUndef undef = new ASTUndef(fTranslationUnit, name, startOffset, nameOffset, nameEndOffset, definition);
fDirectives.add(undef);
addMacroReference(definition, undef.getMacroName());
}
public void setRootNode(IASTTranslationUnit root) {
@ -341,14 +345,76 @@ public class LocationMap implements ILocationResolver {
}
public String getContainingFilename(int sequenceNumber) {
LocationCtx ctx= fRootContext.ctxForNumberRange(sequenceNumber, 1);
LocationCtx ctx= fRootContext.findSurroundingContext(sequenceNumber, 1);
return new String(ctx.getFilePath());
}
public IASTFileLocation getMappedFileLocation(int sequenceNumber, int length) {
return fRootContext.fileLocationForNumberRange(sequenceNumber, length);
return fRootContext.findMappedFileLocation(sequenceNumber, length);
}
public char[] getUnpreprocessedSignature(IASTFileLocation loc) {
if (loc instanceof ASTFileLocation) {
return ((ASTFileLocation) loc).getSource();
}
return CharArrayUtils.EMPTY;
}
public IASTNodeLocation[] getLocations(int sequenceNumber, int length) {
ArrayList result= new ArrayList();
fRootContext.collectLocations(sequenceNumber, length, result);
return (IASTNodeLocation[]) result.toArray(new IASTNodeLocation[result.size()]);
}
public IASTNode findSurroundingPreprocessorNode(int sequenceNumber, int length) {
int lower=0;
int upper= fDirectives.size()-1;
while(lower <= upper) {
int middle= (lower+upper)/2;
ASTPreprocessorNode node= (ASTPreprocessorNode) fDirectives.get(middle);
final int nodeSequenceNumber= node.getOffset();
if (nodeSequenceNumber <= sequenceNumber) {
final int nodeEndSequenceNumber= nodeSequenceNumber + node.getLength();
if (sequenceNumber+length <= nodeEndSequenceNumber) {
return node.findSurroundingNode(sequenceNumber, length);
}
else {
lower= middle+1;
}
}
else {
upper= middle-1;
}
}
return null;
}
public int getSequenceNumberForFileOffset(String filePath, int fileOffset) {
LocationCtx ctx= fRootContext;
if (filePath != null) {
LinkedList contexts= new LinkedList();
while(ctx != null) {
if (ctx instanceof LocationCtxFile) {
if (filePath.equals(ctx.getFilePath())) {
break;
}
}
contexts.addAll(ctx.getChildren());
if (contexts.isEmpty()) {
ctx= null;
}
else {
ctx= (LocationCtx) contexts.removeFirst();
}
}
}
if (ctx != null) {
return ctx.getSequenceNumberForOffset(fileOffset, true);
}
return -1;
}
public IASTPreprocessorMacroDefinition[] getMacroDefinitions() {
ArrayList result= new ArrayList();
for (Iterator iterator = fDirectives.iterator(); iterator.hasNext();) {
@ -389,22 +455,27 @@ public class LocationMap implements ILocationResolver {
public IASTName[] getDeclarations(IMacroBinding binding) {
IASTPreprocessorMacroDefinition def = getMacroDefinition(binding);
return def == null ? EMPTY_NAMES : new IASTName[] {def.getName()};
}
IASTPreprocessorMacroDefinition getMacroDefinition(IMacroBinding binding) {
if (fMacroDefinitionMap == null) {
fMacroDefinitionMap= new IdentityHashMap();
IASTPreprocessorMacroDefinition[] defs= getMacroDefinitions();
for (int i = 0; i < defs.length; i++) {
final IASTName name = defs[i].getName();
final IASTPreprocessorMacroDefinition def = defs[i];
final IASTName name = def.getName();
if (name != null) {
fMacroDefinitionMap.put(name.getBinding(), name);
fMacroDefinitionMap.put(name.getBinding(), def);
}
}
}
IASTName name= (IASTName) fMacroDefinitionMap.get(binding);
return name == null ? EMPTY_NAMES : new IASTName[] {name};
return (IASTPreprocessorMacroDefinition) fMacroDefinitionMap.get(binding);
}
public IASTName[] getReferences(IMacroBinding binding) {
List list= (List) fMacroExpansions.get(binding);
List list= (List) fMacroReferences.get(binding);
if (list == null) {
return EMPTY_NAMES;
}
@ -418,36 +489,19 @@ public class LocationMap implements ILocationResolver {
public void cleanup() {
}
// stuff to remove from ILocationResolver
public IASTName[] getMacroExpansions() {
throw new UnsupportedOperationException();
}
// mstodo- locations
public IASTFileLocation flattenLocations(IASTNodeLocation[] locations) {
if (locations.length != 1 || !(locations[0] instanceof IASTFileLocation)) {
throw new IllegalArgumentException();
}
return (IASTFileLocation) locations[0];
}
// mstodo- locations
public IASTNodeLocation[] getLocations(int offset, int length) {
return new IASTNodeLocation[] {getMappedFileLocation(offset, length)};
}
public ASTPreprocessorSelectionResult getPreprocessorNode(String path, int offset, int length) {
throw new UnsupportedOperationException();
}
// mstodo- locations
public char[] getUnpreprocessedSignature(IASTNodeLocation[] locations) {
switch(locations.length) {
case 0: return CharArrayUtils.EMPTY;
case 1: break;
default: throw new IllegalArgumentException();
throw new UnsupportedOperationException();
}
if (!(locations[0] instanceof ASTFileLocation)) {
throw new IllegalArgumentException();
// mstodo- scanner removal
public IASTFileLocation flattenLocations(IASTNodeLocation[] locations) {
throw new UnsupportedOperationException();
}
ASTFileLocation floc= (ASTFileLocation) locations[0];
return floc.getSource();
// mstodo- scanner removal
public IASTName[] getMacroExpansions() {
throw new UnsupportedOperationException();
}
}

View file

@ -23,6 +23,11 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
* @since 5.0
*/
class MacroDefinitionParser {
private static final int ORIGIN_PREPROCESSOR_DIRECTIVE = OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE;
/**
* Exception for reporting problems while parsing a macro definition.
*/
static class InvalidMacroDefinitionException extends Exception {
public char[] fName;
public int fStartOffset;
@ -34,7 +39,25 @@ class MacroDefinitionParser {
}
}
private static final int ORIGIN_PREPROCESSOR_DIRECTIVE = OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE;
/**
* Token used for macro parameters found in the replacement list.
*/
static class TokenParameterReference extends TokenWithImage {
private final int fIndex;
public TokenParameterReference(int type, int idx, Object source, int offset, int endOffset, char[] name) {
super(type, source, offset, endOffset, name);
fIndex= idx;
}
public int getIndex() {
return fIndex;
}
public String toString() {
return "[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
private int fHasVarArgs;
private int fExpansionOffset;
@ -208,7 +231,7 @@ class MacroDefinitionParser {
final char[] image = candidate.getCharImage();
int idx= CharArrayUtils.indexOf(image, paramList);
if (idx >= 0) {
candidate= new PlaceHolderToken(CPreprocessor.tMACRO_PARAMETER, idx, lexer.getSource(), candidate.getOffset(), candidate.getEndOffset(), paramList[idx]);
candidate= new TokenParameterReference(CPreprocessor.tMACRO_PARAMETER, idx, lexer.getSource(), candidate.getOffset(), candidate.getEndOffset(), paramList[idx]);
needParam= false;
}
else {
@ -225,6 +248,7 @@ class MacroDefinitionParser {
break;
case IToken.tPOUND:
needParam= paramList != null;
needAnotherToken= null;
break;
case IToken.tPOUNDPOUND:
if (needParam || isFirst) {

View file

@ -20,6 +20,7 @@ import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.TokenParameterReference;
/**
* Utility class to perform macro expansion.
@ -220,10 +221,10 @@ public class MacroExpander {
final Object s2= t.fSource;
if (s1 == s2 && s1 != null) {
if (l.getEndOffset() == t.getOffset()) {
target.append(new SimpleToken(CPreprocessor.tNOSPACE, null, 0, 0));
target.append(new Token(CPreprocessor.tNOSPACE, null, 0, 0));
}
else {
target.append(new SimpleToken(CPreprocessor.tSPACE, null, 0, 0));
target.append(new Token(CPreprocessor.tSPACE, null, 0, 0));
}
}
}
@ -350,7 +351,7 @@ public class MacroExpander {
switch(t.getType()) {
case CPreprocessor.tMACRO_PARAMETER:
int idx= ((PlaceHolderToken) t).getIndex();
int idx= ((TokenParameterReference) t).getIndex();
if (idx < args.length) { // be defensive
addSpacemarker(l, t, result); // start argument replacement
TokenList arg= clone(pasteNext ? args[idx] : expandedArgs[idx]);
@ -373,7 +374,7 @@ public class MacroExpander {
StringBuffer buf= new StringBuffer();
buf.append('"');
if (n != null && n.getType() == CPreprocessor.tMACRO_PARAMETER) {
idx= ((PlaceHolderToken) n).getIndex();
idx= ((TokenParameterReference) n).getIndex();
if (idx < args.length) { // be defensive
stringify(args[idx], buf);
}
@ -386,7 +387,7 @@ public class MacroExpander {
final char[] image= new char[length];
buf.getChars(0, length, image, 0);
Token generated= new ImageToken(IToken.tSTRING, null, 0, 0, image);
Token generated= new TokenWithImage(IToken.tSTRING, null, 0, 0, image);
if (pasteNext) { // start token paste, same as start stringify
pasteArg1= generated;
}
@ -402,7 +403,7 @@ public class MacroExpander {
TokenList rest= null;
if (n != null) {
if (n.getType() == CPreprocessor.tMACRO_PARAMETER) {
idx= ((PlaceHolderToken) n).getIndex();
idx= ((TokenParameterReference) n).getIndex();
if (idx < args.length) { // be defensive
TokenList arg= clone(args[idx]);
pasteArg2= arg.first();
@ -417,7 +418,7 @@ public class MacroExpander {
pasteArg1= pasteArg2= null;
}
}
if (pasteArg2 != null) {
if (pasteArg2 != null && arg.first() != arg.last()) {
rest= arg;
rest.removeFirst();
}

View file

@ -13,7 +13,7 @@ package org.eclipse.cdt.internal.core.parser.scanner;
public class ScannerContextMacroExpansion extends ScannerContext {
private static final Token END_TOKEN = new SimpleToken(Lexer.tEND_OF_INPUT, null, 0, 0);
private static final Token END_TOKEN = new Token(Lexer.tEND_OF_INPUT, null, 0, 0);
private Token fTokens;

View file

@ -70,7 +70,7 @@ public final class ScannerContextPPDirective extends ScannerContext {
private Token convertToken(Token t) {
switch (t.getType()) {
case Lexer.tNEWLINE:
t= new SimpleToken(Lexer.tEND_OF_INPUT, null, t.getEndOffset(), t.getEndOffset());
t= new Token(Lexer.tEND_OF_INPUT, null, t.getEndOffset(), t.getEndOffset());
break;
case IToken.tIDENTIFIER:
if (fConvertDefinedToken && CharArrayUtils.equals(Keywords.cDEFINED, t.getCharImage())) {

View file

@ -17,7 +17,7 @@ import org.eclipse.cdt.core.parser.IToken;
* them on to the parsers.
* @since 5.0
*/
public abstract class Token implements IToken, Cloneable {
public class Token implements IToken, Cloneable {
private int fKind;
private int fOffset;
private int fEndOffset;
@ -65,10 +65,8 @@ public abstract class Token implements IToken, Cloneable {
fEndOffset= endOffset;
}
public abstract char[] getCharImage();
final public boolean hasGap(Token t) {
return fSource == t.fSource && fEndOffset != t.getOffset();
public char[] getCharImage() {
return TokenUtil.getImage(getType());
}
public String toString() {
@ -116,79 +114,3 @@ public abstract class Token implements IToken, Cloneable {
throw new UnsupportedOperationException();
}
}
class SimpleToken extends Token {
public SimpleToken(int kind, Object source, int offset, int endOffset) {
super(kind, source, offset, endOffset);
}
public char[] getCharImage() {
return TokenUtil.getImage(getType());
}
}
class PlaceHolderToken extends ImageToken {
private final int fIndex;
public PlaceHolderToken(int type, int idx, Object source, int offset, int endOffset, char[] name) {
super(type, source, offset, endOffset, name);
fIndex= idx;
}
public int getIndex() {
return fIndex;
}
public String toString() {
return "[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
class DigraphToken extends Token {
public DigraphToken(int kind, Object source, int offset, int endOffset) {
super(kind, source, offset, endOffset);
}
public char[] getCharImage() {
return TokenUtil.getDigraphImage(getType());
}
}
class ImageToken extends Token {
private char[] fImage;
public ImageToken(int kind, Object source, int offset, int endOffset, char[] image) {
super(kind, source, offset, endOffset);
fImage= image;
}
public char[] getCharImage() {
return fImage;
}
}
class SourceImageToken extends Token {
private char[] fSourceImage;
private char[] fImage;
public SourceImageToken(int kind, Object source, int offset, int endOffset, char[] sourceImage) {
super(kind, source, offset, endOffset);
fSourceImage= sourceImage;
}
public char[] getCharImage() {
if (fImage == null) {
final int length= getLength();
fImage= new char[length];
System.arraycopy(fSourceImage, getOffset(), fImage, 0, length);
}
return fImage;
}
public void setOffset(int offset, int endOffset) {
getCharImage();
super.setOffset(offset, endOffset);
}
}

View file

@ -0,0 +1,25 @@
/*******************************************************************************
* Copyright (c) 2007 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
/**
* Tokens for digraphs simply have a different image.
* @since 5.0
*/
public class TokenForDigraph extends Token {
public TokenForDigraph(int kind, Object source, int offset, int endOffset) {
super(kind, source, offset, endOffset);
}
public char[] getCharImage() {
return TokenUtil.getDigraphImage(getType());
}
}

View file

@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2007 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
public class TokenWithImage extends Token {
private char[] fImage;
public TokenWithImage(int kind, Object source, int offset, int endOffset, char[] image) {
super(kind, source, offset, endOffset);
fImage= image;
}
public char[] getCharImage() {
return fImage;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* Copyright (c) 2005, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -7,12 +7,15 @@
*
* Contributors:
* IBM Rational Software - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.token;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.core.parser.ISourceElementRequestor;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.ITokenDuple;
@ -20,27 +23,125 @@ import org.eclipse.cdt.core.parser.ITokenDuple;
* @author johnc
*/
public class TokenFactory {
protected static final char[] EMPTY_CHAR_ARRAY = "".toCharArray(); //$NON-NLS-1$
private static class TokenWrapper implements ITokenDuple {
private final IToken fToken;
public TokenWrapper(IToken t) {
fToken= t;
}
public String toString() {
return fToken.toString();
}
public boolean contains(ITokenDuple duple) {
return fToken == duple.getFirstToken() && fToken == duple.getLastToken();
}
public char[] extractNameFromTemplateId(){
return fToken.getCharImage();
}
public int findLastTokenType(int t) {
return fToken.getType() == t ? 0 : -1;
}
public IToken getFirstToken() {
return fToken;
}
public ITokenDuple getLastSegment() {
return this;
}
public IToken getLastToken() {
return fToken;
}
public ITokenDuple getLeadingSegments() {
return null;
}
public int getSegmentCount() {
return 1;
}
public int getStartOffset() {
return fToken.getOffset();
}
public ITokenDuple getSubrange(int startIndex, int endIndex) {
if( startIndex == 0 && endIndex == 0 ) return this;
return null;
}
public List[] getTemplateIdArgLists() {
return null;
}
public IToken getToken(int index) {
if( index == 0 ) return fToken;
return null;
}
public boolean isIdentifier() {
return ( fToken.getType() == IToken.tIDENTIFIER );
}
public Iterator iterator() {
return new Iterator() {
private boolean hasNext = true;
public void remove() {
throw new UnsupportedOperationException();
}
public boolean hasNext() {
return hasNext;
}
public Object next() {
hasNext = false;
return fToken;
}
};
}
public int length() {
return 1;
}
public boolean syntaxOfName() {
return isIdentifier();
}
public String[] toQualifiedName() {
return new String[] {fToken.getImage()};
}
public void freeReferences() {
}
public void acceptElement(ISourceElementRequestor requestor) {
}
public ITokenDuple[] getSegments() {
return new ITokenDuple[] {this};
}
public int getEndOffset() {
return fToken.getEndOffset();
}
public char[] getFilename() {
return fToken.getFilename();
}
public int getLineNumber() {
return fToken.getLineNumber();
}
public char[] toCharArray() {
return fToken.getCharImage();
}
}
public static IToken createStandAloneToken( int type, String image )
{
return new ImagedToken( type, image.toCharArray(), 0, EMPTY_CHAR_ARRAY, 0);
}
public static ITokenDuple createTokenDuple( IToken first, IToken last )
{
if( (first == last) && ( first instanceof ITokenDuple )) return (ITokenDuple) first;
public static ITokenDuple createTokenDuple(IToken first, IToken last) {
if (first == last) {
if (first instanceof ITokenDuple) {
return (ITokenDuple) first;
}
return new TokenWrapper(first);
}
return new BasicTokenDuple( first, last );
}
public static ITokenDuple createTokenDuple( IToken first, IToken last, List templateArgLists )
{
if( (first == last) && ( templateArgLists == null ) && ( first instanceof ITokenDuple ))
return (ITokenDuple) first;
if( templateArgLists != null && !templateArgLists.isEmpty())
public static ITokenDuple createTokenDuple(IToken first, IToken last, List templateArgLists) {
if (templateArgLists == null || templateArgLists.isEmpty()) {
return createTokenDuple(first, last);
}
return new TemplateTokenDuple( first, last, templateArgLists );
return new BasicTokenDuple( first, last );
}
public static ITokenDuple createTokenDuple( ITokenDuple firstDuple, ITokenDuple secondDuple ){