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 } 093 094 public DependencyStructure getDependencyGraph() { 095 return dependencyGraph; 096 } 097 098 public void initialize(ParserConfiguration parserConfiguration) throws MaltChainedException { 099 if (parserConfiguration != null) { 100 NivreConfig nivreConfig = (NivreConfig)parserConfiguration; 101 Stack<DependencyNode> sourceStack = nivreConfig.getStack(); 102 Stack<DependencyNode> sourceInput = nivreConfig.getInput(); 103 setDependencyGraph(nivreConfig.getDependencyGraph()); 104 for (int i = 0, n = sourceStack.size(); i < n; i++) { 105 stack.add(dependencyGraph.getDependencyNode(sourceStack.get(i).getIndex())); 106 } 107 for (int i = 0, n = sourceInput.size(); i < n; i++) { 108 input.add(dependencyGraph.getDependencyNode(sourceInput.get(i).getIndex())); 109 } 110 } else { 111 stack.push(dependencyGraph.getDependencyRoot()); 112 for (int i = dependencyGraph.getHighestTokenIndex(); i > 0; i--) { 113 final DependencyNode node = dependencyGraph.getDependencyNode(i); 114 if (node != null) { 115 input.push(node); 116 } 117 } 118 } 119 } 120 121 public int getRootHandling() { 122 return rootHandling; 123 } 124 125 public void setRootHandling(int rootHandling) { 126 this.rootHandling = rootHandling; 127 } 128 129 protected void setRootHandling(String rh) throws MaltChainedException { 130 if (rh.equalsIgnoreCase("strict")) { 131 rootHandling = STRICT; 132 } else if (rh.equalsIgnoreCase("relaxed")) { 133 rootHandling = RELAXED; 134 } else if (rh.equalsIgnoreCase("normal")) { 135 rootHandling = NORMAL; 136 } else { 137 throw new ParsingException("The root handling '"+rh+"' is unknown"); 138 } 139 } 140 141 public void clear() throws MaltChainedException { 142 dependencyGraph.clear(); 143 stack.clear(); 144 input.clear(); 145 historyNode = null; 146 } 147 148 public boolean equals(Object obj) { 149 if (this == obj) 150 return true; 151 if (obj == null) 152 return false; 153 if (getClass() != obj.getClass()) 154 return false; 155 NivreConfig that = (NivreConfig)obj; 156 157 if (stack.size() != that.getStack().size()) 158 return false; 159 if (input.size() != that.getInput().size()) 160 return false; 161 if (dependencyGraph.nEdges() != that.getDependencyGraph().nEdges()) 162 return false; 163 for (int i = 0; i < stack.size(); i++) { 164 if (stack.get(i).getIndex() != that.getStack().get(i).getIndex()) { 165 return false; 166 } 167 } 168 for (int i = 0; i < input.size(); i++) { 169 if (input.get(i).getIndex() != that.getInput().get(i).getIndex()) { 170 return false; 171 } 172 } 173 return dependencyGraph.getEdges().equals(that.getDependencyGraph().getEdges()); 174 } 175 176 public String toString() { 177 final StringBuilder sb = new StringBuilder(); 178 sb.append(stack.size()); 179 sb.append(", "); 180 sb.append(input.size()); 181 sb.append(", "); 182 sb.append(dependencyGraph.nEdges()); 183 return sb.toString(); 184 } 185 }