001 package org.maltparser.parser.algorithm.stack; 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 StackConfig extends ParserConfiguration { 019 private Stack<DependencyNode> stack; 020 private Stack<DependencyNode> input; 021 private DependencyStructure dependencyGraph; 022 private int lookahead; 023 024 public StackConfig(SymbolTableHandler symbolTableHandler) throws MaltChainedException { 025 super(); 026 stack = new Stack<DependencyNode>(); 027 input = new Stack<DependencyNode>(); 028 dependencyGraph = new DependencyGraph(symbolTableHandler); 029 } 030 031 public Stack<DependencyNode> getStack() { 032 return stack; 033 } 034 035 public Stack<DependencyNode> getInput() { 036 return input; 037 } 038 039 public DependencyStructure getDependencyStructure() { 040 return dependencyGraph; 041 } 042 043 public boolean isTerminalState() { 044 return input.isEmpty() && stack.size() == 1; 045 } 046 047 public DependencyNode getStackNode(int index) throws MaltChainedException { 048 if (index < 0) { 049 throw new ParsingException("Stack index must be non-negative in feature specification. "); 050 } 051 if (stack.size()-index > 0) { 052 return stack.get(stack.size()-1-index); 053 } 054 return null; 055 } 056 057 private DependencyNode getBufferNode(int index) throws MaltChainedException { 058 if (index < 0) { 059 throw new ParsingException("Input index must be non-negative in feature specification. "); 060 } 061 if (input.size()-index > 0) { 062 return input.get(input.size()-1-index); 063 } 064 return null; 065 } 066 067 public DependencyNode getLookaheadNode(int index) throws MaltChainedException { 068 return getBufferNode(lookahead+index); 069 } 070 071 public DependencyNode getInputNode(int index) throws MaltChainedException { 072 if (index < lookahead) { 073 return getBufferNode(index); 074 } 075 return null; 076 } 077 078 public void setDependencyGraph(DependencyStructure source) throws MaltChainedException { 079 dependencyGraph.clear(); 080 for (int index : source.getTokenIndices()) { 081 DependencyNode gnode = source.getTokenNode(index); 082 DependencyNode pnode = dependencyGraph.addTokenNode(gnode.getIndex()); 083 for (SymbolTable table : gnode.getLabelTypes()) { 084 pnode.addLabel(table, gnode.getLabelSymbol(table)); 085 } 086 087 if (gnode.hasHead()) { 088 Edge s = gnode.getHeadEdge(); 089 Edge t = dependencyGraph.addDependencyEdge(s.getSource().getIndex(), s.getTarget().getIndex()); 090 091 for (SymbolTable table : s.getLabelTypes()) { 092 t.addLabel(table, s.getLabelSymbol(table)); 093 } 094 } 095 } 096 for (SymbolTable table : source.getDefaultRootEdgeLabels().keySet()) { 097 dependencyGraph.setDefaultRootEdgeLabel(table, source.getDefaultRootEdgeLabelSymbol(table)); 098 } 099 } 100 101 public void lookaheadIncrement() { 102 lookahead++; 103 } 104 105 public void lookaheadDecrement() { 106 if (lookahead > 0) { 107 lookahead--; 108 } 109 } 110 111 public DependencyStructure getDependencyGraph() { 112 return dependencyGraph; 113 } 114 115 public void initialize(ParserConfiguration parserConfiguration) throws MaltChainedException { 116 if (parserConfiguration != null) { 117 StackConfig config = (StackConfig)parserConfiguration; 118 Stack<DependencyNode> sourceStack = config.getStack(); 119 Stack<DependencyNode> sourceInput = config.getInput(); 120 setDependencyGraph(config.getDependencyGraph()); 121 for (int i = 0, n = sourceStack.size(); i < n; i++) { 122 stack.add(dependencyGraph.getDependencyNode(sourceStack.get(i).getIndex())); 123 } 124 for (int i = 0, n = sourceInput.size(); i < n; i++) { 125 input.add(dependencyGraph.getDependencyNode(sourceInput.get(i).getIndex())); 126 } 127 } else { 128 stack.push(dependencyGraph.getDependencyRoot()); 129 for (int i = dependencyGraph.getHighestTokenIndex(); i > 0; i--) { 130 final DependencyNode node = dependencyGraph.getDependencyNode(i); 131 if (node != null && !node.hasHead()) { 132 input.push(node); 133 } 134 } 135 } 136 } 137 138 public boolean equals(Object obj) { 139 if (this == obj) 140 return true; 141 if (obj == null) 142 return false; 143 if (getClass() != obj.getClass()) 144 return false; 145 StackConfig that = (StackConfig)obj; 146 147 if (lookahead != that.lookahead) 148 return false; 149 if (stack.size() != that.getStack().size()) 150 return false; 151 if (input.size() != that.getInput().size()) 152 return false; 153 if (dependencyGraph.nEdges() != that.getDependencyGraph().nEdges()) 154 return false; 155 for (int i = 0; i < stack.size(); i++) { 156 if (stack.get(i).getIndex() != that.getStack().get(i).getIndex()) { 157 return false; 158 } 159 } 160 for (int i = 0; i < input.size(); i++) { 161 if (input.get(i).getIndex() != that.getInput().get(i).getIndex()) { 162 return false; 163 } 164 } 165 return dependencyGraph.getEdges().equals(that.getDependencyGraph().getEdges()); 166 } 167 168 public void clear() throws MaltChainedException { 169 dependencyGraph.clear(); 170 stack.clear(); 171 input.clear(); 172 historyNode = null; 173 lookahead = 0; 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 }