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