1 21 22 package net.percederberg.grammatica.output; 23 24 import java.io.IOException ; 25 import java.util.HashMap ; 26 27 import net.percederberg.grammatica.code.java.JavaClass; 28 import net.percederberg.grammatica.code.java.JavaComment; 29 import net.percederberg.grammatica.code.java.JavaConstructor; 30 import net.percederberg.grammatica.code.java.JavaFile; 31 import net.percederberg.grammatica.code.java.JavaImport; 32 import net.percederberg.grammatica.code.java.JavaMethod; 33 import net.percederberg.grammatica.code.java.JavaVariable; 34 import net.percederberg.grammatica.parser.ProductionPattern; 35 import net.percederberg.grammatica.parser.ProductionPatternAlternative; 36 import net.percederberg.grammatica.parser.ProductionPatternElement; 37 38 45 class JavaParserFile { 46 47 50 private static final String TYPE_COMMENT = 51 "A token stream parser."; 52 53 56 private static final String PRODUCTION_COMMENT = 57 "A generated production node identity constant."; 58 59 62 private static final String CONSTRUCTOR1_COMMENT = 63 "Creates a new parser.\n\n" + 64 "@param in the input stream to read from\n\n" + 65 "@throws ParserCreationException if the parser couldn't be\n" + 66 " initialized correctly"; 67 68 71 private static final String CONSTRUCTOR2_COMMENT = 72 "Creates a new parser.\n\n" + 73 "@param in the input stream to read from\n" + 74 "@param analyzer the analyzer to use while parsing\n\n" + 75 "@throws ParserCreationException if the parser couldn't be\n" + 76 " initialized correctly"; 77 78 81 private static final String INIT_METHOD_COMMENT = 82 "Initializes the parser by creating all the production patterns.\n\n" + 83 "@throws ParserCreationException if the parser couldn't be\n" + 84 " initialized correctly"; 85 86 89 private JavaParserGenerator gen; 90 91 94 private JavaTokenizerFile tokenizer; 95 96 99 private JavaFile file; 100 101 104 private JavaClass cls; 105 106 109 private JavaMethod initMethod; 110 111 116 private HashMap constantNames = new HashMap (); 117 118 121 private int constantId = 1; 122 123 129 public JavaParserFile(JavaParserGenerator gen, 130 JavaTokenizerFile tokenizer) { 131 132 int modifiers; 133 134 this.gen = gen; 135 this.tokenizer = tokenizer; 136 this.file = gen.createJavaFile(); 137 if (gen.getPublicAccess()) { 138 modifiers = JavaClass.PUBLIC; 139 } else { 140 modifiers = JavaClass.PACKAGE_LOCAL; 141 } 142 this.cls = new JavaClass(modifiers, 143 gen.getBaseName() + "Parser", 144 "RecursiveDescentParser"); 145 this.initMethod = new JavaMethod(JavaMethod.PRIVATE, 146 "createPatterns", 147 "", 148 "void"); 149 initializeCode(); 150 } 151 152 155 private void initializeCode() { 156 JavaConstructor constr; 157 String str; 158 159 file.addImport(new JavaImport("java.io", "Reader")); 161 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 162 "Analyzer")); 163 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 164 "ParserCreationException")); 165 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 166 "ProductionPattern")); 167 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 168 "ProductionPatternAlternative")); 169 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 170 "RecursiveDescentParser")); 171 172 file.addClass(cls); 174 str = TYPE_COMMENT; 175 if (gen.getClassComment() != null) { 176 str += "\n\n" + gen.getClassComment(); 177 } 178 cls.addComment(new JavaComment(str)); 179 180 str = file.toString() + "\n\n" + gen.getFileComment(); 182 file.addComment(new JavaComment(JavaComment.BLOCK, str)); 183 184 constr = new JavaConstructor("Reader in"); 186 cls.addConstructor(constr); 187 constr.addComment(new JavaComment(CONSTRUCTOR1_COMMENT)); 188 constr.addThrows("ParserCreationException"); 189 constr.addCode("super(" + tokenizer.getConstructorCall("in") + ");"); 190 constr.addCode("createPatterns();"); 191 192 constr = new JavaConstructor("Reader in, Analyzer analyzer"); 194 cls.addConstructor(constr); 195 constr.addComment(new JavaComment(CONSTRUCTOR2_COMMENT)); 196 constr.addThrows("ParserCreationException"); 197 constr.addCode("super(" + tokenizer.getConstructorCall("in") + 198 ", analyzer);"); 199 constr.addCode("createPatterns();"); 200 201 cls.addMethod(initMethod); 203 initMethod.addComment(new JavaComment(INIT_METHOD_COMMENT)); 204 initMethod.addThrows("ParserCreationException"); 205 initMethod.addCode("ProductionPattern pattern;"); 206 initMethod.addCode("ProductionPatternAlternative alt;"); 207 } 208 209 214 public void addProductionConstant(ProductionPattern pattern) { 215 String constant; 216 JavaVariable var; 217 int modifiers; 218 219 if (pattern.isSynthetic()) { 220 constant = "SUBPRODUCTION_" + constantId; 221 modifiers = JavaVariable.PRIVATE + JavaVariable.STATIC + 222 JavaVariable.FINAL; 223 var = new JavaVariable(modifiers, 224 "int", 225 constant, 226 String.valueOf(constantId + 3000)); 227 var.addComment(new JavaComment(PRODUCTION_COMMENT)); 228 cls.addVariable(var); 229 constantNames.put(new Integer (pattern.getId()), constant); 230 constantId++; 231 } 232 } 233 234 240 public void addProduction(ProductionPattern pattern, 241 JavaConstantsFile constants) { 242 StringBuffer code; 243 String str; 244 245 code = new StringBuffer (); 247 code.append("pattern = new ProductionPattern("); 248 code.append(getConstant(constants, pattern.getId())); 249 code.append(",\n"); 250 code.append(" \""); 251 if (pattern.isSynthetic()) { 252 str = getConstant(constants, pattern.getId()); 253 code.append(gen.getCodeStyle().getMixedCase(str, true)); 254 } else { 255 code.append(pattern.getName()); 256 } 257 code.append("\");"); 258 initMethod.addCode(""); 259 initMethod.addCode(code.toString()); 260 261 if (pattern.isSynthetic()) { 263 initMethod.addCode("pattern.setSynthetic(true);"); 264 } 265 266 for (int i = 0; i < pattern.getAlternativeCount(); i++) { 268 addProductionAlternative(pattern.getAlternative(i), 269 constants); 270 } 271 272 initMethod.addCode("addPattern(pattern);"); 274 } 275 276 283 private void addProductionAlternative(ProductionPatternAlternative alt, 284 JavaConstantsFile constants) { 285 286 ProductionPatternElement elem; 287 StringBuffer code; 288 289 initMethod.addCode("alt = new ProductionPatternAlternative();"); 290 for (int i = 0; i < alt.getElementCount(); i++) { 291 elem = alt.getElement(i); 292 code = new StringBuffer (); 293 code.append("alt."); 294 if (elem.isToken()) { 295 code.append("addToken("); 296 } else { 297 code.append("addProduction("); 298 } 299 code.append(getConstant(constants, elem.getId())); 300 code.append(", "); 301 code.append(elem.getMinCount()); 302 code.append(", "); 303 if (elem.getMaxCount() == Integer.MAX_VALUE) { 304 code.append("-1"); 305 } else { 306 code.append(elem.getMaxCount()); 307 } 308 code.append(");"); 309 initMethod.addCode(code.toString()); 310 } 311 initMethod.addCode("pattern.addAlternative(alt);"); 312 } 313 314 322 private String getConstant(JavaConstantsFile constants, int id) { 323 Integer value = new Integer (id); 324 325 if (constantNames.containsKey(value)) { 326 return (String ) constantNames.get(value); 327 } else { 328 return constants.getConstant(id); 329 } 330 } 331 332 338 public void writeCode() throws IOException { 339 file.writeCode(gen.getCodeStyle()); 340 } 341 } 342 | Popular Tags |