001 package org.maltparser.parser.algorithm.nivre;
002
003 import java.util.Stack;
004
005 import org.maltparser.core.exception.MaltChainedException;
006 import org.maltparser.core.symbol.SymbolTable;
007 import org.maltparser.core.symbol.SymbolTableHandler;
008 import org.maltparser.core.syntaxgraph.DependencyGraph;
009 import org.maltparser.core.syntaxgraph.DependencyStructure;
010 import org.maltparser.core.syntaxgraph.edge.Edge;
011 import org.maltparser.core.syntaxgraph.node.DependencyNode;
012 import org.maltparser.parser.ParserConfiguration;
013 import org.maltparser.parser.ParsingException;
014 /**
015 * @author Johan Hall
016 *
017 */
018 public class NivreConfig extends ParserConfiguration {
019 // Root Handling
020 public static final int STRICT = 1; //root tokens unattached, Reduce not permissible
021 public static final int RELAXED = 2; //root tokens unattached, Reduce permissible
022 public static final int NORMAL = 3; //root tokens attached to Root with RightArc
023
024 private Stack<DependencyNode> stack;
025 private Stack<DependencyNode> input;
026 private DependencyStructure dependencyGraph;
027 private int rootHandling;
028
029
030 public NivreConfig(SymbolTableHandler symbolTableHandler, String rootHandling) throws MaltChainedException {
031 super();
032 stack = new Stack<DependencyNode>();
033 input = new Stack<DependencyNode>();
034 dependencyGraph = new DependencyGraph(symbolTableHandler);
035 setRootHandling(rootHandling);
036 }
037
038 public Stack<DependencyNode> getStack() {
039 return stack;
040 }
041
042 public Stack<DependencyNode> getInput() {
043 return input;
044 }
045
046 public DependencyStructure getDependencyStructure() {
047 return dependencyGraph;
048 }
049
050 public boolean isTerminalState() {
051 return input.isEmpty();
052 }
053
054 public DependencyNode getStackNode(int index) throws MaltChainedException {
055 if (index < 0) {
056 throw new ParsingException("Stack index must be non-negative in feature specification. ");
057 }
058 if (stack.size()-index > 0) {
059 return stack.get(stack.size()-1-index);
060 }
061 return null;
062 }
063
064 public DependencyNode getInputNode(int index) throws MaltChainedException {
065 if (index < 0) {
066 throw new ParsingException("Input index must be non-negative in feature specification. ");
067 }
068 if (input.size()-index > 0) {
069 return input.get(input.size()-1-index);
070 }
071 return null;
072 }
073
074 public void setDependencyGraph(DependencyStructure source) throws MaltChainedException {
075 dependencyGraph.clear();
076 for (int index : source.getTokenIndices()) {
077 DependencyNode gnode = source.getTokenNode(index);
078 DependencyNode pnode = dependencyGraph.addTokenNode(gnode.getIndex());
079 for (SymbolTable table : gnode.getLabelTypes()) {
080 pnode.addLabel(table, gnode.getLabelSymbol(table));
081 }
082
083 if (gnode.hasHead()) {
084 Edge s = gnode.getHeadEdge();
085 Edge t = dependencyGraph.addDependencyEdge(s.getSource().getIndex(), s.getTarget().getIndex());
086
087 for (SymbolTable table : s.getLabelTypes()) {
088 t.addLabel(table, s.getLabelSymbol(table));
089 }
090 }
091 }
092 for (SymbolTable table : source.getDefaultRootEdgeLabels().keySet()) {
093 dependencyGraph.setDefaultRootEdgeLabel(table, source.getDefaultRootEdgeLabelSymbol(table));
094 }
095 }
096
097 public DependencyStructure getDependencyGraph() {
098 return dependencyGraph;
099 }
100
101 public void initialize(ParserConfiguration parserConfiguration) throws MaltChainedException {
102 if (parserConfiguration != null) {
103 NivreConfig nivreConfig = (NivreConfig)parserConfiguration;
104 Stack<DependencyNode> sourceStack = nivreConfig.getStack();
105 Stack<DependencyNode> sourceInput = nivreConfig.getInput();
106 setDependencyGraph(nivreConfig.getDependencyGraph());
107 for (int i = 0, n = sourceStack.size(); i < n; i++) {
108 stack.add(dependencyGraph.getDependencyNode(sourceStack.get(i).getIndex()));
109 }
110 for (int i = 0, n = sourceInput.size(); i < n; i++) {
111 input.add(dependencyGraph.getDependencyNode(sourceInput.get(i).getIndex()));
112 }
113 } else {
114 stack.push(dependencyGraph.getDependencyRoot());
115 for (int i = dependencyGraph.getHighestTokenIndex(); i > 0; i--) {
116 final DependencyNode node = dependencyGraph.getDependencyNode(i);
117 if (node != null && !node.hasHead()) { // added !node.hasHead()
118 input.push(node);
119 }
120 }
121 }
122 }
123
124 public int getRootHandling() {
125 return rootHandling;
126 }
127
128 public void setRootHandling(int rootHandling) {
129 this.rootHandling = rootHandling;
130 }
131
132 protected void setRootHandling(String rh) throws MaltChainedException {
133 if (rh.equalsIgnoreCase("strict")) {
134 rootHandling = STRICT;
135 } else if (rh.equalsIgnoreCase("relaxed")) {
136 rootHandling = RELAXED;
137 } else if (rh.equalsIgnoreCase("normal")) {
138 rootHandling = NORMAL;
139 } else {
140 throw new ParsingException("The root handling '"+rh+"' is unknown");
141 }
142 }
143
144 public void clear() throws MaltChainedException {
145 dependencyGraph.clear();
146 stack.clear();
147 input.clear();
148 historyNode = null;
149 }
150
151 public boolean equals(Object obj) {
152 if (this == obj)
153 return true;
154 if (obj == null)
155 return false;
156 if (getClass() != obj.getClass())
157 return false;
158 NivreConfig that = (NivreConfig)obj;
159
160 if (stack.size() != that.getStack().size())
161 return false;
162 if (input.size() != that.getInput().size())
163 return false;
164 if (dependencyGraph.nEdges() != that.getDependencyGraph().nEdges())
165 return false;
166 for (int i = 0; i < stack.size(); i++) {
167 if (stack.get(i).getIndex() != that.getStack().get(i).getIndex()) {
168 return false;
169 }
170 }
171 for (int i = 0; i < input.size(); i++) {
172 if (input.get(i).getIndex() != that.getInput().get(i).getIndex()) {
173 return false;
174 }
175 }
176 return dependencyGraph.getEdges().equals(that.getDependencyGraph().getEdges());
177 }
178
179 public String toString() {
180 final StringBuilder sb = new StringBuilder();
181 sb.append(stack.size());
182 sb.append(", ");
183 sb.append(input.size());
184 sb.append(", ");
185 sb.append(dependencyGraph.nEdges());
186 return sb.toString();
187 }
188 }