1 21 22 package net.percederberg.grammatica.output; 23 24 import java.io.IOException ; 25 26 import net.percederberg.grammatica.code.csharp.CSharpClass; 27 import net.percederberg.grammatica.code.csharp.CSharpComment; 28 import net.percederberg.grammatica.code.csharp.CSharpFile; 29 import net.percederberg.grammatica.code.csharp.CSharpMethod; 30 import net.percederberg.grammatica.code.csharp.CSharpNamespace; 31 import net.percederberg.grammatica.code.csharp.CSharpUsing; 32 import net.percederberg.grammatica.parser.ProductionPattern; 33 import net.percederberg.grammatica.parser.TokenPattern; 34 35 42 class CSharpAnalyzerFile { 43 44 47 private static final String TYPE_COMMENT = 48 "<remarks>A class providing callback methods for the\n" + 49 "parser.</remarks>"; 50 51 54 private static final String ENTER_COMMENT = 55 "<summary>Called when entering a parse tree node.</summary>\n\n" + 56 "<param name='node'>the node being entered</param>\n\n" + 57 "<exception cref='ParseException'>if the node analysis\n" + 58 "discovered errors</exception>"; 59 60 63 private static final String EXIT_COMMENT = 64 "<summary>Called when exiting a parse tree node.</summary>\n\n" + 65 "<param name='node'>the node being exited</param>\n\n" + 66 "<returns>the node to add to the parse tree, or\n" + 67 " null if no parse tree should be created</returns>\n\n" + 68 "<exception cref='ParseException'>if the node analysis\n" + 69 "discovered errors</exception>"; 70 71 74 private static final String CHILD_COMMENT = 75 "<summary>Called when adding a child to a parse tree\n" + 76 "node.</summary>\n\n" + 77 "<param name='node'>the parent node</param>\n" + 78 "<param name='child'>the child node, or null</param>\n\n" + 79 "<exception cref='ParseException'>if the node analysis\n" + 80 "discovered errors</exception>"; 81 82 85 private CSharpParserGenerator gen; 86 87 90 private CSharpFile file; 91 92 95 private CSharpClass cls; 96 97 100 private CSharpMethod enter; 101 102 105 private CSharpMethod exit; 106 107 110 private CSharpMethod child; 111 112 117 public CSharpAnalyzerFile(CSharpParserGenerator gen) { 118 String name = gen.getBaseName() + "Analyzer"; 119 int modifiers; 120 121 this.gen = gen; 122 this.file = new CSharpFile(gen.getBaseDir(), name); 123 if (gen.getPublicAccess()) { 124 modifiers = CSharpClass.PUBLIC + CSharpClass.ABSTRACT; 125 } else { 126 modifiers = CSharpClass.INTERNAL + CSharpClass.ABSTRACT; 127 } 128 this.cls = new CSharpClass(modifiers, name, "Analyzer"); 129 modifiers = CSharpMethod.PUBLIC + CSharpMethod.OVERRIDE; 130 this.enter = new CSharpMethod(modifiers, 131 "Enter", 132 "Node node", 133 "void"); 134 this.exit = new CSharpMethod(modifiers, 135 "Exit", 136 "Node node", 137 "Node"); 138 this.child = new CSharpMethod(modifiers, 139 "Child", 140 "Production node, Node child", 141 "void"); 142 initializeCode(); 143 } 144 145 148 private void initializeCode() { 149 String str; 150 151 file.addUsing(new CSharpUsing("PerCederberg.Grammatica.Runtime")); 153 154 if (gen.getNamespace() == null) { 156 file.addClass(cls); 157 } else { 158 CSharpNamespace n = new CSharpNamespace(gen.getNamespace()); 159 n.addClass(cls); 160 file.addNamespace(n); 161 } 162 163 str = file.toString() + "\n\n" + gen.getFileComment(); 165 file.addComment(new CSharpComment(CSharpComment.BLOCK, str)); 166 167 cls.addComment(new CSharpComment(TYPE_COMMENT)); 169 170 enter.addComment(new CSharpComment(ENTER_COMMENT)); 172 enter.addCode("switch (node.Id) {"); 173 cls.addMethod(enter); 174 175 exit.addComment(new CSharpComment(EXIT_COMMENT)); 177 exit.addCode("switch (node.Id) {"); 178 cls.addMethod(exit); 179 180 child.addComment(new CSharpComment(CHILD_COMMENT)); 182 child.addCode("switch (node.Id) {"); 183 cls.addMethod(child); 184 } 185 186 192 public void addToken(TokenPattern pattern, 193 CSharpConstantsFile constants) { 194 195 String constant = constants.getConstant(pattern.getId()); 196 String name; 197 198 if (!pattern.isIgnore()) { 199 name = gen.getCodeStyle().getMixedCase(pattern.getName(), true); 200 addEnterCase(constant, name, "Token"); 201 addEnterMethod(name, "Token"); 202 addExitCase(constant, name, "Token"); 203 addExitMethod(name, "Token"); 204 } 205 } 206 207 213 public void addProduction(ProductionPattern pattern, 214 CSharpConstantsFile constants) { 215 216 String constant = constants.getConstant(pattern.getId()); 217 String name; 218 219 if (!pattern.isSynthetic()) { 220 name = gen.getCodeStyle().getMixedCase(pattern.getName(), 221 true); 222 addEnterCase(constant, name, "Production"); 223 addEnterMethod(name, "Production"); 224 addExitCase(constant, name, "Production"); 225 addExitMethod(name, "Production"); 226 addChildCase(constant, name); 227 addChildMethod(name); 228 } 229 } 230 231 238 private void addEnterCase(String constant, String name, String type) { 239 enter.addCode("case (int) " + constant + ":"); 240 enter.addCode(" Enter" + name + "((" + type + ") node);"); 241 enter.addCode(" break;"); 242 } 243 244 251 private void addExitCase(String constant, String name, String type) { 252 exit.addCode("case (int) " + constant + ":"); 253 exit.addCode(" return Exit" + name + "((" + type + ") node);"); 254 } 255 256 262 private void addChildCase(String constant, String name) { 263 child.addCode("case (int) " + constant + ":"); 264 child.addCode(" Child" + name + "(node, child);"); 265 child.addCode(" break;"); 266 } 267 268 274 private void addEnterMethod(String name, String type) { 275 CSharpMethod m; 276 277 m = new CSharpMethod(CSharpMethod.PUBLIC + CSharpMethod.VIRTUAL, 278 "Enter" + name, 279 type + " node", 280 "void"); 281 m.addComment(new CSharpComment(ENTER_COMMENT)); 282 cls.addMethod(m); 283 } 284 285 291 private void addExitMethod(String name, String type) { 292 CSharpMethod m; 293 294 m = new CSharpMethod(CSharpMethod.PUBLIC + CSharpMethod.VIRTUAL, 295 "Exit" + name, 296 type + " node", 297 "Node"); 298 m.addComment(new CSharpComment(EXIT_COMMENT)); 299 m.addCode("return node;"); 300 cls.addMethod(m); 301 } 302 303 308 private void addChildMethod(String name) { 309 CSharpMethod m; 310 311 m = new CSharpMethod(CSharpMethod.PUBLIC + CSharpMethod.VIRTUAL, 312 "Child" + name, 313 "Production node, Node child", 314 "void"); 315 m.addComment(new CSharpComment(CHILD_COMMENT)); 316 m.addCode("node.AddChild(child);"); 317 cls.addMethod(m); 318 } 319 320 326 public void writeCode() throws IOException { 327 enter.addCode("}"); 328 exit.addCode("}"); 329 exit.addCode("return node;"); 330 child.addCode("}"); 331 file.writeCode(gen.getCodeStyle()); 332 } 333 } 334 | Popular Tags |