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