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.csharp.CSharpClass; 28 import net.percederberg.grammatica.code.csharp.CSharpComment; 29 import net.percederberg.grammatica.code.csharp.CSharpConstructor; 30 import net.percederberg.grammatica.code.csharp.CSharpEnumeration; 31 import net.percederberg.grammatica.code.csharp.CSharpFile; 32 import net.percederberg.grammatica.code.csharp.CSharpMethod; 33 import net.percederberg.grammatica.code.csharp.CSharpNamespace; 34 import net.percederberg.grammatica.code.csharp.CSharpUsing; 35 import net.percederberg.grammatica.parser.ProductionPattern; 36 import net.percederberg.grammatica.parser.ProductionPatternAlternative; 37 import net.percederberg.grammatica.parser.ProductionPatternElement; 38 39 46 class CSharpParserFile { 47 48 51 private static final String TYPE_COMMENT = 52 "<remarks>A token stream parser.</remarks>"; 53 54 57 private static final String ENUM_COMMENT = 58 "<summary>An enumeration with the generated production node\n" + 59 "identity constants.</summary>"; 60 61 64 private static final String CONSTRUCTOR1_COMMENT = 65 "<summary>Creates a new parser.</summary>\n\n" + 66 "<param name='input'>the input stream to read from</param>\n\n" + 67 "<exception cref='ParserCreationException'>if the parser\n" + 68 "couldn't be initialized correctly</exception>"; 69 70 73 private static final String CONSTRUCTOR2_COMMENT = 74 "<summary>Creates a new parser.</summary>\n\n" + 75 "<param name='input'>the input stream to read from</param>\n\n" + 76 "<param name='analyzer'>the analyzer to parse with</param>\n\n" + 77 "<exception cref='ParserCreationException'>if the parser\n" + 78 "couldn't be initialized correctly</exception>"; 79 80 83 private static final String INIT_METHOD_COMMENT = 84 "<summary>Initializes the parser by creating all the production\n" + 85 "patterns.</summary>\n\n" + 86 "<exception cref='ParserCreationException'>if the parser\n" + 87 "couldn't be initialized correctly</exception>"; 88 89 92 private CSharpParserGenerator gen; 93 94 97 private CSharpTokenizerFile tokenizer; 98 99 102 private CSharpFile file; 103 104 107 private CSharpClass cls; 108 109 112 private CSharpEnumeration enm; 113 114 117 private CSharpMethod initMethod; 118 119 124 private HashMap constantNames = new HashMap (); 125 126 129 private int constantId = 1; 130 131 137 public CSharpParserFile(CSharpParserGenerator gen, 138 CSharpTokenizerFile tokenizer) { 139 140 String name = gen.getBaseName() + "Parser"; 141 int modifiers; 142 143 this.gen = gen; 144 this.tokenizer = tokenizer; 145 this.file = new CSharpFile(gen.getBaseDir(), name); 146 if (gen.getPublicAccess()) { 147 modifiers = CSharpClass.PUBLIC; 148 } else { 149 modifiers = CSharpClass.INTERNAL; 150 } 151 this.cls = new CSharpClass(modifiers, 152 name, 153 "RecursiveDescentParser"); 154 this.enm = new CSharpEnumeration(CSharpEnumeration.PRIVATE, 155 "SynteticPatterns"); 156 this.initMethod = new CSharpMethod(CSharpMethod.PRIVATE, 157 "CreatePatterns", 158 "", 159 "void"); 160 initializeCode(); 161 } 162 163 166 private void initializeCode() { 167 CSharpConstructor constr; 168 String str; 169 170 file.addUsing(new CSharpUsing("System.IO")); 172 file.addUsing(new CSharpUsing("PerCederberg.Grammatica.Runtime")); 173 174 if (gen.getNamespace() == null) { 176 file.addClass(cls); 177 } else { 178 CSharpNamespace n = new CSharpNamespace(gen.getNamespace()); 179 n.addClass(cls); 180 file.addNamespace(n); 181 } 182 183 str = file.toString() + "\n\n" + gen.getFileComment(); 185 file.addComment(new CSharpComment(CSharpComment.BLOCK, str)); 186 187 cls.addComment(new CSharpComment(TYPE_COMMENT)); 189 190 cls.addEnumeration(enm); 192 enm.addComment(new CSharpComment(ENUM_COMMENT)); 193 194 constr = new CSharpConstructor("TextReader input"); 196 cls.addConstructor(constr); 197 constr.addComment(new CSharpComment(CONSTRUCTOR1_COMMENT)); 198 constr.addInitializer("base(" + 199 tokenizer.getConstructorCall("input") + 200 ")"); 201 constr.addCode("CreatePatterns();"); 202 203 constr = new CSharpConstructor("TextReader input, " + 205 "Analyzer analyzer"); 206 cls.addConstructor(constr); 207 constr.addComment(new CSharpComment(CONSTRUCTOR2_COMMENT)); 208 constr.addInitializer("base(" + 209 tokenizer.getConstructorCall("input") + 210 ", analyzer)"); 211 constr.addCode("CreatePatterns();"); 212 213 cls.addMethod(initMethod); 215 initMethod.addComment(new CSharpComment(INIT_METHOD_COMMENT)); 216 initMethod.addCode("ProductionPattern pattern;"); 217 initMethod.addCode("ProductionPatternAlternative alt;"); 218 } 219 220 225 public void addProductionConstant(ProductionPattern pattern) { 226 String constant; 227 228 if (pattern.isSynthetic()) { 229 constant = "SUBPRODUCTION_" + constantId; 230 enm.addConstant(constant, String.valueOf(constantId + 3000)); 231 constantNames.put(new Integer (pattern.getId()), constant); 232 constantId++; 233 } 234 } 235 236 242 public void addProduction(ProductionPattern pattern, 243 CSharpConstantsFile constants) { 244 StringBuffer code; 245 String str; 246 247 code = new StringBuffer (); 249 code.append("pattern = new ProductionPattern((int) "); 250 code.append(getConstant(constants, pattern.getId())); 251 code.append(",\n"); 252 code.append(" \""); 253 if (pattern.isSynthetic()) { 254 str = (String ) constantNames.get(new Integer (pattern.getId())); 255 code.append(gen.getCodeStyle().getMixedCase(str, true)); 256 } else { 257 code.append(pattern.getName()); 258 } 259 code.append("\");"); 260 initMethod.addCode(""); 261 initMethod.addCode(code.toString()); 262 263 if (pattern.isSynthetic()) { 265 initMethod.addCode("pattern.Synthetic = true;"); 266 } 267 268 for (int i = 0; i < pattern.getAlternativeCount(); i++) { 270 addProductionAlternative(pattern.getAlternative(i), 271 constants); 272 } 273 274 initMethod.addCode("AddPattern(pattern);"); 276 } 277 278 285 private void addProductionAlternative(ProductionPatternAlternative alt, 286 CSharpConstantsFile constants) { 287 288 ProductionPatternElement elem; 289 StringBuffer code; 290 291 initMethod.addCode("alt = new ProductionPatternAlternative();"); 292 for (int i = 0; i < alt.getElementCount(); i++) { 293 elem = alt.getElement(i); 294 code = new StringBuffer (); 295 code.append("alt."); 296 if (elem.isToken()) { 297 code.append("AddToken("); 298 } else { 299 code.append("AddProduction("); 300 } 301 code.append("(int) "); 302 code.append(getConstant(constants, elem.getId())); 303 code.append(", "); 304 code.append(elem.getMinCount()); 305 code.append(", "); 306 if (elem.getMaxCount() == Integer.MAX_VALUE) { 307 code.append("-1"); 308 } else { 309 code.append(elem.getMaxCount()); 310 } 311 code.append(");"); 312 initMethod.addCode(code.toString()); 313 } 314 initMethod.addCode("pattern.AddAlternative(alt);"); 315 } 316 317 325 private String getConstant(CSharpConstantsFile constants, int id) { 326 Integer value = new Integer (id); 327 328 if (constantNames.containsKey(value)) { 329 return "SynteticPatterns." + constantNames.get(value); 330 } else { 331 return constants.getConstant(id); 332 } 333 } 334 335 341 public void writeCode() throws IOException { 342 file.writeCode(gen.getCodeStyle()); 343 } 344 } 345 | Popular Tags |