Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Kucera2008-03-13 14:36:47 +0000
committerMike Kucera2008-03-13 14:36:47 +0000
commit6cb825d13ff6fca9747e2cc537f67b2a585bb00e (patch)
tree680c93fc152cab7efb7e0dd32d0f5cc1f1d874b8 /core/org.eclipse.cdt.core/parser
parent08bfbd1229ddd6ff26aeff46f6e66589b4fc2157 (diff)
downloadorg.eclipse.cdt-6cb825d13ff6fca9747e2cc537f67b2a585bb00e.tar.gz
org.eclipse.cdt-6cb825d13ff6fca9747e2cc537f67b2a585bb00e.tar.xz
org.eclipse.cdt-6cb825d13ff6fca9747e2cc537f67b2a585bb00e.zip
moved utility classes into core util package
Diffstat (limited to 'core/org.eclipse.cdt.core/parser')
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ASTPrinter.java538
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayMap.java105
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CollectionUtils.java115
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/DebugUtil.java61
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ICharArrayMap.java120
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java186
6 files changed, 886 insertions, 239 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ASTPrinter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ASTPrinter.java
new file mode 100644
index 00000000000..5ff27cb00a8
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ASTPrinter.java
@@ -0,0 +1,538 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core.parser.util;
+
+import java.io.PrintStream;
+
+import org.eclipse.cdt.core.dom.ast.DOMException;
+import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
+import org.eclipse.cdt.core.dom.ast.IASTComment;
+import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
+import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
+import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
+import org.eclipse.cdt.core.dom.ast.IASTExpression;
+import org.eclipse.cdt.core.dom.ast.IASTInitializer;
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
+import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
+import org.eclipse.cdt.core.dom.ast.IASTProblem;
+import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
+import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
+import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
+import org.eclipse.cdt.core.dom.ast.IASTStatement;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.dom.ast.IASTTypeId;
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.IProblemBinding;
+import org.eclipse.cdt.core.dom.ast.IType;
+import org.eclipse.cdt.core.dom.ast.IVariable;
+import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
+import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
+import org.eclipse.cdt.core.dom.ast.c.ICASTArrayModifier;
+import org.eclipse.cdt.core.dom.ast.c.ICASTDesignator;
+import org.eclipse.cdt.core.dom.ast.c.ICASTPointer;
+import org.eclipse.cdt.core.dom.ast.c.ICArrayType;
+import org.eclipse.cdt.core.dom.ast.c.ICPointerType;
+import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
+import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
+
+
+/**
+ * A utility that prints an AST to the console, useful for debugging purposes.
+ *
+ *
+ * @author Mike Kucera
+ */
+@SuppressWarnings("nls")
+public class ASTPrinter {
+
+ private static boolean PRINT_PARENT_PROPERTIES = false;
+ private static boolean RESOLVE_BINDINGS = false;
+
+ /**
+ * Prints the AST to the given PrintStream.
+ *
+ * @return Always returns false, boolean return type allows this method
+ * to be called from a conditional breakpoint during debugging.
+ */
+ public static boolean print(IASTNode root, PrintStream out) {
+ if(root == null) {
+ out.println("null");
+ return false;
+ }
+
+ if(root instanceof IASTTranslationUnit) {
+ IASTPreprocessorStatement[] preStats = ((IASTTranslationUnit)root).getAllPreprocessorStatements();
+ if(preStats != null) {
+ for(IASTPreprocessorStatement stat : preStats)
+ print(out, 0, stat);
+ }
+ }
+
+ root.accept(new PrintVisitor(out));
+
+ if(root instanceof IASTTranslationUnit) {
+ IASTProblem[] problems = ((IASTTranslationUnit)root).getPreprocessorProblems();
+ if(problems != null) {
+ for(IASTProblem problem : problems)
+ print(out, 0, problem);
+ }
+
+ IASTComment[] comments = ((IASTTranslationUnit)root).getComments();
+ if(comments != null) {
+ for(IASTComment comment : comments)
+ print(out, 0, comment);
+ }
+ }
+ return false;
+ }
+
+
+
+ /**
+ * Prints the AST to stdout.
+ *
+ * @return Always returns false, boolean return type allows this method
+ * to be called from a conditional breakpoint during debugging.
+ */
+ public static boolean print(IASTNode root) {
+ return print(root, System.out);
+ }
+
+
+ /**
+ * Prints problem nodes in the AST to the given printstream.
+ *
+ * @return Always returns false, boolean return type allows this method
+ * to be called from a conditional breakpoint during debugging.
+ */
+ public static boolean printProblems(IASTNode root, PrintStream out) {
+ if(root == null) {
+ out.println("null");
+ return false;
+ }
+
+ root.accept(new ProblemVisitor(out));
+
+ if(root instanceof IASTTranslationUnit) {
+ IASTProblem[] problems = ((IASTTranslationUnit)root).getPreprocessorProblems();
+ if(problems != null) {
+ for(IASTProblem problem : problems) {
+ print(out, 0, problem);
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Prints problem nodes in the AST to stdout.
+ *
+ * @return Always returns false, boolean return type allows this method
+ * to be called from a conditional breakpoint during debugging.
+ */
+ public static boolean printProblems(IASTNode root) {
+ return printProblems(root, System.out);
+ }
+
+
+
+ private static void print(PrintStream out, int indentLevel, Object n) {
+ for(int i = 0; i < indentLevel; i++)
+ out.print(" ");
+
+ if(n == null) {
+ out.println("NULL");
+ return;
+ }
+
+ String classname = n.getClass().getName();
+ out.print(classname);
+
+ if(n instanceof ASTNode) {
+ ASTNode node = (ASTNode) n;
+ out.print(" (" + node.getOffset() + "," + node.getLength() + ") ");
+ if(node.getParent() == null && !(node instanceof IASTTranslationUnit)) {
+ out.print("PARENT IS NULL ");
+ }
+ if(PRINT_PARENT_PROPERTIES)
+ out.print(node.getPropertyInParent());
+ }
+
+ if(n instanceof ICArrayType) {
+ ICArrayType at = (ICArrayType)n;
+ try {
+ if(at.isRestrict()) {
+ out.print(" restrict");
+ }
+ } catch (DOMException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if(n instanceof IASTName) {
+ out.print(" " + ((IASTName)n).toString());
+ }
+ else if(n instanceof ICASTPointer) {
+ ICASTPointer pointer = (ICASTPointer) n;
+ if(pointer.isConst())
+ out.print(" const");
+ if(pointer.isVolatile())
+ out.print(" volatile");
+ if(pointer.isRestrict())
+ out.print(" restrict");
+ }
+ else if(n instanceof ICPointerType) {
+ ICPointerType pointer = (ICPointerType)n;
+ try {
+ if(pointer.isConst())
+ out.print(" const");
+ if(pointer.isVolatile())
+ out.print(" volatile");
+ if(pointer.isRestrict())
+ out.print(" restrict");
+ } catch (DOMException e) {
+ e.printStackTrace();
+ }
+ out.println();
+ try {
+ print(out, indentLevel, ((ITypeContainer)n).getType());
+ } catch(Exception e) {}
+ }
+ else if(n instanceof ICASTArrayModifier) {
+ if(((ICASTArrayModifier)n).isRestrict()) {
+ out.print(" restrict");
+ }
+ }
+ else if(n instanceof IASTComment) {
+ out.print("'" + new String(((IASTComment)n).getComment()) + "'");
+ }
+// else if(n instanceof ICompositeType) {
+// try {
+// IField[] fields = ((ICompositeType)n).getFields();
+// if(fields == null || fields.length == 0) {
+// out.print(" no fields");
+// }
+// for(IField field : fields) {
+// out.println();
+// print(out, indentLevel + 1, field);
+// }
+// } catch (DOMException e) {
+// e.printStackTrace();
+// }
+// }
+ else if(n instanceof ITypeContainer) {
+ out.println();
+ try {
+ print(out, indentLevel, ((ITypeContainer)n).getType());
+ } catch(Exception e) {}
+ }
+ else if(n instanceof IVariable) {
+ IVariable var = (IVariable) n;
+ IType t;
+ try {
+ t = var.getType();
+ out.println();
+ print(out, indentLevel, t);
+ } catch (DOMException e) {
+ //e.printStackTrace();
+ }
+
+ }
+ else if(n instanceof IProblemBinding) {
+ IProblemBinding problem = (IProblemBinding)n;
+ out.print(problem.getMessage());
+ }
+
+
+ out.println();
+ }
+
+
+ private static class ProblemVisitor extends CASTVisitor {
+ private PrintStream out;
+
+ ProblemVisitor(PrintStream out) {
+ this.out = out;
+ shouldVisitProblems = true;
+ shouldVisitDeclarations = true;
+ shouldVisitStatements = true;
+ shouldVisitExpressions = true;
+ }
+
+ @Override
+ public int visit(IASTProblem problem) {
+ print(out, 1, problem);
+ return PROCESS_CONTINUE;
+ }
+
+ @Override
+ public int visit(IASTDeclaration declaration) {
+ if(declaration instanceof IASTProblemDeclaration)
+ print(out, 0, declaration);
+ return PROCESS_CONTINUE;
+ }
+
+ @Override
+ public int visit(IASTExpression expression) {
+ if(expression instanceof IASTProblemExpression)
+ print(out, 0, expression);
+ return PROCESS_CONTINUE;
+ }
+
+ @Override
+ public int visit(IASTStatement statement) {
+ if(statement instanceof IASTProblemStatement)
+ print(out, 0, statement);
+ return PROCESS_CONTINUE;
+ }
+ }
+
+
+ private static class PrintVisitor extends CASTVisitor {
+
+
+ private PrintStream out;
+ private int indentLevel = 0;
+
+ PrintVisitor(PrintStream out) {
+ this.out = out;
+ shouldVisitDesignators = true;
+ shouldVisitNames = true;
+ shouldVisitDeclarations = true;
+ shouldVisitInitializers = true;
+ shouldVisitParameterDeclarations = true;
+ shouldVisitDeclarators = true;
+ shouldVisitDeclSpecifiers = true;
+ shouldVisitExpressions = true;
+ shouldVisitStatements = true;
+ shouldVisitTypeIds = true;
+ shouldVisitEnumerators = true;
+ shouldVisitTranslationUnit = true;
+ shouldVisitProblems = true;
+ }
+
+ private void print(IASTNode node) {
+ ASTPrinter.print(out, indentLevel, node);
+ }
+
+ private void print(IBinding binding) {
+ ASTPrinter.print(out, indentLevel, binding);
+ }
+
+
+ @Override
+ public int visit(IASTComment comment) {
+ print(comment);
+ indentLevel++;
+ return super.visit(comment);
+ }
+
+ @Override
+ public int visit(ICASTDesignator designator) {
+ print(designator);
+ indentLevel++;
+ return super.visit(designator);
+ }
+
+ @Override
+ public int visit(IASTDeclaration declaration) {
+ print(declaration);
+ indentLevel++;
+ return super.visit(declaration);
+ }
+
+ @Override
+ public int visit(IASTDeclarator declarator) {
+ print(declarator);
+ indentLevel++;
+ IASTPointerOperator[] pointers = declarator.getPointerOperators();
+ for(int i = 0; i < pointers.length; i++) {
+ print(pointers[i]);
+ }
+ if(declarator instanceof IASTArrayDeclarator) {
+ IASTArrayDeclarator decl = (IASTArrayDeclarator)declarator;
+ org.eclipse.cdt.core.dom.ast.IASTArrayModifier[] modifiers = decl.getArrayModifiers();
+ for(int i = 0; i < modifiers.length; i++) {
+ print(modifiers[i]);
+ }
+ }
+ return super.visit(declarator);
+ }
+
+ @Override
+ public int visit(IASTDeclSpecifier declSpec) {
+ print(declSpec);
+ indentLevel++;
+ return super.visit(declSpec);
+ }
+
+ @Override
+ public int visit(IASTEnumerator enumerator) {
+ print(enumerator);
+ indentLevel++;
+ return super.visit(enumerator);
+ }
+
+ @Override
+ public int visit(IASTExpression expression) {
+ print(expression);
+ indentLevel++;
+ return super.visit(expression);
+ }
+
+ @Override
+ public int visit(IASTInitializer initializer) {
+ print(initializer);
+ indentLevel++;
+ return super.visit(initializer);
+ }
+
+ @Override
+ public int visit(IASTName name) {
+ print(name);
+ if(RESOLVE_BINDINGS) {
+ try {
+ IBinding binding = name.resolveBinding();
+ print(binding);
+ } catch(Exception e) {
+ System.out.println("Exception while resolving binding: " + name);
+ }
+ }
+ indentLevel++;
+ return super.visit(name);
+ }
+
+ @Override
+ public int visit(IASTParameterDeclaration parameterDeclaration) {
+ print(parameterDeclaration);
+ indentLevel++;
+ return super.visit(parameterDeclaration);
+ }
+
+ @Override
+ public int visit(IASTProblem problem) {
+ print(problem);
+ indentLevel++;
+ return super.visit(problem);
+ }
+
+ @Override
+ public int visit(IASTStatement statement) {
+ print(statement);
+ indentLevel++;
+ return super.visit(statement);
+ }
+
+ @Override
+ public int visit(IASTTranslationUnit tu) {
+ print(tu);
+ indentLevel++;
+ return super.visit(tu);
+ }
+
+ @Override
+ public int visit(IASTTypeId typeId) {
+ print(typeId);
+ indentLevel++;
+ return super.visit(typeId);
+ }
+
+ @Override
+ public int leave(IASTComment comment) {
+ indentLevel--;
+ return super.leave(comment);
+ }
+
+ @Override
+ public int leave(ICASTDesignator designator) {
+ indentLevel--;
+ return super.leave(designator);
+ }
+
+ @Override
+ public int leave(IASTDeclaration declaration) {
+ indentLevel--;
+ return super.leave(declaration);
+ }
+
+ @Override
+ public int leave(IASTDeclarator declarator) {
+ indentLevel--;
+ return super.leave(declarator);
+ }
+
+ @Override
+ public int leave(IASTDeclSpecifier declSpec) {
+ indentLevel--;
+ return super.leave(declSpec);
+ }
+
+ @Override
+ public int leave(IASTEnumerator enumerator) {
+ indentLevel--;
+ return super.leave(enumerator);
+ }
+
+ @Override
+ public int leave(IASTExpression expression) {
+ indentLevel--;
+ return super.leave(expression);
+ }
+
+ @Override
+ public int leave(IASTInitializer initializer) {
+ indentLevel--;
+ return super.leave(initializer);
+ }
+
+ @Override
+ public int leave(IASTName name) {
+ indentLevel--;
+ return super.leave(name);
+ }
+
+ @Override
+ public int leave(IASTParameterDeclaration parameterDeclaration) {
+ indentLevel--;
+ return super.leave(parameterDeclaration);
+ }
+
+ @Override
+ public int leave(IASTProblem problem) {
+ indentLevel--;
+ return super.leave(problem);
+ }
+
+ @Override
+ public int leave(IASTStatement statement) {
+ indentLevel--;
+ return super.leave(statement);
+ }
+
+ @Override
+ public int leave(IASTTranslationUnit tu) {
+ indentLevel--;
+ return super.leave(tu);
+ }
+
+ @Override
+ public int leave(IASTTypeId typeId) {
+ indentLevel--;
+ return super.leave(typeId);
+ }
+
+ }
+} \ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayMap.java
index 7f63168f471..55d6a80a95d 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayMap.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CharArrayMap.java
@@ -19,12 +19,31 @@ import java.util.TreeMap;
/**
- * A facade for a Map that allows char[] slices to be used as keys.
+ * Provides functionality similar to a Map, with the feature that char arrays
+ * and sections of char arrays (known as slices) may be used as keys.
+ *
+ * This class is useful because small pieces of an existing large char[] buffer
+ * can be directly used as map keys. This avoids the need to create many String
+ * objects as would normally be needed as keys in a standard java.util.Map.
+ * Thus performance is improved in the CDT core.
+ *
+ * Most methods are overloaded with two versions, one that uses a
+ * section of a char[] as the key (a slice), and one that uses
+ * the entire char[] as the key.
+ *
+ * This class is intended as a replacement for CharArrayObjectMap.
+ *
+ * ex:
+ * char[] key = "one two three".toCharArray();
+ * map.put(key, 4, 3, new Integer(99));
+ * map.get(key, 4, 3); // returns 99
+ * map.get("two".toCharArray()); // returns 99
*
- * @see ICharArrayMap for API docs
* @author Mike Kucera
+ *
+ * @param <V>
*/
-public final class CharArrayMap<V> implements ICharArrayMap<V> {
+public final class CharArrayMap<V> {
/**
* Wrapper class used as keys in the map. The purpose
@@ -82,10 +101,11 @@ public final class CharArrayMap<V> implements ICharArrayMap<V> {
return result;
}
- @Override
+ @SuppressWarnings("nls")
+ @Override
public String toString() {
String slice = new String(buffer, start, length);
- return "'" + slice + "'@(" + start + "," + length + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ return "'" + slice + "'@(" + start + "," + length + ")";
}
@@ -152,60 +172,103 @@ public final class CharArrayMap<V> implements ICharArrayMap<V> {
map = new HashMap<Key,V>(initialCapacity);
}
-
+ /**
+ * Creates a new mapping in this map, uses the given array slice as the key.
+ * If the map previously contained a mapping for this key, the old value is replaced.
+ * @throws NullPointerException if chars is null
+ * @throws IndexOutOfBoundsException if the boundaries specified by start and length are out of range
+ */
public void put(char[] chars, int start, int length, V value) {
checkBoundaries(chars, start, length);
map.put(new Key(chars, start, length), value);
}
-
+ /**
+ * Creates a new mapping in this map, uses all of the given array as the key.
+ * If the map previously contained a mapping for this key, the old value is replaced.
+ * @throws NullPointerException if chars is null
+ */
public void put(char[] chars, V value) {
map.put(new Key(chars), value);
}
-
+ /**
+ * Returns the value to which the specified array slice is mapped in this map,
+ * or null if the map contains no mapping for this key.
+ * @throws NullPointerException if chars is null
+ * @throws IndexOutOfBoundsException if the boundaries specified by start and length are out of range
+ */
public V get(char[] chars, int start, int length) {
checkBoundaries(chars, start, length);
return map.get(new Key(chars, start, length));
}
-
+ /**
+ * Returns the value to which the specified array is mapped in this map,
+ * or null if the map contains no mapping for this key.
+ * @throws NullPointerException if chars is null
+ */
public V get(char[] chars) {
return map.get(new Key(chars));
}
-
+ /**
+ * Removes the mapping for the given array slice if present.
+ * Returns the value object that corresponded to the key
+ * or null if the key was not in the map.
+ * @throws NullPointerException if chars is null
+ * @throws IndexOutOfBoundsException if the boundaries specified by start and length are out of range
+ */
public V remove(char[] chars, int start, int length) {
checkBoundaries(chars, start, length);
return map.remove(new Key(chars, start, length));
}
-
+ /**
+ * Removes the mapping for the given array if present.
+ * Returns the value object that corresponded to the key
+ * or null if the key was not in the map.
+ * @throws NullPointerException if chars is null
+ */
public V remove(char[] chars) {
return map.remove(new Key(chars));
}
-
+ /**
+ * Returns true if the given key has a value associated with it in the map.
+ * @throws NullPointerException if chars is null
+ * @throws IndexOutOfBoundsException if the boundaries specified by start and length are out of range
+ */
public boolean containsKey(char[] chars, int start, int length) {
checkBoundaries(chars, start, length);
return map.containsKey(new Key(chars, start, length));
}
-
+ /**
+ * Returns true if the given key has a value associated with it in the map.
+ * @throws NullPointerException if chars is null
+ */
public boolean containsKey(char[] chars) {
return map.containsKey(new Key(chars));
}
-
+ /**
+ * Returns true if the given value is contained in the map.
+ */
public boolean containsValue(V value) {
return map.containsValue(value);
}
-
+ /**
+ * Use this in a foreach loop.
+ */
public Collection<V> values() {
return map.values();
}
+ /**
+ * Returns the keys stored in the map.
+ */
public Collection<char[]> keys() {
Set<Key> keys= map.keySet();
ArrayList<char[]> r= new ArrayList<char[]>(keys.size());
@@ -215,17 +278,23 @@ public final class CharArrayMap<V> implements ICharArrayMap<V> {
return r;
}
-
+ /**
+ * Removes all mappings from the map.
+ */
public void clear() {
map.clear();
}
-
+ /**
+ * Returns the number of mappings.
+ */
public int size() {
return map.size();
}
-
+ /**
+ * Returns true if the map is empty.
+ */
public boolean isEmpty() {
return map.isEmpty();
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CollectionUtils.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CollectionUtils.java
new file mode 100644
index 00000000000..c2e174be6e2
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/CollectionUtils.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core.parser.util;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+
+/**
+ * Useful utility methods for dealing with Collections.
+ *
+ * @author Mike Kucera
+ */
+public final class CollectionUtils {
+
+ private CollectionUtils() {
+ // this class has just static utility methods
+ }
+
+
+ /**
+ * Returns an iterator that iterates backwards over the given list.
+ * The remove() method is not implemented and will throw UnsupportedOperationException.
+ * The returned iterator does not support the remove() method.
+ *
+ * @throws NullPointerException if list is null
+ */
+ public static <T> Iterator<T> reverseIterator(final List<T> list) {
+ return new Iterator<T>() {
+ ListIterator<T> iterator = list.listIterator(list.size());
+
+ public boolean hasNext() {
+ return iterator.hasPrevious();
+ }
+ public T next() {
+ return iterator.previous();
+ }
+ public void remove() {
+ throw new UnsupportedOperationException("remove() not supported"); //$NON-NLS-1$
+ }
+ };
+ }
+
+
+ /**
+ * Allows a foreach loop to iterate backwards over a list
+ * from the end to the start.
+ *
+ * eg)
+ * for(Object o : reverseIterable(list)) { ... }
+ *
+ * @throws NullPointerException if list is null
+ */
+ public static <T> Iterable<T> reverseIterable(final List<T> list) {
+ return iterable(reverseIterator(list));
+ }
+
+
+ /**
+ * Creates an Iterable instance that just returns
+ * the given Iterator from its iterator() method.
+ *
+ * This is useful for using an iterator in a foreach loop directly.
+ *
+ * eg)
+ *
+ * for(Object o : iterable(list.listIterator())) {
+ * // do something
+ * }
+ *
+ * @throws NullPointerException if list is null
+ */
+ public static <T> Iterable<T> iterable(final Iterator<T> iter) {
+ if(iter == null)
+ throw new NullPointerException("iter parameter is null"); //$NON-NLS-1$
+
+ return new Iterable<T>() {
+ public Iterator<T> iterator() {
+ return iter;
+ }
+ };
+ }
+
+
+
+ /**
+ * Finds the first object in the heterogeneous list that is an instance of
+ * the given class, removes it from the list, and returns it.
+ * If there is not object in the list of the given type the list is left
+ * unmodified and null is returned.
+ *
+ * @throws NullPointerException if list or clazz is null
+ * @throws UnsupportedOperationException if the list's Iterator does not support the remove() method
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T findFirstAndRemove(List<?> list, Class<T> clazz) {
+ for(Iterator<?> iter = list.iterator(); iter.hasNext();) {
+ Object o = iter.next();
+ if(clazz.isInstance(o)) {
+ iter.remove();
+ return (T) o; // safe
+ }
+ }
+ return null;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/DebugUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/DebugUtil.java
new file mode 100644
index 00000000000..1c9cfd12f0f
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/DebugUtil.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core.parser.util;
+
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+
+/**
+ * This class contains several convenience methods
+ * mainly for debugging purposes.
+ *
+ * @author Mike Kucera
+ *
+ */
+public class DebugUtil {
+
+ private DebugUtil() { // class just contains static methods
+ }
+
+
+ /**
+ * Prints a trace message to stdout that gives info
+ * about the method that calls this method.
+ */
+ public static void printMethodTrace() {
+ StackTraceElement[] trace = Thread.currentThread().getStackTrace();
+ printMethodTrace(trace, null);
+ }
+
+ /**
+ * Prints a trace message to stdout that gives info
+ * about the method that calls this method.
+ */
+ public static void printMethodTrace(String extraMessage) {
+ StackTraceElement[] trace = Thread.currentThread().getStackTrace();
+ printMethodTrace(trace, extraMessage);
+ }
+
+ private static void printMethodTrace(StackTraceElement[] trace, String extraMessage) {
+ StackTraceElement caller = trace[3];
+
+ String className = caller.getClassName();
+ className = className.substring(className.lastIndexOf(".") + 1);//$NON-NLS-1$
+
+ String message = String.format("%s.%s(%s:%d)", //$NON-NLS-1$
+ className, caller.getMethodName(), caller.getFileName(), caller.getLineNumber());
+
+ if(extraMessage != null)
+ message += ": " + extraMessage;//$NON-NLS-1$
+
+ System.out.println(message);
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ICharArrayMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ICharArrayMap.java
deleted file mode 100644
index 58a0f6dbc77..00000000000
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ICharArrayMap.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.eclipse.cdt.core.parser.util;
-
-import java.util.Collection;
-
-/**
- * Provides an interface similar to Map, with the feature that char arrays
- * and sections of char arrays (known as slices) may be used as keys.
- *
- * This interface is useful because small pieces of an existing large char[] buffer
- * can be directly used as map keys. This avoids the need to create many String
- * objects as would normally be needed as keys in a standard java.util.Map.
- * Thus performance is improved in the CDT core.
- *
- * Most methods are overloaded with two versions, one that uses a
- * section of a char[] as the key (a slice), and one that uses
- * the entire char[] as the key.
- *
- * ex:
- * char[] key = "one two three".toCharArray();
- * map.put(key, 4, 3, new Integer(99));
- * map.get(key, 4, 3); // returns 99
- * map.get("two".toCharArray()); // returns 99
- *
- * @author Mike Kucera
- *
- * @param <V>
- */
-public interface ICharArrayMap<V> {
-
- /**
- * Creates a new mapping in this map, uses the given array slice as the key.
- * If the map previously contained a mapping for this key, the old value is replaced.
- * @throws NullPointerException if chars is null
- * @throws IndexOutOfBoundsException if the boundaries specified by start and length are out of range
- */
- void put(char[] chars, int start, int length, V value);
-
- /**
- * Creates a new mapping in this map, uses all of the given array as the key.
- * If the map previously contained a mapping for this key, the old value is replaced.
- * @throws NullPointerException if chars is null
- */
- void put(char[] chars, V value);
-
- /**
- * Returns the value to which the specified array slice is mapped in this map,
- * or null if the map contains no mapping for this key.
- * @throws NullPointerException if chars is null
- * @throws IndexOutOfBoundsException if the boundaries specified by start and length are out of range
- */
- V get(char[] chars, int start, int length);
-
- /**
- * Returns the value to which the specified array is mapped in this map,
- * or null if the map contains no mapping for this key.
- * @throws NullPointerException if chars is null
- */
- V get(char[] chars);
-
- /**
- * Removes the mapping for the given array slice if present.
- * Returns the value object that corresponded to the key
- * or null if the key was not in the map.
- * @throws NullPointerException if chars is null
- * @throws IndexOutOfBoundsException if the boundaries specified by start and length are out of range
- */
- V remove(char[] chars, int start, int length);
-
- /**
- * Removes the mapping for the given array if present.
- * Returns the value object that corresponded to the key
- * or null if the key was not in the map.
- * @throws NullPointerException if chars is null
- */
- V remove(char[] chars);
-
- /**
- * Returns true if the given key has a value associated with it in the map.
- * @throws NullPointerException if chars is null
- * @throws IndexOutOfBoundsException if the boundaries specified by start and length are out of range
- */
- boolean containsKey(char[] chars, int start, int length);
-
- /**
- * Returns true if the given key has a value associated with it in the map.
- * @throws NullPointerException if chars is null
- */
- boolean containsKey(char[] chars);
-
- /**
- * Returns true if the given value is contained in the map.
- */
- boolean containsValue(V value);
-
- /**
- * Use this in a foreach loop.
- */
- Collection<V> values();
-
- /**
- * Returns the keys stored in the map.
- */
- Collection<char[]> keys();
-
- /**
- * Removes all mappings from the map.
- */
- void clear();
-
- /**
- * Returns the number of mappings.
- */
- int size();
-
- /**
- * Returns true if the map is empty.
- */
- boolean isEmpty();
-
-} \ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java
index 1b23a8128d4..bb3f380f3d7 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java
@@ -10,7 +10,7 @@
* Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX) - https://bugs.eclipse.org/bugs/show_bug.cgi?id=151207
* Ed Swartz (Nokia)
- * Mike Kucera (IBM) - bug #206952
+ * Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@@ -139,7 +139,9 @@ import org.eclipse.cdt.core.parser.IScanner;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.ITokenDuple;
import org.eclipse.cdt.core.parser.ParserMode;
+import org.eclipse.cdt.core.parser.util.ASTPrinter;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
+import org.eclipse.cdt.core.parser.util.DebugUtil;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser;
@@ -162,11 +164,7 @@ import org.eclipse.cdt.internal.core.parser.token.TokenFactory;
*/
public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
- private static final String CONST_CAST = "const_cast"; //$NON-NLS-1$
- private static final String REINTERPRET_CAST = "reinterpret_cast"; //$NON-NLS-1$
- private static final String STATIC_CAST = "static_cast"; //$NON-NLS-1$
- private static final String DYNAMIC_CAST = "dynamic_cast"; //$NON-NLS-1$
-
+
private static final int DEFAULT_CATCH_HANDLER_LIST_SIZE = 4;
@@ -216,69 +214,65 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
/**
- * Consumes template parameters.
+ * Identifies the first and last tokens that make up the template parameter list.
+ * Used as part of parsing an idExpression().
*
- * @param previousLast
- * Previous "last" token (returned if nothing was consumed)
- * @return Last consumed token, or <code>previousLast</code> if nothing
- * was consumed
- * @throws BacktrackException
- * request a backtrack
+ * @param previousLast Previous "last" token (returned if nothing was consumed)
+ * @return Last consumed token, or <code>previousLast</code> if nothing was consumed
+ * @throws BacktrackException request a backtrack
*/
- protected IToken consumeTemplateParameters(IToken previousLast)
- throws EndOfFileException, BacktrackException {
- int startingOffset = previousLast == null ? LA(1).getOffset()
- : previousLast.getOffset();
- IToken last = previousLast;
+ protected IToken consumeTemplateParameters(IToken previousLast) throws EndOfFileException, BacktrackException {
+ int startingOffset = previousLast == null ? LA(1).getOffset() : previousLast.getOffset();
+ IToken last = previousLast; // if there are no parameters then previousLast gets returned
+
if (LT(1) == IToken.tLT) {
last = consume();
- // until we get all the names sorted out
- ScopeStack scopes = new ScopeStack();
+
+ // used to match brackets, parens and angle brackets
+ // capable of recognizing cases like T<(a>b)> correctly
+ ScopeStack scopes = new ScopeStack();
scopes.push(IToken.tLT);
- while (scopes.size() > 0) {
+ while(scopes.size() > 0) {
int top;
last = consume();
- switch (last.getType()) {
- case IToken.tGT:
- if (scopes.peek() == IToken.tLT) {
- scopes.pop();
- }
- break;
- case IToken.tRBRACKET:
- do {
- top = scopes.pop();
- } while (scopes.size() > 0
- && (top == IToken.tGT || top == IToken.tLT));
- if (top != IToken.tLBRACKET)
- throwBacktrack(startingOffset, last.getEndOffset()
- - startingOffset);
-
- break;
- case IToken.tRPAREN:
- do {
- top = scopes.pop();
- } while (scopes.size() > 0
- && (top == IToken.tGT || top == IToken.tLT));
- if (top != IToken.tLPAREN)
- throwBacktrack(startingOffset, last.getEndOffset()
- - startingOffset);
-
- break;
- case IToken.tLT:
- case IToken.tLBRACKET:
- case IToken.tLPAREN:
- scopes.push(last.getType());
- break;
+ switch(last.getType()) {
+ case IToken.tGT: // '>'
+ if(scopes.peek() == IToken.tLT) {
+ scopes.pop();
+ }
+ break;
+
+ case IToken.tRBRACKET: // ']'
+ do {
+ top = scopes.pop();
+ } while (scopes.size() > 0 && top == IToken.tLT);
+ if(top != IToken.tLBRACKET)
+ throwBacktrack(startingOffset, last.getEndOffset() - startingOffset);
+ break;
+
+ case IToken.tRPAREN: // ')'
+ do {
+ top = scopes.pop();
+ } while (scopes.size() > 0 && top == IToken.tLT);
+ if(top != IToken.tLPAREN)
+ throwBacktrack(startingOffset, last.getEndOffset() - startingOffset);
+ break;
+
+ case IToken.tLT: // '<'
+ case IToken.tLBRACKET: // '['
+ case IToken.tLPAREN: // '('
+ scopes.push(last.getType());
+ break;
}
}
}
return last;
}
- protected List<IASTNode> templateArgumentList() throws EndOfFileException,
- BacktrackException {
+
+ protected List<IASTNode> templateArgumentList() throws EndOfFileException, BacktrackException {
IToken start = LA(1);
int startingOffset = start.getOffset();
int endOffset = 0;
@@ -334,11 +328,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
/**
- * Parse a name. name : ("::")? name2 ("::" name2)* name2 : IDENTIFER :
- * template-id
+ * Parse a name.
+ * name ::= ("::")? name2 ("::" name2)*
+ * name2 ::= IDENTIFER | template-id
*
- * @throws BacktrackException
- * request a backtrack
+ * @throws BacktrackException request a backtrack
*/
protected ITokenDuple name() throws BacktrackException, EndOfFileException {
@@ -420,14 +414,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
/**
- * @param last
- * @param argumentList
- * @return
- * @throws EndOfFileException
- * @throws BacktrackException
*/
- protected IToken consumeTemplateArguments(IToken last,
- TemplateParameterManager argumentList) throws EndOfFileException, BacktrackException {
+ protected IToken consumeTemplateArguments(IToken last, TemplateParameterManager argumentList) throws EndOfFileException, BacktrackException {
if (LT(1) == IToken.tLT) {
IToken secondMark = mark();
consume();
@@ -456,11 +444,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return last;
}
- protected IASTName operatorId(IToken originalToken,
- TemplateParameterManager templateArgs) throws BacktrackException,
- EndOfFileException {
+
+
+ protected IASTName operatorId(IToken originalToken, TemplateParameterManager templateArgs) throws BacktrackException, EndOfFileException {
// we know this is an operator
-
IToken operatorToken = consume();
IToken toSend = null;
IASTTypeId typeId = null;
@@ -978,8 +965,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return null;
}
if (LT(1) != IToken.tEOC)
- declarator = declarator(SimpleDeclarationStrategy.TRY_FUNCTION,
- forNewExpression);
+ declarator = declarator(SimpleDeclarationStrategy.TRY_FUNCTION, forNewExpression);
} catch (BacktrackException bt) {
return null;
/*
@@ -1327,8 +1313,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* @throws BacktrackException
*/
@Override
- protected IASTExpression unaryExpression() throws EndOfFileException,
- BacktrackException {
+ protected IASTExpression unaryExpression() throws EndOfFileException, BacktrackException {
switch (LT(1)) {
case IToken.tSTAR:
return unaryOperatorCastExpression(IASTUnaryExpression.op_star);// IASTExpression.Kind.UNARY_STAR_CASTEXPRESSION);
@@ -1380,8 +1365,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* @param expression
* @throws BacktrackException
*/
- protected IASTExpression postfixExpression() throws EndOfFileException,
- BacktrackException {
+ protected IASTExpression postfixExpression() throws EndOfFileException, BacktrackException {
IASTExpression firstExpression = null;
boolean isTemplate = false;
@@ -1796,8 +1780,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return new CPPASTIdExpression();
}
- protected IASTName idExpression() throws EndOfFileException,
- BacktrackException {
+ protected IASTName idExpression() throws EndOfFileException, BacktrackException {
IASTName name = null;
try {
name = createName(name());
@@ -1818,8 +1801,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
name = operatorId(start, null);
else {
backup(mark);
- throwBacktrack(start.getOffset(), (end != null ? end.getEndOffset() : start.getEndOffset())
- - start.getOffset());
+ throwBacktrack(start.getOffset(), end == null ? start.getLength() : end.getEndOffset());
}
} else if (LT(1) == IToken.t_operator)
name = operatorId(null, null);
@@ -1828,8 +1810,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
- protected IASTExpression specialCastExpression(int kind)
- throws EndOfFileException, BacktrackException {
+ protected IASTExpression specialCastExpression(int kind) throws EndOfFileException, BacktrackException {
int startingOffset = LA(1).getOffset();
IToken op = consume();
consume(IToken.tLT);
@@ -1844,18 +1825,26 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
result.setTypeId(typeID);
result.setOperand(lhs);
- if (op.toString().equals(DYNAMIC_CAST)) {
- result.setOperator(ICPPASTCastExpression.op_dynamic_cast);
- } else if (op.toString().equals(STATIC_CAST)) {
- result.setOperator(ICPPASTCastExpression.op_static_cast);
- } else if (op.toString().equals(REINTERPRET_CAST)) {
- result.setOperator(ICPPASTCastExpression.op_reinterpret_cast);
- } else if (op.toString().equals(CONST_CAST)) {
- result.setOperator(ICPPASTCastExpression.op_const_cast);
- } else {
- result.setOperator(IASTCastExpression.op_cast);
+ int operator;
+ switch(op.getType()) {
+ case IToken.t_dynamic_cast:
+ operator = ICPPASTCastExpression.op_dynamic_cast;
+ break;
+ case IToken.t_static_cast:
+ operator = ICPPASTCastExpression.op_static_cast;
+ break;
+ case IToken.t_reinterpret_cast:
+ operator = ICPPASTCastExpression.op_reinterpret_cast;
+ break;
+ case IToken.t_const_cast:
+ operator = ICPPASTCastExpression.op_const_cast;
+ break;
+ default:
+ operator = IASTCastExpression.op_cast;
+ break;
}
+ result.setOperator(operator);
return result;
}
@@ -2352,8 +2341,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
}
- protected IASTDeclaration simpleDeclarationStrategyUnion()
- throws EndOfFileException, BacktrackException {
+
+ protected IASTDeclaration simpleDeclarationStrategyUnion() throws EndOfFileException, BacktrackException {
IToken simpleDeclarationMark = mark();
IASTDeclaration d1 = null, d2 = null;
IToken after = null;
@@ -2376,8 +2365,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return d1;
if (d1 instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration sd = (IASTSimpleDeclaration) d1;
- if( sd.getDeclSpecifier() instanceof ICPPASTDeclSpecifier &&
- ((ICPPASTDeclSpecifier)sd.getDeclSpecifier()).isFriend() )
+ if( sd.getDeclSpecifier() instanceof ICPPASTDeclSpecifier && ((ICPPASTDeclSpecifier)sd.getDeclSpecifier()).isFriend() )
return d1;
if (sd.getDeclarators().length != 1)
return d1;
@@ -2423,7 +2411,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
result.addDeclaration(d1);
result.addDeclaration(d2);
return result;
-
}
protected IASTAmbiguousDeclaration createAmbiguousDeclaration() {
@@ -2442,9 +2429,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* @throws BacktrackException
* request a backtrack
*/
- protected IASTDeclaration namespaceDefinitionOrAlias()
- throws BacktrackException, EndOfFileException {
-
+ protected IASTDeclaration namespaceDefinitionOrAlias() throws BacktrackException, EndOfFileException {
IToken first = consume();
int last = first.getEndOffset();
IASTName name = null;
@@ -4215,8 +4200,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
consume(IToken.tELLIPSIS);
isEllipsis = true;
} else {
- decl = simpleDeclaration(
- SimpleDeclarationStrategy.TRY_VARIABLE, true);
+ decl = simpleDeclaration(SimpleDeclarationStrategy.TRY_VARIABLE, true);
}
if (LT(1) != IToken.tEOC)
consume(IToken.tRPAREN);

Back to the top