Commit 1c8367a2 authored by Johannes Roith's avatar Johannes Roith

- Open Declarations fully works now.

- Open Definitions works when clicked inside a Production.
parent 28f39d2b
......@@ -5,8 +5,11 @@ import java.util.HashMap;
import java.util.List;
import de.in.tum.www2.cup.ast.AbstractNode;
import de.in.tum.www2.cup.ast.IHasDeclarationReference;
import de.in.tum.www2.cup.ast.IHasDefinitionReference;
import de.in.tum.www2.cup.ast.Production;
import de.in.tum.www2.cup.ast.ProductionSymbolRef;
import de.in.tum.www2.cup.ast.StartWith;
import de.in.tum.www2.cup.ast.Terminal;
import de.in.tum.www2.cup.ast.NonTerminal;
import de.in.tum.www2.cup.ast.NonTerminalDeclaration;
......@@ -16,20 +19,52 @@ import de.in.tum.www2.cup.ast.TypedTerminalDeclaration;
public class RefResolutionVisitor extends Visitor<Object>
{
private HashMap<String, AbstractNode> declarations = new HashMap<String, AbstractNode> ();
private HashMap<String, AbstractNode> definitions = new HashMap<String, AbstractNode> ();
private HashMap<String, List<ProductionSymbolRef>> forwardRefs = new HashMap<String, List<ProductionSymbolRef>> ();
private HashMap<String, AbstractNode> declarations;
private HashMap<String, AbstractNode> definitions;
private HashMap<String, List<IHasDefinitionReference>> forwardDefRefs;
// should resolve:
public RefResolutionVisitor() {
declarations = new HashMap<String, AbstractNode> ();
definitions = new HashMap<String, AbstractNode> ();
forwardDefRefs = new HashMap<String, List<IHasDefinitionReference>> ();
}
// should also resolve:
// 1. declarations
// 2. matching precedences
// 3. definitions (of non-terminals)
// resolve ProductionRef nodes and all identifiers.
private void resolveDeclarationFrom(String name, IHasDeclarationReference node) {
if (declarations.containsKey(name)) {
AbstractNode def = declarations.get(name);
node.setDeclaration(def);
}
}
private void resolveDefinitionFrom(String name, IHasDefinitionReference node) {
if (definitions.containsKey(name)) {
AbstractNode def = definitions.get(name);
node.setDefinition(def);
} else {
// the production might still be defined, below, accumulate.
if (!forwardDefRefs.containsKey(name))
forwardDefRefs.put(name, new ArrayList<IHasDefinitionReference>());
forwardDefRefs.get(name).add(node);
}
}
@Override public Object preVisit (StartWith node, Object data) {
NonTerminal nt = node.getNonTerminal();
if (nt != null)
resolveDefinitionFrom(nt.getName().name, nt);
return data;
}
@Override public Object preVisit (NonTerminalDeclaration node, Object data) {
for(NonTerminal nt : node.getNonTerminals())
declarations.put(nt.getName().name, nt);
for(NonTerminal nt : node.getNonTerminals()) {
String name = nt.getName().name;
declarations.put(name, nt);
resolveDefinitionFrom(name, nt);
}
return data;
}
......@@ -40,8 +75,11 @@ public class RefResolutionVisitor extends Visitor<Object>
}
@Override public Object preVisit (TypedNonTerminalDeclaration node, Object data) {
for(NonTerminal nt : node.getNonTerminals())
declarations.put(nt.getName().name, nt);
for(NonTerminal nt : node.getNonTerminals()) {
String name = nt.getName().name;
declarations.put(name, nt);
resolveDefinitionFrom(name, nt);
}
return data;
}
......@@ -56,25 +94,17 @@ public class RefResolutionVisitor extends Visitor<Object>
definitions.put(name, node);
// update any forward references.
if (forwardRefs.containsKey(name)) {
for (ProductionSymbolRef pr : forwardRefs.get(name))
pr.setDefinition(node);
if (forwardDefRefs.containsKey(name)) {
for (IHasDefinitionReference d : forwardDefRefs.get(name))
d.setDefinition(node);
}
return data;
}
@Override public Object preVisit (ProductionSymbolRef node, Object data) {
String name = node.getName().name;
if (definitions.containsKey(name)) {
AbstractNode def = definitions.get(name);
if (def instanceof Production)
node.setDefinition((Production) def);
} else {
// the production might still be defined, below, accumulate.
if (!forwardRefs.containsKey(name))
forwardRefs.put(name, new ArrayList<ProductionSymbolRef>());
forwardRefs.get(name).add(node);
}
resolveDefinitionFrom(name, node);
resolveDeclarationFrom(name, node);
return data;
}
}
......@@ -24,13 +24,13 @@ public class NonTerminal extends AbstractNode
}
public void setDeclaration(AbstractNode node) {
if (node instanceof NonTerminal)
if (!(node instanceof NonTerminal))
throw new RuntimeException("Declaration must be a NonTerminal");
this.declarationRef = (NonTerminal) node;
}
public void setDefinition(AbstractNode node) {
if (node instanceof NonTerminal)
if (!(node instanceof Production))
throw new RuntimeException("Definition must be a Production");
this.definitionRef = (Production) node;
}
......@@ -46,7 +46,11 @@ public class NonTerminal extends AbstractNode
@Override
public <T> void accept(AbstractVisitor<T> visitor, T data) {
visitor.preVisit(this, data);
T childArg = visitor.preVisit(this, data);
if (visitor.resetDescend()) {
if (name != null)
name.accept(visitor, childArg);
}
visitor.postVisit(this, data);
}
......
......@@ -5,11 +5,12 @@ import java.util.List;
import de.in.tum.www2.cup.analysis.AbstractVisitor;
import de.in.tum.www2.cup.Range;
public class Production extends AbstractNode {
public class Production extends AbstractNode implements IWithName {
private Name lhs;
private List<ProductionRight> rhs;
@Override
public Name getName() {
return lhs;
}
......@@ -33,6 +34,8 @@ public class Production extends AbstractNode {
public <T> void accept(AbstractVisitor<T> visitor, T data) {
T childArg = visitor.preVisit(this, data);
if (visitor.resetDescend()) {
if (lhs != null)
lhs.accept(visitor, childArg);
if (rhs != null) {
for (ProductionRight pr : rhs)
pr.accept(visitor, childArg);
......
......@@ -10,7 +10,7 @@ public class ProductionSymbolRef extends AbstractNode
private Name name;
private Production definitionRef; // has to be resolved first.
private NonTerminal declarationRef; // has to be resolved first.
private AbstractNode declarationRef; // has to be resolved first.
@Override
public Name getName () {
......@@ -26,19 +26,16 @@ public class ProductionSymbolRef extends AbstractNode
}
public void setDeclaration(AbstractNode node) {
// TODO: this might be wrong, since the reference could also be a terminal.
if (node instanceof NonTerminal)
throw new RuntimeException("Declaration must be a NonTerminal");
this.declarationRef = (NonTerminal) node;
if (! (node instanceof NonTerminal) && ! (node instanceof Terminal))
throw new RuntimeException("Declaration must be a NonTerminal or Terminal");
this.declarationRef = node;
}
public void setDefinition(AbstractNode node) {
// TODO: this might be wrong, since the reference could also be a terminal.
if (node instanceof NonTerminal)
if (!(node instanceof Production))
throw new RuntimeException("Definition must be a Production");
this.definitionRef = (Production) node;
}
......
......@@ -5,7 +5,11 @@ import de.in.tum.www2.cup.Range;
public class StartWith extends AbstractNode {
public NonTerminal nt;
private NonTerminal nt;
public NonTerminal getNonTerminal() {
return nt;
}
public StartWith(NonTerminal nt, Range range) {
super(range);
......
......@@ -3,14 +3,28 @@ package de.in.tum.www2.cup.ast;
import de.in.tum.www2.cup.analysis.AbstractVisitor;
import de.in.tum.www2.cup.Range;
public class Terminal extends AbstractNode implements IWithName {
public class Terminal extends AbstractNode
implements IWithName, IHasDeclarationReference {
private Name name;
private Terminal declarationRef; // has to be resolved first.
@Override
public Name getName () {
return name;
}
@Override
public AbstractNode getDeclaration() {
return declarationRef;
}
@Override
public void setDeclaration(AbstractNode node) {
if (!(node instanceof Terminal))
throw new RuntimeException("Declaration must be a Terminal");
this.declarationRef = (Terminal) node;
}
public Terminal(Name name, Range range) {
super(range);
......@@ -23,7 +37,11 @@ public class Terminal extends AbstractNode implements IWithName {
@Override
public <T> void accept(AbstractVisitor<T> visitor, T data) {
visitor.preVisit(this, data);
T childArg = visitor.preVisit(this, data);
if (visitor.resetDescend()) {
if (name != null)
name.accept(visitor, childArg);
}
visitor.postVisit(this, data);
}
......@@ -31,5 +49,5 @@ public class Terminal extends AbstractNode implements IWithName {
protected void putDescription(StringBuilder builder) {
builder.append(name);
}
}
......@@ -18,12 +18,6 @@ public class TypedNonTerminalDeclaration extends NonTerminalDeclaration {
@Override protected String getNodeName() { return "TypedNonTerminalDeclaration"; }
@Override
public <T> void accept(AbstractVisitor<T> visitor, T data) {
visitor.preVisit(this, data);
visitor.postVisit(this, data);
}
@Override
protected void putDescription(StringBuilder builder) {
builder.append(type);
......
......@@ -18,12 +18,6 @@ public class TypedTerminalDeclaration extends TerminalDeclaration {
@Override protected String getNodeName() { return "TypedTerminalDeclaration"; }
@Override
public <T> void accept(AbstractVisitor<T> visitor, T data) {
visitor.preVisit(this, data);
visitor.postVisit(this, data);
}
@Override
protected void putDescription(StringBuilder builder) {
builder.append(type);
......
......@@ -10,6 +10,9 @@ import de.in.tum.www2.cup.Position;
import de.in.tum.www2.cup.Range;
import de.in.tum.www2.cup.analysis.FindAtPositionVisitor;
import de.in.tum.www2.cup.ast.AbstractNode;
import de.in.tum.www2.cup.ast.IHasDeclarationReference;
import de.in.tum.www2.cup.ast.IHasDefinitionReference;
import de.in.tum.www2.cup.ast.IWithName;
import de.in.tum.www2.cup.ast.ParserResult;
import de.in.tum.www2.cup.ast.Production;
import de.in.tum.www2.cup.ast.ProductionSymbolRef;
......@@ -23,6 +26,10 @@ public class OpenDeclarationHandler extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
// TODO: this has been copied from the DefinitionHandler, exception
// that IHasDefinitionReference -> IHasDeclarationReference
// an getDefinition() -> getDeclaration()
MultiPageEditor mpe = (MultiPageEditor) HandlerUtil.getActiveEditorChecked(event);
CupTextEditor editor = mpe.getEditor();
......@@ -42,11 +49,15 @@ public class OpenDeclarationHandler extends AbstractHandler {
AbstractNode node = pf.getResult();
if (node != null) {
AbstractNode parent = node.getParent();
if (parent != null && parent instanceof ProductionSymbolRef) {
// TODO!
if (parent != null && parent instanceof IHasDeclarationReference) {
AbstractNode target = ((IHasDeclarationReference) parent).getDeclaration();
if (target != null && target instanceof IWithName) {
Position targetPosition = target.getBegin();
int length = ((IWithName) target).getName().name.length();
editor.selectAndReveal(targetPosition.getOffsetFromStart(), length);
}
}
}
}
return null;
......
......@@ -13,6 +13,8 @@ import de.in.tum.www2.cup.Position;
import de.in.tum.www2.cup.Range;
import de.in.tum.www2.cup.analysis.FindAtPositionVisitor;
import de.in.tum.www2.cup.ast.AbstractNode;
import de.in.tum.www2.cup.ast.IHasDefinitionReference;
import de.in.tum.www2.cup.ast.IWithName;
import de.in.tum.www2.cup.ast.Name;
import de.in.tum.www2.cup.ast.NonTerminalDeclaration;
import de.in.tum.www2.cup.ast.ParserResult;
......@@ -46,20 +48,15 @@ public class OpenDefinitionHandler extends AbstractHandler {
AbstractNode node = pf.getResult();
if (node != null) {
AbstractNode parent = node.getParent();
// TODO: we should also support this operation if we click on a declaration.
//
if (parent != null && parent instanceof ProductionSymbolRef) {
ProductionSymbolRef prodRef = (ProductionSymbolRef) parent;
Production definition = (Production) prodRef.getDefinition();
if (definition != null) {
Position targetPosition = definition.getBegin();
int length = definition.getName().name.length();
if (parent != null && parent instanceof IHasDefinitionReference) {
AbstractNode target = ((IHasDefinitionReference) parent).getDefinition();
if (target != null && target instanceof IWithName) {
Position targetPosition = target.getBegin();
int length = ((IWithName) target).getName().name.length();
editor.selectAndReveal(targetPosition.getOffsetFromStart(), length);
}
}
}
}
......
......@@ -334,8 +334,8 @@ public class CupContentOutlinePage extends ContentOutlinePage implements
public void postVisit(StartWith node, OutlineEntry data) {
StringBuilder builder = new StringBuilder();
builder.append("start with ");
if (node.nt != null && node.nt.getName() != null)
builder.append(node.nt.getName());
if (node.getNonTerminal() != null && node.getNonTerminal().getName() != null)
builder.append(node.getNonTerminal().getName());
root.children.add(OutlineEntry.fromNode(builder.toString(), node));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment