001package org.maltparser.parser.algorithm.nivre;
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 * @author Johan Hall
017 *
018 */
019public class ArcEager extends TransitionSystem {
020        protected static final int SHIFT = 1;
021        protected static final int REDUCE = 2;
022        protected static final int RIGHTARC = 3;
023        protected static final int LEFTARC = 4;
024        protected static final int UNSHIFT = 5;
025        
026        public ArcEager(PropagationManager propagationManager) throws MaltChainedException {
027                super(propagationManager);
028        }
029        
030        public void apply(GuideUserAction currentAction, ParserConfiguration config) throws MaltChainedException {
031                final NivreConfig nivreConfig = (NivreConfig)config;
032                final Stack<DependencyNode> stack = nivreConfig.getStack();
033                final Stack<DependencyNode> input = nivreConfig.getInput();
034                currentAction.getAction(actionContainers);
035                Edge e = null;
036                if (!nivreConfig.isEnforceTree()) {
037                        switch (transActionContainer.getActionCode()) {
038                        case LEFTARC:
039                                e = nivreConfig.getDependencyStructure().addDependencyEdge(input.peek().getIndex(), stack.peek().getIndex());
040                                addEdgeLabels(e);
041                                stack.pop();
042                                break;
043                        case RIGHTARC:
044                                e = nivreConfig.getDependencyStructure().addDependencyEdge(stack.peek().getIndex(), input.peek().getIndex());
045                                addEdgeLabels(e);
046                                stack.push(input.pop());
047                                break;
048                        case REDUCE:
049                                stack.pop();
050                                break;
051                        default:
052                                stack.push(input.pop());
053                                break;
054                        }
055                } else {
056                        switch (transActionContainer.getActionCode()) {
057                        case LEFTARC:
058                                e = nivreConfig.getDependencyStructure().addDependencyEdge(input.peek().getIndex(), stack.peek().getIndex());
059                                addEdgeLabels(e);
060                                stack.pop();
061                                break;
062                        case RIGHTARC:
063                                e = nivreConfig.getDependencyStructure().addDependencyEdge(stack.peek().getIndex(), input.peek().getIndex());
064                                addEdgeLabels(e);
065                                stack.push(input.pop());
066                if(input.isEmpty() && !nivreConfig.isEnd()) {
067                        nivreConfig.setEnd(true);
068                }
069                                break;
070                        case REDUCE:
071                                stack.pop();
072                                break;
073                case UNSHIFT:                                                                                                                               
074                    input.push(stack.pop());
075                    break;
076                        default:
077                                stack.push(input.pop());
078                                                                                                                                                         
079                    if (input.isEmpty() && !nivreConfig.isEnd()) {
080                        nivreConfig.setEnd(true);
081                    }
082        
083                                break;
084                        }
085                        
086                }
087        }
088        
089    public GuideUserAction getDeterministicAction(GuideUserHistory history, ParserConfiguration config) throws MaltChainedException {
090        final NivreConfig nivreConfig = (NivreConfig)config;
091        if (!nivreConfig.isEnforceTree()) {
092          if (!nivreConfig.isAllowRoot() && nivreConfig.getStack().peek().isRoot()) {
093                return updateActionContainers(history, ArcEager.SHIFT, null);
094          }
095        } else {
096                //Added
097                if (!nivreConfig.isAllowRoot() && nivreConfig.getStack().peek().isRoot() && !nivreConfig.isEnd()) {
098                        return updateActionContainers(history, ArcEager.SHIFT, null);
099                }
100                                                                                                                                                                
101                if (nivreConfig.getInput().isEmpty() && nivreConfig.getStack().peek().hasHead()) {
102                    return updateActionContainers(history, ArcEager.REDUCE, null);
103                }
104                
105                if (nivreConfig.getInput().isEmpty() && !nivreConfig.getStack().peek().hasHead()) {
106                    return updateActionContainers(history, ArcEager.UNSHIFT, null);
107                }
108        }
109        return null;
110    }
111
112        
113        protected void addAvailableTransitionToTable(TransitionTable ttable) throws MaltChainedException {
114                ttable.addTransition(SHIFT, "SH", false, null);
115                ttable.addTransition(REDUCE, "RE", false, null);
116                ttable.addTransition(RIGHTARC, "RA", true, null);
117                ttable.addTransition(LEFTARC, "LA", true, null);
118                ttable.addTransition(UNSHIFT, "USH", false, null);//Added
119        }
120        
121        protected void initWithDefaultTransitions(GuideUserHistory history) throws MaltChainedException {
122                GuideUserAction currentAction = new ComplexDecisionAction(history);
123                
124                transActionContainer.setAction(SHIFT);
125                transActionContainer.setAction(REDUCE);
126                for (int i = 0; i < arcLabelActionContainers.length; i++) {
127                        arcLabelActionContainers[i].setAction(-1);
128                }
129                currentAction.addAction(actionContainers);
130        }
131        
132        public String getName() {
133                return "nivreeager";
134        }
135
136        public boolean permissible(GuideUserAction currentAction, ParserConfiguration config) throws MaltChainedException {
137                currentAction.getAction(actionContainers);
138                final int trans = transActionContainer.getActionCode();
139                final NivreConfig nivreConfig = (NivreConfig)config;
140                final DependencyNode stackPeek = nivreConfig.getStack().peek();
141                if ((trans == LEFTARC || trans == RIGHTARC) && !isActionContainersLabeled()) {
142                        return false;
143                }
144                if ((trans == LEFTARC || trans == REDUCE) && stackPeek.isRoot()) { 
145                        return false;
146                }
147                if (trans == LEFTARC && stackPeek.hasHead()) { 
148                        return false;
149                }
150                if (trans == REDUCE && !stackPeek.hasHead() && !nivreConfig.isAllowReduce()) {
151                        return false;
152                }
153        //Added                                                                                                                                                   
154        if (trans == SHIFT && nivreConfig.isEnforceTree() && nivreConfig.isEnd()){
155            return false;
156        }
157
158                return true;
159        }
160        
161        public GuideUserAction defaultAction(GuideUserHistory history, ParserConfiguration configuration) throws MaltChainedException {
162                return updateActionContainers(history, ArcEager.SHIFT, null);
163        }
164}