source: trunk/yao/share/antlr-2.7.7/antlr/DiagnosticCodeGenerator.java @ 1

Last change on this file since 1 was 1, checked in by lnalod, 15 years ago

Initial import of YAO sources

File size: 31.8 KB
Line 
1package antlr;
2
3/* ANTLR Translator Generator
4 * Project led by Terence Parr at http://www.cs.usfca.edu
5 * Software rights: http://www.antlr.org/license.html
6 *
7 * $Id: //depot/code/org.antlr/release/antlr-2.7.7/antlr/DiagnosticCodeGenerator.java#2 $
8 */
9
10import java.util.Enumeration;
11
12import antlr.collections.impl.BitSet;
13import antlr.collections.impl.Vector;
14
15import java.io.PrintWriter; //SAS: changed for proper text file io
16import java.io.IOException;
17import java.io.FileWriter;
18
19/**Generate MyParser.txt, MyLexer.txt and MyParserTokenTypes.txt */
20public 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 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                    antlrTool.panic("Exiting due to errors.");
56                }
57
58            }
59
60            // Loop over all token managers (some of which are lexers)
61            Enumeration tmIter = behavior.tokenManagers.elements();
62            while (tmIter.hasMoreElements()) {
63                TokenManager tm = (TokenManager)tmIter.nextElement();
64                if (!tm.isReadOnly()) {
65                    // Write the token manager tokens as Java
66                    genTokenTypes(tm);
67                }
68            }
69        }
70        catch (IOException e) {
71            antlrTool.reportException(e, null);
72        }
73    }
74
75    /** Generate code for the given grammar element.
76     * @param blk The {...} action to generate
77     */
78    public void gen(ActionElement action) {
79        if (action.isSemPred) {
80            // handled elsewhere
81        }
82        else {
83            print("ACTION: ");
84            _printAction(action.actionText);
85        }
86    }
87
88    /** Generate code for the given grammar element.
89     * @param blk The "x|y|z|..." block to generate
90     */
91    public void gen(AlternativeBlock blk) {
92        println("Start of alternative block.");
93        tabs++;
94        genBlockPreamble(blk);
95
96        boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
97        if (!ok) {
98            println("Warning: This alternative block is non-deterministic");
99        }
100        genCommonBlock(blk);
101        tabs--;
102    }
103
104    /** Generate code for the given grammar element.
105     * @param blk The block-end element to generate.  Block-end
106     * elements are synthesized by the grammar parser to represent
107     * the end of a block.
108     */
109    public void gen(BlockEndElement end) {
110        // no-op
111    }
112
113    /** Generate code for the given grammar element.
114     * @param blk The character literal reference to generate
115     */
116    public void gen(CharLiteralElement atom) {
117        print("Match character ");
118        if (atom.not) {
119            _print("NOT ");
120        }
121        _print(atom.atomText);
122        if (atom.label != null) {
123            _print(", label=" + atom.label);
124        }
125        _println("");
126    }
127
128    /** Generate code for the given grammar element.
129     * @param blk The character-range reference to generate
130     */
131    public void gen(CharRangeElement r) {
132        print("Match character range: " + r.beginText + ".." + r.endText);
133        if (r.label != null) {
134            _print(", label = " + r.label);
135        }
136        _println("");
137    }
138
139    /** Generate the lexer TXT file */
140    public void gen(LexerGrammar g) throws IOException {
141        setGrammar(g);
142        antlrTool.reportProgress("Generating " + grammar.getClassName() + TokenTypesFileExt);
143        currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
144        //SAS: changed for proper text file io
145
146        tabs = 0;
147        doingLexRules = true;
148
149        // Generate header common to all TXT output files
150        genHeader();
151
152        // Output the user-defined lexer premamble
153        println("");
154        println("*** Lexer Preamble Action.");
155        println("This action will appear before the declaration of your lexer class:");
156        tabs++;
157        println(grammar.preambleAction.getText());
158        tabs--;
159        println("*** End of Lexer Preamble Action");
160
161        // Generate lexer class definition
162        println("");
163        println("*** Your lexer class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");
164
165        // Generate user-defined parser class members
166        println("");
167        println("*** User-defined lexer  class members:");
168        println("These are the member declarations that you defined for your class:");
169        tabs++;
170        printAction(grammar.classMemberAction.getText());
171        tabs--;
172        println("*** End of user-defined lexer class members");
173
174        // Generate string literals
175        println("");
176        println("*** String literals used in the parser");
177        println("The following string literals were used in the parser.");
178        println("An actual code generator would arrange to place these literals");
179        println("into a table in the generated lexer, so that actions in the");
180        println("generated lexer could match token text against the literals.");
181        println("String literals used in the lexer are not listed here, as they");
182        println("are incorporated into the mainstream lexer processing.");
183        tabs++;
184        // Enumerate all of the symbols and look for string literal symbols
185        Enumeration ids = grammar.getSymbols();
186        while (ids.hasMoreElements()) {
187            GrammarSymbol sym = (GrammarSymbol)ids.nextElement();
188            // Only processing string literals -- reject other symbol entries
189            if (sym instanceof StringLiteralSymbol) {
190                StringLiteralSymbol s = (StringLiteralSymbol)sym;
191                println(s.getId() + " = " + s.getTokenType());
192            }
193        }
194        tabs--;
195        println("*** End of string literals used by the parser");
196
197        // Generate nextToken() rule.
198        // nextToken() is a synthetic lexer rule that is the implicit OR of all
199        // user-defined lexer rules.
200        genNextToken();
201
202        // Generate code for each rule in the lexer
203        println("");
204        println("*** User-defined Lexer rules:");
205        tabs++;
206
207        ids = grammar.rules.elements();
208        while (ids.hasMoreElements()) {
209            RuleSymbol rs = (RuleSymbol)ids.nextElement();
210            if (!rs.id.equals("mnextToken")) {
211                genRule(rs);
212            }
213        }
214
215        tabs--;
216        println("");
217        println("*** End User-defined Lexer rules:");
218
219        // Close the lexer output file
220        currentOutput.close();
221        currentOutput = null;
222        doingLexRules = false;
223    }
224
225    /** Generate code for the given grammar element.
226     * @param blk The (...)+ block to generate
227     */
228    public void gen(OneOrMoreBlock blk) {
229        println("Start ONE-OR-MORE (...)+ block:");
230        tabs++;
231        genBlockPreamble(blk);
232        boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
233        if (!ok) {
234            println("Warning: This one-or-more block is non-deterministic");
235        }
236        genCommonBlock(blk);
237        tabs--;
238        println("End ONE-OR-MORE block.");
239    }
240
241    /** Generate the parser TXT file */
242    public void gen(ParserGrammar g) throws IOException {
243        setGrammar(g);
244        // Open the output stream for the parser and set the currentOutput
245        antlrTool.reportProgress("Generating " + grammar.getClassName() + TokenTypesFileExt);
246        currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
247        //SAS: changed for proper text file io
248
249        tabs = 0;
250
251        // Generate the header common to all output files.
252        genHeader();
253
254        // Output the user-defined parser premamble
255        println("");
256        println("*** Parser Preamble Action.");
257        println("This action will appear before the declaration of your parser class:");
258        tabs++;
259        println(grammar.preambleAction.getText());
260        tabs--;
261        println("*** End of Parser Preamble Action");
262
263        // Generate parser class definition
264        println("");
265        println("*** Your parser class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");
266
267        // Generate user-defined parser class members
268        println("");
269        println("*** User-defined parser class members:");
270        println("These are the member declarations that you defined for your class:");
271        tabs++;
272        printAction(grammar.classMemberAction.getText());
273        tabs--;
274        println("*** End of user-defined parser class members");
275
276        // Generate code for each rule in the grammar
277        println("");
278        println("*** Parser rules:");
279        tabs++;
280
281        // Enumerate the parser rules
282        Enumeration rules = grammar.rules.elements();
283        while (rules.hasMoreElements()) {
284            println("");
285            // Get the rules from the list and downcast it to proper type
286            GrammarSymbol sym = (GrammarSymbol)rules.nextElement();
287            // Only process parser rules
288            if (sym instanceof RuleSymbol) {
289                genRule((RuleSymbol)sym);
290            }
291        }
292        tabs--;
293        println("");
294        println("*** End of parser rules");
295
296        println("");
297        println("*** End of parser");
298
299        // Close the parser output stream
300        currentOutput.close();
301        currentOutput = null;
302    }
303
304    /** Generate code for the given grammar element.
305     * @param blk The rule-reference to generate
306     */
307    public void gen(RuleRefElement rr) {
308        RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
309
310        // Generate the actual rule description
311        print("Rule Reference: " + rr.targetRule);
312        if (rr.idAssign != null) {
313            _print(", assigned to '" + rr.idAssign + "'");
314        }
315        if (rr.args != null) {
316            _print(", arguments = " + rr.args);
317        }
318        _println("");
319
320        // Perform diagnostics
321        if (rs == null || !rs.isDefined()) {
322            println("Rule '" + rr.targetRule + "' is referenced, but that rule is not defined.");
323            println("\tPerhaps the rule is misspelled, or you forgot to define it.");
324            return;
325        }
326        if (!(rs instanceof RuleSymbol)) {
327            // Should this ever happen??
328            println("Rule '" + rr.targetRule + "' is referenced, but that is not a grammar rule.");
329            return;
330        }
331        if (rr.idAssign != null) {
332            // Warn if the rule has no return type
333            if (rs.block.returnAction == null) {
334                println("Error: You assigned from Rule '" + rr.targetRule + "', but that rule has no return type.");
335            }
336        }
337        else {
338            // Warn about return value if any, but not inside syntactic predicate
339            if (!(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null) {
340                println("Warning: Rule '" + rr.targetRule + "' returns a value");
341            }
342        }
343        if (rr.args != null && rs.block.argAction == null) {
344            println("Error: Rule '" + rr.targetRule + "' accepts no arguments.");
345        }
346    }
347
348    /** Generate code for the given grammar element.
349     * @param blk The string-literal reference to generate
350     */
351    public void gen(StringLiteralElement atom) {
352        print("Match string literal ");
353        _print(atom.atomText);
354        if (atom.label != null) {
355            _print(", label=" + atom.label);
356        }
357        _println("");
358    }
359
360    /** Generate code for the given grammar element.
361     * @param blk The token-range reference to generate
362     */
363    public void gen(TokenRangeElement r) {
364        print("Match token range: " + r.beginText + ".." + r.endText);
365        if (r.label != null) {
366            _print(", label = " + r.label);
367        }
368        _println("");
369    }
370
371    /** Generate code for the given grammar element.
372     * @param blk The token-reference to generate
373     */
374    public void gen(TokenRefElement atom) {
375        print("Match token ");
376        if (atom.not) {
377            _print("NOT ");
378        }
379        _print(atom.atomText);
380        if (atom.label != null) {
381            _print(", label=" + atom.label);
382        }
383        _println("");
384    }
385
386    public void gen(TreeElement t) {
387        print("Tree reference: " + t);
388    }
389
390    /** Generate the tree-walker TXT file */
391    public void gen(TreeWalkerGrammar g) throws IOException {
392        setGrammar(g);
393        // Open the output stream for the parser and set the currentOutput
394        antlrTool.reportProgress("Generating " + grammar.getClassName() + TokenTypesFileExt);
395        currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
396        //SAS: changed for proper text file io
397
398        tabs = 0;
399
400        // Generate the header common to all output files.
401        genHeader();
402
403        // Output the user-defined parser premamble
404        println("");
405        println("*** Tree-walker Preamble Action.");
406        println("This action will appear before the declaration of your tree-walker class:");
407        tabs++;
408        println(grammar.preambleAction.getText());
409        tabs--;
410        println("*** End of tree-walker Preamble Action");
411
412        // Generate tree-walker class definition
413        println("");
414        println("*** Your tree-walker class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");
415
416        // Generate user-defined tree-walker class members
417        println("");
418        println("*** User-defined tree-walker class members:");
419        println("These are the member declarations that you defined for your class:");
420        tabs++;
421        printAction(grammar.classMemberAction.getText());
422        tabs--;
423        println("*** End of user-defined tree-walker class members");
424
425        // Generate code for each rule in the grammar
426        println("");
427        println("*** tree-walker rules:");
428        tabs++;
429
430        // Enumerate the tree-walker rules
431        Enumeration rules = grammar.rules.elements();
432        while (rules.hasMoreElements()) {
433            println("");
434            // Get the rules from the list and downcast it to proper type
435            GrammarSymbol sym = (GrammarSymbol)rules.nextElement();
436            // Only process tree-walker rules
437            if (sym instanceof RuleSymbol) {
438                genRule((RuleSymbol)sym);
439            }
440        }
441        tabs--;
442        println("");
443        println("*** End of tree-walker rules");
444
445        println("");
446        println("*** End of tree-walker");
447
448        // Close the tree-walker output stream
449        currentOutput.close();
450        currentOutput = null;
451    }
452
453    /** Generate a wildcard element */
454    public void gen(WildcardElement wc) {
455        print("Match wildcard");
456        if (wc.getLabel() != null) {
457            _print(", label = " + wc.getLabel());
458        }
459        _println("");
460    }
461
462    /** Generate code for the given grammar element.
463     * @param blk The (...)* block to generate
464     */
465    public void gen(ZeroOrMoreBlock blk) {
466        println("Start ZERO-OR-MORE (...)+ block:");
467        tabs++;
468        genBlockPreamble(blk);
469        boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
470        if (!ok) {
471            println("Warning: This zero-or-more block is non-deterministic");
472        }
473        genCommonBlock(blk);
474        tabs--;
475        println("End ZERO-OR-MORE block.");
476    }
477
478    protected void genAlt(Alternative alt) {
479        for (
480            AlternativeElement elem = alt.head;
481            !(elem instanceof BlockEndElement);
482            elem = elem.next
483            ) {
484            elem.generate();
485        }
486        if (alt.getTreeSpecifier() != null) {
487            println("AST will be built as: " + alt.getTreeSpecifier().getText());
488        }
489    }
490
491    /** Generate the header for a block, which may be a RuleBlock or a
492     * plain AlternativeBLock.  This generates any variable declarations,
493     * init-actions, and syntactic-predicate-testing variables.
494     * @blk The block for which the preamble is to be generated.
495     */
496    protected void genBlockPreamble(AlternativeBlock blk) {
497        // dump out init action
498        if (blk.initAction != null) {
499            printAction("Init action: " + blk.initAction);
500        }
501    }
502
503    /**Generate common code for a block of alternatives; return a postscript
504     * that needs to be generated at the end of the block.  Other routines
505     * may append else-clauses and such for error checking before the postfix
506     * is generated.
507     */
508    public void genCommonBlock(AlternativeBlock blk) {
509        boolean singleAlt = (blk.alternatives.size() == 1);
510
511        println("Start of an alternative block.");
512        tabs++;
513        println("The lookahead set for this block is:");
514        tabs++;
515        genLookaheadSetForBlock(blk);
516        tabs--;
517
518        if (singleAlt) {
519            println("This block has a single alternative");
520            if (blk.getAlternativeAt(0).synPred != null) {
521                // Generate a warning if there is one alt and it has a synPred
522                println("Warning: you specified a syntactic predicate for this alternative,");
523                println("and it is the only alternative of a block and will be ignored.");
524            }
525        }
526        else {
527            println("This block has multiple alternatives:");
528            tabs++;
529        }
530
531        for (int i = 0; i < blk.alternatives.size(); i++) {
532            Alternative alt = blk.getAlternativeAt(i);
533            AlternativeElement elem = alt.head;
534
535            // Print lookahead set for alternate
536            println("");
537            if (i != 0) {
538                print("Otherwise, ");
539            }
540            else {
541                print("");
542            }
543            _println("Alternate(" + (i + 1) + ") will be taken IF:");
544            println("The lookahead set: ");
545            tabs++;
546            genLookaheadSetForAlt(alt);
547            tabs--;
548            if (alt.semPred != null || alt.synPred != null) {
549                print("is matched, AND ");
550            }
551            else {
552                println("is matched.");
553            }
554
555            // Dump semantic predicates
556            if (alt.semPred != null) {
557                _println("the semantic predicate:");
558                tabs++;
559                println(alt.semPred);
560                if (alt.synPred != null) {
561                    print("is true, AND ");
562                }
563                else {
564                    println("is true.");
565                }
566            }
567
568            // Dump syntactic predicate
569            if (alt.synPred != null) {
570                _println("the syntactic predicate:");
571                tabs++;
572                genSynPred(alt.synPred);
573                tabs--;
574                println("is matched.");
575            }
576
577            // Dump the alternative
578            genAlt(alt);
579        }
580        println("");
581        println("OTHERWISE, a NoViableAlt exception will be thrown");
582        println("");
583
584        if (!singleAlt) {
585            tabs--;
586            println("End of alternatives");
587        }
588        tabs--;
589        println("End of alternative block.");
590    }
591
592    /** Generate a textual representation of the follow set
593     * for a block.
594     * @param blk  The rule block of interest
595     */
596    public void genFollowSetForRuleBlock(RuleBlock blk) {
597        Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, blk.endNode);
598        printSet(grammar.maxk, 1, follow);
599    }
600
601    /** Generate a header that is common to all TXT files */
602    protected void genHeader() {
603        println("ANTLR-generated file resulting from grammar " + antlrTool.grammarFile);
604        println("Diagnostic output");
605        println("");
606        println("Terence Parr, MageLang Institute");
607        println("with John Lilley, Empathy Software");
608        println("ANTLR Version " + antlrTool.version + "; 1989-2005");
609        println("");
610        println("*** Header Action.");
611        println("This action will appear at the top of all generated files.");
612        tabs++;
613        printAction(behavior.getHeaderAction(""));
614        tabs--;
615        println("*** End of Header Action");
616        println("");
617    }
618
619    /**Generate the lookahead set for an alternate. */
620    protected void genLookaheadSetForAlt(Alternative alt) {
621        if (doingLexRules && alt.cache[1].containsEpsilon()) {
622            println("MATCHES ALL");
623            return;
624        }
625        int depth = alt.lookaheadDepth;
626        if (depth == GrammarAnalyzer.NONDETERMINISTIC) {
627            // if the decision is nondeterministic, do the best we can: LL(k)
628            // any predicates that are around will be generated later.
629            depth = grammar.maxk;
630        }
631        for (int i = 1; i <= depth; i++) {
632            Lookahead lookahead = alt.cache[i];
633            printSet(depth, i, lookahead);
634        }
635    }
636
637    /** Generate a textual representation of the lookahead set
638     * for a block.
639     * @param blk  The block of interest
640     */
641    public void genLookaheadSetForBlock(AlternativeBlock blk) {
642        // Find the maximal lookahead depth over all alternatives
643        int depth = 0;
644        for (int i = 0; i < blk.alternatives.size(); i++) {
645            Alternative alt = blk.getAlternativeAt(i);
646            if (alt.lookaheadDepth == GrammarAnalyzer.NONDETERMINISTIC) {
647                depth = grammar.maxk;
648                break;
649            }
650            else if (depth < alt.lookaheadDepth) {
651                depth = alt.lookaheadDepth;
652            }
653        }
654
655        for (int i = 1; i <= depth; i++) {
656            Lookahead lookahead = grammar.theLLkAnalyzer.look(i, blk);
657            printSet(depth, i, lookahead);
658        }
659    }
660
661    /** Generate the nextToken rule.
662     * nextToken is a synthetic lexer rule that is the implicit OR of all
663     * user-defined lexer rules.
664     */
665    public void genNextToken() {
666        println("");
667        println("*** Lexer nextToken rule:");
668        println("The lexer nextToken rule is synthesized from all of the user-defined");
669        println("lexer rules.  It logically consists of one big alternative block with");
670        println("each user-defined rule being an alternative.");
671        println("");
672
673        // Create the synthesized rule block for nextToken consisting
674        // of an alternate block containing all the user-defined lexer rules.
675        RuleBlock blk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken");
676
677        // Define the nextToken rule symbol
678        RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
679        nextTokenRs.setDefined();
680        nextTokenRs.setBlock(blk);
681        nextTokenRs.access = "private";
682        grammar.define(nextTokenRs);
683
684        // Analyze the synthesized block
685        if (!grammar.theLLkAnalyzer.deterministic(blk)) {
686            println("The grammar analyzer has determined that the synthesized");
687            println("nextToken rule is non-deterministic (i.e., it has ambiguities)");
688            println("This means that there is some overlap of the character");
689            println("lookahead for two or more of your lexer rules.");
690        }
691
692        genCommonBlock(blk);
693
694        println("*** End of nextToken lexer rule.");
695    }
696
697    /** Generate code for a named rule block
698     * @param s The RuleSymbol describing the rule to generate
699     */
700    public void genRule(RuleSymbol s) {
701        println("");
702        String ruleType = (doingLexRules ? "Lexer" : "Parser");
703        println("*** " + ruleType + " Rule: " + s.getId());
704        if (!s.isDefined()) {
705            println("This rule is undefined.");
706            println("This means that the rule was referenced somewhere in the grammar,");
707            println("but a definition for the rule was not encountered.");
708            println("It is also possible that syntax errors during the parse of");
709            println("your grammar file prevented correct processing of the rule.");
710            println("*** End " + ruleType + " Rule: " + s.getId());
711            return;
712        }
713        tabs++;
714
715        if (s.access.length() != 0) {
716            println("Access: " + s.access);
717        }
718
719        // Get rule return type and arguments
720        RuleBlock rblk = s.getBlock();
721
722        // Gen method return value(s)
723        if (rblk.returnAction != null) {
724            println("Return value(s): " + rblk.returnAction);
725            if (doingLexRules) {
726                println("Error: you specified return value(s) for a lexical rule.");
727                println("\tLexical rules have an implicit return type of 'int'.");
728            }
729        }
730        else {
731            if (doingLexRules) {
732                println("Return value: lexical rule returns an implicit token type");
733            }
734            else {
735                println("Return value: none");
736            }
737        }
738
739        // Gen arguments
740        if (rblk.argAction != null) {
741            println("Arguments: " + rblk.argAction);
742        }
743
744        // Dump any init-action
745        genBlockPreamble(rblk);
746
747        // Analyze the rule
748        boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);
749        if (!ok) {
750            println("Error: This rule is non-deterministic");
751        }
752
753        // Dump the alternates of the rule
754        genCommonBlock(rblk);
755
756        // Search for an unlabeled exception specification attached to the rule
757        ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");
758
759        // Generate user-defined or default catch phrases
760        if (unlabeledUserSpec != null) {
761            println("You specified error-handler(s) for this rule:");
762            tabs++;
763            for (int i = 0; i < unlabeledUserSpec.handlers.size(); i++) {
764                if (i != 0) {
765                    println("");
766                }
767
768                ExceptionHandler handler = (ExceptionHandler)unlabeledUserSpec.handlers.elementAt(i);
769                println("Error-handler(" + (i + 1) + ") catches [" + handler.exceptionTypeAndName.getText() + "] and executes:");
770                printAction(handler.action.getText());
771            }
772            tabs--;
773            println("End error-handlers.");
774        }
775        else if (!doingLexRules) {
776            println("Default error-handling will be generated, which catches all");
777            println("parser exceptions and consumes tokens until the follow-set is seen.");
778        }
779
780        // Dump the follow set
781        // Doesn't seem to work for lexical rules...
782        if (!doingLexRules) {
783            println("The follow set for this rule is:");
784            tabs++;
785            genFollowSetForRuleBlock(rblk);
786            tabs--;
787        }
788
789        tabs--;
790        println("*** End " + ruleType + " Rule: " + s.getId());
791    }
792
793    /** Generate the syntactic predicate.  This basically generates
794     * the alternative block, buts tracks if we are inside a synPred
795     * @param blk  The syntactic predicate block
796     */
797    protected void genSynPred(SynPredBlock blk) {
798        syntacticPredLevel++;
799        gen((AlternativeBlock)blk);
800        syntacticPredLevel--;
801    }
802
803    /** Generate the token types TXT file */
804    protected void genTokenTypes(TokenManager tm) throws IOException {
805        // Open the token output TXT file and set the currentOutput stream
806        antlrTool.reportProgress("Generating " + tm.getName() + TokenTypesFileSuffix + TokenTypesFileExt);
807        currentOutput = antlrTool.openOutputFile(tm.getName() + TokenTypesFileSuffix + TokenTypesFileExt);
808        //SAS: changed for proper text file io
809        tabs = 0;
810
811        // Generate the header common to all diagnostic files
812        genHeader();
813
814        // Generate a string for each token.  This creates a static
815        // array of Strings indexed by token type.
816        println("");
817        println("*** Tokens used by the parser");
818        println("This is a list of the token numeric values and the corresponding");
819        println("token identifiers.  Some tokens are literals, and because of that");
820        println("they have no identifiers.  Literals are double-quoted.");
821        tabs++;
822
823        // Enumerate all the valid token types
824        Vector v = tm.getVocabulary();
825        for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
826            String s = (String)v.elementAt(i);
827            if (s != null) {
828                println(s + " = " + i);
829            }
830        }
831
832        // Close the interface
833        tabs--;
834        println("*** End of tokens used by the parser");
835
836        // Close the tokens output file
837        currentOutput.close();
838        currentOutput = null;
839    }
840
841    /** Get a string for an expression to generate creation of an AST subtree.
842     * @param v A Vector of String, where each element is an expression in the target language yielding an AST node.
843     */
844    public String getASTCreateString(Vector v) {
845        return "***Create an AST from a vector here***" + System.getProperty("line.separator");
846    }
847
848    /** Get a string for an expression to generate creating of an AST node
849     * @param str The arguments to the AST constructor
850     */
851    public String getASTCreateString(GrammarAtom atom, String str) {
852        return "[" + str + "]";
853    }
854
855    /// unused.
856    protected String processActionForSpecialSymbols(String actionStr,
857                                                    int line,
858                                                    RuleBlock currentRule,
859                                                    ActionTransInfo tInfo) {
860        return actionStr;
861    }
862
863    /** Map an identifier to it's corresponding tree-node variable.
864     * This is context-sensitive, depending on the rule and alternative
865     * being generated
866     * @param id The identifier name to map
867     * @param forInput true if the input tree node variable is to be returned, otherwise the output variable is returned.
868     */
869    public String mapTreeId(String id, ActionTransInfo tInfo) {
870        return id;
871    }
872
873    /** Format a lookahead or follow set.
874     * @param depth The depth of the entire lookahead/follow
875     * @param k The lookahead level to print
876     * @param lookahead  The lookahead/follow set to print
877     */
878    public void printSet(int depth, int k, Lookahead lookahead) {
879        int numCols = 5;
880
881        int[] elems = lookahead.fset.toArray();
882
883        if (depth != 1) {
884            print("k==" + k + ": {");
885        }
886        else {
887            print("{ ");
888        }
889        if (elems.length > numCols) {
890            _println("");
891            tabs++;
892            print("");
893        }
894
895        int column = 0;
896        for (int i = 0; i < elems.length; i++) {
897            column++;
898            if (column > numCols) {
899                _println("");
900                print("");
901                column = 0;
902            }
903            if (doingLexRules) {
904                _print(charFormatter.literalChar(elems[i]));
905            }
906            else {
907                _print((String)grammar.tokenManager.getVocabulary().elementAt(elems[i]));
908            }
909            if (i != elems.length - 1) {
910                _print(", ");
911            }
912        }
913
914        if (elems.length > numCols) {
915            _println("");
916            tabs--;
917            print("");
918        }
919        _println(" }");
920    }
921}
Note: See TracBrowser for help on using the repository browser.