1 package persistence.antlr; 2 3 8 9 import java.util.Enumeration ; 10 11 import persistence.antlr.collections.impl.BitSet; 12 import persistence.antlr.collections.impl.Vector; 13 14 import java.io.PrintWriter ; import java.io.IOException ; 16 import java.io.FileWriter ; 17 18 19 public class DiagnosticCodeGenerator extends CodeGenerator { 20 21 protected int syntacticPredLevel = 0; 22 23 24 protected boolean doingLexRules = false; 25 26 30 public DiagnosticCodeGenerator() { 31 super(); 32 charFormatter = new JavaCharFormatter(); 33 } 34 35 36 public void gen() { 37 38 try { 40 Enumeration grammarIter = behavior.grammars.elements(); 42 while (grammarIter.hasMoreElements()) { 43 Grammar g = (Grammar)grammarIter.nextElement(); 44 45 g.setGrammarAnalyzer(analyzer); 47 g.setCodeGenerator(this); 48 analyzer.setGrammar(g); 49 50 g.generate(); 52 53 if (antlrTool.hasError()) { 54 antlrTool.panic("Exiting due to errors."); 55 } 56 57 } 58 59 Enumeration tmIter = behavior.tokenManagers.elements(); 61 while (tmIter.hasMoreElements()) { 62 TokenManager tm = (TokenManager)tmIter.nextElement(); 63 if (!tm.isReadOnly()) { 64 genTokenTypes(tm); 66 } 67 } 68 } 69 catch (IOException e) { 70 antlrTool.reportException(e, null); 71 } 72 } 73 74 77 public void gen(ActionElement action) { 78 if (action.isSemPred) { 79 } 81 else { 82 print("ACTION: "); 83 _printAction(action.actionText); 84 } 85 } 86 87 90 public void gen(AlternativeBlock blk) { 91 println("Start of alternative block."); 92 tabs++; 93 genBlockPreamble(blk); 94 95 boolean ok = grammar.theLLkAnalyzer.deterministic(blk); 96 if (!ok) { 97 println("Warning: This alternative block is non-deterministic"); 98 } 99 genCommonBlock(blk); 100 tabs--; 101 } 102 103 108 public void gen(BlockEndElement end) { 109 } 111 112 115 public void gen(CharLiteralElement atom) { 116 print("Match character "); 117 if (atom.not) { 118 _print("NOT "); 119 } 120 _print(atom.atomText); 121 if (atom.label != null) { 122 _print(", label=" + atom.label); 123 } 124 _println(""); 125 } 126 127 130 public void gen(CharRangeElement r) { 131 print("Match character range: " + r.beginText + ".." + r.endText); 132 if (r.label != null) { 133 _print(", label = " + r.label); 134 } 135 _println(""); 136 } 137 138 139 public void gen(LexerGrammar g) throws IOException { 140 setGrammar(g); 141 antlrTool.reportProgress("Generating " + grammar.getClassName() + TokenTypesFileExt); 142 currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt); 143 145 tabs = 0; 146 doingLexRules = true; 147 148 genHeader(); 150 151 println(""); 153 println("*** Lexer Preamble Action."); 154 println("This action will appear before the declaration of your lexer class:"); 155 tabs++; 156 println(grammar.preambleAction.getText()); 157 tabs--; 158 println("*** End of Lexer Preamble Action"); 159 160 println(""); 162 println("*** Your lexer class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'."); 163 164 println(""); 166 println("*** User-defined lexer class members:"); 167 println("These are the member declarations that you defined for your class:"); 168 tabs++; 169 printAction(grammar.classMemberAction.getText()); 170 tabs--; 171 println("*** End of user-defined lexer class members"); 172 173 println(""); 175 println("*** String literals used in the parser"); 176 println("The following string literals were used in the parser."); 177 println("An actual code generator would arrange to place these literals"); 178 println("into a table in the generated lexer, so that actions in the"); 179 println("generated lexer could match token text against the literals."); 180 println("String literals used in the lexer are not listed here, as they"); 181 println("are incorporated into the mainstream lexer processing."); 182 tabs++; 183 Enumeration ids = grammar.getSymbols(); 185 while (ids.hasMoreElements()) { 186 GrammarSymbol sym = (GrammarSymbol)ids.nextElement(); 187 if (sym instanceof StringLiteralSymbol) { 189 StringLiteralSymbol s = (StringLiteralSymbol)sym; 190 println(s.getId() + " = " + s.getTokenType()); 191 } 192 } 193 tabs--; 194 println("*** End of string literals used by the parser"); 195 196 genNextToken(); 200 201 println(""); 203 println("*** User-defined Lexer rules:"); 204 tabs++; 205 206 ids = grammar.rules.elements(); 207 while (ids.hasMoreElements()) { 208 RuleSymbol rs = (RuleSymbol)ids.nextElement(); 209 if (!rs.id.equals("mnextToken")) { 210 genRule(rs); 211 } 212 } 213 214 tabs--; 215 println(""); 216 println("*** End User-defined Lexer rules:"); 217 218 currentOutput.close(); 220 currentOutput = null; 221 doingLexRules = false; 222 } 223 224 227 public void gen(OneOrMoreBlock blk) { 228 println("Start ONE-OR-MORE (...)+ block:"); 229 tabs++; 230 genBlockPreamble(blk); 231 boolean ok = grammar.theLLkAnalyzer.deterministic(blk); 232 if (!ok) { 233 println("Warning: This one-or-more block is non-deterministic"); 234 } 235 genCommonBlock(blk); 236 tabs--; 237 println("End ONE-OR-MORE block."); 238 } 239 240 241 public void gen(ParserGrammar g) throws IOException { 242 setGrammar(g); 243 antlrTool.reportProgress("Generating " + grammar.getClassName() + TokenTypesFileExt); 245 currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt); 246 248 tabs = 0; 249 250 genHeader(); 252 253 println(""); 255 println("*** Parser Preamble Action."); 256 println("This action will appear before the declaration of your parser class:"); 257 tabs++; 258 println(grammar.preambleAction.getText()); 259 tabs--; 260 println("*** End of Parser Preamble Action"); 261 262 println(""); 264 println("*** Your parser class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'."); 265 266 println(""); 268 println("*** User-defined parser class members:"); 269 println("These are the member declarations that you defined for your class:"); 270 tabs++; 271 printAction(grammar.classMemberAction.getText()); 272 tabs--; 273 println("*** End of user-defined parser class members"); 274 275 println(""); 277 println("*** Parser rules:"); 278 tabs++; 279 280 Enumeration rules = grammar.rules.elements(); 282 while (rules.hasMoreElements()) { 283 println(""); 284 GrammarSymbol sym = (GrammarSymbol)rules.nextElement(); 286 if (sym instanceof RuleSymbol) { 288 genRule((RuleSymbol)sym); 289 } 290 } 291 tabs--; 292 println(""); 293 println("*** End of parser rules"); 294 295 println(""); 296 println("*** End of parser"); 297 298 currentOutput.close(); 300 currentOutput = null; 301 } 302 303 306 public void gen(RuleRefElement rr) { 307 RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule); 308 309 print("Rule Reference: " + rr.targetRule); 311 if (rr.idAssign != null) { 312 _print(", assigned to '" + rr.idAssign + "'"); 313 } 314 if (rr.args != null) { 315 _print(", arguments = " + rr.args); 316 } 317 _println(""); 318 319 if (rs == null || !rs.isDefined()) { 321 println("Rule '" + rr.targetRule + "' is referenced, but that rule is not defined."); 322 println("\tPerhaps the rule is misspelled, or you forgot to define it."); 323 return; 324 } 325 if (!(rs instanceof RuleSymbol)) { 326 println("Rule '" + rr.targetRule + "' is referenced, but that is not a grammar rule."); 328 return; 329 } 330 if (rr.idAssign != null) { 331 if (rs.block.returnAction == null) { 333 println("Error: You assigned from Rule '" + rr.targetRule + "', but that rule has no return type."); 334 } 335 } 336 else { 337 if (!(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null) { 339 println("Warning: Rule '" + rr.targetRule + "' returns a value"); 340 } 341 } 342 if (rr.args != null && rs.block.argAction == null) { 343 println("Error: Rule '" + rr.targetRule + "' accepts no arguments."); 344 } 345 } 346 347 350 public void gen(StringLiteralElement atom) { 351 print("Match string literal "); 352 _print(atom.atomText); 353 if (atom.label != null) { 354 _print(", label=" + atom.label); 355 } 356 _println(""); 357 } 358 359 362 public void gen(TokenRangeElement r) { 363 print("Match token range: " + r.beginText + ".." + r.endText); 364 if (r.label != null) { 365 _print(", label = " + r.label); 366 } 367 _println(""); 368 } 369 370 373 public void gen(TokenRefElement atom) { 374 print("Match token "); 375 if (atom.not) { 376 _print("NOT "); 377 } 378 _print(atom.atomText); 379 if (atom.label != null) { 380 _print(", label=" + atom.label); 381 } 382 _println(""); 383 } 384 385 public void gen(TreeElement t) { 386 print("Tree reference: " + t); 387 } 388 389 390 public void gen(TreeWalkerGrammar g) throws IOException { 391 setGrammar(g); 392 antlrTool.reportProgress("Generating " + grammar.getClassName() + TokenTypesFileExt); 394 currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt); 395 397 tabs = 0; 398 399 genHeader(); 401 402 println(""); 404 println("*** Tree-walker Preamble Action."); 405 println("This action will appear before the declaration of your tree-walker class:"); 406 tabs++; 407 println(grammar.preambleAction.getText()); 408 tabs--; 409 println("*** End of tree-walker Preamble Action"); 410 411 println(""); 413 println("*** Your tree-walker class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'."); 414 415 println(""); 417 println("*** User-defined tree-walker class members:"); 418 println("These are the member declarations that you defined for your class:"); 419 tabs++; 420 printAction(grammar.classMemberAction.getText()); 421 tabs--; 422 println("*** End of user-defined tree-walker class members"); 423 424 println(""); 426 println("*** tree-walker rules:"); 427 tabs++; 428 429 Enumeration rules = grammar.rules.elements(); 431 while (rules.hasMoreElements()) { 432 println(""); 433 GrammarSymbol sym = (GrammarSymbol)rules.nextElement(); 435 if (sym instanceof RuleSymbol) { 437 genRule((RuleSymbol)sym); 438 } 439 } 440 tabs--; 441 println(""); 442 println("*** End of tree-walker rules"); 443 444 println(""); 445 println("*** End of tree-walker"); 446 447 currentOutput.close(); 449 currentOutput = null; 450 } 451 452 453 public void gen(WildcardElement wc) { 454 print("Match wildcard"); 455 if (wc.getLabel() != null) { 456 _print(", label = " + wc.getLabel()); 457 } 458 _println(""); 459 } 460 461 464 public void gen(ZeroOrMoreBlock blk) { 465 println("Start ZERO-OR-MORE (...)+ block:"); 466 tabs++; 467 genBlockPreamble(blk); 468 boolean ok = grammar.theLLkAnalyzer.deterministic(blk); 469 if (!ok) { 470 println("Warning: This zero-or-more block is non-deterministic"); 471 } 472 genCommonBlock(blk); 473 tabs--; 474 println("End ZERO-OR-MORE block."); 475 } 476 477 protected void genAlt(Alternative alt) { 478 for ( 479 AlternativeElement elem = alt.head; 480 !(elem instanceof BlockEndElement); 481 elem = elem.next 482 ) { 483 elem.generate(); 484 } 485 if (alt.getTreeSpecifier() != null) { 486 println("AST will be built as: " + alt.getTreeSpecifier().getText()); 487 } 488 } 489 490 495 protected void genBlockPreamble(AlternativeBlock blk) { 496 if (blk.initAction != null) { 498 printAction("Init action: " + blk.initAction); 499 } 500 } 501 502 507 public void genCommonBlock(AlternativeBlock blk) { 508 boolean singleAlt = (blk.alternatives.size() == 1); 509 510 println("Start of an alternative block."); 511 tabs++; 512 println("The lookahead set for this block is:"); 513 tabs++; 514 genLookaheadSetForBlock(blk); 515 tabs--; 516 517 if (singleAlt) { 518 println("This block has a single alternative"); 519 if (blk.getAlternativeAt(0).synPred != null) { 520 println("Warning: you specified a syntactic predicate for this alternative,"); 522 println("and it is the only alternative of a block and will be ignored."); 523 } 524 } 525 else { 526 println("This block has multiple alternatives:"); 527 tabs++; 528 } 529 530 for (int i = 0; i < blk.alternatives.size(); i++) { 531 Alternative alt = blk.getAlternativeAt(i); 532 AlternativeElement elem = alt.head; 533 534 println(""); 536 if (i != 0) { 537 print("Otherwise, "); 538 } 539 else { 540 print(""); 541 } 542 _println("Alternate(" + (i + 1) + ") will be taken IF:"); 543 println("The lookahead set: "); 544 tabs++; 545 genLookaheadSetForAlt(alt); 546 tabs--; 547 if (alt.semPred != null || alt.synPred != null) { 548 print("is matched, AND "); 549 } 550 else { 551 println("is matched."); 552 } 553 554 if (alt.semPred != null) { 556 _println("the semantic predicate:"); 557 tabs++; 558 println(alt.semPred); 559 if (alt.synPred != null) { 560 print("is true, AND "); 561 } 562 else { 563 println("is true."); 564 } 565 } 566 567 if (alt.synPred != null) { 569 _println("the syntactic predicate:"); 570 tabs++; 571 genSynPred(alt.synPred); 572 tabs--; 573 println("is matched."); 574 } 575 576 genAlt(alt); 578 } 579 println(""); 580 println("OTHERWISE, a NoViableAlt exception will be thrown"); 581 println(""); 582 583 if (!singleAlt) { 584 tabs--; 585 println("End of alternatives"); 586 } 587 tabs--; 588 println("End of alternative block."); 589 } 590 591 595 public void genFollowSetForRuleBlock(RuleBlock blk) { 596 Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, blk.endNode); 597 printSet(grammar.maxk, 1, follow); 598 } 599 600 601 protected void genHeader() { 602 println("ANTLR-generated file resulting from grammar " + antlrTool.grammarFile); 603 println("Diagnostic output"); 604 println(""); 605 println("Terence Parr, MageLang Institute"); 606 println("with John Lilley, Empathy Software"); 607 println("ANTLR Version " + antlrTool.version + "; 1996,1997"); 608 println(""); 609 println("*** Header Action."); 610 println("This action will appear at the top of all generated files."); 611 tabs++; 612 printAction(behavior.getHeaderAction("")); 613 tabs--; 614 println("*** End of Header Action"); 615 println(""); 616 } 617 618 619 protected void genLookaheadSetForAlt(Alternative alt) { 620 if (doingLexRules && alt.cache[1].containsEpsilon()) { 621 println("MATCHES ALL"); 622 return; 623 } 624 int depth = alt.lookaheadDepth; 625 if (depth == GrammarAnalyzer.NONDETERMINISTIC) { 626 depth = grammar.maxk; 629 } 630 for (int i = 1; i <= depth; i++) { 631 Lookahead lookahead = alt.cache[i]; 632 printSet(depth, i, lookahead); 633 } 634 } 635 636 640 public void genLookaheadSetForBlock(AlternativeBlock blk) { 641 int depth = 0; 643 for (int i = 0; i < blk.alternatives.size(); i++) { 644 Alternative alt = blk.getAlternativeAt(i); 645 if (alt.lookaheadDepth == GrammarAnalyzer.NONDETERMINISTIC) { 646 depth = grammar.maxk; 647 break; 648 } 649 else if (depth < alt.lookaheadDepth) { 650 depth = alt.lookaheadDepth; 651 } 652 } 653 654 for (int i = 1; i <= depth; i++) { 655 Lookahead lookahead = grammar.theLLkAnalyzer.look(i, blk); 656 printSet(depth, i, lookahead); 657 } 658 } 659 660 664 public void genNextToken() { 665 println(""); 666 println("*** Lexer nextToken rule:"); 667 println("The lexer nextToken rule is synthesized from all of the user-defined"); 668 println("lexer rules. It logically consists of one big alternative block with"); 669 println("each user-defined rule being an alternative."); 670 println(""); 671 672 RuleBlock blk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken"); 675 676 RuleSymbol nextTokenRs = new RuleSymbol("mnextToken"); 678 nextTokenRs.setDefined(); 679 nextTokenRs.setBlock(blk); 680 nextTokenRs.access = "private"; 681 grammar.define(nextTokenRs); 682 683 if (!grammar.theLLkAnalyzer.deterministic(blk)) { 685 println("The grammar analyzer has determined that the synthesized"); 686 println("nextToken rule is non-deterministic (i.e., it has ambiguities)"); 687 println("This means that there is some overlap of the character"); 688 println("lookahead for two or more of your lexer rules."); 689 } 690 691 genCommonBlock(blk); 692 693 println("*** End of nextToken lexer rule."); 694 } 695 696 699 public void genRule(RuleSymbol s) { 700 println(""); 701 String ruleType = (doingLexRules ? "Lexer" : "Parser"); 702 println("*** " + ruleType + " Rule: " + s.getId()); 703 if (!s.isDefined()) { 704 println("This rule is undefined."); 705 println("This means that the rule was referenced somewhere in the grammar,"); 706 println("but a definition for the rule was not encountered."); 707 println("It is also possible that syntax errors during the parse of"); 708 println("your grammar file prevented correct processing of the rule."); 709 println("*** End " + ruleType + " Rule: " + s.getId()); 710 return; 711 } 712 tabs++; 713 714 if (s.access.length() != 0) { 715 println("Access: " + s.access); 716 } 717 718 RuleBlock rblk = s.getBlock(); 720 721 if (rblk.returnAction != null) { 723 println("Return value(s): " + rblk.returnAction); 724 if (doingLexRules) { 725 println("Error: you specified return value(s) for a lexical rule."); 726 println("\tLexical rules have an implicit return type of 'int'."); 727 } 728 } 729 else { 730 if (doingLexRules) { 731 println("Return value: lexical rule returns an implicit token type"); 732 } 733 else { 734 println("Return value: none"); 735 } 736 } 737 738 if (rblk.argAction != null) { 740 println("Arguments: " + rblk.argAction); 741 } 742 743 genBlockPreamble(rblk); 745 746 boolean ok = grammar.theLLkAnalyzer.deterministic(rblk); 748 if (!ok) { 749 println("Error: This rule is non-deterministic"); 750 } 751 752 genCommonBlock(rblk); 754 755 ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec(""); 757 758 if (unlabeledUserSpec != null) { 760 println("You specified error-handler(s) for this rule:"); 761 tabs++; 762 for (int i = 0; i < unlabeledUserSpec.handlers.size(); i++) { 763 if (i != 0) { 764 println(""); 765 } 766 767 ExceptionHandler handler = (ExceptionHandler)unlabeledUserSpec.handlers.elementAt(i); 768 println("Error-handler(" + (i + 1) + ") catches [" + handler.exceptionTypeAndName.getText() + "] and executes:"); 769 printAction(handler.action.getText()); 770 } 771 tabs--; 772 println("End error-handlers."); 773 } 774 else if (!doingLexRules) { 775 println("Default error-handling will be generated, which catches all"); 776 println("parser exceptions and consumes tokens until the follow-set is seen."); 777 } 778 779 if (!doingLexRules) { 782 println("The follow set for this rule is:"); 783 tabs++; 784 genFollowSetForRuleBlock(rblk); 785 tabs--; 786 } 787 788 tabs--; 789 println("*** End " + ruleType + " Rule: " + s.getId()); 790 } 791 792 796 protected void genSynPred(SynPredBlock blk) { 797 syntacticPredLevel++; 798 gen((AlternativeBlock)blk); 799 syntacticPredLevel--; 800 } 801 802 803 protected void genTokenTypes(TokenManager tm) throws IOException { 804 antlrTool.reportProgress("Generating " + tm.getName() + TokenTypesFileSuffix + TokenTypesFileExt); 806 currentOutput = antlrTool.openOutputFile(tm.getName() + TokenTypesFileSuffix + TokenTypesFileExt); 807 tabs = 0; 809 810 genHeader(); 812 813 println(""); 816 println("*** Tokens used by the parser"); 817 println("This is a list of the token numeric values and the corresponding"); 818 println("token identifiers. Some tokens are literals, and because of that"); 819 println("they have no identifiers. Literals are double-quoted."); 820 tabs++; 821 822 Vector v = tm.getVocabulary(); 824 for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) { 825 String s = (String )v.elementAt(i); 826 if (s != null) { 827 println(s + " = " + i); 828 } 829 } 830 831 tabs--; 833 println("*** End of tokens used by the parser"); 834 835 currentOutput.close(); 837 currentOutput = null; 838 } 839 840 843 public String getASTCreateString(Vector v) { 844 return "***Create an AST from a vector here***" + System.getProperty("line.separator"); 845 } 846 847 850 public String getASTCreateString(GrammarAtom atom, String str) { 851 return "[" + str + "]"; 852 } 853 854 protected String processActionForSpecialSymbols(String actionStr, 856 int line, 857 RuleBlock currentRule, 858 ActionTransInfo tInfo) { 859 return actionStr; 860 } 861 862 868 public String mapTreeId(String id, ActionTransInfo tInfo) { 869 return id; 870 } 871 872 877 public void printSet(int depth, int k, Lookahead lookahead) { 878 int numCols = 5; 879 880 int[] elems = lookahead.fset.toArray(); 881 882 if (depth != 1) { 883 print("k==" + k + ": {"); 884 } 885 else { 886 print("{ "); 887 } 888 if (elems.length > numCols) { 889 _println(""); 890 tabs++; 891 print(""); 892 } 893 894 int column = 0; 895 for (int i = 0; i < elems.length; i++) { 896 column++; 897 if (column > numCols) { 898 _println(""); 899 print(""); 900 column = 0; 901 } 902 if (doingLexRules) { 903 _print(charFormatter.literalChar(elems[i])); 904 } 905 else { 906 _print((String )grammar.tokenManager.getVocabulary().elementAt(elems[i])); 907 } 908 if (i != elems.length - 1) { 909 _print(", "); 910 } 911 } 912 913 if (elems.length > numCols) { 914 _println(""); 915 tabs--; 916 print(""); 917 } 918 _println(" }"); 919 } 920 } 921 | Popular Tags |