1 21 22 package net.percederberg.grammatica.output; 23 24 import java.io.IOException ; 25 26 import net.percederberg.grammatica.code.java.JavaClass; 27 import net.percederberg.grammatica.code.java.JavaComment; 28 import net.percederberg.grammatica.code.java.JavaFile; 29 import net.percederberg.grammatica.code.java.JavaImport; 30 import net.percederberg.grammatica.code.java.JavaMethod; 31 import net.percederberg.grammatica.parser.ProductionPattern; 32 import net.percederberg.grammatica.parser.TokenPattern; 33 34 41 class JavaAnalyzerFile { 42 43 46 private static final String TYPE_COMMENT = 47 "A class providing callback methods for the parser."; 48 49 52 private static final String ENTER_COMMENT = 53 "Called when entering a parse tree node.\n\n" + 54 "@param node the node being entered\n\n" + 55 "@throws ParseException if the node analysis discovered errors"; 56 57 60 private static final String EXIT_COMMENT = 61 "Called when exiting a parse tree node.\n\n" + 62 "@param node the node being exited\n\n" + 63 "@return the node to add to the parse tree, or\n" + 64 " null if no parse tree should be created\n\n" + 65 "@throws ParseException if the node analysis discovered errors"; 66 67 70 private static final String CHILD_COMMENT = 71 "Called when adding a child to a parse tree node.\n\n" + 72 "@param node the parent node\n" + 73 "@param child the child node, or null\n\n" + 74 "@throws ParseException if the node analysis discovered errors"; 75 76 79 private JavaParserGenerator gen; 80 81 84 private JavaFile file; 85 86 89 private JavaClass cls; 90 91 94 private JavaMethod enter; 95 96 99 private JavaMethod exit; 100 101 104 private JavaMethod child; 105 106 111 public JavaAnalyzerFile(JavaParserGenerator gen) { 112 int modifiers; 113 114 this.gen = gen; 115 this.file = gen.createJavaFile(); 116 if (gen.getPublicAccess()) { 117 modifiers = JavaClass.PUBLIC + JavaClass.ABSTRACT; 118 } else { 119 modifiers = JavaClass.PACKAGE_LOCAL + JavaClass.ABSTRACT; 120 } 121 this.cls = new JavaClass(modifiers, 122 gen.getBaseName() + "Analyzer", 123 "Analyzer"); 124 this.enter = new JavaMethod(JavaMethod.PROTECTED, 125 "enter", 126 "Node node", 127 "void"); 128 this.exit = new JavaMethod(JavaMethod.PROTECTED, 129 "exit", 130 "Node node", 131 "Node"); 132 this.child = new JavaMethod(JavaMethod.PROTECTED, 133 "child", 134 "Production node, Node child", 135 "void"); 136 initializeCode(); 137 } 138 139 142 private void initializeCode() { 143 String str; 144 145 file.addClass(cls); 147 148 str = file.toString() + "\n\n" + gen.getFileComment(); 150 file.addComment(new JavaComment(JavaComment.BLOCK, str)); 151 152 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 154 "Analyzer")); 155 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 156 "Node")); 157 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 158 "ParseException")); 159 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 160 "Production")); 161 file.addImport(new JavaImport("net.percederberg.grammatica.parser", 162 "Token")); 163 164 str = TYPE_COMMENT; 166 if (gen.getClassComment() != null) { 167 str += "\n\n" + gen.getClassComment(); 168 } 169 cls.addComment(new JavaComment(str)); 170 171 enter.addComment(new JavaComment(ENTER_COMMENT)); 173 enter.addThrows("ParseException"); 174 enter.addCode("switch (node.getId()) {"); 175 cls.addMethod(enter); 176 177 exit.addComment(new JavaComment(EXIT_COMMENT)); 179 exit.addThrows("ParseException"); 180 exit.addCode("switch (node.getId()) {"); 181 cls.addMethod(exit); 182 183 child.addComment(new JavaComment(CHILD_COMMENT)); 185 child.addThrows("ParseException"); 186 child.addCode("switch (node.getId()) {"); 187 cls.addMethod(child); 188 } 189 190 196 public void addToken(TokenPattern pattern, 197 JavaConstantsFile constants) { 198 199 String constant = constants.getConstant(pattern.getId()); 200 String name; 201 202 if (!pattern.isIgnore()) { 203 name = gen.getCodeStyle().getMixedCase(pattern.getName(), true); 204 addEnterCase(constant, name, "Token"); 205 addEnterMethod(name, "Token"); 206 addExitCase(constant, name, "Token"); 207 addExitMethod(name, "Token"); 208 } 209 } 210 211 217 public void addProduction(ProductionPattern pattern, 218 JavaConstantsFile constants) { 219 220 String constant = constants.getConstant(pattern.getId()); 221 String name; 222 223 if (!pattern.isSynthetic()) { 224 name = gen.getCodeStyle().getMixedCase(pattern.getName(), 225 true); 226 addEnterCase(constant, name, "Production"); 227 addEnterMethod(name, "Production"); 228 addExitCase(constant, name, "Production"); 229 addExitMethod(name, "Production"); 230 addChildCase(constant, name); 231 addChildMethod(name); 232 } 233 } 234 235 242 private void addEnterCase(String constant, String name, String type) { 243 enter.addCode("case " + constant + ":"); 244 enter.addCode(" enter" + name + "((" + type + ") node);"); 245 enter.addCode(" break;"); 246 } 247 248 255 private void addExitCase(String constant, String name, String type) { 256 exit.addCode("case " + constant + ":"); 257 exit.addCode(" return exit" + name + "((" + type + ") node);"); 258 } 259 260 266 private void addChildCase(String constant, String name) { 267 child.addCode("case " + constant + ":"); 268 child.addCode(" child" + name + "(node, child);"); 269 child.addCode(" break;"); 270 } 271 272 278 private void addEnterMethod(String name, String type) { 279 JavaMethod m; 280 281 m = new JavaMethod(JavaMethod.PROTECTED, 282 "enter" + name, 283 type + " node", 284 "void"); 285 m.addComment(new JavaComment(ENTER_COMMENT)); 286 m.addThrows("ParseException"); 287 cls.addMethod(m); 288 } 289 290 296 private void addExitMethod(String name, String type) { 297 JavaMethod m; 298 299 m = new JavaMethod(JavaMethod.PROTECTED, 300 "exit" + name, 301 type + " node", 302 "Node"); 303 m.addComment(new JavaComment(EXIT_COMMENT)); 304 m.addThrows("ParseException"); 305 m.addCode("return node;"); 306 cls.addMethod(m); 307 } 308 309 314 private void addChildMethod(String name) { 315 JavaMethod m; 316 317 m = new JavaMethod(JavaMethod.PROTECTED, 318 "child" + name, 319 "Production node, Node child", 320 "void"); 321 m.addComment(new JavaComment(CHILD_COMMENT)); 322 m.addThrows("ParseException"); 323 m.addCode("node.addChild(child);"); 324 cls.addMethod(m); 325 } 326 327 333 public void writeCode() throws IOException { 334 enter.addCode("}"); 335 exit.addCode("}"); 336 exit.addCode("return node;"); 337 child.addCode("}"); 338 file.writeCode(gen.getCodeStyle()); 339 } 340 } 341 | Popular Tags |