001package org.maltparser.parser.algorithm.stack;
002
003import java.util.Stack;
004
005import org.maltparser.core.exception.MaltChainedException;
006import org.maltparser.core.propagation.PropagationManager;
007import org.maltparser.core.syntaxgraph.edge.Edge;
008import org.maltparser.core.syntaxgraph.node.DependencyNode;
009import org.maltparser.parser.ParserConfiguration;
010import org.maltparser.parser.TransitionSystem;
011import org.maltparser.parser.history.GuideUserHistory;
012import org.maltparser.parser.history.action.ComplexDecisionAction;
013import org.maltparser.parser.history.action.GuideUserAction;
014import org.maltparser.parser.transition.TransitionTable;
015
016
017/**
018 * @author Johan Hall
019 *
020 */
021public class NonProjective extends TransitionSystem {
022        protected static final int SHIFT = 1;
023        protected static final int SWAP = 2;
024        protected static final int RIGHTARC = 3;
025        protected static final int LEFTARC = 4;
026
027        public NonProjective(PropagationManager propagationManager) throws MaltChainedException {
028                super(propagationManager);
029        }
030        
031        public void apply(GuideUserAction currentAction, ParserConfiguration configuration) throws MaltChainedException {
032                final StackConfig config = (StackConfig)configuration;
033                final Stack<DependencyNode> stack = config.getStack();
034                final Stack<DependencyNode> input = config.getInput();
035                currentAction.getAction(actionContainers);
036                Edge e = null;
037                DependencyNode head = null;
038                DependencyNode dep = null;
039                switch (transActionContainer.getActionCode()) {
040                case LEFTARC:
041                        head = stack.pop(); 
042                        dep = stack.pop();
043                        e = config.getDependencyStructure().addDependencyEdge(head.getIndex(), dep.getIndex());
044                        addEdgeLabels(e);
045                        stack.push(head);
046                        break;
047                case RIGHTARC:
048                        dep = stack.pop(); 
049                        e = config.getDependencyStructure().addDependencyEdge(stack.peek().getIndex(), dep.getIndex());
050                        addEdgeLabels(e);
051                        break;
052                case SWAP:
053                        dep = stack.pop();
054                        input.push(stack.pop());
055                        stack.push(dep);
056                        config.lookaheadIncrement();
057                        break;
058                default:
059                        if (input.isEmpty()) {
060                                stack.pop();
061                        } else {
062                                stack.push(input.pop()); // SHIFT
063                        }
064                        config.lookaheadDecrement();
065                        break;
066                }
067        }
068        
069        public boolean permissible(GuideUserAction currentAction, ParserConfiguration configuration) throws MaltChainedException {
070                currentAction.getAction(actionContainers);
071                int trans = transActionContainer.getActionCode();
072                if ((trans == LEFTARC || trans == RIGHTARC) && !isActionContainersLabeled()) {
073                        return false;
074                }
075                final StackConfig config = (StackConfig)configuration;
076                final Stack<DependencyNode> stack = config.getStack();
077                if ((trans == LEFTARC || trans == RIGHTARC || trans == SWAP) && stack.size() < 2) {
078                        return false;
079                }
080                if ((trans == LEFTARC || trans == SWAP) && stack.get(stack.size()-2).isRoot()) { 
081                        return false;
082                }
083                final Stack<DependencyNode> input = config.getInput();
084                if (trans == SHIFT && input.isEmpty()) { 
085                        return false;
086                }
087                if (trans == SWAP && stack.get(stack.size()-2).getIndex() > stack.get(stack.size()-1).getIndex()) {
088                        return false;
089                }
090                return true;
091        }
092        
093        public GuideUserAction getDeterministicAction(GuideUserHistory history, ParserConfiguration config) throws MaltChainedException {
094                return null;
095        }
096        
097        protected void addAvailableTransitionToTable(TransitionTable ttable) throws MaltChainedException {
098                ttable.addTransition(SHIFT, "SH", false, null);
099                ttable.addTransition(SWAP, "SW", false, null);
100                ttable.addTransition(RIGHTARC, "RA", true, null);
101                ttable.addTransition(LEFTARC, "LA", true, null);
102        }
103        
104        protected void initWithDefaultTransitions(GuideUserHistory history) throws MaltChainedException {
105                GuideUserAction currentAction = new ComplexDecisionAction(history);
106                
107                transActionContainer.setAction(SHIFT);
108                //transActionContainer.setAction(SWAP);
109                for (int i = 0; i < arcLabelActionContainers.length; i++) {
110                        arcLabelActionContainers[i].setAction(-1);
111                }
112                currentAction.addAction(actionContainers);
113        }
114        
115        public String getName() {
116                return "nonprojective";
117        }
118        
119        public GuideUserAction defaultAction(GuideUserHistory history, ParserConfiguration configuration) throws MaltChainedException {
120                if (((StackConfig)configuration).getInput().isEmpty()) {
121                        return updateActionContainers(history, RIGHTARC, ((StackConfig)configuration).getDependencyGraph().getDefaultRootEdgeLabels());
122                }       
123                return updateActionContainers(history, SHIFT, null);
124        }
125}