001package org.maltparser.parser.algorithm.stack;
002
003import java.util.Stack;
004
005import org.maltparser.core.exception.MaltChainedException;
006import org.maltparser.core.syntaxgraph.DependencyStructure;
007import org.maltparser.core.syntaxgraph.node.DependencyNode;
008import org.maltparser.parser.ParserConfiguration;
009import org.maltparser.parser.ParsingException;
010/**
011 * @author Johan Hall
012 *
013 */
014public class StackConfig extends ParserConfiguration {
015        private final Stack<DependencyNode> stack;
016        private final Stack<DependencyNode> input;
017        private DependencyStructure dependencyGraph;
018        private int lookahead;
019        
020        public StackConfig() throws MaltChainedException {
021                super();
022                stack = new Stack<DependencyNode>();
023                input = new Stack<DependencyNode>();
024//              dependencyGraph = new DependencyGraph(symbolTableHandler);
025        }
026        
027        public Stack<DependencyNode> getStack() {
028                return stack;
029        }
030        
031        public Stack<DependencyNode> getInput() {
032                return input;
033        }
034        
035        public DependencyStructure getDependencyStructure() {
036                return dependencyGraph;
037        }
038        
039        public boolean isTerminalState() {
040                return input.isEmpty() && stack.size() == 1;
041        }
042        
043        public DependencyNode getStackNode(int index) throws MaltChainedException {
044                if (index < 0) {
045                        throw new ParsingException("Stack index must be non-negative in feature specification. ");
046                }
047                if (stack.size()-index > 0) {
048                        return stack.get(stack.size()-1-index);
049                }
050                return null;
051        }
052        
053        private DependencyNode getBufferNode(int index) throws MaltChainedException {
054                if (index < 0) {
055                        throw new ParsingException("Input index must be non-negative in feature specification. ");
056                }
057                if (input.size()-index > 0) {
058                        return input.get(input.size()-1-index);
059                }       
060                return null;
061        }
062        
063        public DependencyNode getLookaheadNode(int index) throws MaltChainedException { 
064                return getBufferNode(lookahead+index);
065        }
066        
067        public DependencyNode getInputNode(int index) throws MaltChainedException {
068                if (index < lookahead) {
069                        return getBufferNode(index);
070                }
071                return null;
072        }
073        
074        public void setDependencyGraph(DependencyStructure source) throws MaltChainedException {
075                this.dependencyGraph = source;
076//              dependencyGraph.clear();
077//              for (int index : source.getTokenIndices()) {
078//                      DependencyNode gnode = source.getDependencyNode(index);
079//                      DependencyNode pnode = dependencyGraph.addDependencyNode(gnode.getIndex());
080//                      for (SymbolTable table : gnode.getLabelTypes()) {
081//                              pnode.addLabel(table, gnode.getLabelSymbol(table));
082//                      }
083//                      
084//                      if (gnode.hasHead()) {
085//                              Edge s = gnode.getHeadEdge();
086//                              Edge t = dependencyGraph.addDependencyEdge(s.getSource().getIndex(), s.getTarget().getIndex());
087//                              
088//                              for (SymbolTable table : s.getLabelTypes()) {
089//                                      t.addLabel(table, s.getLabelSymbol(table));
090//                              }
091//                      }
092//              }
093//              for (SymbolTable table : source.getDefaultRootEdgeLabels().keySet()) {
094//                      dependencyGraph.setDefaultRootEdgeLabel(table, source.getDefaultRootEdgeLabelSymbol(table));
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 && !node.hasHead()) { 
129                                        input.push(node);
130                                }
131                        }
132                }
133        }
134        
135        public void initialize() throws MaltChainedException {
136                stack.push(dependencyGraph.getDependencyRoot());
137                for (int i = dependencyGraph.getHighestTokenIndex(); i > 0; i--) {
138                        final DependencyNode node = dependencyGraph.getDependencyNode(i);
139                        if (node != null && !node.hasHead()) { 
140                                input.push(node);
141                        }
142                }
143        }
144        
145        public boolean equals(Object obj) {
146                if (this == obj)
147                        return true;
148                if (obj == null)
149                        return false;
150                if (getClass() != obj.getClass())
151                        return false;
152                StackConfig that = (StackConfig)obj;
153                
154                if (lookahead != that.lookahead) 
155                        return false;
156                if (stack.size() != that.getStack().size()) 
157                        return false;
158                if (input.size() != that.getInput().size())
159                        return false;
160                if (dependencyGraph.nEdges() != that.getDependencyGraph().nEdges())
161                        return false;
162                for (int i = 0; i < stack.size(); i++) {
163                        if (stack.get(i).getIndex() != that.getStack().get(i).getIndex()) {
164                                return false;
165                        }
166                }
167                for (int i = 0; i < input.size(); i++) {
168                        if (input.get(i).getIndex() != that.getInput().get(i).getIndex()) {
169                                return false;
170                        }
171                }               
172                return dependencyGraph.getEdges().equals(that.getDependencyGraph().getEdges());
173        }
174        
175        public void clear() throws MaltChainedException {
176//              dependencyGraph.clear();
177                stack.clear();
178                input.clear();
179                historyNode = null;
180                lookahead = 0;
181        }
182        
183        public String toString() {
184                final StringBuilder sb = new StringBuilder();
185                sb.append(stack.size());
186                sb.append(", ");
187                sb.append(input.size());
188                sb.append(", ");
189                sb.append(dependencyGraph.nEdges());
190                return sb.toString();
191        }
192}