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