1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-30 04:15:35 +02:00

fixed bug, builder was creating qualified name nodes when unqualified name required

This commit is contained in:
Mike Kucera 2008-02-13 20:17:29 +00:00
parent 4117aeccbd
commit 8ece714199
10 changed files with 2062 additions and 2958 deletions

View file

@ -15,6 +15,8 @@ import junit.framework.AssertionFailedError;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.lrparser.BaseExtensibleLanguage;
import org.eclipse.cdt.core.dom.lrparser.c99.C99Language;
import org.eclipse.cdt.core.dom.lrparser.cpp.ISOCPPLanguage;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.tests.ast2.AST2CSpecTest;
import org.eclipse.cdt.internal.core.parser.ParserException;
@ -25,25 +27,25 @@ public class C99SpecTests extends AST2CSpecTest {
public C99SpecTests(String name) { super(name); }
/**
* Only parses it as C actually
* @throws ParserException
*/
@Override
protected void parseCandCPP( String code, boolean checkBindings, int expectedProblemBindings ) throws ParserException {
parse(code, ParserLanguage.C, checkBindings, expectedProblemBindings);
//parse(code, ParserLanguage.C, checkBindings, expectedProblemBindings);
parse(code, ParserLanguage.CPP, checkBindings, expectedProblemBindings);
}
@Override
protected IASTTranslationUnit parse( String code, ParserLanguage lang, boolean checkBindings, int expectedProblemBindings ) throws ParserException {
if(lang == ParserLanguage.C)
return ParseHelper.parse(code, getLanguage(), true, checkBindings, expectedProblemBindings );
else
return super.parse(code, lang, checkBindings, expectedProblemBindings);
ILanguage language = lang.isCPP() ? getCPPLanguage() : getCLanguage();
return ParseHelper.parse(code, language, true, checkBindings, expectedProblemBindings );
}
protected BaseExtensibleLanguage getLanguage() {
protected BaseExtensibleLanguage getCLanguage() {
return C99Language.getDefault();
}
protected BaseExtensibleLanguage getCPPLanguage() {
return ISOCPPLanguage.getDefault();
}
//Assignment statements cannot exists outside of a function body
@Override

View file

@ -19,9 +19,10 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.dom.lrparser.BaseExtensibleLanguage;
import org.eclipse.cdt.core.model.AbstractLanguage;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.CodeReader;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ParserUtil;
@ -38,42 +39,48 @@ public class ParseHelper {
static int testsRun = 0;
private static class C99NameResolver extends ASTVisitor {
private static class NameResolver extends CPPASTVisitor {
{
shouldVisitNames = true;
}
public int numProblemBindings=0;
public int numNullBindings=0;
public int numProblemBindings = 0;
public int numNullBindings = 0;
@Override
public int visit( IASTName name ){
System.out.println("Visit Name: '" + name.toString() + "'");
IBinding binding = name.resolveBinding();
if (binding instanceof IProblemBinding)
if (binding instanceof IProblemBinding) {
numProblemBindings++;
if (binding == null)
System.out.println("Problem Binding: " + name);
}
if (binding == null) {
numNullBindings++;
System.out.println("Null Binding: " + name);
}
return PROCESS_CONTINUE;
}
}
public static IASTTranslationUnit parse(char[] code, BaseExtensibleLanguage lang, boolean expectNoProblems, boolean checkBindings, int expectedProblemBindings) {
public static IASTTranslationUnit parse(char[] code, ILanguage lang, boolean expectNoProblems, boolean checkBindings, int expectedProblemBindings) {
CodeReader codeReader = new CodeReader(code);
return parse(codeReader, lang, new ScannerInfo(), null, expectNoProblems, checkBindings, expectedProblemBindings);
}
public static IASTTranslationUnit parse(String code, BaseExtensibleLanguage lang, boolean expectNoProblems, boolean checkBindings, int expectedProblemBindings) {
public static IASTTranslationUnit parse(String code, ILanguage lang, boolean expectNoProblems, boolean checkBindings, int expectedProblemBindings) {
return parse(code.toCharArray(), lang, expectNoProblems, checkBindings, expectedProblemBindings);
}
public static IASTTranslationUnit parse(String code, BaseExtensibleLanguage lang, boolean expectNoProblems) {
public static IASTTranslationUnit parse(String code, ILanguage lang, boolean expectNoProblems) {
return parse(code, lang, expectNoProblems, false, 0);
}
public static IASTTranslationUnit parse(CodeReader codeReader, BaseExtensibleLanguage language, IScannerInfo scanInfo,
public static IASTTranslationUnit parse(CodeReader codeReader, ILanguage language, IScannerInfo scanInfo,
ICodeReaderFactory fileCreator, boolean expectNoProblems, boolean checkBindings, int expectedProblemBindings) {
testsRun++;
@ -100,7 +107,7 @@ public class ParseHelper {
// resolve all bindings
if (checkBindings) {
C99NameResolver res = new C99NameResolver();
NameResolver res = new NameResolver();
tu.accept( res );
if (res.numProblemBindings != expectedProblemBindings )
throw new AssertionFailedError("Expected " + expectedProblemBindings + " problem(s), encountered " + res.numProblemBindings ); //$NON-NLS-1$ //$NON-NLS-2$

View file

@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.lrparser.tests.c99;
import junit.framework.Test;
import junit.framework.TestSuite;
public class ParserTestSuiteConvenient extends TestSuite {
// this test suite is just for my convenience
public static Test suite() {
TestSuite suite = new TestSuite();
// suite.addTestSuite(C99Tests.class); // has some tests that do fail
// suite.addTestSuite(C99SpecTests.class); // a couple of failures
suite.addTest(new C99SpecTests("test6_7_2_3s10"));
// suite.addTestSuite(C99KnRTests.class); // mostly fail due to ambiguities
//
// // The majority of the content assist test are in the ui tests plugin
// suite.addTestSuite(C99CompletionBasicTest.class);
// // this one still has a lot of failing tests though
// suite.addTestSuite(C99SelectionParseTest.class);
//
// suite.addTestSuite(C99DOMLocationInclusionTests.class);
// suite.addTestSuite(C99DOMLocationTests.class);
// suite.addTestSuite(C99DOMLocationMacroTests.class);
// suite.addTestSuite(C99DOMPreprocessorInformationTest.class);
// suite.addTestSuite(C99CommentTests.class);
// suite.addTestSuite(C99DigraphTrigraphTests.class);
// suite.addTestSuite(C99GCCTests.class);
// suite.addTestSuite(C99UtilOldTests.class);
// suite.addTestSuite(C99UtilTests.class);
// suite.addTestSuite(C99CompleteParser2Tests.class);
// suite.addTestSuite(C99TaskParserTest.class);
return suite;
}
}

View file

@ -11,6 +11,7 @@ Export-Package: org.eclipse.cdt.core.dom.lrparser,
org.eclipse.cdt.core.dom.lrparser.action,
org.eclipse.cdt.core.dom.lrparser.action.c99,
org.eclipse.cdt.core.dom.lrparser.c99,
org.eclipse.cdt.core.dom.lrparser.cpp,
org.eclipse.cdt.internal.core.dom.lrparser.c99;x-internal:=true,
org.eclipse.cdt.internal.core.dom.lrparser.c99.bindings
Bundle-Localization: plugin

View file

@ -11,7 +11,7 @@
%options la=2
%options package=org.eclipse.cdt.internal.core.dom.lrparser.cpp
%options template=TrialUndoParserTemplate.g
%options template=btParserTemplateD.g
@ -148,7 +148,7 @@ $End
$Define
-- These macros allow the template and header code to be customized by an extending parser.
$ast_class /.Object./
$additional_interfaces /. ./
$additional_interfaces /. , IParserActionTokenProvider, IParser ./
$build_action_class /. CPPBuildASTParserAction ./
$resolve_action_class /. C99TypedefTrackerParserAction ./
@ -176,9 +176,9 @@ $Define
$builder /. action.builder./
-- comment out when using trial/undo
--$Action /. $BeginAction ./
--$BeginFinal /. ./
--$EndFinal /. ./
$Action /. $BeginAction ./
$BeginFinal /. ./
$EndFinal /. ./
$End
@ -188,8 +188,8 @@ $Headers
private $action_class action;
// uncomment to use with backtracking parser
//public $action_type() { // constructor
//}
public $action_type() { // constructor
}
private void initActions(IASTTranslationUnit tu) {
// binding resolution actions need access to IASTName nodes, temporary
@ -199,7 +199,7 @@ $Headers
//action.builder.setTokenMap(CPPParsersym.orderedTerminalSymbols);
// comment this line to use with backtracking parser
setParserAction(action);
//setParserAction(action);
}
@ -231,7 +231,7 @@ $Headers
action = null;
// Comment this line to use with backtracking parser
parserAction = null;
//parserAction = null;
return compNode;
}
@ -258,9 +258,9 @@ $Headers
// uncomment this method to use with backtracking parser
//public List getRuleTokens() {
// return Collections.unmodifiableList(getTokens().subList(getLeftSpan(), getRightSpan() + 1));
//}
public List getRuleTokens() {
return Collections.unmodifiableList(getTokens().subList(getLeftSpan(), getRightSpan() + 1));
}
./

View file

@ -103,15 +103,13 @@ public abstract class BaseExtensibleLanguage extends AbstractLanguage implements
System.out.println();
System.out.println("********************************************************");
System.out.println("Parsing");
System.out.println("Options: " + options);
System.out.println("GPP AST:");
DebugUtil.printAST(gtu);
System.out.println();
//IParseResult parseResult = parse(reader, scanInfo, fileCreator, index, null, null);
//IASTTranslationUnit tu = parseResult.getTranslationUnit();
// TODO temporary
IScannerExtensionConfiguration config = new GCCScannerExtensionConfiguration();
@ -138,6 +136,7 @@ public abstract class BaseExtensibleLanguage extends AbstractLanguage implements
IScannerInfo scanInfo, ICodeReaderFactory fileCreator,
IIndex index, IParserLogService log) throws CoreException {
System.out.println("Second Method");
return getASTTranslationUnit(reader, scanInfo, fileCreator, index, 0, log);
}

View file

@ -51,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNullStatement;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointer;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
@ -73,6 +74,7 @@ import org.eclipse.cdt.internal.core.dom.lrparser.c99.C99NoCastExpressionParser;
import org.eclipse.cdt.internal.core.dom.lrparser.c99.C99Parsersym;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression;
import org.eclipse.cdt.internal.core.dom.parser.c.CASTAmbiguity;
/**
@ -118,9 +120,6 @@ public abstract class BuildASTParserAction {
private final IASTNodeFactory nodeFactory;
protected static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {
{ shouldVisitStatements = true; }
};
@ -324,11 +323,33 @@ public abstract class BuildASTParserAction {
setOffsetAndLength(tu, 0, offset(d) + length(d));
}
// resolve ambiguities
tu.accept(EMPTY_VISITOR);
resolveAmbiguityNodes();
if(TRACE_AST_STACK) System.out.println(astStack);
}
/**
* Removes ambiguity nodes from the AST by resolving them.
* The ambiguity nodes resolve themselves when visited for the first time.
* All ambiguities must be resolved before the AST is returned.
*
* @see CPPASTAmbiguity.accept()
* @see CASTAmbiguity.accept()
*
* TODO Ambiguity resolution may be avoided in the case that no
* ambiguity nodes were created.
*/
private void resolveAmbiguityNodes() {
tu.accept(EMPTY_VISITOR);
}
/**
* When applied to the AST causes ambiguity nodes to be resolved.
*/
protected static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {
{ shouldVisitStatements = true; }
};
@ -338,9 +359,7 @@ public abstract class BuildASTParserAction {
public void consumeIdentifierName() {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
IToken token = parser.getRightIToken();
IASTName name = createName(token);
astStack.push(name);
astStack.push(createName(parser.getRightIToken()));
if(TRACE_AST_STACK) System.out.println(astStack);
}
@ -814,7 +833,7 @@ public abstract class BuildASTParserAction {
decl = nodeFactory.newDeclarator(nodeFactory.newName());
for(Object pointer : astStack.closeScope())
decl.addPointerOperator((ICASTPointer)pointer);
decl.addPointerOperator((IASTPointer)pointer);
setOffsetAndLength(decl);
astStack.push(decl);
@ -911,7 +930,7 @@ public abstract class BuildASTParserAction {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
List<Object> declarators = (hasDeclaratorList) ? astStack.closeScope() : Collections.emptyList();
ICASTDeclSpecifier declSpecifier = (ICASTDeclSpecifier) astStack.pop(); // may be null
IASTDeclSpecifier declSpecifier = (IASTDeclSpecifier) astStack.pop(); // may be null
IASTSimpleDeclaration declaration = nodeFactory.newSimpleDeclaration(declSpecifier);

View file

@ -88,11 +88,11 @@ import org.eclipse.cdt.core.dom.lrparser.util.DebugUtil;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionDeclarator;
/**
* Semantic actions that build the AST during the parse. These are the actions
* that are specific to the C++ parser.
* Semantic actions that build the AST during the parse.
* These are the actions that are specific to the C++ parser, the superclass
* contains actions that can be shared with the C99 parser.
*
* @author Mike Kucera
*
*/
public class CPPBuildASTParserAction extends BuildASTParserAction {
@ -633,6 +633,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
public void consumeNestedNameSpecifierEmpty() {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
// can't use Collections.EMPTY_LIST because we need a list thats mutable
astStack.push(new LinkedList<IASTName>());
if(TRACE_AST_STACK) System.out.println(astStack);
@ -676,7 +677,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
public void consumeQualifiedId(boolean hasTemplateKeyword) {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
ICPPASTQualifiedName qualifiedName = subRuleQualifiedName(hasTemplateKeyword);
IASTName qualifiedName = subRuleQualifiedName(hasTemplateKeyword);
astStack.push(qualifiedName);
if(TRACE_AST_STACK) System.out.println(astStack);
@ -688,7 +689,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
* Creates a qualified name from a list of names (that must be in reverse order).
* Does not set the offset and length.
*/
private ICPPASTQualifiedName createQualifiedName(LinkedList<IASTName> nestedNames, boolean hasDColon) {
private ICPPASTQualifiedName createQualifiedName(LinkedList<IASTName> nestedNames, boolean startsWithColonColon) {
ICPPASTQualifiedName qualifiedName = nodeFactory.newCPPQualifiedName();
int startOffset = offset(nestedNames.getLast());
@ -698,8 +699,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
for(IASTName name : reverseIterable(nestedNames))
qualifiedName.addName(name);
qualifiedName.setFullyQualified(hasDColon);
qualifiedName.setFullyQualified(startsWithColonColon);
return qualifiedName;
}
@ -713,17 +713,22 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
* Does not place the resulting node on the stack, returns it instead.
*/
@SuppressWarnings("unchecked")
private ICPPASTQualifiedName subRuleQualifiedName(boolean hasOptionalKeyword) {
IASTName subName = (IASTName) astStack.pop();
private IASTName subRuleQualifiedName(boolean hasOptionalKeyword) {
IASTName lastName = (IASTName) astStack.pop();
if(hasOptionalKeyword) // this is usually a template keyword and can be ignored
astStack.pop();
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
boolean hasDColon = astStack.pop() == PLACE_HOLDER;
boolean startsWithColonColon = astStack.pop() == PLACE_HOLDER;
nestedNames.addFirst(subName);
return createQualifiedName(nestedNames, hasDColon);
if(nestedNames.isEmpty() && !startsWithColonColon) { // then its not a qualified name
return lastName;
}
nestedNames.addFirst(lastName); // the list of names is in reverse order
return createQualifiedName(nestedNames, startsWithColonColon);
}
@ -784,7 +789,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
public void consumeNamespaceAliasDefinition() {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
ICPPASTQualifiedName qualifiedName = subRuleQualifiedName(false);
IASTName qualifiedName = subRuleQualifiedName(false);
IASTName alias = createName(parser.getRuleTokens().get(1));
ICPPASTNamespaceAlias namespaceAlias = nodeFactory.newNamespaceAlias(alias, qualifiedName);
@ -803,7 +808,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
public void consumeUsingDeclaration() {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
ICPPASTQualifiedName qualifiedName = subRuleQualifiedName(false);
IASTName qualifiedName = subRuleQualifiedName(false);
boolean hasTypenameKeyword = astStack.pop() == PLACE_HOLDER;
ICPPASTUsingDeclaration usingDeclaration = nodeFactory.newUsingDeclaration(qualifiedName);
@ -823,7 +828,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
public void consumeUsingDirective() {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
ICPPASTQualifiedName qualifiedName = subRuleQualifiedName(false);
IASTName qualifiedName = subRuleQualifiedName(false);
ICPPASTUsingDirective usingDirective = nodeFactory.newUsingDirective(qualifiedName);
setOffsetAndLength(usingDirective);

View file

@ -32,6 +32,8 @@ public final class CollectionUtils {
/**
* Returns an iterator that iterates backwards over the given list.
* The remove() method is not implemented and will throw UnsupportedOperationException.
* The returned iterator does not support the remove() method.
*
* @throws NullPointerException if list is null
*/
public static <T> Iterator<T> reverseIterator(final List<T> list) {
@ -93,7 +95,7 @@ public final class CollectionUtils {
* @throws NullPointerException if source or pattern is null
*/
public static boolean matchTokens(List<IToken> source, Integer ... pattern) {
if(source.size() != pattern.length) // throws NPE if either param is null
if(source.size() != pattern.length) // throws NPE if either parameter is null
return false;
for(int i = 0, n = pattern.length; i < n; i++) {
@ -107,13 +109,14 @@ public final class CollectionUtils {
/**
* Finds the first object in the heterogeneous list that is an instance of
* the given class, removes it from the list, and returns it.
* If there is not object in the list of the given type the list is left
* unmodified and null is returned.
*
* @throws NullPointerException if list or clazz is null
* @throws UnsupportedOperationException if the list's Iterator does not support the remove() method
*/
@SuppressWarnings("unchecked")
public static <T> T findFirstAndRemove(List<Object> list, Class<T> clazz) {
// There's a name somewhere on the stack, find it
for(Iterator<Object> iter = list.iterator(); iter.hasNext();) {
Object o = iter.next();
if(clazz.isInstance(o)) {