diff --git a/core/org.eclipse.cdt.core/.classpath b/core/org.eclipse.cdt.core/.classpath
index 1c9f189c9d3..70f839cf53b 100644
--- a/core/org.eclipse.cdt.core/.classpath
+++ b/core/org.eclipse.cdt.core/.classpath
@@ -5,6 +5,8 @@
+
+
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/core/dom/IScope.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/core/dom/IScope.java
new file mode 100644
index 00000000000..98d6587b8bd
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/core/dom/IScope.java
@@ -0,0 +1,15 @@
+package org.eclipse.cdt.core.dom;
+
+import java.util.List;
+
+import org.eclipse.cdt.internal.core.dom.Declaration;
+
+/**
+ * A scope contains a set of declarations that are defined in that scope.
+ */
+public interface IScope {
+
+ public void addDeclaration(Declaration declaration);
+ public List getDeclarations();
+
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/BaseSpecifier.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/BaseSpecifier.java
new file mode 100644
index 00000000000..3e14f8a1aaa
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/BaseSpecifier.java
@@ -0,0 +1,44 @@
+package org.eclipse.cdt.internal.core.dom;
+
+/**
+ * @author dschaefe
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class BaseSpecifier {
+
+ public BaseSpecifier(ClassSpecifier classSpecifier) {
+ this.classSpecifier = classSpecifier;
+ classSpecifier.addBaseSpecifier(this);
+
+ switch (classSpecifier.getClassKey()) {
+ case ClassSpecifier.t_class:
+ access = t_private;
+ break;
+ case ClassSpecifier.t_struct:
+ access = t_public;
+ break;
+ }
+ }
+
+ private ClassSpecifier classSpecifier;
+ public ClassSpecifier getClassSpecifier() { return classSpecifier; }
+
+ private boolean isVirtual = false;
+ public void setVirtual(boolean isVirtual) { this.isVirtual = isVirtual; }
+ public boolean isVirtual() { return isVirtual; }
+
+ public static final int t_private = 0;
+ public static final int t_protected = 1;
+ public static final int t_public = 2;
+ private int access;
+ public void setAccess(int access) { this.access = access; }
+ public int getAccess() { return access; }
+
+ private String name;
+ public void setName(String name) { this.name = name; }
+ public String getName() { return name; }
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/ClassSpecifier.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/ClassSpecifier.java
new file mode 100644
index 00000000000..025955c9a2b
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/ClassSpecifier.java
@@ -0,0 +1,42 @@
+package org.eclipse.cdt.internal.core.dom;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.core.dom.IScope;
+import org.eclipse.cdt.internal.core.parser.util.Name;
+
+public class ClassSpecifier extends TypeSpecifier implements IScope {
+
+ public static final int t_class = 0;
+ public static final int t_struct = 1;
+ public static final int t_union = 2;
+
+ private final int classKey;
+ public int getClassKey() { return classKey; }
+
+ public ClassSpecifier(int classKey, SimpleDeclaration declaration) {
+ super(declaration);
+ this.classKey = classKey;
+ }
+
+ private Name name;
+ public void setName(Name n) { name = n; }
+ public Name getName() { return name; }
+
+ private List baseSpecifiers = new LinkedList();
+ public void addBaseSpecifier(BaseSpecifier baseSpecifier) {
+ baseSpecifiers.add(baseSpecifier);
+ }
+ public List getBaseSpecifiers() { return baseSpecifiers; }
+
+ private List declarations = new LinkedList();
+
+ public void addDeclaration(Declaration declaration) {
+ declarations.add(declaration);
+ }
+
+ public List getDeclarations() {
+ return declarations;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/DOMBuilder.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/DOMBuilder.java
new file mode 100644
index 00000000000..85eb6631861
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/DOMBuilder.java
@@ -0,0 +1,266 @@
+package org.eclipse.cdt.internal.core.dom;
+
+
+import org.eclipse.cdt.core.dom.IScope;
+import org.eclipse.cdt.internal.core.parser.IParserCallback;
+import org.eclipse.cdt.internal.core.parser.Token;
+import org.eclipse.cdt.internal.core.parser.util.*;
+import org.eclipse.cdt.internal.core.parser.util.Name;
+
+/**
+ * This is the parser callback that creates objects in the DOM.
+ */
+public class DOMBuilder implements IParserCallback
+{
+
+ private TranslationUnit translationUnit;
+
+ public TranslationUnit getTranslationUnit() {
+ return translationUnit;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#argumentsBegin()
+ */
+ public Object argumentsBegin( Object declarator ) {
+ Declarator decl = ((Declarator)declarator);
+ ParameterDeclarationClause clause = new ParameterDeclarationClause( decl );
+ return clause;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#argumentsEnd()
+ */
+ public void argumentsEnd(Object parameterDeclarationClause) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#classBegin(java.lang.String, org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public Object classSpecifierBegin(Object container, Token classKey) {
+ SimpleDeclaration decl = (SimpleDeclaration)container;
+
+ int kind = ClassSpecifier.t_struct;
+
+ switch (classKey.getType()) {
+ case Token.t_class:
+ kind = ClassSpecifier.t_class;
+ break;
+ case Token.t_struct:
+ kind = ClassSpecifier.t_struct;
+ break;
+ case Token.t_union:
+ kind = ClassSpecifier.t_union;
+ break;
+ }
+
+ ClassSpecifier classSpecifier = new ClassSpecifier(kind, decl);
+ decl.setTypeSpecifier(classSpecifier);
+ return classSpecifier;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#classSpecifierName()
+ */
+ public void classSpecifierName(Object classSpecifier) {
+ ((ClassSpecifier)classSpecifier).setName(currName);
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#classEnd()
+ */
+ public void classSpecifierEnd(Object classSpecifier) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declaratorBegin()
+ */
+ public Object declaratorBegin(Object container) {
+ DeclarationSpecifier.Container decl = (DeclarationSpecifier.Container )container;
+ Declarator declarator = new Declarator(decl);
+ decl.addDeclarator(declarator);
+ return declarator;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declaratorEnd()
+ */
+ public void declaratorEnd(Object declarator) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declaratorId(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void declaratorId(Object declarator) {
+ ((Declarator)declarator).setName(currName);
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declSpecifier(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void simpleDeclSpecifier(Object Container, Token specifier) {
+ DeclarationSpecifier.Container decl = (DeclarationSpecifier.Container)Container;
+ DeclarationSpecifier declSpec = decl.getDeclSpecifier();
+ if( declSpec == null )
+ {
+ declSpec = new DeclarationSpecifier();
+ decl.setDeclSpecifier( declSpec );
+ }
+
+ declSpec.setType( specifier );
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#expressionOperator(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void expressionOperator(Token operator) throws Exception {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#expressionTerminal(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void expressionTerminal(Token terminal) throws Exception {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#functionBodyBegin()
+ */
+ public void functionBodyBegin() {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#functionBodyEnd()
+ */
+ public void functionBodyEnd() {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#inclusionBegin(java.lang.String)
+ */
+ public void inclusionBegin(String includeFile, int offset) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#inclusionEnd()
+ */
+ public void inclusionEnd() {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#macro(java.lang.String)
+ */
+ public void macro(String macroName, int offset) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#simpleDeclarationBegin(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public Object simpleDeclarationBegin(Object container) {
+ SimpleDeclaration decl = new SimpleDeclaration();
+ ((IScope)container).addDeclaration(decl);
+ return decl;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#simpleDeclarationEnd(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void simpleDeclarationEnd(Object declaration) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#translationUnitBegin()
+ */
+ public Object translationUnitBegin() {
+ translationUnit = new TranslationUnit();
+ return translationUnit;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#translationUnitEnd()
+ */
+ public void translationUnitEnd(Object unit) {
+ }
+
+ private Name currName;
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#nameBegin(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void nameBegin(Token firstToken) {
+ currName = new Name(firstToken);
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#nameEnd(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void nameEnd(Token lastToken) {
+ currName.setEnd(lastToken);
+ }
+
+ public Object baseSpecifierBegin( Object classSpecifier )
+ {
+ ClassSpecifier cs =(ClassSpecifier)classSpecifier;
+ BaseSpecifier baseSpec = new BaseSpecifier( cs );
+ return baseSpec;
+ }
+
+ public void baseSpecifierEnd( Object baseSpecifier )
+ {
+
+ }
+
+ public void baseSpecifierVirtual( Object baseSpecifier, boolean virtual )
+ {
+ BaseSpecifier bs = (BaseSpecifier)baseSpecifier;
+ bs.setVirtual( virtual );
+ }
+
+ public void baseSpecifierVisibility( Object baseSpecifier, Token visibility )
+ {
+ int access = BaseSpecifier.t_public;
+ switch( visibility.type )
+ {
+ case Token.t_public:
+ access = BaseSpecifier.t_public;
+ break;
+ case Token.t_protected:
+ access = BaseSpecifier.t_protected;
+ break;
+ case Token.t_private:
+ access = BaseSpecifier.t_private;
+ break;
+ default:
+ break;
+ }
+
+ ((BaseSpecifier)baseSpecifier).setAccess(access);
+ }
+
+
+ public void baseSpecifierName( Object baseSpecifier )
+ {
+ ((BaseSpecifier)baseSpecifier).setName(currName.toString());
+ }
+
+ public Object parameterDeclarationBegin( Object container )
+ {
+ ParameterDeclarationClause clause = (ParameterDeclarationClause)container;
+ ParameterDeclaration pd = new ParameterDeclaration();
+ clause.addDeclaration( pd );
+ return pd;
+ }
+
+ public void parameterDeclarationEnd( Object declaration ){
+ }
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declaratorAbort(java.lang.Object, java.lang.Object)
+ */
+ public void declaratorAbort(Object container, Object declarator) {
+ DeclarationSpecifier.Container decl = (DeclarationSpecifier.Container )container;
+ Declarator toBeRemoved = (Declarator)declarator;
+ decl.removeDeclarator( toBeRemoved );
+ currName = null;
+ toBeRemoved = null;
+ }
+
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/Declaration.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/Declaration.java
new file mode 100644
index 00000000000..9b726db0e1c
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/Declaration.java
@@ -0,0 +1,7 @@
+package org.eclipse.cdt.internal.core.dom;
+
+/**
+ */
+public class Declaration {
+
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/Declarator.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/Declarator.java
new file mode 100644
index 00000000000..ab94281ebcf
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/Declarator.java
@@ -0,0 +1,64 @@
+package org.eclipse.cdt.internal.core.dom;
+
+import org.eclipse.cdt.internal.core.parser.util.*;
+import org.eclipse.cdt.internal.core.parser.util.Name;
+
+
+public class Declarator {
+
+ public Declarator(DeclarationSpecifier.Container declaration) {
+ this.declaration = declaration;
+ }
+
+ private DeclarationSpecifier.Container declaration;
+
+ /**
+ * Returns the declaration.
+ * @return SimpleDeclaration
+ */
+ public DeclarationSpecifier.Container getDeclaration() {
+ return declaration;
+ }
+
+ /**
+ * Sets the declaration.
+ * @param declaration The declaration to set
+ */
+ public void setDeclaration(SimpleDeclaration declaration) {
+ this.declaration = declaration;
+ }
+
+ private Name name;
+
+ /**
+ * Returns the name.
+ * @return Name
+ */
+ public Name getName() {
+ return name;
+ }
+
+ /**
+ * Sets the name.
+ * @param name The name to set
+ */
+ public void setName(Name name) {
+ this.name = name;
+ }
+
+ ParameterDeclarationClause parms = null;
+
+ public void addParms( ParameterDeclarationClause parms )
+ {
+ this.parms = parms;
+ }
+
+ /**
+ * Returns the parms.
+ * @return ParameterDeclarationClause
+ */
+ public ParameterDeclarationClause getParms() {
+ return parms;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/MemberDeclaration.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/MemberDeclaration.java
new file mode 100644
index 00000000000..aa932d03688
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/MemberDeclaration.java
@@ -0,0 +1,26 @@
+package org.eclipse.cdt.internal.core.dom;
+
+/**
+ * @author dschaefe
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class MemberDeclaration {
+ public static final int t_private = 0;
+ public static final int t_protected = 1;
+ public static final int t_public = 2;
+
+ public MemberDeclaration(int access, Declaration declaration) {
+ this.access = access;
+ this.declaration = declaration;
+ }
+
+ private int access;
+ public int getAccess() { return access; }
+
+ private Declaration declaration;
+ public Declaration getDeclaration() { return declaration; }
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/ParameterDeclaration.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/ParameterDeclaration.java
new file mode 100644
index 00000000000..cfe7caab72b
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/ParameterDeclaration.java
@@ -0,0 +1,52 @@
+package org.eclipse.cdt.internal.core.dom;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.internal.core.parser.util.*;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ParameterDeclaration extends Declaration implements DeclarationSpecifier.Container {
+
+ DeclarationSpecifier declSpec = null;
+
+ /**
+ * @see org.eclipse.cdt.internal.core.dom.DeclarationSpecifier.CElementWrapper#getDeclSpecifier()
+ */
+ public DeclarationSpecifier getDeclSpecifier() {
+ if( declSpec == null )
+ declSpec = new DeclarationSpecifier();
+
+ return declSpec;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.dom.DeclarationSpecifier.CElementWrapper#setDeclSpecifier(org.eclipse.cdt.internal.core.dom.DeclarationSpecifier)
+ */
+ public void setDeclSpecifier(DeclarationSpecifier in) {
+ declSpec = in;
+ }
+ private List declarators = new LinkedList();
+
+ public void addDeclarator(Object declarator) {
+ declarators.add(declarator);
+ }
+
+ public List getDeclarators() {
+ return declarators;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.util.DeclarationSpecifier.Container#removeDeclarator(java.lang.Object)
+ */
+ public void removeDeclarator(Object declarator) {
+ declarators.remove( declarator );
+ }
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/ParameterDeclarationClause.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/ParameterDeclarationClause.java
new file mode 100644
index 00000000000..a5caa43ac73
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/ParameterDeclarationClause.java
@@ -0,0 +1,40 @@
+package org.eclipse.cdt.internal.core.dom;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.core.dom.IScope;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ParameterDeclarationClause implements IScope {
+
+ /**
+ * @see org.eclipse.cdt.core.dom.IScope#addDeclaration(org.eclipse.cdt.internal.core.dom.Declaration)
+ */
+ public void addDeclaration( Declaration declaration) {
+ declarations.add( declaration );
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.dom.IScope#getDeclarations()
+ */
+ public List getDeclarations() {
+ return declarations;
+ }
+
+ private List declarations = new LinkedList();
+ private Declarator owner;
+
+ ParameterDeclarationClause( Declarator owner )
+ {
+ this.owner = owner;
+ this.owner.addParms( this );
+ }
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/SimpleDeclaration.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/SimpleDeclaration.java
new file mode 100644
index 00000000000..2f7e39aaf4e
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/SimpleDeclaration.java
@@ -0,0 +1,63 @@
+package org.eclipse.cdt.internal.core.dom;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.internal.core.parser.util.*;
+
+public class SimpleDeclaration extends Declaration implements DeclarationSpecifier.Container{
+
+ private DeclarationSpecifier declSpec = null;
+
+ public DeclarationSpecifier getDeclSpecifier()
+ {
+ if( declSpec == null )
+ declSpec = new DeclarationSpecifier();
+ return declSpec;
+ }
+
+ public void setDeclSpecifier( DeclarationSpecifier in )
+ {
+ declSpec = in;
+ }
+
+ /**
+ * This is valid when the type is t_type. It points to a
+ * classSpecifier, etc.
+ */
+ private TypeSpecifier typeSpecifier;
+
+ /**
+ * Returns the typeSpecifier.
+ * @return TypeSpecifier
+ */
+ public TypeSpecifier getTypeSpecifier() {
+ return typeSpecifier;
+ }
+
+ /**
+ * Sets the typeSpecifier.
+ * @param typeSpecifier The typeSpecifier to set
+ */
+ public void setTypeSpecifier(TypeSpecifier typeSpecifier) {
+ getDeclSpecifier().setType(DeclarationSpecifier.t_type);
+ this.typeSpecifier = typeSpecifier;
+ }
+
+ private List declarators = new LinkedList();
+
+ public void addDeclarator(Object declarator) {
+ declarators.add(declarator);
+ }
+
+ public List getDeclarators() {
+ return declarators;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.util.DeclarationSpecifier.Container#removeDeclarator(java.lang.Object)
+ */
+ public void removeDeclarator(Object declarator) {
+ declarators.remove( declarator );
+ }
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/TranslationUnit.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/TranslationUnit.java
new file mode 100644
index 00000000000..95454b73e57
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/TranslationUnit.java
@@ -0,0 +1,21 @@
+package org.eclipse.cdt.internal.core.dom;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.core.dom.IScope;
+
+/**
+ */
+public class TranslationUnit implements IScope {
+
+ private List declarations = new LinkedList();
+
+ public void addDeclaration(Declaration declaration) {
+ declarations.add(declaration);
+ }
+
+ public List getDeclarations() {
+ return declarations;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/TypeSpecifier.java b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/TypeSpecifier.java
new file mode 100644
index 00000000000..899ce4a394e
--- /dev/null
+++ b/core/org.eclipse.cdt.core/dom/org/eclipse/cdt/internal/core/dom/TypeSpecifier.java
@@ -0,0 +1,30 @@
+package org.eclipse.cdt.internal.core.dom;
+
+public class TypeSpecifier {
+
+ public TypeSpecifier(SimpleDeclaration declaration) {
+ this.declaration = declaration;
+ }
+
+ /**
+ * Owner declaration.
+ */
+ private SimpleDeclaration declaration;
+
+ /**
+ * Returns the declaration.
+ * @return SimpleDeclaration
+ */
+ public SimpleDeclaration getDeclaration() {
+ return declaration;
+ }
+
+ /**
+ * Sets the declaration.
+ * @param declaration The declaration to set
+ */
+ public void setDeclaration(SimpleDeclaration declaration) {
+ this.declaration = declaration;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java
index 58d70fe0056..5efd24e05c1 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java
@@ -194,7 +194,7 @@ public abstract class CElement extends PlatformObject implements ICElement {
}
if (fType != other.fType)
return false;
- if (fName.equals(other.fName)) {
+ if (other.fName != null && fName.equals(other.fName)) {
if (fParent != null && fParent.equals(other.fParent)) {
return true;
}
diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java
index bfd10e15238..1400aede4ec 100644
--- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java
+++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/TranslationUnitInfo.java
@@ -8,15 +8,15 @@ package org.eclipse.cdt.internal.core.model;
import java.io.IOException;
import java.io.InputStream;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.CoreException;
-
-import org.eclipse.cdt.internal.parser.CStructurizer;
-
-import org.eclipse.cdt.core.model.ISourceRange;
+import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ISourceRange;
+import org.eclipse.cdt.internal.core.parser.Parser;
+import org.eclipse.cdt.internal.parser.CStructurizer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
class TranslationUnitInfo extends CFileInfo {
@@ -55,10 +55,18 @@ class TranslationUnitInfo extends CFileInfo {
protected void parse(InputStream in) {
try {
removeChildren();
- ModelBuilder modelBuilder= new ModelBuilder((TranslationUnit)getElement());
- CStructurizer.getCStructurizer().parse(modelBuilder, in);
- } catch (IOException e) {
- //e.printStackTrace();
+ if (CCorePlugin.getDefault().useNewParser()) {
+ // new parser
+ NewModelBuilder modelBuilder = new NewModelBuilder((TranslationUnit)getElement());
+ Parser parser = new Parser(in, modelBuilder, true);
+ parser.parse();
+ } else {
+ // cdt 1.0 parser
+ ModelBuilder modelBuilder= new ModelBuilder((TranslationUnit)getElement());
+ CStructurizer.getCStructurizer().parse(modelBuilder, in);
+ }
+ } catch (Exception e) {
+ System.out.println(e);
}
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/Declarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/Declarator.java
new file mode 100644
index 00000000000..95698cc37a0
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/Declarator.java
@@ -0,0 +1,52 @@
+package org.eclipse.cdt.internal.core.model;
+
+import java.util.List;
+
+import org.eclipse.cdt.internal.core.parser.util.Name;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class Declarator {
+
+ private Name name;
+
+ /**
+ * Returns the name.
+ * @return Name
+ */
+ public Name getName() {
+ return name;
+ }
+
+ /**
+ * Sets the name.
+ * @param name The name to set
+ */
+ public void setName(Name name) {
+ this.name = name;
+ }
+
+ private List parameterDeclarationClause = null;
+
+ /**
+ * Returns the parameterDeclarationClause.
+ * @return List
+ */
+ public List getParameterDeclarationClause() {
+ return parameterDeclarationClause;
+ }
+
+ /**
+ * Sets the parameterDeclarationClause.
+ * @param parameterDeclarationClause The parameterDeclarationClause to set
+ */
+ public void setParameterDeclarationClause(List parameterDeclarationClause) {
+ this.parameterDeclarationClause = parameterDeclarationClause;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/ICElementWrapper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/ICElementWrapper.java
new file mode 100644
index 00000000000..5f3db2b35d1
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/ICElementWrapper.java
@@ -0,0 +1,15 @@
+package org.eclipse.cdt.internal.core.model;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public interface ICElementWrapper {
+
+ public CElement getElement();
+ public void setElement (CElement item);
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/NewModelBuilder.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/NewModelBuilder.java
new file mode 100644
index 00000000000..e5ea3d488ff
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/NewModelBuilder.java
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.model;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.internal.core.parser.IParserCallback;
+import org.eclipse.cdt.internal.core.parser.Token;
+import org.eclipse.cdt.internal.core.parser.util.DeclSpecifier;
+import org.eclipse.cdt.internal.core.parser.util.DeclarationSpecifier;
+import org.eclipse.cdt.internal.core.parser.util.Name;
+
+public class NewModelBuilder implements IParserCallback {
+
+ private TranslationUnitWrapper translationUnit = new TranslationUnitWrapper();
+
+
+ public NewModelBuilder(TranslationUnit tu) {
+ translationUnit.setElement( tu );
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginTranslationUnit()
+ */
+ public Object translationUnitBegin() {
+ return translationUnit;
+ }
+
+
+ private Token classKey;
+ /**
+ * @see org.eclipse.cdt.core.newparser.IParserCallback#beginClass(String, String)
+ */
+ public Object classSpecifierBegin(Object container, Token classKey) {
+
+ SimpleDeclarationWrapper c = (SimpleDeclarationWrapper)container;
+
+ int kind;
+ switch (classKey.getType()) {
+ case Token.t_class:
+ kind = ICElement.C_CLASS;
+ break;
+ case Token.t_struct:
+ kind = ICElement.C_STRUCT;
+ break;
+ default:
+ kind = ICElement.C_UNION;
+ }
+ this.classKey = classKey;
+
+ Structure elem = new Structure( c.getParent(), kind, null );
+ c.getParent().addChild(elem);
+ return new SimpleDeclarationWrapper( elem );
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#classSpecifierName()
+ */
+ public void classSpecifierName(Object classSpecifier) {
+
+ SimpleDeclarationWrapper container = (SimpleDeclarationWrapper)classSpecifier;
+ String name = currName.toString();
+ Structure elem = ((Structure)container.getElement());
+ elem.setElementName( name );
+ elem.setIdPos(currName.getEndOffset(), name.length());
+ elem.setPos(currName.getEndOffset(), name.length());
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.newparser.IParserCallback#endClass()
+ */
+ public void classSpecifierEnd(Object classSpecifier) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.newparser.IParserCallback#beginDeclarator()
+ */
+ public Object declaratorBegin(Object container) {
+ DeclarationSpecifier.Container declSpec = (DeclarationSpecifier.Container)container;
+ List declarators = declSpec.getDeclarators();
+ Declarator declarator =new Declarator();
+ declarators.add( declarator );
+ return declarator;
+ }
+
+
+ private int startIdPos;
+ private int idLength;
+
+ private CElement elem;
+
+ /**
+ * @see org.eclipse.cdt.core.newparser.IParserCallback#endDeclarator()
+ */
+ public void declaratorEnd( Object declarator) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginFunctionBody()
+ */
+ public void functionBodyBegin() {
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.newparser.IParserCallback#macro(String)
+ */
+ public void macro(String macroName, int offset) {
+ Macro elem = new Macro((TranslationUnit)translationUnit.getElement(), macroName);
+ elem.setIdPos(offset, macroName.length());
+ elem.setPos(offset, macroName.length());
+
+ ((TranslationUnit)translationUnit.getElement()).addChild(elem);
+
+ }
+
+ private int startPos;
+
+ /**
+ * @see
+org.eclipse.cdt.internal.core.newparser.IParserCallback#beginSimpleDeclaration(Token)
+ */
+ public Object simpleDeclarationBegin(Object container) {
+ ICElementWrapper wrapper = (ICElementWrapper)container;
+ Object parent = wrapper.getElement();
+ SimpleDeclarationWrapper result = new SimpleDeclarationWrapper();
+ if( wrapper instanceof SimpleDeclarationWrapper )
+ result.setParent( (CElement)wrapper.getElement() );
+ else if ( wrapper instanceof TranslationUnitWrapper )
+ result.setParent( (TranslationUnit)wrapper.getElement());
+ return result;
+ }
+
+
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginInclusion(String)
+ */
+ public void inclusionBegin(String includeFile, int offset) {
+ Include elem = new Include(((TranslationUnit)translationUnit.getElement()), includeFile);
+ ((TranslationUnit)translationUnit.getElement()).addChild(elem);
+ elem.setIdPos(offset, includeFile.length());
+ elem.setPos(offset, includeFile.length());
+
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#endInclusion()
+ */
+ public void inclusionEnd() {
+ }
+
+ private Name currName;
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#nameBegin(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void nameBegin(Token firstToken) {
+ currName = new Name(firstToken);
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#nameEnd(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void nameEnd(Token lastToken) {
+ currName.setEnd(lastToken);
+ }
+
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#simpleDeclarationEnd(java.lang.Object)
+ */
+ public void simpleDeclarationEnd(Object declaration) {
+ SimpleDeclarationWrapper wrapper = (SimpleDeclarationWrapper)declaration;
+ wrapper.createElements();
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#simpleDeclSpecifier(java.lang.Object, org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void simpleDeclSpecifier(Object declSpec, Token specifier) {
+ DeclSpecifier declSpecifier = (DeclSpecifier)declSpec;
+ declSpecifier.setType( specifier );
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declaratorId(java.lang.Object)
+ */
+ public void declaratorId(Object declarator) {
+ Declarator decl = (Declarator)declarator;
+ decl.setName( currName );
+ }
+
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#argumentsBegin(java.lang.Object)
+ */
+ public Object argumentsBegin(Object declarator) {
+ Declarator decl = (Declarator)declarator;
+ List parameterDeclarationClause = new LinkedList();
+ decl.setParameterDeclarationClause( parameterDeclarationClause );
+ return parameterDeclarationClause;
+
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#baseSpecifierBegin(java.lang.Object)
+ */
+ public Object baseSpecifierBegin(Object containingClassSpec) {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#baseSpecifierEnd(java.lang.Object)
+ */
+ public void baseSpecifierEnd(Object baseSpecifier) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#baseSpecifierName(java.lang.Object)
+ */
+ public void baseSpecifierName(Object baseSpecifier) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#baseSpecifierVirtual(java.lang.Object, boolean)
+ */
+ public void baseSpecifierVirtual(Object baseSpecifier, boolean virtual) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#baseSpecifierVisibility(java.lang.Object, org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void baseSpecifierVisibility(
+ Object baseSpecifier,
+ Token visibility) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#expressionOperator(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void expressionOperator(Token operator) throws Exception {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#expressionTerminal(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void expressionTerminal(Token terminal) throws Exception {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#functionBodyEnd()
+ */
+ public void functionBodyEnd() {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#parameterDeclarationBegin(java.lang.Object, org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public Object parameterDeclarationBegin(
+ Object container ) {
+ List parameterDeclarationClause = (List)container;
+ Parameter p = new Parameter();
+ parameterDeclarationClause.add( p );
+ return p;
+
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#parameterDeclarationEnd(java.lang.Object)
+ */
+ public void parameterDeclarationEnd(Object declaration) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#translationUnitEnd(java.lang.Object)
+ */
+ public void translationUnitEnd(Object unit) {
+ }
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#argumentsEnd()
+ */
+ public void argumentsEnd(Object parameterDeclarationClause) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declaratorAbort(java.lang.Object, java.lang.Object)
+ */
+ public void declaratorAbort(Object container, Object declarator) {
+ DeclarationSpecifier.Container declSpec = (DeclarationSpecifier.Container)container;
+ Declarator toBeRemoved =(Declarator)declarator;
+ declSpec.removeDeclarator( toBeRemoved );
+ toBeRemoved = null;
+ currName = null;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/Parameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/Parameter.java
new file mode 100644
index 00000000000..56370297289
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/Parameter.java
@@ -0,0 +1,53 @@
+package org.eclipse.cdt.internal.core.model;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.internal.core.parser.util.DeclSpecifier;
+import org.eclipse.cdt.internal.core.parser.util.DeclarationSpecifier;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class Parameter extends DeclSpecifier implements DeclarationSpecifier.Container
+{
+ DeclarationSpecifier declSpec = null;
+
+ /**
+ * @see org.eclipse.cdt.internal.core.dom.DeclarationSpecifier.CElementWrapper#getDeclSpecifier()
+ */
+ public DeclarationSpecifier getDeclSpecifier() {
+ if( declSpec == null )
+ declSpec = new DeclarationSpecifier();
+
+ return declSpec;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.dom.DeclarationSpecifier.CElementWrapper#setDeclSpecifier(org.eclipse.cdt.internal.core.dom.DeclarationSpecifier)
+ */
+ public void setDeclSpecifier(DeclarationSpecifier in) {
+ declSpec = in;
+ }
+ private List declarators = new LinkedList();
+
+ public void addDeclarator(Object declarator) {
+ declarators.add(declarator);
+ }
+
+ public List getDeclarators() {
+ return declarators;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.util.DeclarationSpecifier.Container#removeDeclarator(java.lang.Object)
+ */
+ public void removeDeclarator(Object declarator) {
+ declarators.remove( declarator );
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/SimpleDeclarationWrapper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/SimpleDeclarationWrapper.java
new file mode 100644
index 00000000000..1e6bf4e9521
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/SimpleDeclarationWrapper.java
@@ -0,0 +1,163 @@
+package org.eclipse.cdt.internal.core.model;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.core.model.IStructure;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.internal.core.parser.util.DeclSpecifier;
+import org.eclipse.cdt.internal.core.parser.util.DeclarationSpecifier;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class SimpleDeclarationWrapper extends DeclSpecifier implements DeclarationSpecifier.Container, ICElementWrapper {
+
+ private CElement element = null;
+ private CElement parent = null;
+
+ public SimpleDeclarationWrapper( CElement item )
+ {
+ this.element = item;
+ }
+
+ public SimpleDeclarationWrapper()
+ {
+ }
+
+ /**
+ * Returns the item.
+ * @return CElement
+ */
+ public CElement getElement() {
+ return element;
+ }
+
+ /**
+ * Sets the item.
+ * @param item The item to set
+ */
+ public void setElement (CElement item) {
+ this.element = (CElement)item;
+ }
+
+ /**
+ * Returns the parent.
+ * @return CElement
+ */
+ public CElement getParent() {
+ return parent;
+ }
+
+ /**
+ * Sets the parent.
+ * @param parent The parent to set
+ */
+ public void setParent(CElement parent) {
+ this.parent = parent;
+ }
+
+ public void createElements()
+ {
+ // creates the appropriate C Elements
+ List declaratorList = getDeclarators();
+ Declarator [] declarators = (Declarator []) declaratorList.toArray( new Declarator[ declaratorList.size() ] );
+ CElement parentElement = getParent();
+
+ for( int i = 0; i < declarators.length; ++i )
+ {
+ Declarator currentDeclarator = declarators[i];
+ CElement declaration = null;
+
+ // instantiate the right element
+ List clause =currentDeclarator.getParameterDeclarationClause();
+ if( clause == null )
+ {
+ // this is an attribute or a varaible
+ if( parentElement instanceof IStructure )
+ {
+ declaration = new Field( parentElement, currentDeclarator.getName().toString() );
+ }
+ else if( parentElement instanceof ITranslationUnit )
+ {
+ declaration = new Variable( parentElement, currentDeclarator.getName().toString() );
+ }
+ }
+ else
+ {
+ // this is a function or a method
+ if( parentElement instanceof IStructure )
+ {
+ declaration = new Method( parentElement, currentDeclarator.getName().toString() );
+
+ }
+ else if( parentElement instanceof ITranslationUnit )
+ {
+ declaration = new FunctionDeclaration( parentElement, currentDeclarator.getName().toString() );
+ }
+
+ Parameter [] parameters = (Parameter []) clause.toArray( new Parameter[ clause.size() ]);
+
+ for( int j = 0; j< parameters.length; ++j )
+ {
+ Parameter parm = parameters[j];
+
+ }
+
+ }
+
+ // hook up the offsets
+ declaration.setIdPos(
+currentDeclarator.getName().getEndOffset(),currentDeclarator.getName().toString().length());
+ declaration.setPos( currentDeclarator.getName().getEndOffset(), currentDeclarator.getName().toString().length() );
+
+ // add to parent
+ parentElement.addChild( declaration );
+ }
+
+ }
+
+ List declarators = new LinkedList();
+
+ public void addDeclarator( Object in )
+ {
+ declarators.add( in );
+ }
+
+ public List getDeclarators()
+ {
+ return declarators;
+ }
+
+ DeclarationSpecifier declSpec = null;
+
+ /**
+ * @see org.eclipse.cdt.internal.core.dom.DeclarationSpecifier.CElementWrapper#getDeclSpecifier()
+ */
+ public DeclarationSpecifier getDeclSpecifier() {
+ if( declSpec == null )
+ declSpec = new DeclarationSpecifier();
+
+ return declSpec;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.dom.DeclarationSpecifier.CElementWrapper#setDeclSpecifier(org.eclipse.cdt.internal.core.dom.DeclarationSpecifier)
+ */
+ public void setDeclSpecifier(DeclarationSpecifier in) {
+ declSpec = in;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.util.DeclarationSpecifier.Container#removeDeclarator(java.lang.Object)
+ */
+ public void removeDeclarator(Object declarator) {
+ declarators.remove( declarator );
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/TranslationUnitWrapper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/TranslationUnitWrapper.java
new file mode 100644
index 00000000000..7284d695401
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/model/TranslationUnitWrapper.java
@@ -0,0 +1,32 @@
+package org.eclipse.cdt.internal.core.model;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class TranslationUnitWrapper implements ICElementWrapper {
+
+ TranslationUnit unit = null;
+
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IWrapper#getElement()
+ */
+ public CElement getElement() {
+ return unit;
+ }
+ /**
+ * @see org.eclipse.cdt.internal.core.model.IWrapper#setElement(java.lang.Object)
+ */
+ public void setElement(CElement item) {
+ unit = (TranslationUnit)item;
+ }
+
+ public TranslationUnitWrapper( )
+ {
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/BranchTracker.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/BranchTracker.java
new file mode 100644
index 00000000000..4aab6428b9b
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/BranchTracker.java
@@ -0,0 +1,180 @@
+package org.eclipse.cdt.internal.core.parser;
+
+import java.util.EmptyStackException;
+import java.util.Stack;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable
+"typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class BranchTracker {
+
+ private static final int IGNORE_SENTINEL = -1;
+
+ /**
+ * Default constructor.
+ *
+ * @see java.lang.Object#Object()
+ */
+ public BranchTracker()
+ {
+ }
+
+ private Stack branches = new Stack();
+
+ private int ignore = IGNORE_SENTINEL;
+ private static final Boolean FALSE = new Boolean( false );
+ private static final Boolean TRUE = new Boolean( true );
+
+ /**
+ * Method poundif.
+ *
+ * This method is called whenever one encounters a #if, #ifndef
+ * or #ifdef preprocessor directive.
+ *
+ * @param taken - boolean indicates whether or not the condition
+ * evaluates to true or false
+ * @return boolean - are we set to continue scanning or not?
+ */
+ public boolean poundif( boolean taken )
+ {
+ if( ignore == IGNORE_SENTINEL )
+ {
+ // we are entering an if
+ // push the taken value onto the stack
+ branches.push( new Boolean( taken ) );
+
+ if( taken == false )
+ {
+ ignore = branches.size();
+ }
+
+ return taken;
+ }
+ else
+ {
+ branches.push( FALSE );
+ return false;
+ }
+ }
+
+ public boolean poundelif( boolean taken ) throws ScannerException
+ {
+ if( ignore != IGNORE_SENTINEL && ignore < branches.size() )
+ {
+ branches.pop();
+ branches.push( FALSE );
+ return false;
+ }
+
+ // so at this point we are either
+ // --> ignore == IGNORE_SENTINEL
+ // --> ignore >= branches.size()
+ // check the branch queue to see whether or not the branch has already been taken
+ Boolean branchAlreadyTaken;
+ try
+ {
+ branchAlreadyTaken = (Boolean) branches.peek();
+ }
+ catch( EmptyStackException ese )
+ {
+ throw new ScannerException( "#elif without a #if ");
+ }
+
+ if( ignore == IGNORE_SENTINEL )
+ {
+ if( ! branchAlreadyTaken.booleanValue() )
+ {
+ branches.pop();
+ branches.push( new Boolean( taken ) );
+ if( ! taken )
+ ignore = branches.size();
+
+ return taken;
+ }
+
+ // otherwise this section is to be ignored as well
+ ignore = branches.size();
+ return false;
+ }
+
+ // if we have gotten this far then ignore == branches.size()
+ if( ! branchAlreadyTaken.booleanValue() )
+ {
+ branches.pop();
+ branches.push( new Boolean( taken ) );
+ if( taken )
+ ignore = IGNORE_SENTINEL;
+
+ return taken;
+ }
+ ignore = branches.size();
+ return false;
+ }
+
+ public boolean poundelse() throws ScannerException
+ {
+ if( ignore != IGNORE_SENTINEL && ignore < branches.size() )
+ {
+ branches.pop();
+ branches.push( FALSE );
+ return false;
+ }
+
+ Boolean branchAlreadyTaken;
+ try
+ {
+ branchAlreadyTaken = (Boolean) branches.peek();
+ }
+ catch( EmptyStackException ese )
+ {
+ throw new ScannerException( "#else without a #if ");
+ }
+
+ if( ignore == IGNORE_SENTINEL )
+ {
+ if( branchAlreadyTaken.booleanValue() )
+ {
+ ignore = branches.size();
+ return false;
+ }
+
+ branches.pop();
+ branches.push( TRUE );
+ return true;
+
+ }
+
+ // now ignore >= branches.size()
+ if( branchAlreadyTaken.booleanValue() )
+ {
+ ignore = branches.size();
+ return false;
+ }
+
+ branches.pop();
+ branches.push( TRUE );
+ ignore = IGNORE_SENTINEL;
+ return true;
+
+ }
+
+ // taken only on an #endif
+ public boolean poundendif( )
+ {
+ if( ignore == branches.size() )
+ ignore = IGNORE_SENTINEL;
+ branches.pop();
+ return ( ignore == IGNORE_SENTINEL );
+ }
+
+ public int getDepth()
+ {
+ return branches.size();
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Declaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Declaration.java
new file mode 100644
index 00000000000..8ad426e9437
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Declaration.java
@@ -0,0 +1,220 @@
+package org.eclipse.cdt.internal.core.parser;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * @author aniefer
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class Declaration {
+
+ /**
+ * Constructor for Declaration.
+ */
+ public Declaration() {
+ super();
+ }
+
+ public Declaration( String name ){
+ _name = name;
+ }
+
+ public Declaration( String name, Object obj ){
+ _name = name;
+ _object = obj;
+ }
+
+ //Type information, only what we need for now...
+ public static final int typeMask = 0x0001f;
+ public static final int isStatic = 0x00020;
+
+ // Types
+ public static final int t_type = 0; // Type Specifier
+ public static final int t_class = 1;
+ public static final int t_struct = 2;
+ public static final int t_union = 3;
+ public static final int t_enum = 4;
+
+ public void setStatic( boolean b ) { setBit( b, isStatic ); }
+ public boolean isStatic() { return checkBit( isStatic ); }
+
+ public void setType(int t) throws ParserSymbolTableException {
+ if( t > typeMask )
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
+ _typeInfo = _typeInfo & ~typeMask | t;
+ }
+ public int getType(){
+ return _typeInfo & typeMask;
+ }
+ public boolean isType( int t ){
+ return ( t == -1 || getType() == t );
+ }
+
+ public Declaration getTypeDeclaration() { return _typeDeclaration; }
+ public void setTypeDeclaration( Declaration type ){
+ try { setType( t_type ); }
+ catch (ParserSymbolTableException e) { /*will never happen*/ }
+
+ _typeDeclaration = type;
+ }
+
+ public String getName() { return _name; }
+ public void setName(String name) { _name = name; }
+
+ public Object getObject() { return _object; }
+ public void setObject( Object obj ) { _object = obj; }
+
+ public Declaration getContainingScope() { return _containingScope; }
+ protected void setContainingScope( Declaration scope ) { _containingScope = scope; }
+
+ public void addParent( Declaration parent ){
+ addParent( parent, false );
+ }
+ public void addParent( Declaration parent, boolean virtual ){
+ _parentScopes.add( new ParentWrapper( parent, virtual ) );
+ }
+
+ protected void addDeclaration( Declaration obj ){
+ obj.setContainingScope( this );
+ _containedDeclarations.put( obj.getName(), obj );
+ }
+
+ public Map getContainedDeclarations(){
+ return _containedDeclarations;
+ }
+
+ /**
+ * Lookup the given name in this context.
+ * @param type: for elaborated lookups, only return declarations of this
+ * type
+ * @param name: Name of the object to lookup
+ * @return Declaration
+ * @throws ParserSymbolTableException
+ * @see ParserSymbolTable#Lookup
+ */
+ protected Declaration Lookup( int type, String name ) throws ParserSymbolTableException{
+
+ if( type != -1 && type < t_class && type > t_union )
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
+
+ Declaration decl = null;
+
+ //if this name define in this scope?
+ decl = (Declaration) _containedDeclarations.get( name );
+
+ //if yes, it hides any others, we are done.
+ if( decl != null && decl.isType( type ) ){
+ return decl;
+ }
+
+ //if no, we next check any parents we have
+ decl = LookupInParents( type, name, new HashSet() );
+
+ //if still not found, check our containing scope.
+ if( decl == null && _containingScope != null )
+ decl = _containingScope.Lookup( type, name );
+
+ return decl;
+ }
+
+ private Declaration LookupInParents( int type, String name, Set virtualsVisited ) throws ParserSymbolTableException{
+
+ Declaration decl = null, temp = null;
+
+ Iterator iterator = _parentScopes.iterator();
+
+ ParentWrapper wrapper = null;
+ try{
+ wrapper = (ParentWrapper) iterator.next();
+ }
+ catch ( NoSuchElementException e ){
+ wrapper = null;
+ }
+
+ while( wrapper != null )
+ {
+ if( !wrapper.isVirtual || !virtualsVisited.contains( wrapper.parent ) ){
+ if( wrapper.isVirtual )
+ virtualsVisited.add( wrapper.parent );
+
+ //is this name define in this scope?
+ temp = (Declaration) wrapper.parent._containedDeclarations.get( name );
+ if( temp == null || !temp.isType( type ) )
+ temp = wrapper.parent.LookupInParents( type, name, virtualsVisited );
+ }
+
+ if( temp != null && temp.isType( type ) ){
+ if( decl == null )
+ decl = temp;
+ else if ( temp != null )
+ {
+ //it is not ambiguous if temp & decl are the same thing and it is static
+ //or an enum
+ if( decl == temp && ( temp.isStatic() || temp.getType() == t_enum) )
+ temp = null;
+ else
+ throw( new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ) );
+
+ }
+ }
+ else
+ temp = null;
+
+ try{
+ wrapper = (ParentWrapper) iterator.next();
+ }
+ catch (NoSuchElementException e){
+ wrapper = null;
+ }
+ }
+
+ return decl;
+ }
+
+
+ // Convenience methods
+ private void setBit(boolean b, int mask) {
+ if (b) _typeInfo = _typeInfo | mask;
+ else _typeInfo = _typeInfo & ~mask;
+ }
+
+ private boolean checkBit(int mask) {
+ return (_typeInfo & mask) != 0;
+ }
+
+
+ //Other scopes to check if the name is not in currRegion
+ //we might want another Vector to deal with namespaces & using...
+ private Declaration _containingScope = null;
+ private Declaration _type = null;
+ private Declaration _typeDeclaration = null;
+ private int _typeInfo = 0;
+ private Object _object = null;
+ private List _parentScopes = new LinkedList();
+ private Map _containedDeclarations = new HashMap();
+ private String _name;
+
+
+ private class ParentWrapper{
+ public ParentWrapper( Declaration p, boolean v ){
+ parent = p;
+ isVirtual = v;
+ }
+
+ public boolean isVirtual = false;
+ public Declaration parent = null;
+ }
+
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ExpressionEvaluator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ExpressionEvaluator.java
new file mode 100644
index 00000000000..bfb67a30d0e
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ExpressionEvaluator.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.parser;
+
+import java.util.Stack;
+
+public class ExpressionEvaluator extends NullParserCallback {
+
+ public class ExpressionException extends Exception {
+ public ExpressionException(String msg) {
+ super(msg);
+ }
+ }
+
+ private Stack stack = new Stack();
+
+ private int popInt() {
+ return ((Integer)stack.pop()).intValue();
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.newparser.IParserCallback#expressionOperator(Token)
+ */
+ public void expressionOperator(Token operator) throws Exception {
+
+ int second = popInt();
+ int first;
+ switch (operator.getType()) {
+
+ case Token.tPLUS:
+ first = popInt();
+ stack.push(new Integer(first + second));
+ break;
+ case Token.tMINUS:
+ first = popInt();
+ stack.push(new Integer(first - second));
+ break;
+ case Token.tSTAR:
+ first = popInt();
+ stack.push(new Integer(first * second));
+ break;
+ case Token.tDIV:
+ first = popInt();
+ stack.push(new Integer(first / second));
+ break;
+ case Token.tLT:
+ first = popInt();
+ stack.push(new Integer(first < second ? 1 : 0));
+ break;
+ case Token.tLTEQUAL:
+ first = popInt();
+ stack.push(new Integer(first <= second ? 1 : 0));
+ break;
+ case Token.tGT:
+ first = popInt();
+ stack.push(new Integer(first > second ? 1 : 0));
+ break;
+ case Token.tGTEQUAL:
+ first = popInt();
+ stack.push(new Integer(first >= second ? 1 : 0));
+ break;
+ case Token.tEQUAL:
+ first = popInt();
+ stack.push(new Integer(first == second ? 1 : 0));
+ break;
+ case Token.tNOTEQUAL:
+ first = popInt();
+ stack.push(new Integer(first != second ? 1 : 0));
+ break;
+ case Token.tAND:
+ first = popInt();
+ stack.push( new Integer( ( ( first != 0 ) && ( second != 0 ) ) ? 1 : 0 ) );
+ break;
+ case Token.tOR:
+ first = popInt();
+ stack.push( new Integer( ( ( first != 0 ) || ( second != 0 ) ) ? 1 : 0 ) );
+ break;
+ case Token.tNOT:
+ stack.push( new Integer( ( second == 0 ) ? 1 : 0 ) );
+ break;
+ default:
+ throw new ExpressionException("Unhandled operator: " + operator );
+ }
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.newparser.IParserCallback#expressionTerminal(Token)
+ */
+ public void expressionTerminal(Token terminal) throws Exception {
+ switch (terminal.getType()) {
+ case Token.tINTEGER:
+ stack.push(new Integer(terminal.getImage()));
+ break;
+ default:
+ throw new ExpressionException("Unhandled terminal: " + terminal.getImage());
+ }
+ }
+
+ public Object getResult() {
+ return stack.peek();
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IMacroDescriptor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IMacroDescriptor.java
new file mode 100644
index 00000000000..9c9fba8e3dc
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IMacroDescriptor.java
@@ -0,0 +1,18 @@
+package org.eclipse.cdt.internal.core.parser;
+import java.util.List;
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable
+"typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public interface IMacroDescriptor {
+ void initialize(String name, List identifiers, List tokens, String sig);
+ List getParameters();
+ List getTokenizedExpansion();
+ String getName();
+ String getSignature();
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IParserCallback.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IParserCallback.java
new file mode 100644
index 00000000000..f8d7fe7dc7a
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IParserCallback.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.parser;
+
+public interface IParserCallback {
+
+ public Object translationUnitBegin();
+ public void translationUnitEnd(Object unit);
+
+ public void inclusionBegin(String includeFile, int offset);
+ public void inclusionEnd();
+ public void macro(String macroName, int offset);
+
+ public Object simpleDeclarationBegin(Object Container);
+ public void simpleDeclarationEnd(Object declaration);
+
+ public Object parameterDeclarationBegin( Object Container );
+ public void parameterDeclarationEnd( Object declaration );
+
+ public void simpleDeclSpecifier(Object Container, Token specifier);
+
+ public void nameBegin(Token firstToken);
+ public void nameEnd(Token lastToken);
+
+ public Object declaratorBegin(Object container);
+ public void declaratorId(Object declarator);
+ public void declaratorAbort( Object container, Object declarator );
+ public void declaratorEnd(Object declarator);
+
+ public Object argumentsBegin( Object declarator );
+ public void argumentsEnd(Object parameterDeclarationClause);
+
+
+ public void functionBodyBegin();
+ public void functionBodyEnd();
+
+ public Object classSpecifierBegin(Object container, Token classKey);
+ public void classSpecifierName(Object classSpecifier);
+ public void classSpecifierEnd(Object classSpecifier);
+
+ public Object baseSpecifierBegin( Object containingClassSpec );
+ public void baseSpecifierName( Object baseSpecifier );
+ public void baseSpecifierVisibility( Object baseSpecifier, Token visibility );
+ public void baseSpecifierVirtual( Object baseSpecifier, boolean virtual );
+ public void baseSpecifierEnd( Object baseSpecifier );
+
+ public void expressionOperator(Token operator) throws Exception;
+ public void expressionTerminal(Token terminal) throws Exception;
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IScanner.java
new file mode 100644
index 00000000000..63ef33190a4
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IScanner.java
@@ -0,0 +1,31 @@
+package org.eclipse.cdt.internal.core.parser;
+
+import java.io.Reader;
+import java.util.List;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable
+"typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public interface IScanner {
+
+ public IScanner initialize( Reader sourceToBeRead, String fileName );
+
+ public void addDefinition(String key, IMacroDescriptor macroToBeAdded );
+ public void addDefinition(String key, String value);
+ public Object getDefinition(String key);
+
+ public Object[] getIncludePaths();
+ public void addIncludePath(String includePath);
+ public void overwriteIncludePath( List newIncludePaths );
+
+ public Token nextToken() throws ScannerException;
+
+ public void setQuickScan(boolean qs);
+ public void setCallback(IParserCallback c);
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IScannerContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IScannerContext.java
new file mode 100644
index 00000000000..b96f3f2aa2d
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/IScannerContext.java
@@ -0,0 +1,21 @@
+package org.eclipse.cdt.internal.core.parser;
+import java.io.Reader;
+import java.io.IOException;
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable
+"typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public interface IScannerContext {
+ IScannerContext initialize(Reader r, String f, int u);
+ int read() throws IOException;
+ String getFilename();
+ int getOffset();
+ Reader getReader();
+ int getUndo();
+ void setUndo(int undo);
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/MacroDescriptor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/MacroDescriptor.java
new file mode 100644
index 00000000000..13874ca22ea
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/MacroDescriptor.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.parser;
+
+import java.util.Iterator;
+import java.util.List;
+
+public class MacroDescriptor implements IMacroDescriptor {
+
+ public MacroDescriptor()
+ {
+ }
+
+ /**
+ * Method initialize.
+ * @param name The name or label that the Macro can be identified by.
+ * @param identifiers An ordered list of parameters in the macro
+ * definition.
+ * @param tokens An ordered list of tokens that describe the
+ * RHS expansion in the macro definition.
+ * @param sig The complete signature of the macro, as a string.
+ */
+ public void initialize( String name, List identifiers, List tokens, String sig )
+ {
+ this.name = name;
+ identifierParameters = identifiers;
+ tokenizedExpansion = tokens;
+ signature = sig;
+ }
+
+ private String name;
+ private List identifierParameters;
+ private List tokenizedExpansion;
+ private String signature;
+ /**
+ * Returns the identifiers.
+ * @return List
+ */
+ public final List getParameters() {
+ return identifierParameters;
+ }
+
+ /**
+ * Returns the tokens.
+ * @return List
+ */
+ public final List getTokenizedExpansion() {
+ return tokenizedExpansion;
+ }
+
+ /**
+ * Returns the name.
+ * @return String
+ */
+ public final String getName()
+ {
+ return name;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer( 128 );
+ int count = getParameters().size();
+
+ buffer.append( "MacroDescriptor with name=" + getName() + "\n" );
+ buffer.append( "Number of parameters = " + count + "\n" );
+ Iterator iter = getParameters().iterator();
+ int current = 0;
+ while( iter.hasNext() )
+ {
+ buffer.append( "Parameter #" + current++ + " with name=" + (String) iter.next() + "\n" );
+ }
+
+ count = getTokenizedExpansion().size();
+ iter = getTokenizedExpansion().iterator();
+
+ buffer.append( "Number of tokens = " + count + "\n" );
+ current = 0;
+ while( iter.hasNext() )
+ {
+ buffer.append( "Token #" + current++ + " is " + ((Token)iter.next()).toString() + "\n" );
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the signature.
+ * @return String
+ */
+ public final String getSignature()
+ {
+ return signature;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Main.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Main.java
new file mode 100644
index 00000000000..85636acb0e5
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Main.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.parser;
+
+import java.io.FileReader;
+import java.io.Reader;
+
+public class Main {
+
+ public static void main(String[] args) {
+
+ String fileName = null;
+
+ // Find the file
+ for (int i = 0; i < args.length; ++i) {
+ if (!args[i].startsWith("-"))
+ fileName = args[i];
+ }
+
+ if (fileName == null) {
+ System.out.println("Error: no files.");
+ return;
+ }
+
+ Reader reader;
+ try {
+ reader = new FileReader(fileName);
+ } catch (Exception e) {
+ System.err.println(e);
+ return;
+ }
+
+ Scanner scanner = new Scanner();
+ scanner.initialize( reader, fileName );
+
+ // Now pass on the preprocessing options
+ for (int i = 0; i < args.length; ++i) {
+ if (args[i].startsWith("-I")) {
+ String dir = args[i].substring(2);
+ scanner.addIncludePath(dir);
+ } else if (args[i].startsWith("-D")) {
+ int pos = args[i].indexOf('=');
+ String name;
+ String value = "";
+ if (pos < 0) {
+ name = args[i].substring(2);
+ } else {
+ name = args[i].substring(2, pos);
+ value = args[i].substring(pos + 1);
+ }
+ scanner.addDefinition(name, value);
+ }
+ }
+
+ Parser parser = null;
+ try {
+ parser = new Parser(scanner);
+ } catch (Exception e) {
+ System.out.println(e);
+ return;
+ }
+
+ long startTime = System.currentTimeMillis();
+ try {
+ parser.parse();
+ } catch (Exception e) {
+ System.err.println(e);
+ }
+
+ long time = System.currentTimeMillis() - startTime;
+
+ System.out.println("done " + scanner.getCount() + " tokens in " + time + "ms.");
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/NullParserCallback.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/NullParserCallback.java
new file mode 100644
index 00000000000..2560d7466d1
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/NullParserCallback.java
@@ -0,0 +1,175 @@
+package org.eclipse.cdt.internal.core.parser;
+
+public class NullParserCallback implements IParserCallback {
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginArguments()
+ */
+ public Object argumentsBegin( Object container ) {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginClass(String, Token)
+ */
+ public Object classSpecifierBegin(Object container, Token classKey) {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginDeclarator()
+ */
+ public Object declaratorBegin(Object container) {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginFunctionBody()
+ */
+ public void functionBodyBegin() {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginInclusion(String)
+ */
+ public void inclusionBegin(String includeFile, int offset) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginSimpleDeclaration(Token)
+ */
+ public Object simpleDeclarationBegin(Object Container) {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#beginTranslationUnit()
+ */
+ public Object translationUnitBegin() {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declaratorId(Token)
+ */
+ public void declaratorId(Object declarator) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declSpecifier(Token)
+ */
+ public void simpleDeclSpecifier(Object Container, Token specifier) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#endArguments()
+ */
+ public void argumentsEnd(Object parameterDeclarationClause) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#endClass()
+ */
+ public void classSpecifierEnd(Object classSpecifier) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#endDeclarator()
+ */
+ public void declaratorEnd(Object declarator) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#endFunctionBody()
+ */
+ public void functionBodyEnd() {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#endInclusion()
+ */
+ public void inclusionEnd() {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#endSimpleDeclaration(Token)
+ */
+ public void simpleDeclarationEnd(Object declaration) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#endTranslationUnit()
+ */
+ public void translationUnitEnd(Object unit) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#expressionOperator(Token)
+ */
+ public void expressionOperator(Token operator) throws Exception {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#expressionTerminal(Token)
+ */
+ public void expressionTerminal(Token terminal) throws Exception {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#macro(String)
+ */
+ public void macro(String macroName, int offset) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#nameBegin(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void nameBegin(Token firstToken) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#nameEnd(org.eclipse.cdt.internal.core.newparser.Token)
+ */
+ public void nameEnd(Token lastToken) {
+ }
+
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#classSpecifierName()
+ */
+ public void classSpecifierName(Object classSpecifier) {
+ }
+
+ public Object baseSpecifierBegin( Object classSpecifier )
+ {
+ return null;
+ }
+
+ public void baseSpecifierEnd( Object x )
+ {
+ }
+
+ public void baseSpecifierName( Object baseSpecifier )
+ {
+ }
+
+ public void baseSpecifierVisibility( Object baseSpecifier, Token visibility )
+ {
+ }
+
+ public void baseSpecifierVirtual( Object baseSpecifier, boolean virtual )
+ {
+ }
+
+ public Object parameterDeclarationBegin( Object container )
+ {
+ return null;
+ }
+
+ public void parameterDeclarationEnd( Object declaration ){
+ }
+ /**
+ * @see org.eclipse.cdt.internal.core.newparser.IParserCallback#declaratorAbort(java.lang.Object, java.lang.Object)
+ */
+ public void declaratorAbort(Object container, Object declarator) {
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java
new file mode 100644
index 00000000000..d44b0c02d46
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Parser.java
@@ -0,0 +1,1286 @@
+package org.eclipse.cdt.internal.core.parser;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This is an attempt at a copyright clean parser. The grammar is based
+ * on the ISO C++ standard
+ */
+public class Parser {
+
+ private IParserCallback callback;
+ private boolean quickParse = false;
+ private boolean parsePassed = true;
+
+ // TO DO: convert to a real symbol table
+ private Map currRegion = new HashMap();
+
+ public Parser(IScanner s, IParserCallback c, boolean quick) throws Exception {
+ callback = c;
+ scanner = s;
+ quickParse = quick;
+ scanner.setQuickScan(quick);
+ scanner.setCallback(c);
+ //fetchToken();
+ }
+
+ public Parser(IScanner s, IParserCallback c) throws Exception {
+ this(s, c, false);
+ }
+
+ public Parser( IScanner s) throws Exception {
+ this(s, new NullParserCallback(), false);
+ }
+
+ public Parser(String code) throws Exception {
+ this(new Scanner().initialize( new StringReader( code ), null
+));
+ }
+
+ public Parser(String code, IParserCallback c) throws Exception {
+ this(new Scanner().initialize( new StringReader( code ), null
+), c, false);
+ }
+
+ public Parser(InputStream stream, IParserCallback c, boolean quick) throws Exception {
+ this(new Scanner().initialize( new InputStreamReader(stream), null ),
+c, quick);
+ }
+
+ private static int parseCount = 0;
+
+ public boolean parse() throws Exception {
+ long startTime = System.currentTimeMillis();
+ translationUnit();
+ System.out.println("Parse " + (++parseCount) + ": "
+ + ( System.currentTimeMillis() - startTime ) + "ms"
+ + ( parsePassed ? "" : " - parse failure" ));
+
+ return parsePassed;
+ }
+
+ /**
+ * translationUnit
+ * : (declaration)*
+ *
+ */
+ public void translationUnit() throws Exception {
+ Object translationUnit = callback.translationUnitBegin();
+ Token lastBacktrack = null;
+ while (LT(1) != Token.tEOF) {
+ try {
+ declaration( translationUnit );
+ } catch (Backtrack b) {
+ // Mark as failure and try to reach a recovery point
+ parsePassed = false;
+
+ if (lastBacktrack != null && lastBacktrack == LA(1)) {
+ // we haven't progressed from the last backtrack
+ // try and find tne next definition
+ for (int t = LT(1); t != Token.tEOF; t = LT(1)) {
+ consume();
+ // TO DO: we should really check for matching braces too
+ if (t == Token.tSEMI)
+ break;
+ }
+ } else {
+ // start again from here
+ lastBacktrack = LA(1);
+ }
+ }
+ }
+ callback.translationUnitEnd(translationUnit);
+ }
+
+ /**
+ * declaration
+ * : {"asm"} asmDefinition
+ * | {"namespace"} namespaceDefinition
+ * | {"using"} usingDeclaration
+ * | {"export"|"template"} templateDeclaration
+ * | {"extern"} linkageSpecification
+ * | simpleDeclaration
+ *
+ * Notes:
+ * - folded in blockDeclaration
+ * - merged alternatives that required same LA
+ * - functionDefinition into simpleDeclaration
+ * - namespaceAliasDefinition into namespaceDefinition
+ * - usingDirective into usingDeclaration
+ * - explicitInstantiation and explicitSpecialization into
+ * templateDeclaration
+ */
+ public void declaration( Object container ) throws Exception {
+ switch (LT(1)) {
+ case Token.t_asm:
+ // asmDefinition( );
+ consume();
+ return;
+ case Token.t_namespace:
+ // namespaceDefinition();
+ consume();
+ return;
+ case Token.t_using:
+ // usingDeclaration();
+ consume();
+ return;
+ case Token.t_export:
+ case Token.t_template:
+ // templateDeclaration();
+ consume();
+ return;
+ case Token.t_extern:
+ if (LT(2) == Token.tSTRING)
+ {
+ // linkageSpecification();
+ consume();
+ return;
+ }
+
+ // else drop through
+ default:
+ simpleDeclaration( container );
+ }
+ }
+
+
+
+ /**
+ * simpleDeclaration
+ * : (declSpecifier)* (initDeclarator ("," initDeclarator)*)?
+ * (";" | {"{"} functionBody)
+ *
+ * Notes:
+ * - append functionDefinition stuff to end of this rule
+ *
+ * To do:
+ * - work in ctorInitializer and functionTryBlock
+ */
+ public void simpleDeclaration( Object container ) throws Exception {
+ Object simpleDecl = callback.simpleDeclarationBegin( container);
+ declSpecifierSeq(simpleDecl);
+
+ if (LT(1) != Token.tSEMI)
+ try {
+ initDeclarator(simpleDecl);
+
+ while (LT(1) == Token.tCOMMA) {
+ consume();
+
+ try {
+ initDeclarator(simpleDecl);
+ } catch (Backtrack b) {
+ throw b;
+ }
+ }
+ } catch (Backtrack b) {
+ // allowed to be empty
+ }
+
+ switch (LT(1)) {
+ case Token.tSEMI:
+ consume();
+ break;
+ case Token.tLBRACE:
+ callback.functionBodyBegin();
+ if (quickParse) {
+ // speed up the parser by skiping the body
+ // simply look for matching brace and return
+ consume();
+ int depth = 1;
+ while (depth > 0) {
+ switch (consume().getType()) {
+ case Token.tRBRACE:
+ --depth;
+ break;
+ case Token.tLBRACE:
+ ++depth;
+ break;
+ case Token.tEOF:
+ // Oops, no match
+ throw backtrack;
+ }
+ }
+ } else {
+ functionBody();
+ }
+ callback.functionBodyEnd();
+ break;
+ default:
+ break;
+ }
+
+ callback.simpleDeclarationEnd(simpleDecl);
+ }
+
+
+ public void parameterDeclaration( Object containerObject ) throws Exception
+ {
+ Object parameterDecl = callback.parameterDeclarationBegin( containerObject );
+ declSpecifierSeq( parameterDecl );
+
+ if (LT(1) != Token.tSEMI)
+ try {
+ initDeclarator(parameterDecl);
+
+ } catch (Backtrack b) {
+ // allowed to be empty
+ }
+
+ callback.parameterDeclarationEnd( parameterDecl );
+
+ }
+
+ /**
+ * declSpecifier
+ * : "auto" | "register" | "static" | "extern" | "mutable"
+ * | "inline" | "virtual" | "explicit"
+ * | "char" | "wchar_t" | "bool" | "short" | "int" | "long"
+ * | "signed" | "unsigned" | "float" | "double" | "void"
+ * | "const" | "volatile"
+ * | "friend" | "typedef"
+ * | ("typename")? name
+ * | {"class"|"struct"|"union"} classSpecifier
+ * | {"enum"} enumSpecifier
+ *
+ * Notes:
+ * - folded in storageClassSpecifier, typeSpecifier, functionSpecifier
+ * - folded elaboratedTypeSpecifier into classSpecifier and enumSpecifier
+ * - find template names in name
+ */
+ public void declSpecifierSeq( Object decl ) throws Exception {
+ boolean encounteredTypename = false;
+ boolean encounteredRawType = false;
+ declSpecifiers:
+ for (;;) {
+ switch (LT(1)) {
+ case Token.t_auto:
+ case Token.t_register:
+ case Token.t_static:
+ case Token.t_extern:
+ case Token.t_mutable:
+ case Token.t_inline:
+ case Token.t_virtual:
+ case Token.t_explicit:
+ case Token.t_typedef:
+ case Token.t_friend:
+ case Token.t_const:
+ case Token.t_volatile:
+ case Token.t_char:
+ case Token.t_wchar_t:
+ case Token.t_bool:
+ case Token.t_short:
+ case Token.t_int:
+ case Token.t_long:
+ case Token.t_signed:
+ case Token.t_unsigned:
+ case Token.t_float:
+ case Token.t_double:
+ case Token.t_void:
+ encounteredRawType = true;
+ callback.simpleDeclSpecifier(decl, consume());
+ break;
+ case Token.t_typename:
+ consume();
+ name();
+ break;
+ case Token.tCOLONCOLON:
+ consume();
+ // handle nested later:
+ case Token.tIDENTIFIER:
+ if( ! encounteredRawType )
+ {
+ // handle nested later:
+ if( ! encounteredTypename )
+ {
+ callback.simpleDeclSpecifier(decl,consume());
+ encounteredTypename = true;
+ break;
+ }
+ else
+ return;
+ }
+ else
+ return;
+
+ case Token.t_class:
+ case Token.t_struct:
+ case Token.t_union:
+ classSpecifier(decl);
+ return;
+ case Token.t_enum:
+ // enumSpecifier();
+ break;
+ default:
+ break declSpecifiers;
+ }
+ }
+ }
+
+ /**
+ * name
+ * : ("::")? name2 ("::" name2)*
+ *
+ * name2
+ * : IDENTIFER
+ *
+ * To Do:
+ * - Handle template ids
+ * - Handle unqualifiedId
+ */
+ public boolean name() throws Exception {
+ Token last = null;
+
+ callback.nameBegin(LA(1));
+
+ if (LT(1) == Token.tCOLONCOLON)
+ last = consume();
+
+ last = consume(Token.tIDENTIFIER);
+
+ while (LT(1) == Token.tCOLONCOLON) {
+ last = consume();
+
+ last = consume(Token.tIDENTIFIER);
+ }
+
+ callback.nameEnd(last);
+
+ return true;
+ }
+
+ /**
+ * cvQualifier
+ * : "const" | "volatile"
+ */
+ public Object cvQualifier() throws Exception {
+ switch (LT(1)) {
+ case Token.t_const:
+ case Token.t_volatile:
+ consume();
+ return null;
+ default:
+ throw backtrack;
+ }
+ }
+
+ /**
+ * initDeclarator
+ * : declarator ("=" initializerClause | "(" expressionList ")")?
+ *
+ * To Do:
+ * - handle initializers
+ */
+ public void initDeclarator( Object owner ) throws Exception {
+ declarator( owner );
+ }
+
+ /**
+ * declarator
+ * : (ptrOperator)* directDeclarator
+ *
+ * directDeclarator
+ * : declaratorId
+ * | directDeclarator "(" parameterDeclarationClause ")" (cvQualifier)*
+ * (exceptionSpecification)*
+ * | directDeclarator "[" (constantExpression)? "]"
+ * | "(" declarator")"
+ *
+ * declaratorId
+ * : name
+ */
+ public void declarator( Object container ) throws Exception {
+
+ boolean aborted;
+ do
+ {
+ aborted = false;
+ Object declarator = callback.declaratorBegin( container );
+
+ for (;;) {
+ try {
+ ptrOperator();
+ } catch (Backtrack b) {
+ break;
+ }
+ }
+
+ if (LT(1) == Token.tLPAREN) {
+ consume();
+ declarator(declarator);
+ consume(Token.tRPAREN);
+ return;
+ }
+
+ name();
+ callback.declaratorId(declarator);
+
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tLPAREN:
+ // parameterDeclarationClause
+ Object clause = callback.argumentsBegin(declarator);
+ consume();
+ parameterDeclarationLoop:
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tRPAREN:
+ consume();
+ break parameterDeclarationLoop;
+ case Token.tELIPSE:
+ consume();
+ break;
+ case Token.tCOMMA:
+ consume();
+ break;
+ default:
+ parameterDeclaration( clause );
+ }
+ }
+ callback.argumentsEnd(clause);
+ break;
+ case Token.tLBRACKET:
+ consume();
+ // constantExpression();
+ consume(Token.tRBRACKET);
+ continue;
+ }
+ break;
+ }
+
+ if( LA(1).getType() == Token.tIDENTIFIER )
+ {
+ callback.declaratorAbort( container, declarator );
+ declarator = null;
+ aborted = true;
+ }
+ else
+ callback.declaratorEnd(declarator);
+ } while( aborted );
+ }
+
+ /**
+ * ptrOperator
+ * : "*" (cvQualifier)*
+ * | "&"
+ * | name "*" (cvQualifier)*
+ */
+ public Object ptrOperator() throws Exception {
+ int t = LT(1);
+
+ if (t == Token.tAMPER) {
+ consume();
+ return null;
+ }
+
+ Token mark = mark();
+ if (t == Token.tIDENTIFIER || t == Token.tCOLONCOLON)
+ name();
+
+ if (t == Token.tSTAR) {
+ consume();
+
+ for (;;) {
+ try {
+ cvQualifier();
+ } catch (Backtrack b) {
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ backup(mark);
+ throw backtrack;
+ }
+
+ /**
+ * classSpecifier
+ * : classKey name (baseClause)? "{" (memberSpecification)* "}"
+ */
+ public void classSpecifier( Object owner ) throws Exception {
+ Token classKey = null;
+
+ // class key
+ switch (LT(1)) {
+ case Token.t_class:
+ case Token.t_struct:
+ case Token.t_union:
+ classKey = consume();
+ break;
+ default:
+ throw backtrack;
+ }
+
+ Object classSpec = callback.classSpecifierBegin( owner, classKey);
+
+ // class name
+ if (LT(1) == Token.tIDENTIFIER) {
+ name();
+ callback.classSpecifierName(classSpec);
+ }
+
+ //currRegion.put(name.getImage(), classKey);
+
+ // base clause
+ if (LT(1) == Token.tCOLON) {
+ consume();
+ baseSpecifier( classSpec );
+ }
+
+ // If we don't get a "{", assume elaborated type
+ if (LT(1) == Token.tLBRACE) {
+ consume();
+
+ memberDeclarationLoop:
+ while (LT(1) != Token.tRBRACE) {
+ switch (LT(1)) {
+ case Token.t_public:
+ consume();
+ consume(Token.tCOLON);
+ break;
+ case Token.t_protected:
+ consume();
+ consume(Token.tCOLON);
+ break;
+ case Token.t_private:
+ consume();
+ consume(Token.tCOLON);
+ break;
+ case Token.tRBRACE:
+ consume(Token.tRBRACE);
+ break memberDeclarationLoop;
+ default:
+ declaration(classSpec);
+ }
+ }
+ // consume the }
+ consume();
+ }
+
+ callback.classSpecifierEnd(classSpec);
+ }
+
+ public void baseSpecifier( Object classSpecOwner ) throws Exception {
+
+ Object baseSpecifier = callback.baseSpecifierBegin( classSpecOwner );
+
+ baseSpecifierLoop:
+ for (;;) {
+ switch (LT(1)) {
+ case Token.t_virtual:
+ callback.baseSpecifierVirtual( baseSpecifier, true );
+ consume();
+ break;
+ case Token.t_public:
+ case Token.t_protected:
+ case Token.t_private:
+ callback.baseSpecifierVisibility( baseSpecifier, currToken );
+ consume();
+ break;
+ case Token.tCOLONCOLON:
+ case Token.tIDENTIFIER:
+ name();
+ callback.baseSpecifierName( baseSpecifier );
+ break;
+ case Token.tCOMMA:
+ callback.baseSpecifierEnd( baseSpecifier );
+ baseSpecifier = callback.baseSpecifierBegin( classSpecOwner );
+ consume();
+ continue baseSpecifierLoop;
+ default:
+ break baseSpecifierLoop;
+ }
+ }
+ callback.baseSpecifierEnd( baseSpecifier );
+ }
+
+ public void functionBody() throws Exception {
+ compoundStatement();
+ }
+
+ // Statements
+ public void statement() throws Exception {
+ switch (LT(1)) {
+ case Token.t_case:
+ consume();
+ constantExpression();
+ consume(Token.tCOLON);
+ statement();
+ return;
+ case Token.t_default:
+ consume();
+ consume(Token.tCOLON);
+ statement();
+ return;
+ case Token.tLBRACE:
+ compoundStatement();
+ return;
+ case Token.t_if:
+ consume();
+ consume(Token.tLPAREN);
+ condition();
+ consume(Token.tRPAREN);
+ statement();
+ if (LT(1) == Token.t_else) {
+ consume();
+ statement();
+ }
+ return;
+ case Token.t_switch:
+ consume();
+ consume(Token.tLPAREN);
+ condition();
+ consume(Token.tRPAREN);
+ statement();
+ return;
+ case Token.t_while:
+ consume();
+ consume(Token.tLPAREN);
+ condition();
+ consume(Token.tRPAREN);
+ statement();
+ return;
+ case Token.t_do:
+ consume();
+ statement();
+ consume(Token.t_while);
+ consume(Token.tLPAREN);
+ condition();
+ consume(Token.tRPAREN);
+ return;
+ case Token.t_for:
+ consume();
+ consume(Token.tLPAREN);
+ forInitStatement();
+ if (LT(1) != Token.tSEMI)
+ condition();
+ consume(Token.tSEMI);
+ if (LT(1) != Token.tRPAREN)
+ expression();
+ consume(Token.tRPAREN);
+ statement();
+ return;
+ case Token.t_break:
+ consume();
+ consume(Token.tSEMI);
+ return;
+ case Token.t_continue:
+ consume();
+ consume(Token.tSEMI);
+ return;
+ case Token.t_return:
+ consume();
+ if (LT(1) != Token.tSEMI)
+ expression();
+ consume(Token.tSEMI);
+ return;
+ case Token.t_goto:
+ consume();
+ consume(Token.tIDENTIFIER);
+ consume(Token.tSEMI);
+ return;
+ case Token.t_try:
+ consume();
+ compoundStatement();
+ while (LT(1) == Token.t_catch) {
+ consume();
+ consume(Token.tLPAREN);
+ declaration(null); // was exceptionDeclaration
+ consume(Token.tRPAREN);
+ compoundStatement();
+ }
+ return;
+ case Token.tSEMI:
+ consume();
+ return;
+ default:
+ // can be many things:
+ // label
+ if (LT(1) == Token.tIDENTIFIER && LT(2) == Token.tCOLON) {
+ consume();
+ consume();
+ statement();
+ return;
+ }
+
+ // expressionStatement
+ // Note: the function style cast ambiguity is handled in expression
+ // Since it only happens when we are in a statement
+ try {
+ expression();
+ consume(Token.tSEMI);
+ return;
+ } catch (Backtrack b) {
+ }
+
+ // declarationStatement
+ declaration(null);
+ }
+ }
+
+ public void condition() throws Exception {
+ // TO DO
+ }
+
+ public void forInitStatement() throws Exception {
+ // TO DO
+ }
+
+ public void compoundStatement() throws Exception {
+ consume(Token.tLBRACE);
+ while (LT(1) != Token.tRBRACE)
+ statement();
+ consume();
+ }
+
+ // Expressions
+ public void constantExpression() throws Exception {
+ conditionalExpression();
+ }
+
+ public void expression() throws Exception {
+ assignmentExpression();
+
+ while (LT(1) == Token.tCOMMA) {
+ Token t = consume();
+ assignmentExpression();
+ callback.expressionOperator(t);
+ }
+ }
+
+ public void assignmentExpression() throws Exception {
+ if (LT(1) == Token.t_throw) {
+ throwExpression();
+ return;
+ }
+
+ // if the condition not taken, try assignment operators
+ if (!conditionalExpression()) {
+ switch (LT(1)) {
+ case Token.tASSIGN:
+ case Token.tSTARASSIGN:
+ case Token.tDIVASSIGN:
+ case Token.tMODASSIGN:
+ case Token.tPLUSASSIGN:
+ case Token.tMINUSASSIGN:
+ case Token.tSHIFTRASSIGN:
+ case Token.tSHIFTLASSIGN:
+ case Token.tAMPERASSIGN:
+ case Token.tXORASSIGN:
+ case Token.tBITORASSIGN:
+ Token t = consume();
+ conditionalExpression();
+ callback.expressionOperator(t);
+ break;
+ }
+ }
+ }
+
+ public void throwExpression() throws Exception {
+ consume(Token.t_throw);
+
+ try {
+ expression();
+ } catch (Backtrack b) {
+ }
+ }
+
+ public boolean conditionalExpression() throws Exception {
+ logicalOrExpression();
+
+ if (LT(1) == Token.tQUESTION) {
+ consume();
+ expression();
+ consume(Token.tCOLON);
+ assignmentExpression();
+ return true;
+ } else
+ return false;
+ }
+
+ public void logicalOrExpression() throws Exception {
+ logicalAndExpression();
+
+ while (LT(1) == Token.tOR) {
+ Token t = consume();
+ logicalAndExpression();
+ callback.expressionOperator(t);
+ }
+ }
+
+ public void logicalAndExpression() throws Exception {
+ inclusiveOrExpression();
+
+ while (LT(1) == Token.tAND) {
+ Token t = consume();
+ inclusiveOrExpression();
+ callback.expressionOperator(t);
+ }
+ }
+
+ public void inclusiveOrExpression() throws Exception {
+ exclusiveOrExpression();
+
+ while (LT(1) == Token.tBITOR) {
+ Token t = consume();
+ exclusiveOrExpression();
+ callback.expressionOperator(t);
+ }
+ }
+
+ public void exclusiveOrExpression() throws Exception {
+ andExpression();
+
+ while (LT(1) == Token.tXOR) {
+ Token t = consume();
+ andExpression();
+ callback.expressionOperator(t);
+ }
+ }
+
+ public void andExpression() throws Exception {
+ equalityExpression();
+
+ while (LT(1) == Token.tAMPER) {
+ Token t = consume();
+ equalityExpression();
+ callback.expressionOperator(t);
+ }
+ }
+
+ public void equalityExpression() throws Exception {
+ relationalExpression();
+
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tEQUAL:
+ case Token.tNOTEQUAL:
+ Token t = consume();
+ relationalExpression();
+ callback.expressionOperator(t);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+ public void relationalExpression() throws Exception {
+ shiftExpression();
+
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tGT:
+ // For template args, the GT means end of args
+ //if (templateArgs)
+ // return;
+ case Token.tLT:
+ case Token.tLTEQUAL:
+ case Token.tGTEQUAL:
+ Token t = consume();
+ shiftExpression();
+ callback.expressionOperator(t);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+ public void shiftExpression() throws Exception {
+ additiveExpression();
+
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tSHIFTL:
+ case Token.tSHIFTR:
+ Token t = consume();
+ additiveExpression();
+ callback.expressionOperator(t);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+ public void additiveExpression() throws Exception {
+ multiplicativeExpression();
+
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tPLUS:
+ case Token.tMINUS:
+ Token t = consume();
+ multiplicativeExpression();
+ callback.expressionOperator(t);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+ public void multiplicativeExpression() throws Exception {
+ pmExpression();
+
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tSTAR:
+ case Token.tDIV:
+ case Token.tMOD:
+ Token t = consume();
+ pmExpression();
+ callback.expressionOperator(t);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+ public void pmExpression() throws Exception {
+ castExpression();
+
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tDOTSTAR:
+ case Token.tARROWSTAR:
+ Token t = consume();
+ castExpression();
+ callback.expressionOperator(t);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+ /**
+ * castExpression
+ * : unaryExpression
+ * | "(" typeId ")" castExpression
+ */
+ public void castExpression() throws Exception {
+ // TO DO: we need proper symbol checkint to ensure type name
+ if (false && LT(1) == Token.tLPAREN) {
+ Token mark = mark();
+ consume();
+
+ // If this isn't a type name, then we shouldn't be here
+ try {
+ typeId();
+ consume(Token.tRPAREN);
+ castExpression();
+ return;
+ } catch (Backtrack b) {
+ backup(mark);
+ }
+ }
+
+ unaryExpression();
+ }
+
+ public void typeId() throws Exception {
+ try {
+ name();
+ return;
+ } catch (Backtrack b) {
+ }
+ }
+
+ public void deleteExpression() throws Exception {
+ if (LT(1) == Token.tCOLONCOLON) {
+ // global scope
+ consume();
+ }
+
+ consume(Token.t_delete);
+
+ if (LT(1) == Token.tLBRACKET) {
+ // array delete
+ consume();
+ consume(Token.tRBRACKET);
+ }
+
+ castExpression();
+ }
+
+ public void newExpression() throws Exception {
+ if (LT(1) == Token.tCOLONCOLON) {
+ // global scope
+ consume();
+ }
+
+ consume (Token.t_new);
+
+ // TO DO: finish this horrible mess...
+ }
+
+ public void unaryExpression() throws Exception {
+ switch (LT(1)) {
+ case Token.tSTAR:
+ case Token.tAMPER:
+ case Token.tPLUS:
+ case Token.tMINUS:
+ case Token.tNOT:
+ case Token.tCOMPL:
+ case Token.tINCR:
+ case Token.tDECR:
+ Token t = consume();
+ castExpression();
+ callback.expressionOperator(t);
+ return;
+ case Token.t_sizeof:
+ if (LT(1) == Token.tLPAREN) {
+ consume();
+ typeId();
+ consume(Token.tRPAREN);
+ } else {
+ unaryExpression();
+ }
+ return;
+ case Token.t_new:
+ newExpression();
+ return;
+ case Token.t_delete:
+ deleteExpression();
+ return;
+ case Token.tCOLONCOLON:
+ switch (LT(2)) {
+ case Token.t_new:
+ newExpression();
+ return;
+ case Token.t_delete:
+ deleteExpression();
+ return;
+ default:
+ postfixExpression();
+ return;
+ }
+ default:
+ postfixExpression();
+ return;
+ }
+ }
+
+ public void postfixExpression() throws Exception {
+ switch (LT(1)) {
+ case Token.t_typename:
+ consume();
+ // TO DO: this
+ break;
+ case Token.t_dynamic_cast:
+ case Token.t_static_cast:
+ case Token.t_reinterpret_cast:
+ case Token.t_const_cast:
+ consume();
+ consume(Token.tLT);
+ typeId();
+ consume(Token.tGT);
+ consume(Token.tLPAREN);
+ expression();
+ consume(Token.tRPAREN);
+ break;
+ case Token.t_typeid:
+ consume();
+ consume(Token.tLPAREN);
+ try {
+ typeId();
+ } catch (Backtrack b) {
+ expression();
+ }
+ consume(Token.tRPAREN);
+ break;
+ default:
+ // TO DO: try simpleTypeSpecifier "(" expressionList ")"
+ primaryExpression();
+ }
+
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tLBRACKET:
+ // array access
+ consume();
+ expression();
+ consume(Token.tRBRACKET);
+ break;
+ case Token.tLPAREN:
+ // function call
+ consume();
+ // Note: since expressionList and expression are the same...
+ expression();
+ consume(Token.tRPAREN);
+ break;
+ case Token.tINCR:
+ case Token.tDECR:
+ // post incr/decr
+ consume();
+ break;
+ case Token.tDOT:
+ case Token.tARROW:
+ // member access
+ consume();
+ // TO DO: handle this
+ //varName();
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+ public void primaryExpression() throws Exception {
+ switch (LT(1)) {
+ // TO DO: we need more literals...
+ case Token.tINTEGER:
+ callback.expressionTerminal(consume());
+ return;
+ case Token.tSTRING:
+ callback.expressionTerminal(consume());
+ return;
+ case Token.t_this:
+ consume();
+ return;
+ case Token.tLPAREN:
+ consume();
+ expression();
+ consume(Token.tRPAREN);
+ return;
+ default:
+ // TO DO: idExpression which yeilds a variable
+ //idExpression();
+ return;
+ }
+ }
+
+ public void varName() throws Exception {
+ if (LT(1) == Token.tCOLONCOLON)
+ consume();
+
+ for (;;) {
+ switch (LT(1)) {
+ case Token.tIDENTIFIER:
+ consume();
+ //if (isTemplateArgs()) {
+ // rTemplateArgs();
+ //}
+
+ if (LT(1) == Token.tCOLONCOLON) {
+ switch (LT(2)) {
+ case Token.tIDENTIFIER:
+ case Token.tCOMPL:
+ case Token.t_operator:
+ consume();
+ break;
+ default:
+ return;
+ }
+ } else
+ return;
+ break;
+ case Token.tCOMPL:
+ consume();
+ consume(Token.tIDENTIFIER);
+ return;
+ case Token.t_operator:
+ consume();
+ //rOperatorName();
+ return;
+ default:
+ throw backtrack;
+ }
+ }
+ }
+
+ // Backtracking
+ private static class Backtrack extends Exception {
+ }
+
+ private static Backtrack backtrack = new Backtrack();
+
+ // Token management
+ private IScanner scanner;
+ private Token currToken;
+
+ private Token fetchToken() {
+ try {
+ return scanner.nextToken();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ protected Token LA(int i) {
+ if (i < 1)
+ // can't go backwards
+ return null;
+
+ if (currToken == null)
+ currToken = fetchToken();
+
+ Token retToken = currToken;
+
+ for (; i > 1; --i) {
+ if (retToken.getNext() == null)
+ fetchToken();
+ retToken = retToken.getNext();
+ }
+
+ return retToken;
+ }
+
+ protected int LT(int i) {
+ return LA(i).type;
+ }
+
+ protected Token consume() {
+ if (currToken.getNext() == null)
+ fetchToken();
+ Token retToken = currToken;
+ currToken = currToken.getNext();
+ return retToken;
+ }
+
+ protected Token consume(int type) throws Exception {
+ if (LT(1) == type)
+ return consume();
+ else
+ throw backtrack;
+ }
+
+ protected Token mark() {
+ return currToken;
+ }
+
+ protected void backup(Token mark) {
+ currToken = mark;
+ }
+
+ // Utility routines that require a knowledge of the grammar
+ public static String generateName(Token startToken) throws Exception {
+ Token currToken = startToken.getNext();
+
+ if (currToken == null || currToken.getType() != Token.tCOLONCOLON)
+ return startToken.getImage();
+
+ StringBuffer buff = new StringBuffer(startToken.getImage());
+ while (currToken != null && currToken.getType() == Token.tCOLONCOLON) {
+ currToken = currToken.getNext();
+ if (currToken == null || currToken.getType() != Token.tIDENTIFIER)
+ // Not good
+ throw new ParserException(startToken);
+ buff.append("::");
+ buff.append(currToken.getImage());
+ currToken = currToken.getNext();
+ }
+
+ return buff.toString();
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserException.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserException.java
new file mode 100644
index 00000000000..90246f0a00d
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserException.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.parser;
+
+public class ParserException extends Exception {
+
+ public ParserException(Token t) {
+ }
+
+ public ParserException( String msg )
+ {
+ super( msg );
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java
new file mode 100644
index 00000000000..3f4f5ab35f7
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java
@@ -0,0 +1,55 @@
+package org.eclipse.cdt.internal.core.parser;
+
+import java.util.Stack;
+/**
+ * @author aniefer
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ParserSymbolTable {
+
+ /**
+ * Constructor for ParserSymbolTable.
+ */
+ public ParserSymbolTable() {
+ super();
+ _compilationUnit = new Declaration();
+ push( _compilationUnit );
+ }
+
+ public void push( Declaration obj ){
+ if( _contextStack.empty() == false )
+ obj.setContainingScope( (Declaration) _contextStack.peek() );
+ _contextStack.push( obj );
+ }
+
+ public Declaration pop(){
+ return (Declaration) _contextStack.pop();
+ }
+
+ public Declaration peek(){
+ return (Declaration) _contextStack.peek();
+ }
+
+ public Declaration Lookup( String name ) throws ParserSymbolTableException {
+ return ( (Declaration) _contextStack.peek() ).Lookup( -1, name );
+ }
+
+ public Declaration ElaboratedLookup( int type, String name ) throws ParserSymbolTableException{
+ return ( (Declaration) _contextStack.peek() ).Lookup( type, name );
+ }
+
+ public void addDeclaration( Declaration obj ){
+ ((Declaration) _contextStack.peek() ).addDeclaration( obj );
+ }
+
+ public Declaration getCompilationUnit(){
+ return _compilationUnit;
+ }
+
+ private Stack _contextStack = new Stack();
+ private Declaration _compilationUnit;
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java
new file mode 100644
index 00000000000..b031325bced
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java
@@ -0,0 +1,33 @@
+package org.eclipse.cdt.internal.core.parser;
+
+/**
+ * @author aniefer
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ParserSymbolTableException extends Exception {
+
+ /**
+ * Constructor for ParserSymbolTableException.
+ */
+ public ParserSymbolTableException() {
+ super();
+ }
+
+ /**
+ * Constructor for ParserSymbolTableException.
+ * @param int r: reason
+ */
+ public ParserSymbolTableException( int r ) {
+ reason = r;
+ }
+
+ public static final int r_Unspecified = -1;
+ public static final int r_AmbiguousName = 0;
+ public static final int r_BadTypeInfo = 1;
+
+ public int reason = -1;
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java
new file mode 100644
index 00000000000..ee57683c4ed
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java
@@ -0,0 +1,1433 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.parser;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+
+public class Scanner implements IScanner {
+
+ public IScanner initialize(Reader reader, String filename) {
+ init(reader, filename);
+ return this;
+ }
+
+ protected void init(Reader reader, String filename) {
+ // this is a hack to get around a sudden EOF experience
+ contextStack.push(
+ new ScannerContext().initialize(
+ new StringReader("\n"),
+ START,
+ NOCHAR));
+ if (filename == null)
+ currentContext =
+ new ScannerContext().initialize(reader, TEXT, NOCHAR);
+ else
+ currentContext =
+ new ScannerContext().initialize(reader, filename, NOCHAR);
+ }
+
+ public Scanner() {
+ }
+
+ protected Scanner(Reader reader, String filename, Hashtable defns) {
+ initialize(reader, filename);
+ definitions = defns;
+ }
+
+ protected void updateContext(Reader reader, String filename) {
+// if (callback != null)
+// callback.inclusionBegin(filename); // not quite right ... fix me!!!
+
+ contextStack.push(currentContext);
+ currentContext =
+ new ScannerContext().initialize(reader, filename, NOCHAR);
+ }
+
+ protected boolean rollbackContext() {
+ try {
+ currentContext.getReader().close();
+ } catch (IOException ie) {
+ System.out.println("Error closing reader");
+ }
+
+ if (contextStack.isEmpty()) {
+ currentContext = null;
+ return false;
+ }
+
+ //if (callback != null)
+ // callback.inclusionEnd();
+
+ currentContext = (ScannerContext) contextStack.pop();
+ return true;
+ }
+
+ public void addIncludePath(String includePath) {
+ includePaths.add(includePath);
+ }
+
+ public void overwriteIncludePath(List newIncludePaths) {
+ includePaths = null;
+ includePaths = new ArrayList();
+ includePaths.addAll(newIncludePaths);
+ }
+
+ public void addDefinition(String key, IMacroDescriptor macro) {
+ definitions.put(key, macro);
+ }
+
+ public void addDefinition(String key, String value) {
+ definitions.put(key, value);
+ }
+
+ public final Object getDefinition(String key) {
+ return definitions.get(key);
+ }
+
+ public final Object[] getIncludePaths() {
+ return includePaths.toArray();
+ }
+
+ protected void skipOverWhitespace() {
+ int c = getChar();
+ while ((c != NOCHAR) && ((c == ' ') || (c == '\t')))
+ c = getChar();
+ if (c != NOCHAR)
+ ungetChar(c);
+
+ }
+
+ protected String getRestOfPreprocessorLine() throws ScannerException {
+ StringBuffer buffer = new StringBuffer();
+ skipOverWhitespace();
+ int c = getChar();
+
+ while (true) {
+ while ((c != '\n')
+ && (c != '\r')
+ && (c != '\\')
+ && (c != '/')
+ && (c != NOCHAR)) {
+ buffer.append((char) c);
+ c = getChar();
+ }
+ if (c == '/') {
+ // we need to peek ahead at the next character to see if
+ // this is a comment or not
+ int next = getChar();
+ if (next == '/') {
+ // single line comment
+ skipOverTextUntilNewline();
+ break;
+ } else if (next == '*') {
+ // multiline comment
+ if (skipOverMultilineComment())
+ break;
+ else
+ c = getChar();
+ continue;
+ } else {
+ // we are not in a comment
+ buffer.append((char) c);
+ c = next;
+ continue;
+ }
+ } else {
+ if (c != '\\') {
+ ungetChar(c);
+ } else {
+ c = getChar();
+ }
+ break;
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ protected void skipOverTextUntilNewline() {
+ for (;;) {
+ switch (getChar()) {
+ case NOCHAR :
+ case '\n' :
+ return;
+ case '\\' :
+ getChar();
+ }
+ }
+ }
+
+ private void setCurrentToken(Token t) {
+ if (currentToken != null)
+ currentToken.setNext(t);
+ currentToken = t;
+ }
+
+ protected Token newToken(int t, String i, IScannerContext c) {
+ setCurrentToken(new Token(t, i, c));
+ return currentToken;
+ }
+
+ protected Token newToken(int t, String i) {
+ setCurrentToken(new Token(t, i));
+ return currentToken;
+ }
+
+ protected String getNextIdentifier() {
+ StringBuffer buffer = new StringBuffer();
+ skipOverWhitespace();
+ int c = getChar();
+
+ if (((c >= 'a') && (c <= 'z'))
+ || ((c >= 'A') && (c <= 'Z')) | (c == '_')) {
+ buffer.append((char) c);
+
+ c = getChar();
+ while (((c >= 'a') && (c <= 'z'))
+ || ((c >= 'A') && (c <= 'Z'))
+ || ((c >= '0') && (c <= '9'))
+ || (c == '_')) {
+ buffer.append((char) c);
+ c = getChar();
+ }
+ }
+ ungetChar(c);
+
+ return buffer.toString();
+ }
+
+ protected void handleInclusion(String fileName) throws ScannerException {
+ // Skip over inclusions in quickScan mode
+ if (quickScan)
+ return;
+
+ // iterate through the include paths
+ Iterator iter = includePaths.iterator();
+
+ while (iter.hasNext()) {
+ String path = (String) iter.next();
+
+ java.io.File pathFile = new java.io.File(path);
+ if (pathFile.isDirectory()) {
+ String newPath = pathFile + "\\" + fileName;
+
+ java.io.File includeFile = new java.io.File(newPath);
+
+ if (includeFile.exists() && includeFile.isFile()) {
+ try {
+ FileReader inclusionReader =
+ new FileReader(includeFile);
+ //System.out.println( "Parsing inclusion file " + newPath );
+ updateContext(inclusionReader, newPath);
+ return;
+ } catch (FileNotFoundException fnf) {
+ // do nothing
+ }
+ }
+ }
+ }
+ if (throwExceptionOnInclusionNotFound)
+ throw new ScannerException("Cannot find inclusion " + fileName);
+ }
+
+ // constants
+ public static final int NOCHAR = -1;
+
+ private static final String TEXT = "";
+ private static final String START = "";
+ private static final String EXPRESSION = "";
+ private static final String BAD_PP =
+ "Invalid preprocessor directive encountered at offset ";
+ private static final String DEFINED = "defined";
+ private static final String POUND_DEFINE = "#define ";
+
+ private IScannerContext currentContext;
+ private Stack contextStack = new Stack();
+
+ private List includePaths = new ArrayList();
+ private Hashtable definitions = new Hashtable();
+ private int count = 0;
+ private static HashMap keywords = new HashMap();
+ private static HashMap ppDirectives = new HashMap();
+
+ private Token currentToken = null;
+
+ private boolean passOnToClient = true;
+ private BranchTracker branches = new BranchTracker();
+
+ // these are scanner configuration aspects that we perhaps want to tweak
+ // eventually, these should be configurable by the client, but for now
+ // we can just leave it internal
+ private boolean throwExceptionPPError = true;
+ private boolean throwExceptionOnRedefinition = false;
+ private boolean throwExceptionOnBadPPDirective = true;
+ private boolean throwExceptionOnInclusionNotFound = true;
+ private boolean throwExceptionOnBadMacroExpansion = true;
+ private boolean throwExceptionOnUnboundedString = true;
+ private boolean throwExceptionOnEOFWithinMultilineComment = true;
+ private boolean throwExceptionOnEOFWithoutBalancedEndifs = true;
+ private boolean providedDefinedMacro = true;
+
+ private boolean quickScan = false;
+ public void setQuickScan(boolean qs) {
+ quickScan = qs;
+ }
+
+ private IParserCallback callback;
+ public void setCallback(IParserCallback c) {
+ callback = c;
+ }
+
+ private int getChar() {
+ int c = NOCHAR;
+
+ boolean done;
+ do {
+ done = true;
+
+ if (currentContext.getUndo() != NOCHAR) {
+ c = currentContext.getUndo();
+ currentContext.setUndo(NOCHAR);
+ } else {
+ try {
+ c = currentContext.read();
+ if (c == NOCHAR) {
+ if (rollbackContext() == false) {
+ c = NOCHAR;
+ break;
+ } else {
+ done = false;
+ }
+ }
+ } catch (IOException e) {
+ if (rollbackContext() == false) {
+ c = NOCHAR;
+ } else {
+ done = false;
+ }
+ }
+ }
+ } while (!done);
+
+ if (c == '\\') {
+ c = getChar();
+ if (c == '\r') {
+ c = getChar();
+ if (c == '\n')
+ c = getChar();
+ } else if (c == '\n')
+ c = getChar();
+ }
+
+ return c;
+ }
+
+ private void ungetChar(int c) {
+ // Should really check whether there already is a char there
+ // If so, we should be using a buffer, instead of a single char
+ currentContext.setUndo(c);
+ }
+
+ public Token nextToken() throws ScannerException {
+
+ count++;
+
+ int c = getChar();
+
+ while (c != NOCHAR) {
+ if ( ! passOnToClient ) {
+ while (c != '#') {
+ c = getChar();
+ }
+ }
+
+ if ((c == ' ') || (c == '\r') || (c == '\t') || (c == '\n')) {
+ c = getChar();
+ continue;
+ } else if (
+ ((c >= 'a') && (c <= 'z'))
+ || ((c >= 'A') && (c <= 'Z')) | (c == '_')) {
+ // String buffer is slow, we need a better way such as memory mapped files
+ StringBuffer buff = new StringBuffer();
+ buff.append((char) c);
+
+ c = getChar();
+ while (((c >= 'a') && (c <= 'z'))
+ || ((c >= 'A') && (c <= 'Z'))
+ || ((c >= '0') && (c <= '9'))
+ || (c == '_')) {
+ buff.append((char) c);
+ c = getChar();
+ }
+
+ ungetChar(c);
+
+ String ident = buff.toString();
+
+ if (providedDefinedMacro) {
+ if (ident.equals(DEFINED)) {
+ return newToken(Token.tINTEGER, handleDefinedMacro());
+ }
+ }
+
+ Object mapping = definitions.get(ident);
+
+ if (mapping != null) {
+ expandDefinition(ident, mapping);
+ c = getChar();
+ continue;
+ }
+
+ Object tokenTypeObject = keywords.get(ident);
+ int tokenType = Token.tIDENTIFIER;
+ if (tokenTypeObject != null)
+ tokenType = ((Integer) tokenTypeObject).intValue();
+
+ return newToken(tokenType, ident, currentContext);
+ } else if (c == '"') {
+ // string
+ StringBuffer buff = new StringBuffer();
+ c = getChar();
+
+ while (c != '"' && c != '\n') {
+ buff.append((char) c);
+ c = getChar();
+ }
+
+ if (c != '\n') {
+ return newToken(
+ Token.tSTRING,
+ buff.toString(),
+ currentContext);
+ } else {
+ if (throwExceptionOnUnboundedString)
+ throw new ScannerException(
+ "Unbounded string found at offset "
+ + currentContext.getOffset());
+ }
+
+ } else if ((c >= '0') && (c <= '9')) {
+ StringBuffer buff = new StringBuffer();
+ buff.append((char) c);
+
+ c = getChar();
+ boolean hex = false;
+ if (c == 'x') {
+ hex = true;
+ c = getChar();
+ }
+
+ while ((c >= '0' && c <= '9')
+ || (hex
+ && ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')))) {
+ buff.append((char) c);
+ c = getChar();
+ }
+
+ ungetChar(c);
+ return newToken(
+ Token.tINTEGER,
+ buff.toString(),
+ currentContext);
+ } else if (c == '#') {
+ // lets prepare for a preprocessor statement
+ StringBuffer buff = new StringBuffer();
+ buff.append((char) c);
+
+ // we are allowed arbitrary whitespace after the '#' and before the rest of the text
+ skipOverWhitespace();
+
+ c = getChar();
+ while (((c >= 'a') && (c <= 'z'))
+ || ((c >= 'A') && (c <= 'Z')) | (c == '_')) {
+ buff.append((char) c);
+ c = getChar();
+ }
+ ungetChar(c);
+
+ String token = buff.toString();
+
+ Object directive = ppDirectives.get(token);
+ if (directive == null) {
+ if (throwExceptionOnBadPPDirective)
+ throw new ScannerException(
+ BAD_PP + currentContext.getOffset());
+
+ } else {
+ int type = ((Integer) directive).intValue();
+ switch (type) {
+ case PreprocessorDirectives.DEFINE :
+ if ( ! passOnToClient ) {
+ skipOverTextUntilNewline();
+ c = getChar();
+ continue;
+ }
+
+ poundDefine();
+
+ c = getChar();
+ continue;
+
+ case PreprocessorDirectives.INCLUDE :
+ if (! passOnToClient ) {
+ skipOverTextUntilNewline();
+ c = getChar();
+ continue;
+ }
+
+ poundInclude();
+
+ c = getChar();
+ continue;
+ case PreprocessorDirectives.UNDEFINE :
+ if (! passOnToClient) {
+ skipOverTextUntilNewline();
+ c = getChar();
+ continue;
+ }
+ skipOverWhitespace();
+ // definition
+ String toBeUndefined = getNextIdentifier();
+ // TODO -- Should we throw an exception if we
+ // do not have this in our table?
+ definitions.remove(toBeUndefined);
+ skipOverTextUntilNewline();
+ c = getChar();
+ continue;
+ case PreprocessorDirectives.IF :
+ // get the rest of the line
+ String expression = getRestOfPreprocessorLine();
+
+ boolean expressionEvalResult =
+ evaluateExpression(expression);
+
+ passOnToClient = branches.poundif( expressionEvalResult );
+ c = getChar();
+ continue;
+
+ case PreprocessorDirectives.IFDEF :
+ skipOverWhitespace();
+ String definition = getNextIdentifier();
+ Object mapping = definitions.get(definition);
+
+ if (mapping == null) {
+ // not defined
+ passOnToClient = branches.poundif( false );
+ skipOverTextUntilNewline();
+ } else {
+ passOnToClient = branches.poundif( true );
+ // continue along, act like nothing is wrong :-)
+ c = getChar();
+ }
+ continue;
+ case PreprocessorDirectives.ENDIF :
+ // TODO - make sure there is nothing after endif
+
+ passOnToClient = branches.poundendif();
+ c = getChar();
+ continue;
+
+ case PreprocessorDirectives.IFNDEF :
+ skipOverWhitespace();
+ String def = getNextIdentifier();
+ Object map = definitions.get(def);
+
+ if (map != null) {
+ // not defined
+ skipOverTextUntilNewline();
+ passOnToClient = branches.poundif( false );
+ } else {
+ passOnToClient = branches.poundif( true );
+ // continue along, act like nothing is wrong :-)
+ c = getChar();
+ }
+ continue;
+
+ case PreprocessorDirectives.ELSE :
+ passOnToClient = branches.poundelse();
+
+ skipOverTextUntilNewline();
+ c = getChar();
+ continue;
+
+ case PreprocessorDirectives.ELIF :
+
+ String elsifExpression = getRestOfPreprocessorLine();
+
+ if (elsifExpression.equals(""))
+ if (throwExceptionOnBadPPDirective)
+ throw new ScannerException("Malformed #elsif clause");
+
+ boolean elsifResult =
+ evaluateExpression(elsifExpression);
+
+ passOnToClient = branches.poundelif( elsifResult );
+ c = getChar();
+ continue;
+
+ case PreprocessorDirectives.LINE :
+ //TO DO
+ skipOverTextUntilNewline();
+ c = getChar();
+ continue;
+ case PreprocessorDirectives.ERROR :
+ if (! passOnToClient) {
+ skipOverTextUntilNewline();
+ c = getChar();
+ continue;
+ }
+
+ String error = getRestOfPreprocessorLine();
+
+ if (throwExceptionPPError) {
+ throw new ScannerException("#error " + error);
+ }
+ c = getChar();
+ continue;
+ case PreprocessorDirectives.PRAGMA :
+ //TO DO
+ skipOverTextUntilNewline();
+ c = getChar();
+ continue;
+ case PreprocessorDirectives.BLANK :
+ String remainderOfLine =
+ getRestOfPreprocessorLine().trim();
+ if (!remainderOfLine.equals("")) {
+ if (throwExceptionOnBadPPDirective)
+ throw new ScannerException(
+ BAD_PP + currentContext.getOffset());
+ }
+
+ c = getChar();
+ continue;
+ default :
+ if (throwExceptionOnBadPPDirective)
+ throw new ScannerException(
+ BAD_PP + currentContext.getOffset());
+
+ }
+ }
+ } else {
+ switch (c) {
+ case ':' :
+ c = getChar();
+ switch (c) {
+ case ':' :
+ return newToken(
+ Token.tCOLONCOLON,
+ "::",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tCOLON,
+ ":",
+ currentContext);
+ }
+ case ';' :
+ return newToken(Token.tSEMI, ";", currentContext);
+ case ',' :
+ return newToken(Token.tCOMMA, ",", currentContext);
+ case '?' :
+ return newToken(Token.tQUESTION, "?", currentContext);
+ case '(' :
+ return newToken(Token.tLPAREN, "(", currentContext);
+ case ')' :
+ return newToken(Token.tRPAREN, ")", currentContext);
+ case '[' :
+ return newToken(Token.tLBRACKET, "[", currentContext);
+ case ']' :
+ return newToken(Token.tRBRACKET, "]", currentContext);
+ case '{' :
+ return newToken(Token.tLBRACE, "{", currentContext);
+ case '}' :
+ return newToken(Token.tRBRACE, "}", currentContext);
+ case '+' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tPLUSASSIGN,
+ "+=",
+ currentContext);
+ case '+' :
+ return newToken(
+ Token.tINCR,
+ "++",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tPLUS,
+ "+",
+ currentContext);
+ }
+ case '-' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tMINUSASSIGN,
+ "-=",
+ currentContext);
+ case '-' :
+ return newToken(
+ Token.tDECR,
+ "--",
+ currentContext);
+ case '>' :
+ c = getChar();
+ switch (c) {
+ case '*' :
+ return newToken(
+ Token.tARROWSTAR,
+ "->*",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tARROW,
+ "->",
+ currentContext);
+ }
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tMINUS,
+ "-",
+ currentContext);
+ }
+ case '*' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tSTARASSIGN,
+ "*=",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tSTAR,
+ "*",
+ currentContext);
+ }
+ case '%' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tMODASSIGN,
+ "%=",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tMOD,
+ "%",
+ currentContext);
+ }
+ case '^' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tXORASSIGN,
+ "^=",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tXOR,
+ "^",
+ currentContext);
+ }
+ case '&' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tAMPERASSIGN,
+ "&=",
+ currentContext);
+ case '&' :
+ return newToken(
+ Token.tAND,
+ "&&",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tAMPER,
+ "&",
+ currentContext);
+ }
+ case '|' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tBITORASSIGN,
+ "|=",
+ currentContext);
+ case '|' :
+ return newToken(
+ Token.tOR,
+ "||",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tBITOR,
+ "|",
+ currentContext);
+ }
+ case '~' :
+ return newToken(Token.tCOMPL, "~", currentContext);
+ case '!' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tNOTEQUAL,
+ "!=",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tNOT,
+ "!",
+ currentContext);
+ }
+ case '=' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tEQUAL,
+ "==",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tASSIGN,
+ "=",
+ currentContext);
+ }
+ case '<' :
+ c = getChar();
+ switch (c) {
+ case '<' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tSHIFTLASSIGN,
+ "<<=",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tSHIFTL,
+ "<<",
+ currentContext);
+ }
+ case '=' :
+ return newToken(
+ Token.tLTEQUAL,
+ "<=",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(Token.tLT, "<", currentContext);
+ }
+ case '>' :
+ c = getChar();
+ switch (c) {
+ case '>' :
+ c = getChar();
+ switch (c) {
+ case '=' :
+ return newToken(
+ Token.tSHIFTRASSIGN,
+ ">>=",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tSHIFTR,
+ ">>",
+ currentContext);
+ }
+ case '=' :
+ return newToken(
+ Token.tGTEQUAL,
+ ">=",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(Token.tGT, ">", currentContext);
+ }
+ case '.' :
+ c = getChar();
+ switch (c) {
+ case '.' :
+ c = getChar();
+ switch (c) {
+ case '.' :
+ return newToken(
+ Token.tELIPSE,
+ "...",
+ currentContext);
+ default :
+ break;
+ }
+ break;
+ case '*' :
+ return newToken(
+ Token.tDOTSTAR,
+ ".*",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tDOT,
+ ".",
+ currentContext);
+ }
+ break;
+ case '/' :
+ c = getChar();
+ switch (c) {
+ case '/' :
+ c = getChar();
+ while (c != '\n' && c != NOCHAR)
+ c = getChar();
+ continue;
+ case '*' :
+ skipOverMultilineComment();
+ c = getChar();
+ continue;
+ case '=' :
+ return newToken(
+ Token.tDIVASSIGN,
+ "/=",
+ currentContext);
+ default :
+ ungetChar(c);
+ return newToken(
+ Token.tDIV,
+ "/",
+ currentContext);
+ }
+ default :
+ break;
+ }
+
+ return newToken(
+ Token.tEOF,
+ "Bad Char: " + (char) c,
+ currentContext);
+ }
+ }
+
+ if (throwExceptionOnEOFWithoutBalancedEndifs && (getDepth() != 0))
+ throw new ScannerException("End of file encountered without terminating #endif");
+
+ // we're done
+ if (currentToken != null)
+ currentToken.setNext(Token.EOF);
+ return Token.EOF;
+ }
+
+ static {
+ keywords.put("and", new Integer(Token.t_and));
+ keywords.put("and_eq", new Integer(Token.t_and_eq));
+ keywords.put("asm", new Integer(Token.t_asm));
+ keywords.put("auto", new Integer(Token.t_auto));
+ keywords.put("bitand", new Integer(Token.t_bitand));
+ keywords.put("bitor", new Integer(Token.t_bitor));
+ keywords.put("bool", new Integer(Token.t_bool));
+ keywords.put("break", new Integer(Token.t_break));
+ keywords.put("case", new Integer(Token.t_case));
+ keywords.put("catch", new Integer(Token.t_catch));
+ keywords.put("char", new Integer(Token.t_char));
+ keywords.put("class", new Integer(Token.t_class));
+ keywords.put("compl", new Integer(Token.t_compl));
+ keywords.put("const", new Integer(Token.t_const));
+ keywords.put("const_cast", new Integer(Token.t_const_cast));
+ keywords.put("continue", new Integer(Token.t_continue));
+ keywords.put("default", new Integer(Token.t_default));
+ keywords.put("delete", new Integer(Token.t_delete));
+ keywords.put("do", new Integer(Token.t_do));
+ keywords.put("double", new Integer(Token.t_double));
+ keywords.put("dynamic_cast", new Integer(Token.t_dynamic_cast));
+ keywords.put("else", new Integer(Token.t_else));
+ keywords.put("enum", new Integer(Token.t_enum));
+ keywords.put("explicit", new Integer(Token.t_explicit));
+ keywords.put("export", new Integer(Token.t_export));
+ keywords.put("extern", new Integer(Token.t_extern));
+ keywords.put("false", new Integer(Token.t_false));
+ keywords.put("float", new Integer(Token.t_float));
+ keywords.put("for", new Integer(Token.t_for));
+ keywords.put("friend", new Integer(Token.t_friend));
+ keywords.put("goto", new Integer(Token.t_goto));
+ keywords.put("if", new Integer(Token.t_if));
+ keywords.put("inline", new Integer(Token.t_inline));
+ keywords.put("int", new Integer(Token.t_int));
+ keywords.put("long", new Integer(Token.t_long));
+ keywords.put("mutable", new Integer(Token.t_mutable));
+ keywords.put("namespace", new Integer(Token.t_namespace));
+ keywords.put("new", new Integer(Token.t_new));
+ keywords.put("not", new Integer(Token.t_not));
+ keywords.put("not_eq", new Integer(Token.t_not_eq));
+ keywords.put("operator", new Integer(Token.t_operator));
+ keywords.put("or", new Integer(Token.t_or));
+ keywords.put("or_eq", new Integer(Token.t_or_eq));
+ keywords.put("private", new Integer(Token.t_private));
+ keywords.put("protected", new Integer(Token.t_protected));
+ keywords.put("public", new Integer(Token.t_public));
+ keywords.put("register", new Integer(Token.t_register));
+ keywords.put("reinterpret_cast", new Integer(Token.t_reinterpret_cast));
+ keywords.put("return", new Integer(Token.t_return));
+ keywords.put("short", new Integer(Token.t_short));
+ keywords.put("signed", new Integer(Token.t_signed));
+ keywords.put("sizeof", new Integer(Token.t_sizeof));
+ keywords.put("static", new Integer(Token.t_static));
+ keywords.put("static_cast", new Integer(Token.t_static_cast));
+ keywords.put("struct", new Integer(Token.t_struct));
+ keywords.put("switch", new Integer(Token.t_switch));
+ keywords.put("template", new Integer(Token.t_template));
+ keywords.put("this", new Integer(Token.t_this));
+ keywords.put("throw", new Integer(Token.t_throw));
+ keywords.put("true", new Integer(Token.t_true));
+ keywords.put("try", new Integer(Token.t_try));
+ keywords.put("typedef", new Integer(Token.t_typedef));
+ keywords.put("typeid", new Integer(Token.t_typeid));
+ keywords.put("typename", new Integer(Token.t_typename));
+ keywords.put("union", new Integer(Token.t_union));
+ keywords.put("unsigned", new Integer(Token.t_unsigned));
+ keywords.put("using", new Integer(Token.t_using));
+ keywords.put("virtual", new Integer(Token.t_virtual));
+ keywords.put("void", new Integer(Token.t_void));
+ keywords.put("volatile", new Integer(Token.t_volatile));
+ keywords.put("wchar_t", new Integer(Token.t_wchar_t));
+ keywords.put("while", new Integer(Token.t_while));
+ keywords.put("xor", new Integer(Token.t_xor));
+ keywords.put("xor_eq", new Integer(Token.t_xor_eq));
+
+ ppDirectives.put("#define", new Integer(PreprocessorDirectives.DEFINE));
+ ppDirectives.put(
+ "#undef",
+ new Integer(PreprocessorDirectives.UNDEFINE));
+ ppDirectives.put("#if", new Integer(PreprocessorDirectives.IF));
+ ppDirectives.put("#ifdef", new Integer(PreprocessorDirectives.IFDEF));
+ ppDirectives.put("#ifndef", new Integer(PreprocessorDirectives.IFNDEF));
+ ppDirectives.put("#else", new Integer(PreprocessorDirectives.ELSE));
+ ppDirectives.put("#endif", new Integer(PreprocessorDirectives.ENDIF));
+ ppDirectives.put(
+ "#include",
+ new Integer(PreprocessorDirectives.INCLUDE));
+ ppDirectives.put("#line", new Integer(PreprocessorDirectives.LINE));
+ ppDirectives.put("#error", new Integer(PreprocessorDirectives.ERROR));
+ ppDirectives.put("#pragma", new Integer(PreprocessorDirectives.PRAGMA));
+ ppDirectives.put("#elif", new Integer(PreprocessorDirectives.ELIF));
+ ppDirectives.put("#", new Integer(PreprocessorDirectives.BLANK));
+
+ }
+
+ static public class PreprocessorDirectives {
+ static public final int DEFINE = 0;
+ static public final int UNDEFINE = 1;
+ static public final int IF = 2;
+ static public final int IFDEF = 3;
+ static public final int IFNDEF = 4;
+ static public final int ELSE = 5;
+ static public final int ENDIF = 6;
+ static public final int INCLUDE = 7;
+ static public final int LINE = 8;
+ static public final int ERROR = 9;
+ static public final int PRAGMA = 10;
+ static public final int BLANK = 11;
+ static public final int ELIF = 12;
+ }
+
+ public final int getCount() {
+ return count;
+ }
+
+ public final int getDepth() {
+ return branches.getDepth();
+ }
+
+ protected boolean evaluateExpression(String expression)
+ throws ScannerException {
+ Object expressionEvalResult = null;
+ try {
+ ExpressionEvaluator evaluator = new ExpressionEvaluator();
+ Scanner trial =
+ new Scanner(
+ new StringReader(expression),
+ EXPRESSION,
+ definitions);
+ Parser parser = new Parser(trial, evaluator);
+ parser.expression();
+ expressionEvalResult = evaluator.getResult();
+ } catch (Exception e) {
+ System.out.println("Exception from Parser : " + e.toString());
+ }
+
+ if (expressionEvalResult == null)
+ throw new ScannerException(
+ "Expression "
+ + expression
+ + " evaluates to an undefined value");
+
+ if (expressionEvalResult.getClass() == java.lang.Integer.class) {
+ int i = ((Integer) expressionEvalResult).intValue();
+ if (i == 0) {
+ return false;
+ }
+ return true;
+ } else if (
+ expressionEvalResult.getClass() == java.lang.Boolean.class) {
+ return ((Boolean) expressionEvalResult).booleanValue();
+ } else {
+ throw new ScannerException(
+ "Unexpected expression type - we do not expect "
+ + expressionEvalResult.getClass().getName());
+ }
+ }
+
+ protected boolean skipOverMultilineComment() throws ScannerException {
+ int state = 0;
+ boolean encounteredNewline = false;
+ // simple state machine to handle multi-line comments
+ // state 0 == no end of comment in site
+ // state 1 == encountered *, expecting /
+ // state 2 == we are no longer in a comment
+
+ int c = getChar();
+ while (state != 2 && c != NOCHAR) {
+ if (c == '\n')
+ encounteredNewline = true;
+
+ switch (state) {
+ case 0 :
+ if (c == '*')
+ state = 1;
+ break;
+ case 1 :
+ if (c == '/')
+ state = 2;
+ else if (c != '*')
+ state = 0;
+ break;
+ }
+ c = getChar();
+ }
+
+ if (c == NOCHAR) {
+ if (throwExceptionOnEOFWithinMultilineComment)
+ throw new ScannerException("Encountered EOF while in multiline comment");
+ }
+
+ ungetChar(c);
+
+ return encounteredNewline;
+ }
+
+ protected void poundInclude() throws ScannerException {
+ skipOverWhitespace();
+ int c = getChar();
+ int offset;
+
+ StringBuffer fileName = new StringBuffer();
+ if (c == '<') {
+ c = getChar();
+ while ((c != '>')) {
+ fileName.append((char) c);
+ c = getChar();
+ }
+ }
+ else if (c == '"') {
+ c = getChar();
+ while ((c != '"')) {
+ fileName.append((char) c);
+ c = getChar();
+ }
+
+ // TO DO: Make sure the directory of the current file is in the
+ // inclusion paths.
+ }
+
+ String f = fileName.toString();
+
+ if( quickScan )
+ {
+ if( callback != null )
+ {
+ offset = currentContext.getOffset() - f.length() - 1; // -1 for the end quote
+
+ callback.inclusionBegin( f, offset );
+ callback.inclusionEnd();
+ }
+ }
+ else
+ handleInclusion(f.trim());
+ }
+
+ protected void poundDefine() throws ScannerException {
+ skipOverWhitespace();
+ // definition
+ String key = getNextIdentifier();
+ int offset = currentContext.getOffset() - key.length();
+ if( currentContext.getUndo() != Scanner.NOCHAR )
+ offset -= 1;
+
+ if (throwExceptionOnRedefinition) {
+ String checkForRedefinition = (String) definitions.get(key);
+ if (checkForRedefinition != null) {
+ throw new ScannerException(
+ "Preprocessor symbol "
+ + key
+ + " has already been defined to "
+ + checkForRedefinition
+ + " cannot redefined.");
+ }
+ }
+
+ // get the next character
+ // the C++ standard says that macros must not put
+ // whitespace between the end of the definition
+ // identifier and the opening parenthesis
+ int c = getChar();
+ if (c == '(') {
+ StringBuffer buffer = new StringBuffer();
+ c = getChar();
+ while (c != ')') {
+ buffer.append((char) c);
+ c = getChar();
+ }
+
+ String parameters = buffer.toString();
+
+ // replace StringTokenizer later -- not performant
+ StringTokenizer tokenizer = new StringTokenizer(parameters, ",");
+ ArrayList parameterIdentifiers =
+ new ArrayList(tokenizer.countTokens());
+ while (tokenizer.hasMoreTokens()) {
+ parameterIdentifiers.add(tokenizer.nextToken().trim());
+ }
+
+ skipOverWhitespace();
+
+ ArrayList macroReplacementTokens = new ArrayList();
+ String replacementString = getRestOfPreprocessorLine();
+ Scanner helperScanner = new Scanner();
+ helperScanner.initialize(
+ new StringReader(replacementString),
+ null);
+ Token t = helperScanner.nextToken();
+
+ while (t.type != Token.tEOF) {
+ macroReplacementTokens.add(t);
+ t = helperScanner.nextToken();
+ }
+
+ IMacroDescriptor descriptor = new MacroDescriptor();
+ descriptor.initialize(
+ key,
+ parameterIdentifiers,
+ macroReplacementTokens,
+ key + "(" + parameters + ")");
+ addDefinition(key, descriptor);
+
+ } else if ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r')) {
+ // this is a simple definition
+ skipOverWhitespace();
+
+ // get what we are to map the name to and add it to the definitions list
+ String value = getRestOfPreprocessorLine();
+ addDefinition(key, value);
+ } else if (c == '/') {
+ // this could be a comment
+ c = getChar();
+ if (c == '/') // one line comment
+ {
+ skipOverTextUntilNewline();
+ addDefinition(key, "");
+ } else if (c == '*') // multi-line comment
+ {
+ if (skipOverMultilineComment()) {
+ // we have gone over a newline
+ // therefore, this symbol was defined to an empty string
+ addDefinition(key, "");
+ } else {
+ String value = getRestOfPreprocessorLine();
+ addDefinition(key, value);
+ }
+ } else {
+ // this is not a comment
+ // it is a bad statement
+ if (throwExceptionOnBadPPDirective)
+ throw new ScannerException(
+ BAD_PP + currentContext.getOffset());
+ }
+ } else {
+ System.out.println("Unexpected character " + ((char) c));
+ if (throwExceptionOnBadPPDirective)
+ throw new ScannerException(BAD_PP + currentContext.getOffset());
+ }
+
+ // call the callback accordingly
+ if( callback != null )
+ callback.macro( key, offset );
+ }
+
+ protected void expandDefinition(String symbol, Object expansion)
+ throws ScannerException {
+ if (expansion.getClass() == String.class) {
+ String replacementValue = (String) expansion;
+ updateContext(
+ new StringReader(replacementValue),
+ POUND_DEFINE + symbol);
+ } else if (expansion.getClass() == MacroDescriptor.class) {
+ IMacroDescriptor macro = (IMacroDescriptor) expansion;
+ skipOverWhitespace();
+ int c = getChar();
+
+ if (c == '(') {
+ StringBuffer buffer = new StringBuffer();
+ int bracketCount = 1;
+ c = getChar();
+
+ while (true) {
+ if (c == '(')
+ ++bracketCount;
+ else if (c == ')')
+ --bracketCount;
+
+ if (bracketCount == 0)
+ break;
+ buffer.append((char) c);
+ c = getChar();
+ }
+ String betweenTheBrackets = buffer.toString();
+ StringTokenizer tokenizer =
+ new StringTokenizer(betweenTheBrackets, ",");
+ Vector parameterValues = new Vector(tokenizer.countTokens());
+ while (tokenizer.hasMoreTokens()) {
+ parameterValues.add(tokenizer.nextToken().trim());
+ }
+
+ // create a string that represents what needs to be tokenized
+ buffer = new StringBuffer();
+ List tokens = macro.getTokenizedExpansion();
+ List parameterNames = macro.getParameters();
+
+ if (parameterNames.size() != parameterValues.size()) {
+ if (throwExceptionOnBadMacroExpansion)
+ throw new ScannerException(
+ "Improper use of macro " + symbol);
+ }
+
+ int numberOfTokens = tokens.size();
+
+ for (int i = 0; i < numberOfTokens; ++i) {
+ Token t = (Token) tokens.get(i);
+ if (t.type == Token.tIDENTIFIER) {
+ String identifierName = t.image;
+
+ // is this identifier in the parameterNames
+ // list?
+
+ int index = parameterNames.indexOf(t.image);
+ if (index == -1 ) {
+ // not found
+ // just add image to buffer
+ buffer.append(t.image);
+ } else {
+ buffer.append(
+ (String) parameterValues.elementAt(index));
+ }
+ } else {
+ buffer.append(t.image);
+ }
+ }
+ updateContext(
+ new StringReader(buffer.toString()),
+ POUND_DEFINE + macro.getSignature());
+ } else {
+ if (throwExceptionOnBadMacroExpansion)
+ throw new ScannerException(
+ "Improper use of macro " + symbol);
+
+ }
+
+ } else {
+ System.out.println(
+ "Unexpected class stored in definitions table. "
+ + expansion.getClass().getName());
+ }
+
+ }
+
+ protected String handleDefinedMacro() throws ScannerException {
+ skipOverWhitespace();
+
+ int c = getChar();
+
+ if (c != '(') {
+ if (throwExceptionOnBadMacroExpansion)
+ throw new ScannerException("Improper use of macro defined()");
+ }
+
+ StringBuffer buffer = new StringBuffer();
+ c = getChar();
+ while ((c != NOCHAR) && (c != ')')) {
+ buffer.append((char) c);
+ c = getChar();
+ }
+ if (c == NOCHAR) {
+ if (throwExceptionOnBadMacroExpansion)
+ throw new ScannerException("Improper use of macro defined()");
+ }
+
+ String definitionIdentifier = buffer.toString().trim();
+
+ if (definitions.get(definitionIdentifier) != null)
+ return "1";
+
+ return "0";
+ }
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerContext.java
new file mode 100644
index 00000000000..e7df6008604
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerContext.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.parser;
+
+import java.io.IOException;
+import java.io.Reader;
+
+public class ScannerContext implements IScannerContext
+{
+ private Reader reader;
+ private String filename;
+ private int offset;
+ private int undo;
+
+ public ScannerContext(){}
+ public IScannerContext initialize(Reader r, String f, int u )
+ {
+ reader = r;
+ filename = f;
+ offset = 0;
+ undo = u;
+ return this;
+ }
+
+ public int read() throws IOException {
+ ++offset;
+ return reader.read();
+ }
+
+ /**
+ * Returns the filename.
+ * @return String
+ */
+ public final String getFilename()
+ {
+ return filename;
+ }
+
+ /**
+ * Returns the offset.
+ * @return int
+ */
+ public final int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the reader.
+ * @return Reader
+ */
+ public final Reader getReader()
+ {
+ return reader;
+ }
+
+ /**
+ * Returns the undo.
+ * @return int
+ */
+ public final int getUndo()
+ {
+ return undo;
+ }
+
+ /**
+ * Sets the undo.
+ * @param undo The undo to set
+ */
+ public void setUndo(int undo)
+ {
+ this.undo= undo;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerException.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerException.java
new file mode 100644
index 00000000000..8f299523ef7
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ScannerException.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.parser;
+
+public class ScannerException extends Exception {
+
+ /**
+ * Constructor for ScannerException.
+ */
+ public ScannerException() {
+ super();
+ }
+
+ /**
+ * Constructor for ScannerException.
+ * @param s
+ */
+ public ScannerException(String s) {
+ super(s);
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Token.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Token.java
new file mode 100644
index 00000000000..5a7dd39da8c
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Token.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * Copyright (c) 2001 Rational Software Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * Rational Software - initial implementation
+ ******************************************************************************/
+package org.eclipse.cdt.internal.core.parser;
+
+public class Token {
+
+ public Token(int t, String i, IScannerContext context ) {
+ type = t;
+ image = i;
+ filename = context.getFilename();
+ offset = context.getOffset() - image.length();
+
+ if( context.getUndo() != Scanner.NOCHAR )
+ offset -= 1;
+ }
+
+ public Token(int t, String i) {
+ type = t;
+ image = i;
+ }
+
+ public static Token EOF = new Token(Token.tEOF, "");
+
+ public String toString()
+ {
+ return "Token type=" + type + " image =" + image + " offset=" + offset;
+ }
+
+ public int type;
+ public int getType() { return type; }
+
+ public String image;
+ public String getImage() { return image; }
+
+ public String filename;
+ public int offset;
+ public int getOffset() { return offset; }
+ public int getLength() { return image.length(); }
+
+ private Token next;
+ public Token getNext() { return next; }
+ public void setNext(Token t) { next = t; }
+
+ // Token types
+ static public final int tEOF = 0;
+ static public final int tIDENTIFIER = 1;
+ static public final int tINTEGER = 2;
+ static public final int tCOLONCOLON = 3;
+ static public final int tCOLON = 4;
+ static public final int tSEMI = 5;
+ static public final int tCOMMA = 6;
+ static public final int tQUESTION = 7;
+ static public final int tLPAREN = 8;
+ static public final int tRPAREN = 9;
+ static public final int tLBRACKET = 10;
+ static public final int tRBRACKET = 11;
+ static public final int tLBRACE = 12;
+ static public final int tRBRACE = 13;
+ static public final int tPLUSASSIGN = 14;
+ static public final int tINCR = 15;
+ static public final int tPLUS = 16;
+ static public final int tMINUSASSIGN = 17;
+ static public final int tDECR = 18;
+ static public final int tARROWSTAR = 19;
+ static public final int tARROW = 20;
+ static public final int tMINUS = 21;
+ static public final int tSTARASSIGN = 22;
+ static public final int tSTAR = 23;
+ static public final int tMODASSIGN = 24;
+ static public final int tMOD = 25;
+ static public final int tXORASSIGN = 26;
+ static public final int tXOR = 27;
+ static public final int tAMPERASSIGN = 28;
+ static public final int tAND = 29;
+ static public final int tAMPER = 30;
+ static public final int tBITORASSIGN = 31;
+ static public final int tOR = 32;
+ static public final int tBITOR = 33;
+ static public final int tCOMPL = 34;
+ static public final int tNOTEQUAL = 35;
+ static public final int tNOT = 36;
+ static public final int tEQUAL = 37;
+ static public final int tASSIGN = 38;
+ static public final int tSHIFLASSIGN = 39;
+ static public final int tSHIFTL = 40;
+ static public final int tLTEQUAL = 41;
+ static public final int tLT = 42;
+ static public final int tSHIFTRASSIGN = 43;
+ static public final int tSHIFTR = 44;
+ static public final int tGTEQUAL = 45;
+ static public final int tGT = 46;
+ static public final int tSHIFTLASSIGN = 47;
+ static public final int tELIPSE = 48;
+ static public final int tDOTSTAR = 49;
+ static public final int tDOT = 50;
+ static public final int tDIVASSIGN = 51;
+ static public final int tDIV = 52;
+ static public final int tCLASSNAME = 53;
+ static public final int t_and = 54;
+ static public final int t_and_eq = 55;
+ static public final int t_asm = 56;
+ static public final int t_auto = 57;
+ static public final int t_bitand = 58;
+ static public final int t_bitor = 59;
+ static public final int t_bool = 60;
+ static public final int t_break = 61;
+ static public final int t_case = 62;
+ static public final int t_catch = 63;
+ static public final int t_char = 64;
+ static public final int t_class = 65;
+ static public final int t_compl = 66;
+ static public final int t_const = 67;
+ static public final int t_const_cast = 69;
+ static public final int t_continue = 70;
+ static public final int t_default = 71;
+ static public final int t_delete = 72;
+ static public final int t_do = 73;
+ static public final int t_double = 74;
+ static public final int t_dynamic_cast = 75;
+ static public final int t_else = 76;
+ static public final int t_enum = 77;
+ static public final int t_explicit = 78;
+ static public final int t_export = 79;
+ static public final int t_extern = 80;
+ static public final int t_false = 81;
+ static public final int t_float = 82;
+ static public final int t_for = 83;
+ static public final int t_friend = 84;
+ static public final int t_goto = 85;
+ static public final int t_if = 86;
+ static public final int t_inline = 87;
+ static public final int t_int = 88;
+ static public final int t_long = 89;
+ static public final int t_mutable = 90;
+ static public final int t_namespace = 91;
+ static public final int t_new = 92;
+ static public final int t_not = 93;
+ static public final int t_not_eq = 94;
+ static public final int t_operator = 95;
+ static public final int t_or = 96;
+ static public final int t_or_eq = 97;
+ static public final int t_private = 98;
+ static public final int t_protected = 99;
+ static public final int t_public = 100;
+ static public final int t_register = 101;
+ static public final int t_reinterpret_cast = 102;
+ static public final int t_return = 103;
+ static public final int t_short = 104;
+ static public final int t_sizeof = 105;
+ static public final int t_static = 106;
+ static public final int t_static_cast = 107;
+ static public final int t_signed = 108;
+ static public final int t_struct = 109;
+ static public final int t_switch = 110;
+ static public final int t_template = 111;
+ static public final int t_this = 112;
+ static public final int t_throw = 113;
+ static public final int t_true = 114;
+ static public final int t_try = 115;
+ static public final int t_typedef = 116;
+ static public final int t_typeid = 117;
+ static public final int t_typename = 118;
+ static public final int t_union = 119;
+ static public final int t_unsigned = 120;
+ static public final int t_using = 121;
+ static public final int t_virtual = 122;
+ static public final int t_void = 123;
+ static public final int t_volatile = 124;
+ static public final int t_wchar_t = 125;
+ static public final int t_while = 126;
+ static public final int t_xor = 127;
+ static public final int t_xor_eq = 128;
+ static public final int tSTRING = 129;
+
+ static public final int tLAST = tSTRING;
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/DeclSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/DeclSpecifier.java
new file mode 100644
index 00000000000..6ed3b42b04d
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/DeclSpecifier.java
@@ -0,0 +1,191 @@
+package org.eclipse.cdt.internal.core.parser.util;
+
+import org.eclipse.cdt.internal.core.parser.Token;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class DeclSpecifier {
+
+ // DeclSpecifier layed out as bit array
+ // leftmost 5 bits are type
+ public static final int typeMask = 0x001f;
+ public static final int isAuto = 0x0020;
+ public static final int isRegister = 0x0040;
+ public static final int isStatic = 0x0080;
+ public static final int isExtern = 0x0100;
+ public static final int isMutable = 0x0200;
+ public static final int isInline = 0x0400;
+ public static final int isVirtual = 0x0800;
+ public static final int isExplicit = 0x1000;
+ public static final int isTypedef = 0x2000;
+ public static final int isFriend = 0x4000;
+ public static final int isConst = 0x8000;
+ public static final int isVolatile = 0x10000;
+ public static final int isUnsigned = 0x20000;
+ public static final int isShort = 0x40000;
+ public static final int isLong = 0x80000;
+
+ private int declSpecifierSeq = 0;
+ public int getDeclSpecifierSeq() { return declSpecifierSeq; }
+
+ // Convenience methods
+ private void setBit(boolean b, int mask) {
+ if (b)
+ declSpecifierSeq = declSpecifierSeq | mask;
+ else
+ declSpecifierSeq = declSpecifierSeq & ~mask;
+ }
+
+ private boolean checkBit(int mask) {
+ return (declSpecifierSeq & mask) == 1;
+ }
+
+ public void setAuto(boolean b) { setBit(b, isAuto); }
+ public boolean isAuto() { return checkBit(isAuto); }
+
+ public void setRegister(boolean b) { setBit(b, isRegister); }
+ public boolean isRegister() { return checkBit(isRegister); }
+
+ public void setStatic(boolean b) { setBit(b, isStatic); }
+ public boolean isStatic() { return checkBit(isStatic); }
+
+ public void setExtern(boolean b) { setBit(b, isExtern); }
+ public boolean isExtern() { return checkBit(isExtern); }
+
+ public void setMutable(boolean b) { setBit(b, isMutable); }
+ public boolean isMutable() { return checkBit(isMutable); }
+
+ public void setInline(boolean b) { setBit(b, isInline); }
+ public boolean isInline() { return checkBit(isInline); }
+
+ public void setVirtual(boolean b) { setBit(b, isVirtual); }
+ public boolean isVirtual() { return checkBit(isVirtual); }
+
+ public void setExplicit(boolean b) { setBit(b, isExplicit); }
+ public boolean isExplicit() { return checkBit(isExplicit); }
+
+ public void setTypedef(boolean b) { setBit(b, isTypedef); }
+ public boolean isTypedef() { return checkBit(isTypedef); }
+
+ public void setFriend(boolean b) { setBit(b, isFriend); }
+ public boolean isFriend() { return checkBit(isFriend); }
+
+ public void setConst(boolean b) { setBit(b, isConst); }
+ public boolean isConst() { return checkBit(isConst); }
+
+ public void setVolatile(boolean b) { setBit(b, isVolatile); }
+ public boolean isVolatile() { return checkBit(isVolatile); }
+
+ public void setUnsigned(boolean b) { setBit(b, isUnsigned); }
+ public boolean isUnsigned() { return checkBit(isUnsigned); }
+
+ public void setShort(boolean b) { setBit(b, isShort); }
+ public boolean isShort() { return checkBit(isShort); }
+
+ public void setLong(boolean b) { setBit(b, isLong); }
+ public boolean isLong() { return checkBit(isLong); }
+
+ // Simple Types
+ public static final int t_type = 0; // Type Specifier
+ public static final int t_char = 1;
+ public static final int t_wchar_t = 2;
+ public static final int t_bool = 3;
+ public static final int t_int = 4;
+ public static final int t_float = 5;
+ public static final int t_double = 6;
+ public static final int t_void = 7;
+
+ public void setType( Token token )
+ {
+ switch (token.getType()) {
+ case Token.t_auto:
+ setAuto(true);
+ break;
+ case Token.t_register:
+ setRegister(true);
+ break;
+ case Token.t_static:
+ setStatic(true);
+ break;
+ case Token.t_extern:
+ setExtern(true);
+ break;
+ case Token.t_mutable:
+ setMutable(true);
+ break;
+ case Token.t_inline:
+ setInline(true);
+ break;
+ case Token.t_virtual:
+ setVirtual(true);
+ break;
+ case Token.t_explicit:
+ setExplicit(true);
+ break;
+ case Token.t_typedef:
+ setTypedef(true);
+ break;
+ case Token.t_friend:
+ setFriend(true);
+ break;
+ case Token.t_const:
+ setConst(true);
+ break;
+ case Token.t_volatile:
+ setVolatile(true);
+ break;
+ case Token.t_char:
+ setType(DeclarationSpecifier.t_char);
+ break;
+ case Token.t_wchar_t:
+ setType(DeclarationSpecifier.t_wchar_t);
+ break;
+ case Token.t_bool:
+ setType(DeclarationSpecifier.t_bool);
+ break;
+ case Token.t_short:
+ setShort(true);
+ break;
+ case Token.t_int:
+ setType(DeclarationSpecifier.t_int);
+ break;
+ case Token.t_long:
+ setLong(true);
+ break;
+ case Token.t_signed:
+ setUnsigned(false);
+ break;
+ case Token.t_unsigned:
+ setUnsigned(true);
+ break;
+ case Token.t_float:
+ setType(DeclarationSpecifier.t_float);
+ break;
+ case Token.t_double:
+ setType(DeclarationSpecifier.t_double);
+ break;
+ case Token.t_void:
+ setType(DeclarationSpecifier.t_void);
+ break;
+ case Token.tIDENTIFIER:
+ setType(DeclarationSpecifier.t_type);
+ break;
+ }
+
+ }
+
+ public void setType(int t) {
+ declSpecifierSeq = declSpecifierSeq & ~typeMask | t;
+ }
+
+ public int getType() {
+ return declSpecifierSeq & typeMask;
+ }
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/DeclarationSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/DeclarationSpecifier.java
new file mode 100644
index 00000000000..9413877ab9a
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/DeclarationSpecifier.java
@@ -0,0 +1,26 @@
+package org.eclipse.cdt.internal.core.parser.util;
+
+import java.util.List;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class DeclarationSpecifier extends DeclSpecifier {
+
+ public interface Container {
+
+ public DeclarationSpecifier getDeclSpecifier();
+
+ public void setDeclSpecifier( DeclarationSpecifier in );
+
+ public void addDeclarator(Object declarator);
+ public void removeDeclarator( Object declarator );
+ public List getDeclarators();
+
+ };
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/Name.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/Name.java
new file mode 100644
index 00000000000..deb94337417
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/Name.java
@@ -0,0 +1,46 @@
+package org.eclipse.cdt.internal.core.parser.util;
+
+import org.eclipse.cdt.internal.core.parser.Token;
+
+
+/**
+ * @author dschaefe
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class Name {
+
+ private Token nameStart, nameEnd;
+
+ public Name(Token nameStart) {
+ this.nameStart = nameStart;
+ }
+
+ public void setEnd(Token nameEnd) {
+ this.nameEnd = nameEnd;
+ }
+
+ public int getStartOffset()
+ {
+ return nameStart.offset;
+ }
+
+ public int getEndOffset()
+ {
+ return nameEnd.offset;
+ }
+
+ public String toString() {
+ String name = nameStart.getImage();
+
+ for (Token t = nameStart; nameStart != nameEnd;) {
+ t = nameStart.getNext();
+ name += t.getImage();
+ }
+
+ return name;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
index a07e80c0ff5..f1276b4fdee 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
@@ -443,4 +443,17 @@ public class CCorePlugin extends Plugin {
}
return null;
}
-}
+
+ // Preference to turn on/off the new parser
+
+ private boolean useNewParser = false;
+
+ public void setUseNewParser(boolean useNewParser) {
+ this.useNewParser = useNewParser;
+ }
+
+ public boolean useNewParser() {
+ return useNewParser;
+ }
+
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.ui.tests/.classpath b/core/org.eclipse.cdt.ui.tests/.classpath
index a067b89762f..a7f81b4612e 100644
--- a/core/org.eclipse.cdt.ui.tests/.classpath
+++ b/core/org.eclipse.cdt.ui.tests/.classpath
@@ -4,6 +4,7 @@
+
diff --git a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/BranchTrackerTest.java b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/BranchTrackerTest.java
new file mode 100644
index 00000000000..96250bb0401
--- /dev/null
+++ b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/BranchTrackerTest.java
@@ -0,0 +1,200 @@
+package org.eclipse.cdt.core.parser.tests;
+
+import junit.framework.TestCase;
+
+import org.eclipse.cdt.internal.core.parser.BranchTracker;
+import org.eclipse.cdt.internal.core.parser.ScannerException;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class BranchTrackerTest extends TestCase {
+
+ public BranchTrackerTest( String ignoreMe )
+ {
+ super( ignoreMe );
+ }
+
+ public static void assertFalse( boolean input )
+ {
+ assertTrue( input == false );
+ }
+
+ public void testIgnore()
+ {
+
+ BranchTracker bt = new BranchTracker();
+ try
+ {
+ /*
+ * #if 0
+ * # if 1
+ * # elif 1
+ * # else
+ * # endif
+ * #else
+ * #endif
+ */
+
+ assertFalse( bt.poundif( false ) );
+ assertFalse( bt.poundif( true ) );
+ assertFalse( bt.poundelif( true ) );
+ assertFalse( bt.poundelse() );
+ assertFalse( bt.poundendif() );
+ assertTrue( bt.poundelse() );
+ assertTrue( bt.poundendif() );
+
+ /*
+ * #if 0
+ * # if 1
+ * # elif 1
+ * # else
+ * # endif
+ * #else
+ * # if 0
+ * # elif 1
+ * # elif 0
+ * # elif 1
+ * # else
+ * # endif
+ * #endif
+ */
+
+ bt = new BranchTracker();
+ assertFalse( bt.poundif( false ) );
+ assertFalse( bt.poundif( true ));
+ assertFalse( bt.poundelif( true ) );
+ assertFalse( bt.poundelse() );
+ assertFalse( bt.poundendif() );
+ assertTrue( bt.poundelse() );
+ assertFalse( bt.poundif( false ) );
+ assertTrue( bt.poundelif( true ) );
+ assertFalse( bt.poundelif( false ) );
+ assertFalse( bt.poundelif( true ) );
+ assertFalse( bt.poundelse() );
+ assertTrue( bt.poundendif() );
+ assertTrue( bt.poundendif() );
+ assertEquals( 0, bt.getDepth() );
+
+ /*
+ * #if 0
+ * # if 1
+ * # elif 0
+ * # elif 1
+ * # else
+ * # endif
+ * #elif 0
+ * # if 0
+ * # elif 0
+ * # elif 1
+ * # else
+ * # endif
+ * #elif 1
+ * # if 0
+ * # elif 0
+ * # elif 0
+ * # else
+ * # endif
+ * #else
+ * # if 1
+ * # elif 0
+ * # elif 1
+ * # else
+ * # endif
+ * #endif
+ */
+
+ assertFalse(bt.poundif(false));
+ assertFalse(bt.poundif(true));
+ assertFalse(bt.poundelif(false));
+ assertFalse(bt.poundelif(true));
+ assertFalse(bt.poundelse());
+ assertFalse( bt.poundendif() );
+ assertFalse(bt.poundelif(false));
+ assertFalse(bt.poundif(false));
+ assertFalse(bt.poundelif(false));
+ assertFalse(bt.poundelif(true));
+ assertFalse(bt.poundelse());
+ assertFalse( bt.poundendif());
+ assertTrue(bt.poundelif(true));
+ assertFalse(bt.poundif(false));
+ assertFalse(bt.poundelif(false));
+ assertFalse(bt.poundelif(false));
+ assertTrue(bt.poundelse());
+ assertTrue( bt.poundendif() );
+ assertFalse(bt.poundelse());
+ assertFalse(bt.poundif(true));
+ assertFalse(bt.poundelif(false));
+ assertFalse(bt.poundelif(true));
+ assertFalse(bt.poundelse());
+ assertFalse( bt.poundendif() );
+ assertTrue( bt.poundendif() );
+ assertEquals(0, bt.getDepth());
+ } catch (ScannerException se) {
+ fail("Unexpected Scanner exception thrown");
+ }
+ }
+
+ public void testSimpleBranches()
+ {
+ try
+ {
+ /*
+ * code sequence is
+ * #if 1
+ * #else
+ * #endif
+ */
+ BranchTracker bt = new BranchTracker();
+ assertTrue( bt.poundif( true ) );
+ assertFalse( bt.poundelse() );
+ assertTrue( bt.poundendif() );
+
+ /*
+ * code sequence is
+ * #if 1
+ * # if 0
+ * # elif 0
+ * # else
+ * # endif
+ * #else
+ * #endif
+ */
+ bt = new BranchTracker();
+ assertTrue( bt.poundif( true ));
+ assertFalse( bt.poundif( false ));
+ assertFalse( bt.poundelif( false ));
+ assertTrue( bt.poundelse());
+ assertTrue( bt.poundendif() );
+ assertFalse( bt.poundelse() );
+ assertTrue( bt.poundendif() );
+
+ /*
+ * #if 1
+ * #elsif 1
+ * #elsif 0
+ * #else
+ * #endif
+ */
+
+ bt = new BranchTracker();
+ assertTrue( bt.poundif( true ) );
+ assertFalse( bt.poundelif( true ));
+ assertFalse( bt.poundelif( false ));
+ assertFalse( bt.poundelse());
+ assertTrue( bt.poundendif() );
+
+
+ }
+ catch( ScannerException se )
+ {
+ fail( "Exception" );
+ }
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/DOMTests.java b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/DOMTests.java
new file mode 100644
index 00000000000..d7356efebc8
--- /dev/null
+++ b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/DOMTests.java
@@ -0,0 +1,309 @@
+package org.eclipse.cdt.core.parser.tests;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.eclipse.cdt.internal.core.dom.BaseSpecifier;
+import org.eclipse.cdt.internal.core.dom.ClassSpecifier;
+import org.eclipse.cdt.internal.core.dom.DOMBuilder;
+import org.eclipse.cdt.internal.core.dom.Declarator;
+import org.eclipse.cdt.internal.core.dom.ParameterDeclaration;
+import org.eclipse.cdt.internal.core.dom.ParameterDeclarationClause;
+import org.eclipse.cdt.internal.core.dom.SimpleDeclaration;
+import org.eclipse.cdt.internal.core.dom.TranslationUnit;
+import org.eclipse.cdt.internal.core.parser.Parser;
+import org.eclipse.cdt.internal.core.parser.ParserException;
+import org.eclipse.cdt.internal.core.parser.util.DeclarationSpecifier;
+import org.eclipse.cdt.internal.core.parser.util.Name;
+
+/**
+ * Tests the construction of DOMs for snippets of code
+ */
+public class DOMTests extends TestCase {
+
+ public TranslationUnit parse(String code) throws Exception {
+ DOMBuilder domBuilder = new DOMBuilder();
+ Parser parser = new Parser(code, domBuilder);
+ if( ! parser.parse() ) throw new ParserException( "Parse failure" );
+
+ return domBuilder.getTranslationUnit();
+ }
+
+ /**
+ * Test code: int x;
+ * Purpose: to test the simple decaration in it's simplest form.
+ */
+ public void testIntGlobal() throws Exception {
+ // Parse and get the translation Unit
+ TranslationUnit translationUnit = parse("int x;");
+
+ // Get the simple declaration
+ List declarations = translationUnit.getDeclarations();
+ assertEquals(1, declarations.size());
+ SimpleDeclaration declaration = (SimpleDeclaration)declarations.get(0);
+
+ // Make sure it is only an int
+ assertEquals(DeclarationSpecifier.t_int, declaration.getDeclSpecifier().getDeclSpecifierSeq());
+
+ // Get the declarator and check its name
+ List declarators = declaration.getDeclarators();
+ assertEquals(1, declarators.size());
+ Declarator declarator = (Declarator)declarators.get(0);
+ Name name = declarator.getName();
+ assertEquals("x", name.toString());
+ }
+
+ /**
+ * Test code: class A { } a;
+ * Purpose: tests the use of a classSpecifier in
+ */
+ public void testEmptyClass() throws Exception {
+ // Parse and get the translation unit
+ Writer code = new StringWriter();
+ code.write("class A { } a;");
+ TranslationUnit translationUnit = parse(code.toString());
+
+ // Get the simple declaration
+ List declarations = translationUnit.getDeclarations();
+ assertEquals(1, declarations.size());
+ SimpleDeclaration declaration = (SimpleDeclaration)declarations.get(0);
+
+ // Make sure it is a type specifier
+ assertEquals(0, declaration.getDeclSpecifier().getDeclSpecifierSeq());
+
+ // Get the class specifier and check its name
+ ClassSpecifier classSpecifier = (ClassSpecifier)declaration.getTypeSpecifier();
+ Name className = classSpecifier.getName();
+ assertEquals("A", className.toString());
+
+ // Get the declarator and check it's name
+ List declarators = declaration.getDeclarators();
+ assertEquals(1, declarators.size());
+ Declarator declarator = (Declarator)declarators.get(0);
+ Name name = declarator.getName();
+ assertEquals("a", name.toString());
+ }
+
+ /**
+ * Test code: class A { public: int x; };
+ * Purpose: tests a declaration in a class scope.
+ */
+ public void testSimpleClassMember() throws Exception {
+ // Parse and get the translaton unit
+ Writer code = new StringWriter();
+ code.write("class A { public: int x; };");
+ TranslationUnit translationUnit = parse(code.toString());
+
+ // Get the declaration
+ List declarations = translationUnit.getDeclarations();
+ assertEquals(1, declarations.size());
+ SimpleDeclaration declaration = (SimpleDeclaration)declarations.get(0);
+
+ // Make sure there is no declarator
+ assertEquals(0, declaration.getDeclarators().size());
+
+ // Make sure it's a type specifier
+ assertEquals(0, declaration.getDeclSpecifier().getDeclSpecifierSeq());
+
+ // Get the class specifier and check its name
+ ClassSpecifier classSpecifier = (ClassSpecifier)declaration.getTypeSpecifier();
+ Name className = classSpecifier.getName();
+ assertEquals("A", className.toString());
+
+ // Get the member declaration
+ declarations = classSpecifier.getDeclarations();
+ assertEquals(1, declarations.size());
+ declaration = (SimpleDeclaration)declarations.get(0);
+
+ // Make sure it's an int
+ assertEquals(DeclarationSpecifier.t_int, declaration.getDeclSpecifier().getDeclSpecifierSeq());
+
+ // Get the declarator and check it's name
+ List declarators = declaration.getDeclarators();
+ assertEquals(1, declarators.size());
+ Declarator declarator = (Declarator)declarators.get(0);
+ Name name = declarator.getName();
+ assertEquals("x", name.toString());
+ }
+ /**
+ * Test code: class A : public B, private C, virtual protected D { public: int x, y; float a,b,c; }
+ * Purpose: tests a declaration in a class scope.
+ */
+ public void testSimpleClassMembers() throws Exception {
+ // Parse and get the translaton unit
+ Writer code = new StringWriter();
+ code.write("class A : public B, private C, virtual protected D { public: int x, y; float a,b,c; };");
+ TranslationUnit translationUnit = parse(code.toString());
+
+ // Get the declaration
+ List declarations = translationUnit.getDeclarations();
+ assertEquals(1, declarations.size());
+ SimpleDeclaration declaration = (SimpleDeclaration)declarations.get(0);
+
+ // Make sure there is no declarator
+ assertEquals(0, declaration.getDeclarators().size());
+
+ // Make sure it's a type specifier
+ assertEquals(0, declaration.getDeclSpecifier().getDeclSpecifierSeq());
+
+ // Get the class specifier and check its name
+ ClassSpecifier classSpecifier = (ClassSpecifier)declaration.getTypeSpecifier();
+ Name className = classSpecifier.getName();
+ assertEquals("A", className.toString());
+
+ List baseClasses = classSpecifier.getBaseSpecifiers();
+ assertEquals( 3, baseClasses.size() );
+ BaseSpecifier bs = (BaseSpecifier)baseClasses.get( 0 );
+ assertEquals( bs.getAccess(), BaseSpecifier.t_public );
+ assertEquals( bs.isVirtual(), false );
+ assertEquals( bs.getName(), "B" );
+
+ bs = (BaseSpecifier)baseClasses.get( 1 );
+ assertEquals( bs.getAccess(), BaseSpecifier.t_private );
+ assertEquals( bs.isVirtual(), false );
+ assertEquals( bs.getName(), "C" );
+
+ bs = (BaseSpecifier)baseClasses.get( 2 );
+ assertEquals( bs.getAccess(), BaseSpecifier.t_protected );
+ assertEquals( bs.isVirtual(), true );
+ assertEquals( bs.getName(), "D" );
+
+
+ // Get the member declaration
+ declarations = classSpecifier.getDeclarations();
+ assertEquals(2, declarations.size());
+ declaration = (SimpleDeclaration)declarations.get(0);
+
+ // Make sure it's an int
+ assertEquals(DeclarationSpecifier.t_int, declaration.getDeclSpecifier().getDeclSpecifierSeq());
+
+ // Get the declarator and check it's name
+ List declarators = declaration.getDeclarators();
+ assertEquals(2, declarators.size());
+ Declarator declarator = (Declarator)declarators.get(0);
+ Name name = declarator.getName();
+ assertEquals("x", name.toString());
+ declarator = (Declarator)declarators.get(1);
+ name = declarator.getName();
+ assertEquals("y", name.toString());
+
+ declaration = (SimpleDeclaration)declarations.get(1);
+ // Make sure it's an float
+ assertEquals(DeclarationSpecifier.t_float, declaration.getDeclSpecifier().getDeclSpecifierSeq());
+ declarators = declaration.getDeclarators();
+ assertEquals( 3, declarators.size() );
+ name = ((Declarator)declarators.get(0)).getName();
+ assertEquals( "a", name.toString() );
+ name = ((Declarator)declarators.get(1)).getName();
+ assertEquals( "b", name.toString() );
+ name = ((Declarator)declarators.get(2)).getName();
+ assertEquals( "c", name.toString() );
+
+ }
+
+
+ /**
+ * Test code: int myFunction( void );
+ */
+ public void testSimpleFunctionDeclaration() throws Exception
+ {
+ // Parse and get the translaton unit
+ Writer code = new StringWriter();
+ code.write("void myFunction( void );");
+ TranslationUnit translationUnit = parse(code.toString());
+
+ // Get the declaration
+ List declarations = translationUnit.getDeclarations();
+ assertEquals(1, declarations.size());
+ SimpleDeclaration simpleDeclaration = (SimpleDeclaration)declarations.get(0);
+ assertEquals( simpleDeclaration.getDeclSpecifier().getType(), DeclarationSpecifier.t_void );
+ List declarators = simpleDeclaration.getDeclarators();
+ assertEquals( 1, declarators.size() );
+ Declarator functionDeclarator = (Declarator)declarators.get( 0 );
+ assertEquals( functionDeclarator.getName().toString(), "myFunction" );
+ ParameterDeclarationClause pdc = functionDeclarator.getParms();
+ assertNotNull( pdc );
+ List parameterDecls = pdc.getDeclarations();
+ assertEquals( 1, parameterDecls.size() );
+ ParameterDeclaration parm1 = (ParameterDeclaration)parameterDecls.get( 0 );
+ assertEquals( DeclarationSpecifier.t_void, parm1.getDeclSpecifier().getType() );
+ List parm1Decls = parm1.getDeclarators();
+ assertEquals( 1, parm1Decls.size() );
+ Declarator parm1Declarator = (Declarator) parm1Decls.get(0);
+ assertNull( parm1Declarator.getName() );
+ }
+
+ /**
+ * Test code: "class A { int floor( double input ), someInt; };"
+ */
+ public void testMultipleDeclarators() throws Exception
+ {
+ // Parse and get the translaton unit
+ Writer code = new StringWriter();
+ code.write("class A { int floor( double input ), someInt; };");
+ TranslationUnit translationUnit = parse(code.toString());
+
+ List tudeclarations = translationUnit.getDeclarations();
+ assertEquals( 1, tudeclarations.size() );
+ SimpleDeclaration classDecl = (SimpleDeclaration)tudeclarations.get(0);
+ assertEquals( 0, classDecl.getDeclarators().size() );
+ ClassSpecifier classSpec = (ClassSpecifier)classDecl.getTypeSpecifier();
+
+ List classDeclarations = classSpec.getDeclarations();
+ assertEquals( classDeclarations.size(), 1 );
+ SimpleDeclaration simpleDeclaration = (SimpleDeclaration)classDeclarations.get(0);
+ assertEquals( simpleDeclaration.getDeclSpecifier().getType(), DeclarationSpecifier.t_int );
+ List simpleDeclarators = simpleDeclaration.getDeclarators();
+ assertEquals( simpleDeclarators.size(), 2 );
+ Declarator methodDeclarator = (Declarator)simpleDeclarators.get(0);
+ assertEquals( methodDeclarator.getName().toString(), "floor" );
+ ParameterDeclarationClause pdc = methodDeclarator.getParms();
+ assertNotNull( pdc );
+ List parameterDeclarations = pdc.getDeclarations();
+ assertEquals( 1, parameterDeclarations.size() );
+ ParameterDeclaration parm1Declaration = (ParameterDeclaration)parameterDeclarations.get(0);
+ assertEquals( DeclarationSpecifier.t_double, parm1Declaration.getDeclSpecifier().getType() );
+ List parm1Declarators = parm1Declaration.getDeclarators();
+ assertEquals( parm1Declarators.size(), 1 );
+ Declarator parm1Declarator = (Declarator)parm1Declarators.get(0);
+ assertEquals( parm1Declarator.getName().toString(), "input" );
+ Declarator integerDeclarator = (Declarator)simpleDeclarators.get(1);
+ assertEquals( integerDeclarator.getName().toString(), "someInt" );
+ assertNull( integerDeclarator.getParms() );
+ }
+
+// public void testErrors()
+// {
+// validateWeEncounterAnError( "void myFunc( int hey, flo );");
+// }
+
+ public void validateWeEncounterAnError( String codeText )
+ {
+ try
+ {
+ // Parse and get the translaton unit
+ Writer code = new StringWriter();
+ code.write(codeText);
+ try
+ {
+ TranslationUnit translationUnit = parse(code.toString());
+ fail( "We should not reach this line. Failure.");
+ } catch( ParserException pe )
+ {
+ }
+ catch( Exception e )
+ {
+ fail( "Unknown exception " + e.getMessage() );
+ }
+ }catch( IOException io )
+ {
+ fail( "IOException thrown");
+ }
+
+ }
+}
+
diff --git a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ExprEvalTest.java b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ExprEvalTest.java
new file mode 100644
index 00000000000..fd330147e7e
--- /dev/null
+++ b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ExprEvalTest.java
@@ -0,0 +1,41 @@
+package org.eclipse.cdt.core.parser.tests;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.internal.core.parser.ExpressionEvaluator;
+import org.eclipse.cdt.internal.core.parser.Parser;
+
+public class ExprEvalTest extends TestCase {
+
+ public static Test suite() {
+ return new TestSuite(ExprEvalTest.class);
+ }
+
+ public ExprEvalTest(String name) {
+ super(name);
+ }
+
+ public void runTest(String code, int expectedValue) throws Exception {
+ ExpressionEvaluator evaluator = new ExpressionEvaluator();
+ Parser parser = new Parser(code, evaluator);
+ parser.expression();
+ assertEquals(expectedValue, ((Integer)evaluator.getResult()).intValue());
+ }
+
+ public void testInteger() throws Exception {
+ runTest("5", 5);
+ }
+
+ public void testRelational() throws Exception {
+ runTest("1 < 2", 1);
+ runTest("2 < 1", 0);
+ runTest("2 == 1 + 1", 1);
+ runTest("2 != 1 + 1", 0);
+ }
+
+ public void testBracketed() throws Exception {
+ runTest("2 * (3 + 4)", 14);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java
new file mode 100644
index 00000000000..a2cb060dfef
--- /dev/null
+++ b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java
@@ -0,0 +1,500 @@
+package org.eclipse.cdt.core.parser.tests;
+
+import junit.framework.TestCase;
+
+import java.util.Iterator;
+import java.util.Map;
+import org.eclipse.cdt.internal.core.parser.Declaration;
+import org.eclipse.cdt.internal.core.parser.ParserSymbolTable;
+import org.eclipse.cdt.internal.core.parser.ParserSymbolTableException;
+
+/**
+ * @author aniefer
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ParserSymbolTableTest extends TestCase {
+
+ public ParserSymbolTable table = null;
+ public ParserSymbolTable newTable(){
+ table = new ParserSymbolTable();
+ return table;
+ }
+
+ /**
+ * testSimpleAdd.
+ * Add a declaration to the table and confirm it is there.
+ *
+ * @throws Exception
+ */
+ public void testSimpleAdd() throws Exception{
+ newTable(); //create the symbol table
+
+ Declaration decl = new Declaration( "x" );
+
+ table.addDeclaration( decl );
+
+ Declaration compUnit = table.getCompilationUnit();
+ assertEquals( compUnit, table.peek() );
+
+ Map declarations = compUnit.getContainedDeclarations();
+ assertEquals( 1, declarations.size() );
+
+ Iterator iter = declarations.values().iterator();
+ Declaration contained = (Declaration) iter.next();
+
+ assertEquals( false, iter.hasNext() );
+ assertEquals( decl, contained );
+ assertEquals( contained.getName(), "x" );
+ }
+
+ /**
+ * testSimpleLookup
+ * Add a declaration to the table, then look it up.
+ * @throws Exception
+ */
+ public void testSimpleLookup() throws Exception{
+ newTable(); //new symbol table
+
+ Declaration decl = new Declaration( "x" );
+
+ table.addDeclaration( decl );
+
+ Declaration look = table.Lookup( "x" );
+
+ assertEquals( decl, look );
+ }
+
+ public void testLookupNonExistant() throws Exception{
+ newTable();
+
+ Declaration look = table.Lookup( "boo" );
+ assertEquals( look, null );
+ }
+
+ /**
+ * testSimplePushPop
+ * test pushing and popping
+ * @throws Exception
+ */
+ public void testSimplePushPop() throws Exception{
+ newTable();
+
+ Declaration pushing = new Declaration( "class" );
+ assertEquals( pushing.getContainingScope(), null );
+
+ table.push( pushing );
+ assertEquals( pushing, table.peek() );
+ assertEquals( pushing.getContainingScope(), table.getCompilationUnit() );
+
+ Declaration popped = table.pop();
+ assertEquals( pushing, popped );
+ assertEquals( table.peek(), table.getCompilationUnit() );
+ }
+
+ public void testSimpleSetGetObject() throws Exception{
+ newTable();
+
+ Declaration decl = new Declaration( "x" );
+ Object obj = new Object();
+
+ decl.setObject( obj );
+
+ table.addDeclaration( decl );
+
+ Declaration look = table.Lookup( "x" );
+
+ assertEquals( look.getObject(), obj );
+ }
+
+ /**
+ * testHide
+ * test that a declaration in a scope hides declarations in containing
+ * scopes
+ * @throws Exception
+ */
+ public void testHide() throws Exception{
+ newTable();
+
+ Declaration firstX = new Declaration( "x" );
+ table.addDeclaration( firstX );
+
+ Declaration firstClass = new Declaration( "class" );
+ table.addDeclaration( firstClass );
+ table.push( firstClass );
+
+ Declaration look = table.Lookup( "x" );
+ assertEquals( look, firstX );
+
+ Declaration secondX = new Declaration( "x" );
+ table.addDeclaration( secondX );
+
+ look = table.Lookup( "x" );
+ assertEquals( look, secondX );
+
+ table.pop();
+
+ look = table.Lookup( "x" );
+ assertEquals( look, firstX );
+ }
+
+ /**
+ * testContainingScopeLookup
+ * test lookup of something declared in the containing scope
+ * @throws Exception
+ */
+ public void testContainingScopeLookup() throws Exception{
+ newTable();
+
+ Declaration x = new Declaration("x");
+ Declaration cls = new Declaration("class");
+
+ table.addDeclaration( x );
+ table.addDeclaration( cls );
+ table.push( cls );
+
+ Declaration look = table.Lookup( "x" );
+
+ assertEquals( x, look );
+ }
+
+ /**
+ * testParentLookup
+ * test lookup of a variable declaration in the parent
+ *
+ * @throws Exception
+ */
+ public void testParentLookup() throws Exception{
+ newTable();
+
+ Declaration class1 = new Declaration( "class" );
+ Declaration parent = new Declaration( "parent" );
+ Declaration decl = new Declaration( "x" );
+
+ table.addDeclaration( parent );
+ table.push( parent );
+ table.addDeclaration( decl );
+ table.pop();
+
+ class1.addParent( parent );
+ table.addDeclaration( class1 );
+ table.push( class1 );
+
+ Declaration look = table.Lookup( "x" );
+ assertEquals( look, decl );
+
+ table.pop();
+ assertEquals( table.peek(), table.getCompilationUnit() );
+ }
+
+ /**
+ * testAmbiguousParentLookup
+ * calls testParentLookup
+ *
+ * tests that if a variable is declared in two parents that the lookup
+ * returns an ambiguous result.
+ *
+ * @throws Exception
+ */
+ public void testAmbiguousParentLookup() throws Exception{
+ testParentLookup();
+
+ Declaration parent2 = new Declaration( "parent2" );
+
+ table.addDeclaration( parent2 );
+
+ Declaration class1 = table.Lookup( "class" );
+ class1.addParent( parent2 );
+
+ Declaration decl = new Declaration("x");
+ table.push( parent2 );
+ table.addDeclaration( decl );
+ table.pop();
+
+ table.push( class1 );
+ try{
+ table.Lookup( "x" );
+ assertTrue( false );
+ }
+ catch ( ParserSymbolTableException e ){
+ assertTrue( true );
+ }
+
+ }
+
+ /**
+ * testVirtualParentLookup
+ *
+ * @throws Exception
+ * tests lookup of name in virtual baseclass C
+ *
+ * C
+ * / \
+ * A B
+ * \ /
+ * class
+ */
+ public void testVirtualParentLookup() throws Exception{
+ newTable();
+
+ Declaration decl = new Declaration("class");
+ Declaration c = new Declaration("C");
+
+ Declaration a = new Declaration("A");
+ a.addParent( c, true );
+
+ Declaration b = new Declaration("B");
+ b.addParent( c, true );
+
+ decl.addParent( a );
+ decl.addParent( b );
+
+ table.addDeclaration( c );
+ table.push( c );
+ Declaration x = new Declaration( "x" );
+ table.addDeclaration( x );
+ table.pop();
+
+ table.addDeclaration( decl );
+ table.addDeclaration( a );
+ table.addDeclaration( b );
+
+ table.push(decl);
+
+ Declaration look = table.Lookup( "x" );
+
+ assertEquals( look, x );
+
+ table.pop();
+
+ assertEquals( table.peek(), table.getCompilationUnit() );
+ }
+
+ /**
+ * testAmbiguousVirtualParentLookup
+ * @throws Exception
+ *
+ * tests lookup of name in base class C in the following hierarchy
+ * C C
+ * / \ |
+ * A B D
+ * \ / /
+ * class
+ */
+ public void testAmbiguousVirtualParentLookup() throws Exception{
+ testVirtualParentLookup();
+
+ Declaration cls = table.Lookup("class");
+ Declaration c = table.Lookup("C");
+ Declaration d = new Declaration("D");
+
+ d.addParent( c );
+
+ cls.addParent( d );
+
+ table.push( cls );
+
+ try{
+ table.Lookup( "x" );
+ assertTrue( false );
+ }
+ catch( ParserSymbolTableException e){
+ assertTrue( true );
+ }
+ }
+
+ /**
+ * testStaticEnumParentLookup
+ *
+ * @throws Exception
+ *
+ * D D
+ * | |
+ * B C
+ * \ /
+ * A
+ *
+ * Things defined in D are not ambiguous if they are static or an enum
+ */
+ public void testStaticEnumParentLookup() throws Exception{
+ newTable();
+
+ Declaration a = new Declaration( "a" );
+ Declaration b = new Declaration( "b" );
+ Declaration c = new Declaration( "c" );
+ Declaration d = new Declaration( "d" );
+
+ table.addDeclaration( a );
+ table.addDeclaration( b );
+ table.addDeclaration( c );
+ table.addDeclaration( d );
+
+ Declaration enum = new Declaration("enum");
+ enum.setType( Declaration.t_enum );
+
+ Declaration stat = new Declaration("static");
+ stat.setStatic(true);
+
+ Declaration x = new Declaration("x");
+
+ table.push(d);
+ table.addDeclaration( enum );
+ table.addDeclaration( stat );
+ table.addDeclaration( x );
+ table.pop();
+
+ a.addParent( b );
+ a.addParent( c );
+ b.addParent( d );
+ c.addParent( d );
+
+ table.push( a );
+ try{
+ table.Lookup( "enum" );
+ assertTrue( true );
+ }
+ catch ( ParserSymbolTableException e){
+ assertTrue( false );
+ }
+
+ try{
+ table.Lookup( "static" );
+ assertTrue( true );
+ }
+ catch ( ParserSymbolTableException e){
+ assertTrue( false );
+ }
+
+ try{
+ table.Lookup( "x" );
+ assertTrue( false );
+ }
+ catch ( ParserSymbolTableException e){
+ assertTrue( true );
+ }
+ }
+
+ /**
+ * testElaboratedLookup
+ * @throws Exception
+ * test lookup of hidden names using elaborated type spec
+ */
+ public void testElaboratedLookup() throws Exception{
+ newTable();
+
+ Declaration cls = new Declaration( "class" );
+ cls.setType( Declaration.t_class );
+
+ Declaration struct = new Declaration("struct");
+ struct.setType( Declaration.t_struct );
+
+ Declaration union = new Declaration("union");
+ union.setType( Declaration.t_union );
+
+ Declaration hideCls = new Declaration( "class" );
+ Declaration hideStruct = new Declaration("struct");
+ Declaration hideUnion = new Declaration("union");
+
+ Declaration a = new Declaration("a");
+ Declaration b = new Declaration("b");
+
+ table.push(a);
+ table.addDeclaration(hideCls);
+ table.addDeclaration(hideStruct);
+ table.addDeclaration(hideUnion);
+
+ a.addParent( b );
+
+ table.push(b);
+ table.addDeclaration(cls);
+ table.addDeclaration(struct);
+ table.addDeclaration(union);
+ table.pop();
+
+ Declaration look = table.ElaboratedLookup( Declaration.t_class, "class" );
+ assertEquals( look, cls );
+ look = table.ElaboratedLookup( Declaration.t_struct, "struct" );
+ assertEquals( look, struct );
+ look = table.ElaboratedLookup( Declaration.t_union, "union" );
+ assertEquals( look, union );
+ }
+
+ /**
+ * testDeclarationType
+ * @throws Exception
+ * test the use of Declaration type in the scenario
+ * A a;
+ * a.member <=...>;
+ * where A was previously declared
+ */
+ public void testDeclarationType() throws Exception{
+ newTable();
+ //pre-condition
+ Declaration A = new Declaration("A");
+ table.addDeclaration(A);
+
+ Declaration member = new Declaration("member");
+ table.push(A);
+ table.addDeclaration(member);
+ table.pop();
+
+ //at time of "A a;"
+ Declaration look = table.Lookup("A");
+ assertEquals( look, A );
+ Declaration a = new Declaration("a");
+ a.setTypeDeclaration( look );
+ table.addDeclaration( a );
+
+ //later "a.member"
+ look = table.Lookup("a");
+ assertEquals( look, a );
+ Declaration type = look.getTypeDeclaration();
+ assertEquals( type, A );
+ table.push(type);
+ look = table.Lookup("member");
+ assertEquals( look, member );
+ }
+
+ /**
+ * testFunctions
+ * @throws Exception
+ * Functions are stored by signature. Where the signature can really be of
+ * any for you like, as long as it can't possibly be a regular name (ie
+ * including the parenthese is good...)
+ * So lookup of function names proceeds inthe same manner as normal names,
+ * this test doesn't really test anything new
+ */
+
+ public void testFunctions() throws Exception{
+ newTable();
+
+ Declaration cls = new Declaration( "class");
+ Declaration f1 = new Declaration("foo()");
+ Declaration f2 = new Declaration("foo(int)");
+ Declaration f3 = new Declaration("foo(int,char)");
+
+ table.addDeclaration(cls);
+ table.push(cls);
+
+ table.addDeclaration( f1 );
+ table.addDeclaration( f2 );
+ table.addDeclaration( f3 );
+
+ //return type can be specified by setting the TypeDeclaration
+ Declaration returnType = new Declaration("return");
+ f1.setTypeDeclaration( returnType );
+ f2.setTypeDeclaration( returnType );
+ f3.setTypeDeclaration( returnType );
+
+ assertEquals( table.Lookup("foo()"), f1 );
+ assertEquals( table.Lookup("foo(int)"), f2 );
+ assertEquals( table.Lookup("foo(int,char)"), f3 );
+
+ //notice that, with the current implementation, you can't do a lookup
+ //on just the function name without the rest of the signature
+ assertEquals( table.Lookup("foo"), null );
+ }
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java
new file mode 100644
index 00000000000..af88698b8ae
--- /dev/null
+++ b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java
@@ -0,0 +1,990 @@
+package org.eclipse.cdt.core.parser.tests;
+
+import java.io.StringReader;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.internal.core.parser.IMacroDescriptor;
+import org.eclipse.cdt.internal.core.parser.Scanner;
+import org.eclipse.cdt.internal.core.parser.ScannerException;
+import org.eclipse.cdt.internal.core.parser.Token;
+
+/**
+ * @author jcamelon
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class ScannerTestCase extends TestCase
+{
+ public class TableRow
+ {
+ private int[] values;
+ private int length;
+
+ public TableRow(int[] v)
+ {
+ length= v.length;
+ values= new int[length];
+ System.arraycopy(v, 0, values, 0, length);
+ }
+
+ public String toString()
+ {
+ StringBuffer s= new StringBuffer();
+ for (int i= 0; i < length; ++i)
+ {
+ s.append("var").append(i).append("=").append(values[i]).append(" ");
+ }
+ return s.toString();
+ }
+
+ public String symbolName(int index)
+ {
+ return "DEFINITION" + index;
+ }
+
+ public int symbolValue(int index)
+ {
+ return new Long(Math.round(Math.pow(index, index))).intValue();
+ }
+
+ public String generateCode()
+ {
+ if (length < 2)
+ {
+ return "Array must have at least 2 elements";
+ }
+ int numberOfElsifs= length - 1;
+ StringBuffer buffer= new StringBuffer();
+ buffer.append("#if ").append(values[0]).append("\n#\tdefine ");
+ buffer.append(symbolName(0)).append(" ").append(symbolValue(0));
+ for (int i= 0; i < numberOfElsifs; ++i)
+ buffer
+ .append("\n#elif ")
+ .append(values[1 + i])
+ .append("\n#\tdefine ")
+ .append(symbolName(i + 1))
+ .append(" ")
+ .append(symbolValue(i + 1));
+ buffer
+ .append("\n#else \n#\tdefine ")
+ .append(symbolName(length))
+ .append(" ")
+ .append(symbolValue(length))
+ .append("\n#endif");
+ return buffer.toString();
+ }
+
+ public int selectWinner()
+ {
+ for (int i= 0; i < values.length; ++i)
+ {
+ if (values[i] != 0)
+ {
+ return i;
+ }
+ }
+ return length;
+ }
+ /**
+ * Returns the length.
+ * @return int
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ }
+
+ public class TruthTable
+ {
+ private int numberOfVariables;
+ private int numberOfRows;
+ public TableRow[] rows;
+
+ public TruthTable(int n)
+ {
+ numberOfVariables= n;
+ numberOfRows= new Long(Math.round(Math.pow(2, n))).intValue();
+
+ rows= new TableRow[numberOfRows];
+ for (int i= 0; i < numberOfRows; ++i)
+ {
+ String Z= Integer.toBinaryString(i);
+
+ int[] input= new int[numberOfVariables];
+ for (int j= 0; j < numberOfVariables; ++j)
+ {
+ int padding= numberOfVariables - Z.length();
+ int k= 0;
+ for (; k < padding; ++k)
+ {
+ input[k]= 0;
+ }
+ for (int l= 0; l < Z.length(); ++l)
+ {
+ char c= Z.charAt(l);
+ int value= Character.digit(c, 10);
+ input[k++]= value;
+ }
+ }
+ rows[i]= new TableRow(input);
+ }
+ }
+ /**
+ * Returns the numberOfRows.
+ * @return int
+ */
+ public int getNumberOfRows()
+ {
+ return numberOfRows;
+ }
+
+ }
+
+ public final static String EXCEPTION_THROWN= "Exception thrown ";
+ public final static String EXPECTED_FAILURE=
+ "This statement should not be reached "
+ + "as we sent in bad preprocessor input to the scanner";
+ public final static boolean verbose= false;
+ public final static boolean doConcatenation= false;
+ public final static boolean doIncludeStdio= false;
+ public final static boolean doIncludeWindowsH= false;
+ public final static boolean doIncludeWinUserH= false;
+
+ public final static int SIZEOF_TRUTHTABLE = 10;
+
+ public void initializeScanner(String input)
+ {
+ scanner= new Scanner();
+ scanner.initialize( new StringReader(input),"TEXT");
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(ScannerTestCase.class);
+ }
+
+ public int fullyTokenize() throws Exception
+ {
+ try
+ {
+ Token t= scanner.nextToken();
+ while ((t != null) && (t.type != Token.tEOF))
+ {
+ if (verbose)
+ System.out.println("Token t = " + t);
+
+ if ((t.type < Token.tEOF) || (t.type > Token.tLAST))
+ System.out.println("Unknown type for token " + t);
+ t= scanner.nextToken();
+ }
+ }
+ catch (ScannerException se)
+ {
+ throw se;
+ }
+ return scanner.getCount();
+ }
+
+ Scanner scanner;
+
+ /**
+ * Constructor for ScannerTestCase.
+ * @param name
+ */
+ public ScannerTestCase(String name)
+ {
+ super(name);
+ }
+
+ public void testPreprocessorDefines()
+ {
+ try
+ {
+ initializeScanner("#define SIMPLE_NUMERIC 5\nint x = SIMPLE_NUMERIC");
+ validateToken(Token.t_int);
+ validateDefinition("SIMPLE_NUMERIC", "5");
+ validateIdentifier("x");
+ validateToken(Token.tASSIGN);
+ validateInteger("5");
+ validateEOF();
+
+ initializeScanner("#define SIMPLE_STRING \"This is a simple string.\"\n\nconst char * myVariable = SIMPLE_STRING;");
+ validateToken(Token.t_const);
+ validateDefinition("SIMPLE_STRING", "\"This is a simple string.\"");
+ validateToken(Token.t_char);
+ validateToken(Token.tSTAR);
+ validateIdentifier("myVariable");
+ validateToken(Token.tASSIGN);
+ validateString("This is a simple string.");
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ initializeScanner("#define FOOL 5 \n int tryAFOOL = FOOL + FOOL;");
+
+ validateToken(Token.t_int);
+ validateIdentifier("tryAFOOL");
+ validateToken(Token.tASSIGN);
+ validateInteger("5");
+ validateToken(Token.tPLUS);
+ validateInteger("5");
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ initializeScanner("#define FOOL 5 \n int FOOLer = FOOL;");
+
+ validateToken(Token.t_int);
+ validateIdentifier("FOOLer");
+ validateToken(Token.tASSIGN);
+ validateInteger("5");
+ validateToken(Token.tSEMI);
+ validateToken(Token.tEOF);
+
+ // the case we were failing against in ctype.h
+ // this is a definition, not a macro!
+ initializeScanner("#define _ALPHA (0x0100|_UPPER|_LOWER)");
+ validateEOF();
+ validateDefinition("_ALPHA", "(0x0100|_UPPER|_LOWER)");
+
+ // test for comments after the macro
+ initializeScanner("#define NO_COMMENT// ignore me");
+ validateEOF();
+ validateDefinition("NO_COMMENT", "");
+
+ initializeScanner("#define NO_COMMENT/* ignore me*/");
+ validateEOF();
+ validateDefinition("NO_COMMENT", "");
+
+ initializeScanner("#define ANSWER 42 // i think");
+ validateEOF();
+ validateDefinition("ANSWER", "42");
+
+ initializeScanner("#define ANSWER 42 /* i think */");
+ validateEOF();
+ validateDefinition("ANSWER", "42");
+
+ initializeScanner("#define MULTILINE 3 /* comment \n that goes more than one line */");
+ validateEOF();
+ validateDefinition("MULTILINE", "3");
+
+ initializeScanner("#define MULTICOMMENT X /* comment1 */ + Y /* comment 2 */");
+ validateEOF();
+ validateDefinition("MULTICOMMENT", "X + Y");
+
+ for (int i= 0; i < 7; ++i)
+ {
+ switch (i)
+ {
+ case 0 :
+ initializeScanner("#define SIMPLE_STRING This is a simple string.\n");
+ break;
+ case 1 :
+ initializeScanner("# define SIMPLE_NUMERIC 5\n");
+ break;
+ case 2 :
+ initializeScanner("# define SIMPLE_NUMERIC 5\n");
+ break;
+ case 3 :
+ initializeScanner("#define SIMPLE_STRING \"This is a simple string.\"\n");
+ break;
+ case 4 :
+ initializeScanner("#define SIMPLE_STRING This is a simple string.\n");
+ break;
+ case 5 :
+ initializeScanner("#define FLAKE\n\nFLAKE");
+ break;
+ case 6 :
+ initializeScanner("#define SIMPLE_STRING This is a simple string.\\\n Continue please.");
+ break;
+ }
+ validateEOF();
+
+ switch (i)
+ {
+ case 0 :
+ validateDefinition(
+ "SIMPLE_STRING",
+ "This is a simple string.");
+ break;
+ case 1 :
+ validateDefinition("SIMPLE_NUMERIC", "5");
+ break;
+ case 2 :
+ validateDefinition("SIMPLE_NUMERIC", "5");
+ break;
+ case 3 :
+ validateDefinition(
+ "SIMPLE_STRING",
+ "\"This is a simple string.\"");
+ break;
+ case 4 :
+ validateDefinition(
+ "SIMPLE_STRING",
+ "This is a simple string.");
+ break;
+ case 5 :
+ validateDefinition("FLAKE", "");
+ break;
+ case 6 :
+ validateDefinition(
+ "SIMPLE_STRING",
+ "This is a simple string. Continue please.");
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+ }
+
+ public void prepareForWindowsRH()
+ {
+ scanner.addIncludePath(
+ "C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\PlatformSDK\\include");
+ scanner.addDefinition("_WIN32_WINNT", "0x0300");
+ scanner.addDefinition("WINVER", "0x0400");
+ scanner.addDefinition("_WIN32_WINDOWS", "0x0300");
+ scanner.addDefinition("_MSC_VER", "1200");
+ }
+
+ public void prepareForWindowsH()
+ {
+ scanner.addIncludePath(
+ "C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\PlatformSDK\\include");
+ scanner.addIncludePath(
+ "C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\include");
+ scanner.addDefinition("_MSC_VER", "1200");
+ scanner.addDefinition("__cplusplus", "1");
+ scanner.addDefinition("__STDC__", "1");
+ scanner.addDefinition("_WIN32", "");
+ scanner.addDefinition( "__midl", "1000" );
+ }
+
+ public void prepareForStdio()
+ {
+ scanner.addIncludePath(
+ "C:\\Program Files\\Microsoft Visual Studio .NET\\Vc7\\include");
+ scanner.addDefinition("_MSC_VER", "1100");
+ scanner.addDefinition("__STDC__", "1");
+ scanner.addDefinition("_INTEGRAL_MAX_BITS", "64");
+ scanner.addDefinition("_WIN32", "");
+ }
+
+ public void testConcatenation()
+ {
+ if (doConcatenation)
+ {
+ try
+ {
+ initializeScanner("#define F1 3\n#define F2 F1##F1\nint x=F2;");
+ validateToken(Token.t_int);
+ validateDefinition("F1", "3");
+ validateDefinition("F2", "F1##F1");
+ validateIdentifier("x");
+ validateToken(Token.tASSIGN);
+ validateInteger("33");
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ initializeScanner("#define PREFIX RT_\n#define RUN PREFIX##Run");
+ validateEOF();
+ validateDefinition( "PREFIX", "RT_" );
+ validateDefinition( "RUN", "RT_Run" );
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+ }
+ }
+
+ public void testSimpleIfdef()
+ {
+ try
+ {
+
+ initializeScanner("#define SYMBOL 5\n#ifdef SYMBOL\nint counter(SYMBOL);\n#endif");
+
+ validateToken(Token.t_int);
+ validateIdentifier("counter");
+ validateToken(Token.tLPAREN);
+ validateInteger("5");
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ initializeScanner("#define SYMBOL 5\n#ifndef SYMBOL\nint counter(SYMBOL);\n#endif");
+ validateToken(Token.tEOF);
+
+ initializeScanner("#ifndef DEFINED\n#define DEFINED 100\n#endif\nint count = DEFINED;");
+ validateToken(Token.t_int);
+ validateDefinition("DEFINED", "100");
+
+ validateIdentifier("count");
+ validateToken(Token.tASSIGN);
+ validateInteger("100");
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ initializeScanner("#ifndef DEFINED\n#define DEFINED 100\n#endif\nint count = DEFINED;");
+ scanner.addDefinition("DEFINED", "101");
+
+ validateDefinition("DEFINED", "101");
+ validateToken(Token.t_int);
+ validateIdentifier("count");
+ validateToken(Token.tASSIGN);
+ validateInteger("101");
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+ }
+
+ public void testSlightlyComplexIfdefStructure()
+ {
+ try
+ {
+ initializeScanner("#ifndef BASE\n#define BASE 10\n#endif\n#ifndef BASE\n#error BASE is defined\n#endif");
+ validateEOF();
+ validateBalance();
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+
+ try
+ {
+ initializeScanner("#ifndef ONE\n#define ONE 1\n#ifdef TWO\n#define THREE ONE + TWO\n#endif\n#endif\nint three(THREE);");
+
+ validateToken(Token.t_int);
+ validateDefinition("ONE", "1");
+ validateAsUndefined("TWO");
+ validateAsUndefined("THREE");
+ validateIdentifier("three");
+ validateToken(Token.tLPAREN);
+ validateIdentifier("THREE");
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tSEMI);
+ validateEOF();
+ validateBalance();
+
+ initializeScanner("#ifndef ONE\n#define ONE 1\n#ifdef TWO\n#define THREE ONE + TWO\n#endif\n#endif\nint three(THREE);");
+ scanner.addDefinition("TWO", "2");
+ validateToken(Token.t_int);
+ validateDefinition("ONE", "1");
+ validateDefinition("TWO", "2");
+ validateDefinition("THREE", "ONE + TWO");
+
+ validateIdentifier("three");
+ validateToken(Token.tLPAREN);
+ validateInteger("1");
+ validateToken(Token.tPLUS);
+ validateInteger("2");
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tSEMI);
+ validateEOF();
+ validateBalance();
+
+ initializeScanner("#ifndef FOO\n#define FOO 4\n#else\n#undef FOO\n#define FOO 6\n#endif");
+ validateToken(Token.tEOF);
+ validateBalance();
+ validateDefinition("FOO", "4");
+
+ initializeScanner("#ifndef FOO\n#define FOO 4\n#else\n#undef FOO\n#define FOO 6\n#endif");
+ scanner.addDefinition("FOO", "2");
+ validateEOF();
+ validateBalance();
+ validateDefinition("FOO", "6");
+
+ initializeScanner("#ifndef ONE\n# define ONE 1\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#else\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#endif\n");
+ validateEOF();
+ validateBalance();
+ validateDefinition("ONE", "1");
+ validateDefinition("TWO", "ONE + ONE");
+
+ initializeScanner("#ifndef ONE\n# define ONE 1\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#else\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#endif\n");
+ scanner.addDefinition("ONE", "one");
+ validateEOF();
+ validateBalance();
+ validateDefinition("ONE", "one");
+ validateDefinition("TWO", "ONE + ONE");
+
+ initializeScanner("#ifndef ONE\n# define ONE 1\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#else\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#endif\n");
+ scanner.addDefinition("ONE", "one");
+ scanner.addDefinition("TWO", "two");
+ validateEOF();
+ validateBalance();
+
+ validateDefinition("ONE", "one");
+ validateDefinition("TWO", "2");
+
+ initializeScanner("#ifndef ONE\n# define ONE 1\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#else\n# ifndef TWO\n# define TWO ONE + ONE \n# else\n# undef TWO\n# define TWO 2 \n# endif\n#endif\n");
+ scanner.addDefinition("TWO", "two");
+ validateEOF();
+ validateBalance();
+
+ validateDefinition("ONE", "1");
+ validateDefinition("TWO", "2");
+
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+ }
+
+ public void testIfs()
+ {
+ try
+ {
+ initializeScanner("#if 0\n#error NEVER\n#endif\n");
+ validateEOF();
+ validateBalance();
+
+ initializeScanner("#define X 5\n#define Y 7\n#if (X < Y)\n#define Z X + Y\n#endif");
+ validateEOF();
+ validateBalance();
+ validateDefinition("X", "5");
+ validateDefinition("Y", "7");
+ validateDefinition("Z", "X + Y");
+
+ initializeScanner("#if T < 20\n#define Z T + 1\n#endif");
+ scanner.addDefinition("X", "5");
+ scanner.addDefinition("Y", "7");
+ scanner.addDefinition("T", "X + Y");
+ validateEOF();
+ validateBalance();
+ validateDefinition("X", "5");
+ validateDefinition("Y", "7");
+ validateDefinition("T", "X + Y");
+ validateDefinition("Z", "T + 1");
+
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+
+ try
+ {
+ initializeScanner("#if ( 10 / 5 ) != 2\n#error 10/5 seems to not equal 2 anymore\n#endif\n");
+ validateEOF();
+ validateBalance();
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+
+ try
+ {
+ initializeScanner("#ifndef FIVE \n#define FIVE 5\n#endif \n#ifndef TEN\n#define TEN 2 * FIVE\n#endif\n#if TEN != 10\n#define MISTAKE 1\n#error Five does not equal 10\n#endif\n");
+ scanner.addDefinition("FIVE", "55");
+ validateEOF();
+ fail(EXPECTED_FAILURE);
+ }
+ catch (ScannerException se)
+ {
+ validateBalance(1);
+ validateDefinition("FIVE", "55");
+ validateDefinition("TEN", "2 * FIVE");
+ validateDefinition("MISTAKE", "1");
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+
+ try
+ {
+ initializeScanner("#if ((( FOUR / TWO ) * THREE )< FIVE )\n#error 6 is not less than 5 \n#endif\n#if ( ( FIVE * ONE ) != (( (FOUR) + ONE ) * ONE ) )\n#error 5 should equal 5\n#endif \n");
+
+ scanner.addDefinition("ONE", "1");
+ scanner.addDefinition("TWO", "(ONE + ONE)");
+ scanner.addDefinition("THREE", "(TWO + ONE)");
+ scanner.addDefinition("FOUR", "(TWO * TWO)");
+ scanner.addDefinition("FIVE", "(THREE + TWO)");
+
+ validateEOF();
+ validateBalance();
+ validateDefinition("ONE", "1");
+ validateDefinition("TWO", "(ONE + ONE)");
+ validateDefinition("THREE", "(TWO + ONE)");
+ validateDefinition("FOUR", "(TWO * TWO)");
+ validateDefinition("FIVE", "(THREE + TWO)");
+
+ TruthTable table= new TruthTable(SIZEOF_TRUTHTABLE);
+ int numberOfRows= table.getNumberOfRows();
+ TableRow[] rows= table.rows;
+
+ for (int i= 0; i < numberOfRows; ++i)
+ {
+ TableRow row= rows[i];
+ String code= row.generateCode();
+ if (verbose)
+ System.out.println("\n\nRow " + i + " has code\n" + code);
+ initializeScanner(code);
+ validateEOF();
+ validateBalance();
+ validateAllDefinitions(row);
+ }
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+
+ try
+ {
+ initializeScanner("#if ! 0\n#error Correct!\n#endif");
+ Token t= scanner.nextToken();
+ fail(EXPECTED_FAILURE);
+ }
+ catch (ScannerException se)
+ {
+ validateBalance(1);
+ assertTrue(se.getMessage().equals("#error Correct!"));
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+ }
+
+ public void testPreprocessorMacros()
+ {
+ try
+ {
+ initializeScanner("#define GO(x) x+1\nint y(5);\ny = GO(y);");
+ validateToken(Token.t_int);
+ validateIdentifier("y");
+ validateToken(Token.tLPAREN);
+ validateInteger("5");
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tSEMI);
+
+ IMacroDescriptor descriptor=
+ (IMacroDescriptor) scanner.getDefinition("GO");
+ List parms= descriptor.getParameters();
+ assertNotNull(parms);
+ assertTrue(parms.size() == 1);
+ String parm1= (String) parms.get(0);
+ assertTrue(parm1.equals("x"));
+ List expansion= descriptor.getTokenizedExpansion();
+ assertNotNull(parms);
+ assertTrue(expansion.size() == 3);
+ assertTrue(((Token) expansion.get(0)).type == Token.tIDENTIFIER);
+ assertTrue(((Token) expansion.get(0)).image.equals("x"));
+ assertTrue(((Token) expansion.get(1)).type == Token.tPLUS);
+ assertTrue(((Token) expansion.get(2)).type == Token.tINTEGER);
+ assertTrue(((Token) expansion.get(2)).image.equals("1"));
+
+ validateIdentifier("y");
+ validateToken(Token.tASSIGN);
+ validateIdentifier("y");
+ validateToken(Token.tPLUS);
+ validateInteger("1");
+ validateToken(Token.tSEMI);
+ validateEOF();
+ validateBalance();
+
+ initializeScanner(
+ "#define ONE 1\n"
+ + "#define SUM(a,b,c,d,e,f,g) ( a + b + c + d + e + f + g )\n"
+ + "int daSum = SUM(ONE,3,5,7,9,11,13);");
+ validateToken(Token.t_int);
+ validateIdentifier("daSum");
+ validateToken(Token.tASSIGN);
+ validateToken(Token.tLPAREN);
+ validateInteger("1");
+ validateToken(Token.tPLUS);
+ validateInteger("3");
+ validateToken(Token.tPLUS);
+ validateInteger("5");
+ validateToken(Token.tPLUS);
+ validateInteger("7");
+ validateToken(Token.tPLUS);
+ validateInteger("9");
+ validateToken(Token.tPLUS);
+ validateInteger("11");
+ validateToken(Token.tPLUS);
+ validateInteger("13");
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ IMacroDescriptor macro= (IMacroDescriptor) scanner.getDefinition("SUM");
+ List params= macro.getParameters();
+ assertNotNull(params);
+ assertTrue(params.size() == 7);
+
+ List tokens= macro.getTokenizedExpansion();
+ assertNotNull(tokens);
+ assertTrue(tokens.size() == 15);
+
+ initializeScanner("#define LOG( format, var1) printf( format, var1 )\nLOG( \"My name is %s\", \"Bogdan\" );\n");
+ validateIdentifier("printf");
+ validateToken(Token.tLPAREN);
+ validateString("My name is %s");
+ validateToken(Token.tCOMMA);
+ validateString("Bogdan");
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ initializeScanner("#define INCR( x ) ++x\nint y(2);\nINCR(y);");
+ validateToken(Token.t_int);
+ validateIdentifier("y");
+ validateToken(Token.tLPAREN);
+ validateInteger("2");
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tSEMI);
+ validateToken(Token.tINCR);
+ validateIdentifier("y");
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ initializeScanner("#define CHECK_AND_SET( x, y, z ) if( x ) { \\\n y = z; \\\n }\n\nCHECK_AND_SET( 1, balance, 5000 );\nCHECK_AND_SET( confused(), you, dumb );");
+ validateToken(Token.t_if);
+ validateToken(Token.tLPAREN);
+ validateInteger("1");
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tLBRACE);
+ validateIdentifier("balance");
+ validateToken(Token.tASSIGN);
+ validateInteger("5000");
+ validateToken(Token.tSEMI);
+ validateToken(Token.tRBRACE);
+ validateToken(Token.tSEMI);
+
+ validateToken(Token.t_if);
+ validateToken(Token.tLPAREN);
+ validateIdentifier("confused");
+ validateToken(Token.tLPAREN);
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tRPAREN);
+ validateToken(Token.tLBRACE);
+ validateIdentifier("you");
+ validateToken(Token.tASSIGN);
+ validateIdentifier("dumb");
+ validateToken(Token.tSEMI);
+ validateToken(Token.tRBRACE);
+ validateToken(Token.tSEMI);
+ validateEOF();
+
+ initializeScanner("#define ON 7\n#if defined(ON)\nint itsOn = ON;\n#endif");
+ validateToken(Token.t_int);
+ validateBalance(1);
+ validateIdentifier("itsOn");
+ validateToken(Token.tASSIGN);
+ validateInteger("7");
+ validateToken(Token.tSEMI);
+ validateEOF();
+ validateBalance();
+
+ initializeScanner("#if defined( NOTHING ) \nint x = NOTHING;\n#endif");
+ validateEOF();
+ validateBalance();
+
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+ }
+
+ public void testInclusions()
+ {
+ try
+ {
+ if (doIncludeStdio)
+ {
+ initializeScanner("#include ");
+ prepareForStdio();
+ int count= fullyTokenize();
+ if (verbose)
+ System.out.println(
+ "For stdio.h, Scanner produced " + count + " tokens");
+ validateBalance();
+
+ initializeScanner("#include \\\n<\\\nstdio.h \\\n>");
+ prepareForStdio();
+ count= fullyTokenize();
+ if (verbose)
+ System.out.println(
+ "For stdio.h, Scanner produced " + count + " tokens");
+ }
+
+ if (doIncludeWindowsH)
+ {
+ initializeScanner("#include ");
+ prepareForWindowsH();
+ int count= fullyTokenize();
+ if (verbose)
+ System.out.println(
+ "For Windows.h, Scanner produced "
+ + scanner.getCount()
+ + " tokens");
+ validateBalance();
+ }
+
+ if (doIncludeWinUserH)
+ {
+ initializeScanner("#include ");
+ prepareForWindowsRH();
+ validateEOF();
+ validateBalance();
+ if (verbose)
+ System.out.println(
+ "For WinUser.rh, Scanner produced "
+ + scanner.getCount()
+ + " tokens");
+ }
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+
+ }
+
+ public void testOtherPreprocessorCommands()
+ {
+ try
+ {
+ initializeScanner("#\n#\t\n#define MAX_SIZE 1024\n#\n# ");
+ validateEOF();
+ validateDefinition("MAX_SIZE", "1024");
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+
+ for (int i= 0; i < 4; ++i)
+ {
+ switch (i)
+ {
+ case 0 :
+ initializeScanner("# ape");
+ break;
+ case 1 :
+ initializeScanner("# #");
+ break;
+ case 2 :
+ initializeScanner("# 32");
+ break;
+ case 3 :
+ initializeScanner("# defines");
+ break;
+ }
+
+ try
+ {
+ validateEOF();
+ fail(EXPECTED_FAILURE);
+ }
+ catch (ScannerException se)
+ {
+ validateBalance();
+ }
+ catch (Exception e)
+ {
+ fail(EXCEPTION_THROWN + e.toString());
+ }
+ }
+
+ }
+
+ public void validateIdentifier(String expectedImage) throws ScannerException
+ {
+ Token t= scanner.nextToken();
+ assertTrue(t.type == Token.tIDENTIFIER);
+ assertTrue(t.image.equals(expectedImage));
+ }
+
+ public void validateInteger(String expectedImage) throws ScannerException
+ {
+ Token t= scanner.nextToken();
+ assertTrue(t.type == Token.tINTEGER);
+ assertTrue(t.image.equals(expectedImage));
+ }
+
+ public void validateString(String expectedImage) throws ScannerException
+ {
+ Token t= scanner.nextToken();
+ assertTrue(t.type == Token.tSTRING);
+ assertTrue(t.image.equals(expectedImage));
+ }
+
+ public void validateToken(int tokenType) throws ScannerException
+ {
+ Token t= scanner.nextToken();
+ assertTrue(t.type == tokenType);
+ }
+
+ public void validateBalance(int expected)
+ {
+ assertTrue(scanner.getDepth() == expected);
+ }
+
+ public void validateBalance()
+ {
+ assertTrue(scanner.getDepth() == 0);
+ }
+
+ public void validateEOF() throws ScannerException
+ {
+ validateToken(Token.tEOF);
+ }
+
+ public void validateDefinition(String name, String value)
+ {
+ String definition= null;
+ definition= (String) scanner.getDefinition(name);
+ assertNotNull(definition);
+ assertTrue(definition.trim().equals(value));
+ }
+
+ public void validateDefinition(String name, int value)
+ {
+ String definition= null;
+ definition= (String) scanner.getDefinition(name);
+ this.assertNotNull(definition);
+ int intValue= (Integer.valueOf((String) definition)).intValue();
+ assertEquals(value, intValue);
+ }
+
+ public void validateAsUndefined(String name)
+ {
+ assertNull(scanner.getDefinition(name));
+ }
+
+ public void validateAllDefinitions(TableRow row)
+ {
+ int winner= row.selectWinner();
+ int rowLength= row.getLength();
+ for (int i= 0; i <= rowLength; ++i)
+ {
+ if (i == winner)
+ validateDefinition(row.symbolName(i), row.symbolValue(i));
+ else
+ validateAsUndefined(row.symbolName(i));
+ }
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/XMLDumper.java b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/XMLDumper.java
new file mode 100644
index 00000000000..0221d0d25c0
--- /dev/null
+++ b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/XMLDumper.java
@@ -0,0 +1,138 @@
+package org.eclipse.cdt.core.parser.tests;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import org.apache.xerces.dom.DocumentImpl;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * This class implements a utility that will walk through an object
+ * and it's children and create an XML file for it.
+ */
+public class XMLDumper {
+
+ public static class Test {
+ private String msg = "hi";
+
+ public String getMsg() {
+ return msg;
+ }
+
+ public Test self = this;
+ }
+
+ public static void main(String [] args) {
+ Test test = new Test();
+ XMLDumper dumper = new XMLDumper(test);
+ Document document = dumper.getDocument();
+
+ OutputFormat format = new OutputFormat( document ); //Serialize DOM
+ StringWriter stringOut = new StringWriter(); //Writer will be a String
+ XMLSerializer serial = new XMLSerializer( stringOut, format );
+
+ try {
+ serial.asDOMSerializer(); // As a DOM Serializer
+ serial.serialize( document.getDocumentElement() );
+ System.out.println( "STRXML = " + stringOut.toString() ); //Spit out DOM as a String
+ } catch (IOException e) {
+ System.out.println(e);
+ }
+
+ }
+
+ private int id = 0;
+ private HashMap map = new HashMap();
+ private Document document = new DocumentImpl();
+
+ public Document getDocument() {
+ return document;
+ }
+
+ public XMLDumper(Object obj) {
+ document.appendChild(createObject(obj));
+ }
+
+ private Element createObject(Object obj) {
+ Class cls = obj.getClass();
+ String clsName = cls.getName();
+ clsName = clsName.replace('$', '.');
+
+ Element element = document.createElement(clsName);
+ map.put(obj, new Integer(id));
+ element.setAttribute("id",String.valueOf(id++));
+
+ Field [] fields = cls.getDeclaredFields();
+ for (int i = 0; i < fields.length; ++i) {
+ Field field = fields[i];
+ int modifiers = field.getModifiers();
+
+ // Skip over static fields
+ if (Modifier.isStatic(modifiers))
+ continue;
+
+ // Skip fields that start with an underscore
+ if (field.getName().charAt(0) == '_')
+ continue;
+
+ Object value = null;
+
+ String fieldName = field.getName();
+ if (Modifier.isPublic(modifiers)) {
+ try {
+ value = field.get(obj);
+ } catch (Exception e) {
+ value = e;
+ }
+ } else {
+ String methodName = "get" +
+ fieldName.substring(0, 1).toUpperCase() +
+ fieldName.substring(1);
+
+ Method method = null;
+ try {
+ method = cls.getMethod(methodName, null);
+ } catch (NoSuchMethodException e) {
+ continue;
+ }
+
+ try {
+ value = method.invoke(obj, null);
+ } catch (Exception e) {
+ value = e;
+ }
+ }
+
+ Element fieldElement = document.createElement(fieldName);
+ element.appendChild(fieldElement);
+
+ if (value == null)
+ return element;
+
+ Class type = field.getType();
+ if (String.class.isAssignableFrom(type))
+ fieldElement.appendChild(document.createTextNode((String)value));
+ else if (Integer.class.isAssignableFrom(type))
+ fieldElement.appendChild(document.createTextNode(((Integer)value).toString()));
+ else if (Exception.class.isAssignableFrom(type))
+ fieldElement.appendChild(document.createTextNode(value.toString()));
+ else {
+ Object v = map.get(value);
+ if (v != null)
+ fieldElement.setAttribute("refid", v.toString());
+ else
+ fieldElement.appendChild(createObject(value));
+ }
+
+ }
+
+ return element;
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties
index 47639c3c49b..7d6acf1a78d 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginResources.properties
@@ -16,6 +16,7 @@ CBasePreferencePage.autoOpenConsole.label=Open C-Build view when building
CBasePreferencePage.consoleOnTop.label=Bring C-Build view to top when building (if present)
CBasePreferencePage.linkToEditor.label=Link view selection to active editor
CBasePreferencePage.CUChildren.label=Show file members in Project View
+CBasePreferencePage.useNewParser.label=Use New Parser for Code Model
CBasePreferencePage.editorFont.label=C Editor font:
CBasePreferencePage.consoleFont.label=C-Build view font:
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java
index f92edb71d9c..6c52e83cc72 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CPluginPreferencePage.java
@@ -5,6 +5,7 @@ package org.eclipse.cdt.internal.ui.preferences;
* All Rights Reserved.
*/
+import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.jface.preference.BooleanFieldEditor;
@@ -20,11 +21,13 @@ import org.eclipse.ui.help.WorkbenchHelp;
*/
public class CPluginPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
- private static final String PREF_LINK_TO_EDITOR= "linkToEditor";
+ private static final String PREF_LINK_TO_EDITOR= "linkToEditor"; //$NON-NLS-1$
public static final String PREF_SHOW_CU_CHILDREN= "CUChildren"; //$NON-NLS-1$
+ private static final String PREF_USE_NEW_PARSER= "useNewParser"; //$NON-NLS-1$
private static final String LINK_TO_EDITOR_LABEL= "CBasePreferencePage.linkToEditor.label";
private static final String SHOW_CU_CHILDREN_LABEL= "CBasePreferencePage.CUChildren.label";
+ private static final String USE_NEW_PARSER_LABEL= "CBasePreferencePage.useNewParser.label";
public CPluginPreferencePage() {
super(GRID);
@@ -51,6 +54,8 @@ public class CPluginPreferencePage extends FieldEditorPreferencePage implements
BooleanFieldEditor showCUChildrenEditor= new BooleanFieldEditor(PREF_SHOW_CU_CHILDREN, CUIPlugin.getResourceString(SHOW_CU_CHILDREN_LABEL), parent);
addField(showCUChildrenEditor);
+ BooleanFieldEditor useNewParserEditor= new BooleanFieldEditor(PREF_USE_NEW_PARSER, CUIPlugin.getResourceString(USE_NEW_PARSER_LABEL), parent);
+ addField(useNewParserEditor);
}
@@ -62,6 +67,10 @@ public class CPluginPreferencePage extends FieldEditorPreferencePage implements
return CUIPlugin.getDefault().getPreferenceStore().getBoolean(PREF_SHOW_CU_CHILDREN);
}
+ public static boolean useNewParser() {
+ return CUIPlugin.getDefault().getPreferenceStore().getBoolean(PREF_USE_NEW_PARSER);
+ }
+
/**
* @see IWorkbenchPreferencePage#init
*/
@@ -74,6 +83,18 @@ public class CPluginPreferencePage extends FieldEditorPreferencePage implements
public static void initDefaults(IPreferenceStore prefs) {
prefs.setDefault(PREF_LINK_TO_EDITOR, true);
prefs.setDefault(PREF_SHOW_CU_CHILDREN, true);
- }
+ prefs.setDefault(PREF_USE_NEW_PARSER, false);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ if (!super.performOk())
+ return false;
+
+ CCorePlugin.getDefault().setUseNewParser(useNewParser());
+ return true;
+ }
+
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java
index 7f917f69263..80741f2fe2f 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java
@@ -9,6 +9,7 @@ import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
+import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.internal.ui.BuildConsoleManager;
@@ -217,6 +218,10 @@ public class CUIPlugin extends AbstractUIPlugin {
CPluginImages.initialize();
}
});
+
+ // TODO - temporary kludge (maybe) to make sure the core preferences
+ // are kept in sync with the stored preferences
+ CCorePlugin.getDefault().setUseNewParser(CPluginPreferencePage.useNewParser());
}
/**