1 22 23 package net.percederberg.grammatica.output; 24 25 import java.io.IOException ; 26 import java.util.HashMap ; 27 28 import net.percederberg.grammatica.code.visualbasic.VisualBasicClass; 29 import net.percederberg.grammatica.code.visualbasic.VisualBasicComment; 30 import net.percederberg.grammatica.code.visualbasic.VisualBasicConstructor; 31 import net.percederberg.grammatica.code.visualbasic.VisualBasicEnumeration; 32 import net.percederberg.grammatica.code.visualbasic.VisualBasicFile; 33 import net.percederberg.grammatica.code.visualbasic.VisualBasicImports; 34 import net.percederberg.grammatica.code.visualbasic.VisualBasicMethod; 35 import net.percederberg.grammatica.code.visualbasic.VisualBasicNamespace; 36 import net.percederberg.grammatica.parser.ProductionPattern; 37 import net.percederberg.grammatica.parser.ProductionPatternAlternative; 38 import net.percederberg.grammatica.parser.ProductionPatternElement; 39 40 49 class VisualBasicParserFile { 50 51 54 private static final String TYPE_COMMENT = 55 "<remarks>A token stream parser.</remarks>"; 56 57 60 private static final String ENUM_COMMENT = 61 "<summary>An enumeration with the generated production node\n" + 62 "identity constants.</summary>"; 63 64 67 private static final String CONSTRUCTOR1_COMMENT = 68 "<summary>Creates a new parser.</summary>\n\n" + 69 "<param name='input'>the input stream to read from</param>\n\n" + 70 "<exception cref='ParserCreationException'>if the parser\n" + 71 "couldn't be initialized correctly</exception>"; 72 73 76 private static final String CONSTRUCTOR2_COMMENT = 77 "<summary>Creates a new parser.</summary>\n\n" + 78 "<param name='input'>the input stream to read from</param>\n\n" + 79 "<param name='analyzer'>the analyzer to parse with</param>\n\n" + 80 "<exception cref='ParserCreationException'>if the parser\n" + 81 "couldn't be initialized correctly</exception>"; 82 83 86 private static final String INIT_METHOD_COMMENT = 87 "<summary>Initializes the parser by creating all the production\n" + 88 "patterns.</summary>\n\n" + 89 "<exception cref='ParserCreationException'>if the parser\n" + 90 "couldn't be initialized correctly</exception>"; 91 92 95 private VisualBasicParserGenerator gen; 96 97 100 private VisualBasicTokenizerFile tokenizer; 101 102 105 private VisualBasicFile file; 106 107 110 private VisualBasicClass cls; 111 112 115 private VisualBasicEnumeration enm; 116 117 120 private VisualBasicMethod initMethod; 121 122 127 private HashMap constantNames = new HashMap (); 128 129 132 private int constantId = 1; 133 134 140 public VisualBasicParserFile(VisualBasicParserGenerator gen, 141 VisualBasicTokenizerFile tokenizer) { 142 143 String name = gen.getBaseName() + "Parser"; 144 int modifiers; 145 146 this.gen = gen; 147 this.tokenizer = tokenizer; 148 this.file = new VisualBasicFile(gen.getBaseDir(), name); 149 if (gen.getPublicAccess()) { 150 modifiers = VisualBasicClass.PUBLIC; 151 } else { 152 modifiers = VisualBasicClass.FRIEND; 153 } 154 this.cls = new VisualBasicClass(modifiers, 155 name, 156 "RecursiveDescentParser"); 157 this.enm = new VisualBasicEnumeration(VisualBasicEnumeration.PRIVATE, 158 "SynteticPatterns"); 159 this.initMethod = new VisualBasicMethod(VisualBasicMethod.PRIVATE, 160 "CreatePatterns", 161 "", 162 ""); 163 initializeCode(); 164 } 165 166 169 private void initializeCode() { 170 VisualBasicConstructor constr; 171 VisualBasicNamespace n; 172 String str; 173 174 file.addImports(new VisualBasicImports("System.IO")); 176 file.addImports(new VisualBasicImports("PerCederberg.Grammatica.Runtime")); 177 178 if (gen.getNamespace() == null) { 180 file.addClass(cls); 181 } else { 182 n = new VisualBasicNamespace(gen.getNamespace()); 183 n.addClass(cls); 184 file.addNamespace(n); 185 } 186 187 str = file.toString() + "\n\n" + gen.getFileComment(); 189 file.addComment(new VisualBasicComment(VisualBasicComment.SINGLELINE, 190 str)); 191 192 cls.addComment(new VisualBasicComment(TYPE_COMMENT)); 194 195 cls.addEnumeration(enm); 197 enm.addComment(new VisualBasicComment(ENUM_COMMENT)); 198 199 constr = new VisualBasicConstructor("ByVal input As TextReader"); 201 cls.addConstructor(constr); 202 constr.addComment(new VisualBasicComment(CONSTRUCTOR1_COMMENT)); 203 constr.addCode("MyBase.New(" + tokenizer.getConstructorCall("input") + 204 ")"); 205 constr.addCode("CreatePatterns()"); 206 207 constr = new VisualBasicConstructor("ByVal input As TextReader, " + 209 "ByVal analyzer As Analyzer"); 210 cls.addConstructor(constr); 211 constr.addComment(new VisualBasicComment(CONSTRUCTOR2_COMMENT)); 212 constr.addCode("MyBase.New(" + tokenizer.getConstructorCall("input") + 213 ", analyzer)"); 214 constr.addCode("CreatePatterns()"); 215 216 cls.addMethod(initMethod); 218 initMethod.addComment(new VisualBasicComment(INIT_METHOD_COMMENT)); 219 initMethod.addCode("Dim pattern As ProductionPattern"); 220 initMethod.addCode("Dim alt As ProductionPatternAlternative"); 221 } 222 223 228 public void addProductionConstant(ProductionPattern pattern) { 229 String constant; 230 231 if (pattern.isSynthetic()) { 232 constant = "SUBPRODUCTION_" + constantId; 233 enm.addConstant(constant, String.valueOf(constantId + 3000)); 234 constantNames.put(new Integer (pattern.getId()), constant); 235 constantId++; 236 } 237 } 238 239 245 public void addProduction(ProductionPattern pattern, 246 VisualBasicConstantsFile constants) { 247 StringBuffer code; 248 String str; 249 250 code = new StringBuffer (); 252 code.append("pattern = New ProductionPattern(CInt("); 253 code.append(getConstant(constants, pattern.getId())); 254 code.append("), \""); 255 if (pattern.isSynthetic()) { 256 str = (String ) constantNames.get(new Integer (pattern.getId())); 257 code.append(gen.getCodeStyle().getMixedCase(str, true)); 258 } else { 259 code.append(pattern.getName()); 260 } 261 code.append("\")"); 262 initMethod.addCode(""); 263 initMethod.addCode(code.toString()); 264 265 if (pattern.isSynthetic()) { 267 initMethod.addCode("pattern.Synthetic = True"); 268 } 269 270 for (int i = 0; i < pattern.getAlternativeCount(); i++) { 272 addProductionAlternative(pattern.getAlternative(i), 273 constants); 274 } 275 276 initMethod.addCode("AddPattern(pattern)"); 278 } 279 280 287 private void addProductionAlternative(ProductionPatternAlternative alt, 288 VisualBasicConstantsFile constants) { 289 290 ProductionPatternElement elem; 291 StringBuffer code; 292 293 initMethod.addCode("alt = New ProductionPatternAlternative()"); 294 for (int i = 0; i < alt.getElementCount(); i++) { 295 elem = alt.getElement(i); 296 code = new StringBuffer (); 297 code.append("alt."); 298 if (elem.isToken()) { 299 code.append("AddToken("); 300 } else { 301 code.append("AddProduction("); 302 } 303 code.append("CInt("); 304 code.append(getConstant(constants, elem.getId())); 305 code.append("), "); 306 code.append(elem.getMinCount()); 307 code.append(", "); 308 if (elem.getMaxCount() == Integer.MAX_VALUE) { 309 code.append("-1"); 310 } else { 311 code.append(elem.getMaxCount()); 312 } 313 code.append(")"); 314 initMethod.addCode(code.toString()); 315 } 316 initMethod.addCode("pattern.AddAlternative(alt)"); 317 } 318 319 327 private String getConstant(VisualBasicConstantsFile constants, int id) { 328 Integer value = new Integer (id); 329 330 if (constantNames.containsKey(value)) { 331 return "SynteticPatterns." + constantNames.get(value); 332 } else { 333 return constants.getConstant(id); 334 } 335 } 336 337 343 public void writeCode() throws IOException { 344 file.writeCode(gen.getCodeStyle()); 345 } 346 } 347 | Popular Tags |