001 package org.maltparser.parser; 002 003 import java.io.BufferedWriter; 004 import java.io.FileWriter; 005 import java.io.IOException; 006 import java.io.OutputStreamWriter; 007 import java.lang.reflect.Constructor; 008 import java.lang.reflect.InvocationTargetException; 009 010 import org.maltparser.core.config.ConfigurationException; 011 import org.maltparser.core.exception.MaltChainedException; 012 import org.maltparser.core.symbol.SymbolTable; 013 import org.maltparser.core.syntaxgraph.DependencyStructure; 014 import org.maltparser.core.syntaxgraph.TokenStructure; 015 import org.maltparser.core.syntaxgraph.edge.Edge; 016 import org.maltparser.core.syntaxgraph.node.DependencyNode; 017 import org.maltparser.parser.guide.ClassifierGuide; 018 /** 019 * @author Johan Hall 020 * 021 */ 022 public abstract class Algorithm { 023 protected DependencyParserConfig manager; 024 protected ClassifierGuide classifierGuide; 025 protected ParserState parserState; 026 protected ParserConfiguration currentParserConfiguration; 027 protected boolean diagnostics = false; 028 protected BufferedWriter diaWriter; 029 /** 030 * Creates a parsing algorithm 031 * 032 * @param manager a reference to the single malt configuration 033 * @throws MaltChainedException 034 */ 035 public Algorithm(DependencyParserConfig manager) throws MaltChainedException { 036 setManager(manager); 037 setDiagnostics((Boolean)manager.getOptionValue("singlemalt", "diagnostics")); 038 if (diagnostics) { 039 openDiaWriter(manager.getOptionValue("singlemalt", "diafile").toString()); 040 } 041 } 042 043 public abstract void terminate() throws MaltChainedException; 044 045 public boolean isDiagnostics() { 046 return diagnostics; 047 } 048 049 public void setDiagnostics(boolean diagnostics) { 050 this.diagnostics = diagnostics; 051 } 052 053 054 public BufferedWriter getDiaWriter() { 055 return diaWriter; 056 } 057 058 public void writeToDiaFile(String message) throws MaltChainedException { 059 try { 060 getDiaWriter().write(message); 061 } catch (IOException e) { 062 throw new MaltChainedException("Could not write to the diagnostic file. ", e); 063 } 064 } 065 066 public void closeDiaWriter() throws MaltChainedException { 067 if (diaWriter != null) { 068 try { 069 diaWriter.flush(); 070 diaWriter.close(); 071 } catch (IOException e) { 072 throw new MaltChainedException("Could not close the diagnostic file. ", e); 073 } 074 } 075 } 076 077 public void openDiaWriter(String fileName) throws MaltChainedException { 078 if (diagnostics) { 079 try { 080 if (fileName.equals("stdout")) { 081 diaWriter = new BufferedWriter(new OutputStreamWriter(System.out)); 082 } else if (fileName.equals("stderr")) { 083 diaWriter = new BufferedWriter(new OutputStreamWriter(System.err)); 084 } else { 085 diaWriter = new BufferedWriter(new FileWriter(fileName)); 086 } 087 } catch (IOException e) { 088 throw new MaltChainedException("Could not open the diagnostic file. ", e); 089 } 090 } 091 } 092 093 /** 094 * Returns the classifier guide. 095 * 096 * @return the classifier guide 097 */ 098 public ClassifierGuide getGuide() { 099 return classifierGuide; 100 } 101 102 /** 103 * Sets the classifier guide 104 * 105 * @param guide a classifier guide 106 */ 107 public void setGuide(ClassifierGuide guide) { 108 this.classifierGuide = guide; 109 } 110 111 /** 112 * Returns the current active parser configuration 113 * 114 * @return the current active parser configuration 115 */ 116 public ParserConfiguration getCurrentParserConfiguration() { 117 return currentParserConfiguration; 118 } 119 120 /** 121 * Sets the current parser configuration 122 * 123 * @param currentParserConfiguration a parser configuration 124 */ 125 protected void setCurrentParserConfiguration(ParserConfiguration currentParserConfiguration) { 126 this.currentParserConfiguration = currentParserConfiguration; 127 } 128 129 /** 130 * Returns the parser state 131 * 132 * @return the parser state 133 */ 134 public ParserState getParserState() { 135 return parserState; 136 } 137 138 /** 139 * Sets the parser state 140 * 141 * @param parserState a parser state 142 */ 143 protected void setParserState(ParserState parserState) { 144 this.parserState = parserState; 145 } 146 147 /** 148 * Creates a parser factory specified by the --singlemalt-parsing_algorithm option 149 * 150 * @return a parser factory 151 * @throws MaltChainedException 152 */ 153 protected AbstractParserFactory makeParserFactory() throws MaltChainedException { 154 Class<?> clazz = (Class<?>)manager.getOptionValue("singlemalt", "parsing_algorithm"); 155 try { 156 Class<?>[] params = new Class<?>[1]; 157 params[0] = org.maltparser.parser.Algorithm.class; 158 Object[] arguments = new Object[params.length]; 159 arguments[0] = this; 160 Constructor<?> constructor = clazz.getConstructor(params); 161 return (AbstractParserFactory)constructor.newInstance(arguments); 162 } catch (NoSuchMethodException e) { 163 throw new ConfigurationException("The parser factory '"+clazz.getName()+"' cannot be initialized. ", e); 164 } catch (InstantiationException e) { 165 throw new ConfigurationException("The parser factory '"+clazz.getName()+"' cannot be initialized. ", e); 166 } catch (IllegalAccessException e) { 167 throw new ConfigurationException("The parser factory '"+clazz.getName()+"' cannot be initialized. ", e); 168 } catch (InvocationTargetException e) { 169 throw new ConfigurationException("The parser factory '"+clazz.getName()+"' cannot be initialized. ", e); 170 } 171 } 172 173 protected void initParserState(int k) throws MaltChainedException { 174 AbstractParserFactory parserFactory = makeParserFactory(); 175 ((SingleMalt)manager).addRegistry(parserFactory.getClass(), parserFactory); 176 parserState = new ParserState(this, parserFactory, k); 177 } 178 179 /** 180 * Returns the single malt configuration 181 * 182 * @return the single malt configuration 183 */ 184 public DependencyParserConfig getManager() { 185 return manager; 186 } 187 188 /** 189 * Sets the single malt configuration 190 * 191 * @param manager a single malt configuration 192 */ 193 public void setManager(DependencyParserConfig manager) { 194 this.manager = manager; 195 } 196 197 /** 198 * Copies the edges of the source dependency structure to the target dependency structure 199 * 200 * @param source a source dependency structure 201 * @param target a target dependency structure 202 * @throws MaltChainedException 203 */ 204 protected void copyEdges(DependencyStructure source, DependencyStructure target) throws MaltChainedException { 205 for (int index : source.getTokenIndices()) { 206 DependencyNode snode = source.getTokenNode(index); 207 208 if (snode.hasHead()) { 209 Edge s = snode.getHeadEdge(); 210 Edge t = target.addDependencyEdge(s.getSource().getIndex(), s.getTarget().getIndex()); 211 212 for (SymbolTable table : s.getLabelTypes()) { 213 t.addLabel(table, s.getLabelSymbol(table)); 214 } 215 } 216 } 217 } 218 219 protected void copyDynamicInput(DependencyStructure source, DependencyStructure target) throws MaltChainedException { 220 for (int index : source.getTokenIndices()) { 221 DependencyNode snode = source.getTokenNode(index); 222 DependencyNode tnode = target.getTokenNode(index); 223 for (SymbolTable table : snode.getLabelTypes()) { 224 if (!tnode.hasLabel(table)) { 225 tnode.addLabel(table,snode.getLabelSymbol(table)); 226 } 227 } 228 } 229 } 230 }