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}