001package org.maltparser.core.lw.parser; 002import java.util.ArrayList; 003 004import org.maltparser.core.exception.MaltChainedException; 005import org.maltparser.core.feature.FeatureModel; 006import org.maltparser.core.feature.FeatureModelManager; 007import org.maltparser.core.helper.HashMap; 008import org.maltparser.core.symbol.SymbolTableHandler; 009import org.maltparser.core.symbol.TableHandler; 010import org.maltparser.core.syntaxgraph.DependencyStructure; 011import org.maltparser.parser.AlgoritmInterface; 012import org.maltparser.parser.DependencyParserConfig; 013import org.maltparser.parser.ParserConfiguration; 014import org.maltparser.parser.ParserRegistry; 015import org.maltparser.parser.TransitionSystem; 016import org.maltparser.parser.history.GuideUserHistory; 017import org.maltparser.parser.history.action.ComplexDecisionAction; 018import org.maltparser.parser.history.action.GuideUserAction; 019import org.maltparser.parser.history.container.ActionContainer; 020import org.maltparser.parser.history.container.CombinedTableContainer; 021import org.maltparser.parser.history.container.TableContainer; 022 023/** 024* A lightweight version of org.maltparser.parser.DeterministicParser. This class also implements a lightweight version of 025* org.maltparser.parser.history.History and reduces the need of org.maltparser.parser.ParserState. 026* 027* The class must be used in the same thread. 028* 029* @author Johan Hall 030*/ 031public final class LWDeterministicParser implements AlgoritmInterface, GuideUserHistory { 032 private final LWSingleMalt manager; 033 private final ParserRegistry registry; 034 035 private final TransitionSystem transitionSystem; 036 private final ParserConfiguration config; 037 private final FeatureModel featureModel; 038 private final ComplexDecisionAction currentAction; 039 040 private final int kBestSize; 041 private final ArrayList<TableContainer> decisionTables; 042 private final ArrayList<TableContainer> actionTables; 043 private final HashMap<String, TableHandler> tableHandlers; 044 045 public LWDeterministicParser(LWSingleMalt lwSingleMalt, SymbolTableHandler symbolTableHandler, FeatureModel _featureModel) throws MaltChainedException { 046 this.manager = lwSingleMalt; 047 this.registry = new ParserRegistry(); 048 this.registry.setSymbolTableHandler(symbolTableHandler); 049 this.registry.setDataFormatInstance(manager.getDataFormatInstance()); 050 this.registry.setAbstractParserFeatureFactory(manager.getParserFactory()); 051 this.registry.setAlgorithm(this); 052 this.transitionSystem = manager.getParserFactory().makeTransitionSystem(); 053 this.transitionSystem.initTableHandlers(lwSingleMalt.getDecisionSettings(), symbolTableHandler); 054 055 this.tableHandlers = transitionSystem.getTableHandlers(); 056 this.kBestSize = lwSingleMalt.getkBestSize(); 057 this.decisionTables = new ArrayList<TableContainer>(); 058 this.actionTables = new ArrayList<TableContainer>(); 059 initDecisionSettings(lwSingleMalt.getDecisionSettings(), lwSingleMalt.getClassitem_separator()); 060 this.transitionSystem.initTransitionSystem(this); 061 this.config = manager.getParserFactory().makeParserConfiguration(); 062 this.featureModel = _featureModel; 063 this.currentAction = new ComplexDecisionAction(this); 064 } 065 066 public LWDeterministicParser(LWSingleMalt lwSingleMalt, SymbolTableHandler symbolTableHandler) throws MaltChainedException { 067 this.manager = lwSingleMalt; 068 this.registry = new ParserRegistry(); 069 this.registry.setSymbolTableHandler(symbolTableHandler); 070 this.registry.setDataFormatInstance(manager.getDataFormatInstance()); 071 this.registry.setAbstractParserFeatureFactory(manager.getParserFactory()); 072 this.registry.setAlgorithm(this); 073 this.transitionSystem = manager.getParserFactory().makeTransitionSystem(); 074 this.transitionSystem.initTableHandlers(lwSingleMalt.getDecisionSettings(), symbolTableHandler); 075 076 this.tableHandlers = transitionSystem.getTableHandlers(); 077 this.kBestSize = lwSingleMalt.getkBestSize(); 078 this.decisionTables = new ArrayList<TableContainer>(); 079 this.actionTables = new ArrayList<TableContainer>(); 080 initDecisionSettings(lwSingleMalt.getDecisionSettings(), lwSingleMalt.getClassitem_separator()); 081 this.transitionSystem.initTransitionSystem(this); 082 this.config = manager.getParserFactory().makeParserConfiguration(); 083 this.featureModel = manager.getFeatureModelManager().getFeatureModel(lwSingleMalt.getFeatureModelURL(), 0, registry, manager.getDataSplitColumn(), manager.getDataSplitStructure()); 084 this.currentAction = new ComplexDecisionAction(this); 085 } 086 087 public DependencyStructure parse(DependencyStructure parseDependencyGraph) throws MaltChainedException { 088 config.clear(); 089 config.setDependencyGraph(parseDependencyGraph); 090 config.initialize(); 091 092 while (!config.isTerminalState()) { 093 GuideUserAction action = transitionSystem.getDeterministicAction(this, config); 094 if (action == null) { 095 action = predict(); 096 } 097 transitionSystem.apply(action, config); 098 } 099 parseDependencyGraph.linkAllTreesToRoot(); 100 return parseDependencyGraph; 101 } 102 103 private GuideUserAction predict() throws MaltChainedException { 104 currentAction.clear(); 105 try { 106 manager.getDecisionModel().predict(featureModel, currentAction, true); 107 108 while (!transitionSystem.permissible(currentAction, config)) { 109 if (manager.getDecisionModel().predictFromKBestList(featureModel, currentAction) == false) { 110 GuideUserAction defaultAction = transitionSystem.defaultAction(this, config); 111 ActionContainer[] actionContainers = this.getActionContainerArray(); 112 defaultAction.getAction(actionContainers); 113 currentAction.addAction(actionContainers); 114 break; 115 } 116 } 117 } catch (NullPointerException e) { 118 throw new MaltChainedException("The guide cannot be found. ", e); 119 } 120 return currentAction; 121 } 122 123 public ParserRegistry getParserRegistry() { 124 return registry; 125 } 126 127 public ParserConfiguration getCurrentParserConfiguration() { 128 return config; 129 } 130 131 public DependencyParserConfig getManager() { 132 return manager; 133 } 134 135 public String getGuideName() { 136 return null; 137 } 138 139 public void setGuideName(String guideName) { } 140 141 // GuideUserHistory interface 142 public GuideUserAction getEmptyGuideUserAction() throws MaltChainedException { 143 return new ComplexDecisionAction(this); 144 } 145 146 public ArrayList<ActionContainer> getActionContainers() { 147 ArrayList<ActionContainer> actionContainers = new ArrayList<ActionContainer>(); 148 for (int i=0; i<actionTables.size(); i++) { 149 actionContainers.add(new ActionContainer(actionTables.get(i))); 150 } 151 return actionContainers; 152 } 153 154 public ActionContainer[] getActionContainerArray() { 155 ActionContainer[] actionContainers = new ActionContainer[actionTables.size()]; 156 for (int i=0; i<actionTables.size(); i++) { 157 actionContainers[i] = new ActionContainer(actionTables.get(i)); 158 } 159 return actionContainers; 160 } 161 162 public void clear() throws MaltChainedException { } 163 164 public int getNumberOfDecisions() { 165 return decisionTables.size(); 166 } 167 168 public int getKBestSize() { 169 return kBestSize; 170 } 171 172 public int getNumberOfActions() { 173 return actionTables.size(); 174 } 175 176 public ArrayList<TableContainer> getDecisionTables() { 177 return decisionTables; 178 } 179 180 public ArrayList<TableContainer> getActionTables() { 181 return actionTables; 182 } 183 184 private void initDecisionSettings(String decisionSettings, String separator) throws MaltChainedException { 185 if (decisionSettings.equals("T.TRANS+A.DEPREL")) { 186 actionTables.add(new TableContainer(tableHandlers.get("T").getSymbolTable("TRANS"), "T.TRANS", '+')); 187 actionTables.add(new TableContainer(tableHandlers.get("A").getSymbolTable("DEPREL"), "A.DEPREL", ' ')); 188 decisionTables.add(new CombinedTableContainer(tableHandlers.get("A"), separator, actionTables, ' ')); 189 } else if (decisionSettings.equals("T.TRANS,A.DEPREL")) { 190 TableContainer transTableContainer = new TableContainer(tableHandlers.get("T").getSymbolTable("TRANS"), "T.TRANS", ','); 191 TableContainer deprelTableContainer = new TableContainer(tableHandlers.get("A").getSymbolTable("DEPREL"), "A.DEPREL", ','); 192 actionTables.add(transTableContainer); 193 actionTables.add(deprelTableContainer); 194 decisionTables.add(transTableContainer); 195 decisionTables.add(deprelTableContainer); 196 } else if (decisionSettings.equals("T.TRANS#A.DEPREL") || decisionSettings.equals("T.TRANS;A.DEPREL")) { 197 TableContainer transTableContainer = new TableContainer(tableHandlers.get("T").getSymbolTable("TRANS"), "T.TRANS", '#'); 198 TableContainer deprelTableContainer = new TableContainer(tableHandlers.get("A").getSymbolTable("DEPREL"), "A.DEPREL", '#'); 199 actionTables.add(transTableContainer); 200 actionTables.add(deprelTableContainer); 201 decisionTables.add(transTableContainer); 202 decisionTables.add(deprelTableContainer); 203 } else { 204 int start = 0; 205 int k = 0; 206 char prevDecisionSeparator = ' '; 207 TableContainer tmp = null; 208 final StringBuilder sbTableHandler = new StringBuilder(); 209 final StringBuilder sbTable = new StringBuilder(); 210 int state = 0; 211 for (int i = 0; i < decisionSettings.length(); i++) { 212 switch (decisionSettings.charAt(i)) { 213 case '.': 214 state = 1; 215 break; 216 case '+': 217 tmp = new TableContainer(tableHandlers.get(sbTableHandler.toString()).getSymbolTable(sbTable.toString()), 218 sbTableHandler.toString()+"."+sbTable.toString(), '+'); 219 actionTables.add(tmp); 220 k++; 221 sbTableHandler.setLength(0); 222 sbTable.setLength(0); 223 state = 0; 224 break; 225 case '#': 226 state = 2; 227 break; 228 case ';': 229 state = 2; 230 break; 231 case ',': 232 state = 2; 233 break; 234 default: 235 if (state == 0) { 236 sbTableHandler.append(decisionSettings.charAt(i)); 237 } else if (state == 1) { 238 sbTable.append(decisionSettings.charAt(i)); 239 } 240 } 241 if (state == 2 || i == decisionSettings.length()-1) { 242 char decisionSeparator = decisionSettings.charAt(i); 243 if (i == decisionSettings.length()-1) { 244 decisionSeparator = prevDecisionSeparator; 245 } 246 tmp = new TableContainer(tableHandlers.get(sbTableHandler.toString()).getSymbolTable(sbTable.toString()), 247 sbTableHandler.toString()+"."+sbTable.toString(), decisionSeparator); 248 actionTables.add(tmp); 249 k++; 250 if (k-start > 1) { 251 decisionTables.add(new CombinedTableContainer(tableHandlers.get("A"), separator, actionTables.subList(start, k), decisionSeparator)); 252 } else { 253 decisionTables.add(tmp); 254 } 255 sbTableHandler.setLength(0); 256 sbTable.setLength(0); 257 state = 0; 258 start = k; 259 prevDecisionSeparator = decisionSeparator; 260 } 261 } 262 } 263 } 264}