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    }