KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > antlr > DiagnosticCodeGenerator


1 package antlr;
2
3 /* ANTLR Translator Generator
4  * Project led by Terence Parr at http://www.jGuru.com
5  * Software rights: http://www.antlr.org/RIGHTS.html
6  *
7  * $Id: //depot/code/org.antlr/main/main/antlr/DiagnosticCodeGenerator.java#9 $
8  */

9
10 import java.util.Enumeration JavaDoc;
11
12 import antlr.collections.impl.BitSet;
13 import antlr.collections.impl.Vector;
14
15 import java.io.PrintWriter JavaDoc; //SAS: changed for proper text file io
16
import java.io.IOException JavaDoc;
17 import java.io.FileWriter JavaDoc;
18
19 /**Generate MyParser.txt, MyLexer.txt and MyParserTokenTypes.txt */
20 public class DiagnosticCodeGenerator extends CodeGenerator {
21     /** non-zero if inside syntactic predicate generation */
22     protected int syntacticPredLevel = 0;
23
24     /** true during lexer generation, false during parser generation */
25     protected boolean doingLexRules = false;
26
27     /** Create a Diagnostic code-generator using the given Grammar
28      * The caller must still call setTool, setBehavior, and setAnalyzer
29      * before generating code.
30      */

31     public DiagnosticCodeGenerator() {
32         super();
33         charFormatter = new JavaCharFormatter();
34     }
35
36     /**Generate the parser, lexer, and token types documentation */
37     public void gen() {
38
39         // Do the code generation
40
try {
41             // Loop over all grammars
42
Enumeration JavaDoc grammarIter = behavior.grammars.elements();
43             while (grammarIter.hasMoreElements()) {
44                 Grammar g = (Grammar)grammarIter.nextElement();
45
46                 // Connect all the components to each other
47
g.setGrammarAnalyzer(analyzer);
48                 g.setCodeGenerator(this);
49                 analyzer.setGrammar(g);
50
51                 // To get right overloading behavior across hetrogeneous grammars
52
g.generate();
53
54                 if (antlrTool.hasError()) {
55                     System.out.println("Exiting due to errors.");
56                     System.exit(1);
57                 }
58
59             }
60
61             // Loop over all token managers (some of which are lexers)
62
Enumeration JavaDoc tmIter = behavior.tokenManagers.elements();
63             while (tmIter.hasMoreElements()) {
64                 TokenManager tm = (TokenManager)tmIter.nextElement();
65                 if (!tm.isReadOnly()) {
66                     // Write the token manager tokens as Java
67
genTokenTypes(tm);
68                 }
69             }
70         }
71         catch (IOException JavaDoc e) {
72             System.out.println(e.getMessage());
73         }
74     }
75
76     /** Generate code for the given grammar element.
77      * @param blk The {...} action to generate
78      */

79     public void gen(ActionElement action) {
80         if (action.isSemPred) {
81             // handled elsewhere
82
}
83         else {
84             print("ACTION: ");
85             _printAction(action.actionText);
86         }
87     }
88
89     /** Generate code for the given grammar element.
90      * @param blk The "x|y|z|..." block to generate
91      */

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     /** Generate code for the given grammar element.
106      * @param blk The block-end element to generate. Block-end
107      * elements are synthesized by the grammar parser to represent
108      * the end of a block.
109      */

110     public void gen(BlockEndElement end) {
111         // no-op
112
}
113
114     /** Generate code for the given grammar element.
115      * @param blk The character literal reference to generate
116      */

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     /** Generate code for the given grammar element.
130      * @param blk The character-range reference to generate
131      */

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     /** Generate the lexer TXT file */
141     public void gen(LexerGrammar g) throws IOException JavaDoc {
142         setGrammar(g);
143         System.out.println("Generating " + grammar.getClassName() + TokenTypesFileExt);
144         currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
145         //SAS: changed for proper text file io
146

147         tabs = 0;
148         doingLexRules = true;
149
150         // Generate header common to all TXT output files
151
genHeader();
152
153         // Output the user-defined lexer premamble
154
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         // Generate lexer class definition
163
println("");
164         println("*** Your lexer class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");
165
166         // Generate user-defined parser class members
167
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         // Generate string literals
176
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         // Enumerate all of the symbols and look for string literal symbols
186
Enumeration JavaDoc ids = grammar.getSymbols();
187         while (ids.hasMoreElements()) {
188             GrammarSymbol sym = (GrammarSymbol)ids.nextElement();
189             // Only processing string literals -- reject other symbol entries
190
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         // Generate nextToken() rule.
199
// nextToken() is a synthetic lexer rule that is the implicit OR of all
200
// user-defined lexer rules.
201
genNextToken();
202
203         // Generate code for each rule in the lexer
204
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         // Close the lexer output file
221
currentOutput.close();
222         currentOutput = null;
223         doingLexRules = false;
224     }
225
226     /** Generate code for the given grammar element.
227      * @param blk The (...)+ block to generate
228      */

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     /** Generate the parser TXT file */
243     public void gen(ParserGrammar g) throws IOException JavaDoc {
244         setGrammar(g);
245         // Open the output stream for the parser and set the currentOutput
246
System.out.println("Generating " + grammar.getClassName() + TokenTypesFileExt);
247         currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
248         //SAS: changed for proper text file io
249

250         tabs = 0;
251
252         // Generate the header common to all output files.
253
genHeader();
254
255         // Output the user-defined parser premamble
256
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         // Generate parser class definition
265
println("");
266         println("*** Your parser class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");
267
268         // Generate user-defined parser class members
269
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         // Generate code for each rule in the grammar
278
println("");
279         println("*** Parser rules:");
280         tabs++;
281
282         // Enumerate the parser rules
283
Enumeration JavaDoc rules = grammar.rules.elements();
284         while (rules.hasMoreElements()) {
285             println("");
286             // Get the rules from the list and downcast it to proper type
287
GrammarSymbol sym = (GrammarSymbol)rules.nextElement();
288             // Only process parser rules
289
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         // Close the parser output stream
301
currentOutput.close();
302         currentOutput = null;
303     }
304
305     /** Generate code for the given grammar element.
306      * @param blk The rule-reference to generate
307      */

308     public void gen(RuleRefElement rr) {
309         RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
310
311         // Generate the actual rule description
312
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         // Perform diagnostics
322
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             // Should this ever happen??
329
println("Rule '" + rr.targetRule + "' is referenced, but that is not a grammar rule.");
330             return;
331         }
332         if (rr.idAssign != null) {
333             // Warn if the rule has no return type
334
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             // Warn about return value if any, but not inside syntactic predicate
340
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     /** Generate code for the given grammar element.
350      * @param blk The string-literal reference to generate
351      */

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     /** Generate code for the given grammar element.
362      * @param blk The token-range reference to generate
363      */

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     /** Generate code for the given grammar element.
373      * @param blk The token-reference to generate
374      */

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     /** Generate the tree-walker TXT file */
392     public void gen(TreeWalkerGrammar g) throws IOException JavaDoc {
393         setGrammar(g);
394         // Open the output stream for the parser and set the currentOutput
395
System.out.println("Generating " + grammar.getClassName() + TokenTypesFileExt);
396         currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
397         //SAS: changed for proper text file io
398

399         tabs = 0;
400
401         // Generate the header common to all output files.
402
genHeader();
403
404         // Output the user-defined parser premamble
405
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         // Generate tree-walker class definition
414
println("");
415         println("*** Your tree-walker class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");
416
417         // Generate user-defined tree-walker class members
418
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         // Generate code for each rule in the grammar
427
println("");
428         println("*** tree-walker rules:");
429         tabs++;
430
431         // Enumerate the tree-walker rules
432
Enumeration JavaDoc rules = grammar.rules.elements();
433         while (rules.hasMoreElements()) {
434             println("");
435             // Get the rules from the list and downcast it to proper type
436
GrammarSymbol sym = (GrammarSymbol)rules.nextElement();
437             // Only process tree-walker rules
438
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         // Close the tree-walker output stream
450
currentOutput.close();
451         currentOutput = null;
452     }
453
454     /** Generate a wildcard element */
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     /** Generate code for the given grammar element.
464      * @param blk The (...)* block to generate
465      */

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     /** Generate the header for a block, which may be a RuleBlock or a
493      * plain AlternativeBLock. This generates any variable declarations,
494      * init-actions, and syntactic-predicate-testing variables.
495      * @blk The block for which the preamble is to be generated.
496      */

497     protected void genBlockPreamble(AlternativeBlock blk) {
498         // dump out init action
499
if (blk.initAction != null) {
500             printAction("Init action: " + blk.initAction);
501         }
502     }
503
504     /**Generate common code for a block of alternatives; return a postscript
505      * that needs to be generated at the end of the block. Other routines
506      * may append else-clauses and such for error checking before the postfix
507      * is generated.
508      */

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                 // Generate a warning if there is one alt and it has a synPred
523
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             // Print lookahead set for alternate
537
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             // Dump semantic predicates
557
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             // Dump syntactic predicate
570
if (alt.synPred != null) {
571                 _println("the syntactic predicate:");
572                 tabs++;
573                 genSynPred(alt.synPred);
574                 tabs--;
575                 println("is matched.");
576             }
577
578             // Dump the alternative
579
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     /** Generate a textual representation of the follow set
594      * for a block.
595      * @param blk The rule block of interest
596      */

597     public void genFollowSetForRuleBlock(RuleBlock blk) {
598         Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, blk.endNode);
599         printSet(grammar.maxk, 1, follow);
600     }
601
602     /** Generate a header that is common to all TXT files */
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     /**Generate the lookahead set for an alternate. */
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             // if the decision is nondeterministic, do the best we can: LL(k)
629
// any predicates that are around will be generated later.
630
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     /** Generate a textual representation of the lookahead set
639      * for a block.
640      * @param blk The block of interest
641      */

642     public void genLookaheadSetForBlock(AlternativeBlock blk) {
643         // Find the maximal lookahead depth over all alternatives
644
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     /** Generate the nextToken rule.
663      * nextToken is a synthetic lexer rule that is the implicit OR of all
664      * user-defined lexer rules.
665      */

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         // Create the synthesized rule block for nextToken consisting
675
// of an alternate block containing all the user-defined lexer rules.
676
RuleBlock blk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken");
677
678         // Define the nextToken rule symbol
679
RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
680         nextTokenRs.setDefined();
681         nextTokenRs.setBlock(blk);
682         nextTokenRs.access = "private";
683         grammar.define(nextTokenRs);
684
685         // Analyze the synthesized block
686
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     /** Generate code for a named rule block
699      * @param s The RuleSymbol describing the rule to generate
700      */

701     public void genRule(RuleSymbol s) {
702         println("");
703         String JavaDoc 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         // Get rule return type and arguments
721
RuleBlock rblk = s.getBlock();
722
723         // Gen method return value(s)
724
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         // Gen arguments
741
if (rblk.argAction != null) {
742             println("Arguments: " + rblk.argAction);
743         }
744
745         // Dump any init-action
746
genBlockPreamble(rblk);
747
748         // Analyze the rule
749
boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);
750         if (!ok) {
751             println("Error: This rule is non-deterministic");
752         }
753
754         // Dump the alternates of the rule
755
genCommonBlock(rblk);
756
757         // Search for an unlabeled exception specification attached to the rule
758
ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");
759
760         // Generate user-defined or default catch phrases
761
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         // Dump the follow set
782
// Doesn't seem to work for lexical rules...
783
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     /** Generate the syntactic predicate. This basically generates
795      * the alternative block, buts tracks if we are inside a synPred
796      * @param blk The syntactic predicate block
797      */

798     protected void genSynPred(SynPredBlock blk) {
799         syntacticPredLevel++;
800         gen((AlternativeBlock)blk);
801         syntacticPredLevel--;
802     }
803
804     /** Generate the token types TXT file */
805     protected void genTokenTypes(TokenManager tm) throws IOException JavaDoc {
806         // Open the token output TXT file and set the currentOutput stream
807
System.out.println("Generating " + tm.getName() + TokenTypesFileSuffix + TokenTypesFileExt);
808         currentOutput = antlrTool.openOutputFile(tm.getName() + TokenTypesFileSuffix + TokenTypesFileExt);
809         //SAS: changed for proper text file io
810
tabs = 0;
811
812         // Generate the header common to all diagnostic files
813
genHeader();
814
815         // Generate a string for each token. This creates a static
816
// array of Strings indexed by token type.
817
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         // Enumerate all the valid token types
825
Vector v = tm.getVocabulary();
826         for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
827             String JavaDoc s = (String JavaDoc)v.elementAt(i);
828             if (s != null) {
829                 println(s + " = " + i);
830             }
831         }
832
833         // Close the interface
834
tabs--;
835         println("*** End of tokens used by the parser");
836
837         // Close the tokens output file
838
currentOutput.close();
839         currentOutput = null;
840     }
841
842     /** Get a string for an expression to generate creation of an AST subtree.
843      * @param v A Vector of String, where each element is an expression in the target language yielding an AST node.
844      */

845     public String JavaDoc getASTCreateString(Vector v) {
846         return "***Create an AST from a vector here***" + System.getProperty("line.separator");
847     }
848
849     /** Get a string for an expression to generate creating of an AST node
850      * @param str The arguments to the AST constructor
851      */

852     public String JavaDoc getASTCreateString(GrammarAtom atom, String JavaDoc str) {
853         return "[" + str + "]";
854     }
855
856     /// unused.
857
protected String JavaDoc processActionForTreeSpecifiers(String JavaDoc actionStr,
858                                                     int line,
859                                                     RuleBlock currentRule,
860                                                     ActionTransInfo tInfo) {
861         return actionStr;
862     }
863
864     /** Map an identifier to it's corresponding tree-node variable.
865      * This is context-sensitive, depending on the rule and alternative
866      * being generated
867      * @param id The identifier name to map
868      * @param forInput true if the input tree node variable is to be returned, otherwise the output variable is returned.
869      */

870     public String JavaDoc mapTreeId(String JavaDoc id, ActionTransInfo tInfo) {
871         return id;
872     }
873
874     /** Format a lookahead or follow set.
875      * @param depth The depth of the entire lookahead/follow
876      * @param k The lookahead level to print
877      * @param lookahead The lookahead/follow set to print
878      */

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 JavaDoc)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