// This file is part of AceWiki.
// Copyright 2008-2013, AceWiki developers.
//
// AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with AceWiki. If
// not, see http://www.gnu.org/licenses/.
package ch.uzh.ifi.attempto.chartparser;
import java.util.ArrayList;
import java.util.List;
/**
* This class represents a node of the parse tree. Each node has a category and an annotation
* object that are carried over from the edge in the chart parser and originate from the respective
* grammar rule. Additionally, each parse node has start and end positions denoting the covered
* part of the input text.
*
* @author Tobias Kuhn
*/
public class ParseTreeNode {
private final Category category;
private final int startPos;
private final int endPos;
private final Annotation annotation;
private final List<ParseTreeNode> children = new ArrayList<ParseTreeNode>();
/**
* Creates a new parse tree node out of the given edge.
*
* @param edge The edge.
*/
ParseTreeNode(Edge edge) {
this.category = edge.getHead();
this.startPos = edge.getStartPos();
this.endPos = edge.getEndPos();
this.annotation = edge.getAnnotation();
int pos = edge.getStartPos();
for (int i = 0 ; i < edge.getBody().length ; i++) {
Edge e = edge.getLinks().get(i);
if (e != null) {
try {
e.getHead().unify(edge.getBody()[i]);
children.add(new ParseTreeNode(e));
} catch (UnificationFailedException ex) {
throw new RuntimeException("Unexpected unification error", ex);
}
pos = e.getEndPos();
} else {
children.add(new ParseTreeNode(edge.getBody()[i], pos));
}
}
}
/**
* Creates a new parse tree node (without children) out of the given category.
*
* @param category The category.
*/
private ParseTreeNode(Category category, int pos) {
this.category = category;
this.startPos = pos;
this.endPos = pos;
this.annotation = new Annotation();
}
/**
* Returns the category of this node.
*
* @return The category.
*/
public Category getCategory() {
return category;
}
/**
* Returns the start position. 0 is the position before the first token, 1 the position after
* the first token, 2 the position after the second token, and so on.
*
* @return The start position.
*/
public int getStartPos() {
return startPos;
}
/**
* Returns the end position. 0 is the position before the first token, 1 the position after
* the first token, 2 the position after the second token, and so on.
*
* @return The end position.
*/
public int getEndPos() {
return endPos;
}
/**
* Returns the annotation object of this node.
*
* @return The annotation object.
*/
public Annotation getAnnotation() {
return annotation;
}
/**
* Returns the annotation item for the given annotation item name.
*
* @param name The name of the annotation item.
* @return The value of the annotation item.
*/
public Object getAnnotationItem(String name) {
return annotation.getItem(name);
}
/**
* Returns the children of this node.
*
* @return The children.
*/
public List<ParseTreeNode> getChildren() {
return children;
}
/**
* Returns the child at the given position.
*
* @param i The position.
* @return The child.
*/
public ParseTreeNode getChild(int i) {
return children.get(i);
}
/**
* Returns the list of terminals that are descendants of this node.
*
* @return The list of terminals.
*/
public List<Terminal> getTerminals() {
List<Terminal> terminals = new ArrayList<Terminal>();
collectTerminals(terminals);
return terminals;
}
private void collectTerminals(List<Terminal> terminals) {
if (category instanceof Terminal) {
terminals.add((Terminal) category);
} else {
for (ParseTreeNode n : getChildren()) {
n.collectTerminals(terminals);
}
}
}
}