001    package org.maltparser.parser.algorithm.nivre;
002    
003    
004    import org.maltparser.core.exception.MaltChainedException;
005    import org.maltparser.core.syntaxgraph.DependencyStructure;
006    import org.maltparser.core.syntaxgraph.LabelSet;
007    import org.maltparser.core.syntaxgraph.edge.Edge;
008    
009    import org.maltparser.parser.SingleMalt;
010    import org.maltparser.parser.algorithm.ParsingException;
011    import org.maltparser.parser.algorithm.helper.TransitionTable;
012    import org.maltparser.parser.history.container.ActionContainer;
013    
014    /**
015     * 
016     * @author Joakim Nivre
017     * @author Johan Hall
018     * @since 1.0
019    */
020    public class NivreEager extends Nivre {
021            protected static final int REDUCE = 2;
022            protected static final int RIGHTARC = 3;
023            protected static final int LEFTARC = 4;
024            
025            public NivreEager(SingleMalt configuration) throws MaltChainedException {
026                    super(configuration);
027            }
028            
029            protected void transition(DependencyStructure parseDependencyGraph) throws MaltChainedException {
030                    currentAction.getAction(actionContainers);
031                    while (checkParserAction(parseDependencyGraph) == false) {
032                            if (configuration.getMode() == SingleMalt.LEARN || configuration.predictFromKBestList(currentAction) == false) {
033                                    updateActionContainers(SHIFT, null);
034                                    break;
035                            }
036                            currentAction.getAction(actionContainers);
037                    }
038                    Edge e = null;
039                    switch (getTransition()) {
040                    case LEFTARC:
041                            e = parseDependencyGraph.addDependencyEdge(input.peek().getIndex(), stack.peek().getIndex());
042                            addEdgeLabels(e);
043                            stack.pop();
044                            break;
045                    case RIGHTARC:
046                            e = parseDependencyGraph.addDependencyEdge(stack.peek().getIndex(), input.peek().getIndex());
047                            addEdgeLabels(e);
048                            stack.push(input.pop());
049                            break;
050                    case REDUCE:
051                            stack.pop();
052                            break;
053                    default:
054                            stack.push(input.pop()); // SHIFT
055                            break;
056                    }
057            }
058            
059            protected boolean checkParserAction(DependencyStructure dg) throws MaltChainedException {
060                    final int trans = getTransition();
061                    if ((trans == LEFTARC || trans == RIGHTARC) && !isActionContainersLabeled()) {
062                            // LabelCode cannot be found for transition LEFTARC and RIGHTARC
063                            return false;
064                    }
065                    if ((trans == LEFTARC || trans == REDUCE) && stack.peek().isRoot()) { 
066                            // The token on top of the stack is the root for LEFTARC and REDUCE
067                            return false;
068                    }
069                    if (trans == LEFTARC && stack.peek().hasHead()) { 
070                            // The token on top of the stack has already a head for transition LEFTARC
071                            return false;
072                    }
073                    if (trans == REDUCE && !stack.peek().hasHead() && rootHandling == STRICT) {
074                            // The token on top of the stack have not a head for transition REDUCE
075                            return false;
076                    }
077                    return true;
078            }
079    
080            
081            protected void oraclePredict(DependencyStructure gold, DependencyStructure parseDependencyGraph) throws MaltChainedException {
082                    if (!stack.peek().isRoot() && gold.getTokenNode(stack.peek().getIndex()).getHead().getIndex() == input.peek().getIndex()) {
083                            updateActionContainers(LEFTARC, gold.getTokenNode(stack.peek().getIndex()).getHeadEdge().getLabelSet());
084                    } else if (gold.getTokenNode(input.peek().getIndex()).getHead().getIndex() == stack.peek().getIndex()) {
085                            updateActionContainers(RIGHTARC, gold.getTokenNode(input.peek().getIndex()).getHeadEdge().getLabelSet());
086                    } else if (gold.getTokenNode(input.peek().getIndex()).hasLeftDependent() &&
087                                    gold.getTokenNode(input.peek().getIndex()).getLeftmostDependent().getIndex() < stack.peek().getIndex()) {
088                            updateActionContainers(REDUCE, null);
089                    /*} else if (gold.getTokenNode(input.peek().getIndex()).getHead().getIndex() < stack.peek().getIndex() && 
090                                    (!(gold.getTokenNode(input.peek().getIndex()).getLabelCode(deprel) == gold.getRootLabels().getRootLabelCode(deprel)) )) { 
091                            parserAction.addAction(REDUCE); */
092                    } else if (gold.getTokenNode(input.peek().getIndex()).getHead().getIndex() < stack.peek().getIndex() &&
093                            (!gold.getTokenNode(input.peek().getIndex()).getHead().isRoot() || rootHandling == NORMAL )) {
094                            updateActionContainers(REDUCE, null);
095                    } else {
096                            updateActionContainers(SHIFT, null);
097                    }
098            }
099            
100            protected int getTransition() {
101                    return transActionContainer.getActionCode();
102            }
103            
104            protected void updateActionContainers(int transition, LabelSet arcLabels) throws MaltChainedException {
105                    if (complexTransition) {
106                            switch (transition) {
107                            case SHIFT:
108                                    pushActionContainer.setAction(1);
109                                    transActionContainer.setAction(transition);
110                                    break;
111                            case REDUCE:
112                                    pushActionContainer.setAction(2);
113                                    transActionContainer.setAction(transition);
114                                    break;
115                            case RIGHTARC:
116                                    pushActionContainer.setAction(1);
117                                    transActionContainer.setAction(transition);
118                                    break;
119                            case LEFTARC:
120                                    pushActionContainer.setAction(2);
121                                    transActionContainer.setAction(transition);
122                                    break;
123                            default:
124                                    throw new ParsingException("Unknown transition "+transition+". ");
125                            }
126                    } else { 
127                            transActionContainer.setAction(transition);
128                    }
129                    if (arcLabels == null) {
130                            for (ActionContainer container : arcLabelActionContainers) {
131                                    container.setAction(-1);
132                            }
133                    } else {
134                            for (ActionContainer container : arcLabelActionContainers) {
135                                    container.setAction(arcLabels.get(container.getTable()).intValue());
136                            }               
137                    }
138                    currentAction.addAction(actionContainers);
139            }
140            
141            protected void addAvailableTransitionToTable(TransitionTable ttable) throws MaltChainedException {
142                    ttable.addTransition(SHIFT, "SH", false, null);
143                    ttable.addTransition(REDUCE, "RE", false, null);
144                    ttable.addTransition(RIGHTARC, "RA", true, null);
145                    ttable.addTransition(LEFTARC, "LA", true, null);
146            }
147            
148            protected void initWithDefaultTransitions() throws MaltChainedException {
149                    if (!complexTransition) {
150                            if (transActionContainer == null) {
151                                    throw new ParsingException("The decision settings does not contain T.TRANS or T.PUSH;T.TRANS");
152                            }
153                            addTransition(transActionContainer, currentAction, SHIFT);
154                            addTransition(transActionContainer, currentAction, REDUCE);
155                    }  else {
156                            if (pushActionContainer == null || transActionContainer == null) {
157                                    throw new ParsingException("The decision settings does not contain T.TRANS or T.PUSH;T.TRANS");
158                            }
159                            addTransition(transActionContainer, currentAction, SHIFT);
160                            addTransition(transActionContainer, currentAction, REDUCE);
161                    }
162            }
163            
164            public String getName() {
165                    return "nivreeager";
166            }
167    }