| package org.eclipse.cdt.internal.ui.compare; |
| |
| /* |
| * (c) Copyright IBM Corp. 2000, 2001. |
| * All Rights Reserved. |
| */ |
| |
| import java.util.Stack; |
| |
| import org.eclipse.cdt.core.model.ICElement; |
| import org.eclipse.cdt.core.parser.IProblem; |
| import org.eclipse.cdt.core.parser.ast.ASTClassKind; |
| import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier; |
| import org.eclipse.cdt.core.parser.ast.IASTCompilationUnit; |
| import org.eclipse.cdt.core.parser.ast.IASTEnumerationSpecifier; |
| import org.eclipse.cdt.core.parser.ast.IASTField; |
| import org.eclipse.cdt.core.parser.ast.IASTFunction; |
| import org.eclipse.cdt.core.parser.ast.IASTInclusion; |
| import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification; |
| import org.eclipse.cdt.core.parser.ast.IASTMacro; |
| import org.eclipse.cdt.core.parser.ast.IASTMethod; |
| import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; |
| import org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration; |
| import org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation; |
| import org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization; |
| import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration; |
| import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration; |
| import org.eclipse.cdt.core.parser.ast.IASTUsingDirective; |
| import org.eclipse.cdt.core.parser.ast.IASTVariable; |
| import org.eclipse.jface.text.IDocument; |
| |
| /** |
| * |
| */ |
| public class CParseTreeBuilder extends SourceElementRequestorAdapter { |
| |
| private Stack fStack = new Stack(); |
| private IDocument fDocument; |
| |
| /** |
| * Syntax Error. |
| */ |
| public class ParseError extends Error { |
| } |
| |
| public CParseTreeBuilder(CNode root, IDocument doc) { |
| fDocument = doc; |
| fStack.clear(); |
| fStack.push(root); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterClassSpecifier(org.eclipse.cdt.core.parser.ast.IASTClassSpecifier) |
| */ |
| public void enterClassSpecifier(IASTClassSpecifier classSpecification) { |
| String name = classSpecification.getName(); |
| int start = classSpecification.getStartingOffset(); |
| if (classSpecification.getClassKind().equals(ASTClassKind.CLASS)) { |
| push(ICElement.C_CLASS, name, start); |
| } else if (classSpecification.getClassKind().equals(ASTClassKind.STRUCT)) { |
| push(ICElement.C_STRUCT, name, start); |
| } else if (classSpecification.getClassKind().equals(ASTClassKind.UNION)) { |
| push(ICElement.C_UNION, name, start); |
| } else if (classSpecification.getClassKind().equals(ASTClassKind.ENUM)) { |
| push(ICElement.C_ENUMERATION, name, start); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterCompilationUnit(org.eclipse.cdt.core.parser.ast.IASTCompilationUnit) |
| */ |
| public void enterCompilationUnit(IASTCompilationUnit compilationUnit) { |
| push(ICElement.C_UNIT, "Translation Unit", 0); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterFunctionBody(org.eclipse.cdt.core.parser.ast.IASTFunction) |
| */ |
| public void enterFunctionBody(IASTFunction function) { |
| push(ICElement.C_FUNCTION, function.getName(), function.getStartingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterInclusion(org.eclipse.cdt.core.parser.ast.IASTInclusion) |
| */ |
| public void enterInclusion(IASTInclusion inclusion) { |
| push(ICElement.C_INCLUDE, inclusion.getName(), inclusion.getStartingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterLinkageSpecification(org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification) |
| */ |
| public void enterLinkageSpecification(IASTLinkageSpecification linkageSpec) { |
| push(ICElement.C_STORAGE_EXTERN, linkageSpec.getLinkageString(), linkageSpec.getStartingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterMethodBody(org.eclipse.cdt.core.parser.ast.IASTMethod) |
| */ |
| public void enterMethodBody(IASTMethod method) { |
| push(ICElement.C_METHOD, method.getName(), method.getStartingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterNamespaceDefinition(org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition) |
| */ |
| public void enterNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) { |
| push(ICElement.C_NAMESPACE, namespaceDefinition.getName(), namespaceDefinition.getStartingOffset());; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterTemplateDeclaration(org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration) |
| */ |
| public void enterTemplateDeclaration(IASTTemplateDeclaration declaration) { |
| push(ICElement.C_TEMPLATE_VARIABLE, "export", declaration.getStartingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterTemplateInstantiation(org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation) |
| */ |
| public void enterTemplateInstantiation(IASTTemplateInstantiation instantiation) { |
| push(ICElement.C_TEMPLATE_VARIABLE, "template instanciation", instantiation.getStartingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterTemplateSpecialization(org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization) |
| */ |
| public void enterTemplateSpecialization(IASTTemplateSpecialization specialization) { |
| push(ICElement.C_TEMPLATE_VARIABLE, "template specialization", specialization.getStartingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitClassSpecifier(org.eclipse.cdt.core.parser.ast.IASTClassSpecifier) |
| */ |
| public void exitClassSpecifier(IASTClassSpecifier classSpecification) { |
| pop(classSpecification.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitCompilationUnit(org.eclipse.cdt.core.parser.ast.IASTCompilationUnit) |
| */ |
| public void exitCompilationUnit(IASTCompilationUnit translationUnit) { |
| pop(fDocument.getLength()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitFunctionBody(org.eclipse.cdt.core.parser.ast.IASTFunction) |
| */ |
| public void exitFunctionBody(IASTFunction function) { |
| pop(function.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitInclusion(org.eclipse.cdt.core.parser.ast.IASTInclusion) |
| */ |
| public void exitInclusion(IASTInclusion inclusion) { |
| pop(inclusion.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitLinkageSpecification(org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification) |
| */ |
| public void exitLinkageSpecification(IASTLinkageSpecification linkageSpec) { |
| pop(linkageSpec.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitMethodBody(org.eclipse.cdt.core.parser.ast.IASTMethod) |
| */ |
| public void exitMethodBody(IASTMethod method) { |
| pop(method.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitNamespaceDefinition(org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition) |
| */ |
| public void exitNamespaceDefinition(IASTNamespaceDefinition namespaceDefinition) { |
| pop(namespaceDefinition.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitTemplateDeclaration(org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration) |
| */ |
| public void exitTemplateDeclaration(IASTTemplateDeclaration declaration) { |
| pop(declaration.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitTemplateExplicitInstantiation(org.eclipse.cdt.core.parser.ast.IASTTemplateInstantiation) |
| */ |
| public void exitTemplateExplicitInstantiation(IASTTemplateInstantiation instantiation) { |
| pop(instantiation.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#exitTemplateSpecialization(org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization) |
| */ |
| public void exitTemplateSpecialization(IASTTemplateSpecialization specialization) { |
| pop(specialization.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptEnumerationSpecifier(org.eclipse.cdt.core.parser.ast.IASTEnumerationSpecifier) |
| */ |
| public void acceptEnumerationSpecifier(IASTEnumerationSpecifier enumeration) { |
| push(ICElement.C_ENUMERATION, enumeration.getName(), enumeration.getStartingOffset()); |
| pop(enumeration.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptFunctionDeclaration(org.eclipse.cdt.core.parser.ast.IASTFunction) |
| */ |
| public void acceptFunctionDeclaration(IASTFunction function) { |
| push(ICElement.C_FUNCTION_DECLARATION, function.getName(), function.getStartingOffset()); |
| pop(function.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptMacro(org.eclipse.cdt.core.parser.ast.IASTMacro) |
| */ |
| public void acceptMacro(IASTMacro macro) { |
| push(ICElement.C_MACRO, macro.getName(), macro.getStartingOffset()); |
| pop(macro.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptMethodDeclaration(org.eclipse.cdt.core.parser.ast.IASTMethod) |
| */ |
| public void acceptMethodDeclaration(IASTMethod method) { |
| push(ICElement.C_METHOD_DECLARATION, method.getName(), method.getStartingOffset()); |
| pop(method.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptProblem(org.eclipse.cdt.core.parser.IProblem) |
| */ |
| public boolean acceptProblem(IProblem problem) { |
| int problemId = problem.getID(); |
| if (problem.isError() && ((problemId & IProblem.SYNTAX_RELATED) != 0)) { |
| throw new ParseError(); |
| } |
| return true; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptTypedefDeclaration(org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration) |
| */ |
| public void acceptTypedefDeclaration(IASTTypedefDeclaration typedef) { |
| push(ICElement.C_TYPEDEF, typedef.getName(), typedef.getStartingOffset()); |
| pop(typedef.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptUsingDeclaration(org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration) |
| */ |
| public void acceptUsingDeclaration(IASTUsingDeclaration usageDeclaration) { |
| push(ICElement.C_USING, usageDeclaration.usingTypeName(), usageDeclaration.getStartingOffset()); |
| pop(usageDeclaration.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptUsingDirective(org.eclipse.cdt.core.parser.ast.IASTUsingDirective) |
| */ |
| public void acceptUsingDirective(IASTUsingDirective usageDirective) { |
| push(ICElement.C_USING, usageDirective.getNamespaceName(), usageDirective.getStartingOffset()); |
| pop(usageDirective.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptVariable(org.eclipse.cdt.core.parser.ast.IASTVariable) |
| */ |
| public void acceptVariable(IASTVariable variable) { |
| push(ICElement.C_VARIABLE, variable.getName(), variable.getStartingOffset()); |
| pop(variable.getEndingOffset()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#acceptField(org.eclipse.cdt.core.parser.ast.IASTField) |
| */ |
| public void acceptField(IASTField field) { |
| push(ICElement.C_FIELD, field.getName(), field.getStartingOffset()); |
| pop(field.getEndingOffset()); |
| } |
| |
| private CNode getCurrentContainer() { |
| return (CNode) fStack.peek(); |
| } |
| |
| /** |
| * Adds a new JavaNode with the given type and name to the current container. |
| */ |
| private void push(int type, String name, int declarationStart) { |
| fStack.push(new CNode(getCurrentContainer(), type, name, declarationStart, 0)); |
| } |
| |
| /** |
| * Closes the current Java node by setting its end position |
| * and pops it off the stack. |
| */ |
| private void pop(int declarationEnd) { |
| CNode current = getCurrentContainer(); |
| if (current.getTypeCode() == ICElement.C_UNIT) { |
| current.setAppendPosition(declarationEnd + 1); |
| } else { |
| current.setAppendPosition(declarationEnd); |
| } |
| current.setLength(declarationEnd - current.getRange().getOffset() + 1); |
| fStack.pop(); |
| } |
| } |