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:
parent
e0ba2b4f84
commit
981ddadee0
29 changed files with 1110 additions and 525 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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>.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 ){
|
||||
|
|
Loading…
Add table
Reference in a new issue