FileDocCategorySizeDatePackage
DiagnosticCodeGenerator.javaAPI DocGlassfish v2 API32508Wed Aug 30 15:34:06 BST 2006persistence.antlr

DiagnosticCodeGenerator

public class DiagnosticCodeGenerator extends CodeGenerator
Generate MyParser.txt, MyLexer.txt and MyParserTokenTypes.txt

Fields Summary
protected int
syntacticPredLevel
non-zero if inside syntactic predicate generation
protected boolean
doingLexRules
true during lexer generation, false during parser generation
Constructors Summary
public DiagnosticCodeGenerator()
Create a Diagnostic code-generator using the given Grammar The caller must still call setTool, setBehavior, and setAnalyzer before generating code.


                             
      
        super();
        charFormatter = new JavaCharFormatter();
    
Methods Summary
public voidgen(ParserGrammar g)
Generate the parser TXT file

        setGrammar(g);
        // Open the output stream for the parser and set the currentOutput
        antlrTool.reportProgress("Generating " + grammar.getClassName() + TokenTypesFileExt);
        currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
        //SAS: changed for proper text file io

        tabs = 0;

        // Generate the header common to all output files.
        genHeader();

        // Output the user-defined parser premamble
        println("");
        println("*** Parser Preamble Action.");
        println("This action will appear before the declaration of your parser class:");
        tabs++;
        println(grammar.preambleAction.getText());
        tabs--;
        println("*** End of Parser Preamble Action");

        // Generate parser class definition
        println("");
        println("*** Your parser class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");

        // Generate user-defined parser class members
        println("");
        println("*** User-defined parser class members:");
        println("These are the member declarations that you defined for your class:");
        tabs++;
        printAction(grammar.classMemberAction.getText());
        tabs--;
        println("*** End of user-defined parser class members");

        // Generate code for each rule in the grammar
        println("");
        println("*** Parser rules:");
        tabs++;

        // Enumerate the parser rules
        Enumeration rules = grammar.rules.elements();
        while (rules.hasMoreElements()) {
            println("");
            // Get the rules from the list and downcast it to proper type
            GrammarSymbol sym = (GrammarSymbol)rules.nextElement();
            // Only process parser rules
            if (sym instanceof RuleSymbol) {
                genRule((RuleSymbol)sym);
            }
        }
        tabs--;
        println("");
        println("*** End of parser rules");

        println("");
        println("*** End of parser");

        // Close the parser output stream
        currentOutput.close();
        currentOutput = null;
    
public voidgen(RuleRefElement rr)
Generate code for the given grammar element.

param
blk The rule-reference to generate

        RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);

        // Generate the actual rule description
        print("Rule Reference: " + rr.targetRule);
        if (rr.idAssign != null) {
            _print(", assigned to '" + rr.idAssign + "'");
        }
        if (rr.args != null) {
            _print(", arguments = " + rr.args);
        }
        _println("");

        // Perform diagnostics
        if (rs == null || !rs.isDefined()) {
            println("Rule '" + rr.targetRule + "' is referenced, but that rule is not defined.");
            println("\tPerhaps the rule is misspelled, or you forgot to define it.");
            return;
        }
        if (!(rs instanceof RuleSymbol)) {
            // Should this ever happen??
            println("Rule '" + rr.targetRule + "' is referenced, but that is not a grammar rule.");
            return;
        }
        if (rr.idAssign != null) {
            // Warn if the rule has no return type
            if (rs.block.returnAction == null) {
                println("Error: You assigned from Rule '" + rr.targetRule + "', but that rule has no return type.");
            }
        }
        else {
            // Warn about return value if any, but not inside syntactic predicate
            if (!(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null) {
                println("Warning: Rule '" + rr.targetRule + "' returns a value");
            }
        }
        if (rr.args != null && rs.block.argAction == null) {
            println("Error: Rule '" + rr.targetRule + "' accepts no arguments.");
        }
    
public voidgen(StringLiteralElement atom)
Generate code for the given grammar element.

param
blk The string-literal reference to generate

        print("Match string literal ");
        _print(atom.atomText);
        if (atom.label != null) {
            _print(", label=" + atom.label);
        }
        _println("");
    
public voidgen(TokenRangeElement r)
Generate code for the given grammar element.

param
blk The token-range reference to generate

        print("Match token range: " + r.beginText + ".." + r.endText);
        if (r.label != null) {
            _print(", label = " + r.label);
        }
        _println("");
    
public voidgen(TokenRefElement atom)
Generate code for the given grammar element.

param
blk The token-reference to generate

        print("Match token ");
        if (atom.not) {
            _print("NOT ");
        }
        _print(atom.atomText);
        if (atom.label != null) {
            _print(", label=" + atom.label);
        }
        _println("");
    
public voidgen(TreeElement t)

        print("Tree reference: " + t);
    
public voidgen(TreeWalkerGrammar g)
Generate the tree-walker TXT file

        setGrammar(g);
        // Open the output stream for the parser and set the currentOutput
        antlrTool.reportProgress("Generating " + grammar.getClassName() + TokenTypesFileExt);
        currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
        //SAS: changed for proper text file io

        tabs = 0;

        // Generate the header common to all output files.
        genHeader();

        // Output the user-defined parser premamble
        println("");
        println("*** Tree-walker Preamble Action.");
        println("This action will appear before the declaration of your tree-walker class:");
        tabs++;
        println(grammar.preambleAction.getText());
        tabs--;
        println("*** End of tree-walker Preamble Action");

        // Generate tree-walker class definition
        println("");
        println("*** Your tree-walker class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");

        // Generate user-defined tree-walker class members
        println("");
        println("*** User-defined tree-walker class members:");
        println("These are the member declarations that you defined for your class:");
        tabs++;
        printAction(grammar.classMemberAction.getText());
        tabs--;
        println("*** End of user-defined tree-walker class members");

        // Generate code for each rule in the grammar
        println("");
        println("*** tree-walker rules:");
        tabs++;

        // Enumerate the tree-walker rules
        Enumeration rules = grammar.rules.elements();
        while (rules.hasMoreElements()) {
            println("");
            // Get the rules from the list and downcast it to proper type
            GrammarSymbol sym = (GrammarSymbol)rules.nextElement();
            // Only process tree-walker rules
            if (sym instanceof RuleSymbol) {
                genRule((RuleSymbol)sym);
            }
        }
        tabs--;
        println("");
        println("*** End of tree-walker rules");

        println("");
        println("*** End of tree-walker");

        // Close the tree-walker output stream
        currentOutput.close();
        currentOutput = null;
    
public voidgen(WildcardElement wc)
Generate a wildcard element

        print("Match wildcard");
        if (wc.getLabel() != null) {
            _print(", label = " + wc.getLabel());
        }
        _println("");
    
public voidgen(ZeroOrMoreBlock blk)
Generate code for the given grammar element.

param
blk The (...)* block to generate

        println("Start ZERO-OR-MORE (...)+ block:");
        tabs++;
        genBlockPreamble(blk);
        boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
        if (!ok) {
            println("Warning: This zero-or-more block is non-deterministic");
        }
        genCommonBlock(blk);
        tabs--;
        println("End ZERO-OR-MORE block.");
    
public voidgen()
Generate the parser, lexer, and token types documentation


        // Do the code generation
        try {
            // Loop over all grammars
            Enumeration grammarIter = behavior.grammars.elements();
            while (grammarIter.hasMoreElements()) {
                Grammar g = (Grammar)grammarIter.nextElement();

                // Connect all the components to each other
                g.setGrammarAnalyzer(analyzer);
                g.setCodeGenerator(this);
                analyzer.setGrammar(g);

                // To get right overloading behavior across hetrogeneous grammars
                g.generate();

                if (antlrTool.hasError()) {
                    antlrTool.panic("Exiting due to errors.");
                }

            }

            // Loop over all token managers (some of which are lexers)
            Enumeration tmIter = behavior.tokenManagers.elements();
            while (tmIter.hasMoreElements()) {
                TokenManager tm = (TokenManager)tmIter.nextElement();
                if (!tm.isReadOnly()) {
                    // Write the token manager tokens as Java
                    genTokenTypes(tm);
                }
            }
        }
        catch (IOException e) {
            antlrTool.reportException(e, null);
        }
    
public voidgen(ActionElement action)
Generate code for the given grammar element.

param
blk The {...} action to generate

        if (action.isSemPred) {
            // handled elsewhere
        }
        else {
            print("ACTION: ");
            _printAction(action.actionText);
        }
    
public voidgen(AlternativeBlock blk)
Generate code for the given grammar element.

param
blk The "x|y|z|..." block to generate

        println("Start of alternative block.");
        tabs++;
        genBlockPreamble(blk);

        boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
        if (!ok) {
            println("Warning: This alternative block is non-deterministic");
        }
        genCommonBlock(blk);
        tabs--;
    
public voidgen(BlockEndElement end)
Generate code for the given grammar element.

param
blk The block-end element to generate. Block-end elements are synthesized by the grammar parser to represent the end of a block.

        // no-op
    
public voidgen(CharLiteralElement atom)
Generate code for the given grammar element.

param
blk The character literal reference to generate

        print("Match character ");
        if (atom.not) {
            _print("NOT ");
        }
        _print(atom.atomText);
        if (atom.label != null) {
            _print(", label=" + atom.label);
        }
        _println("");
    
public voidgen(CharRangeElement r)
Generate code for the given grammar element.

param
blk The character-range reference to generate

        print("Match character range: " + r.beginText + ".." + r.endText);
        if (r.label != null) {
            _print(", label = " + r.label);
        }
        _println("");
    
public voidgen(LexerGrammar g)
Generate the lexer TXT file

        setGrammar(g);
        antlrTool.reportProgress("Generating " + grammar.getClassName() + TokenTypesFileExt);
        currentOutput = antlrTool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
        //SAS: changed for proper text file io

        tabs = 0;
        doingLexRules = true;

        // Generate header common to all TXT output files
        genHeader();

        // Output the user-defined lexer premamble
        println("");
        println("*** Lexer Preamble Action.");
        println("This action will appear before the declaration of your lexer class:");
        tabs++;
        println(grammar.preambleAction.getText());
        tabs--;
        println("*** End of Lexer Preamble Action");

        // Generate lexer class definition
        println("");
        println("*** Your lexer class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");

        // Generate user-defined parser class members
        println("");
        println("*** User-defined lexer  class members:");
        println("These are the member declarations that you defined for your class:");
        tabs++;
        printAction(grammar.classMemberAction.getText());
        tabs--;
        println("*** End of user-defined lexer class members");

        // Generate string literals
        println("");
        println("*** String literals used in the parser");
        println("The following string literals were used in the parser.");
        println("An actual code generator would arrange to place these literals");
        println("into a table in the generated lexer, so that actions in the");
        println("generated lexer could match token text against the literals.");
        println("String literals used in the lexer are not listed here, as they");
        println("are incorporated into the mainstream lexer processing.");
        tabs++;
        // Enumerate all of the symbols and look for string literal symbols
        Enumeration ids = grammar.getSymbols();
        while (ids.hasMoreElements()) {
            GrammarSymbol sym = (GrammarSymbol)ids.nextElement();
            // Only processing string literals -- reject other symbol entries
            if (sym instanceof StringLiteralSymbol) {
                StringLiteralSymbol s = (StringLiteralSymbol)sym;
                println(s.getId() + " = " + s.getTokenType());
            }
        }
        tabs--;
        println("*** End of string literals used by the parser");

        // Generate nextToken() rule.
        // nextToken() is a synthetic lexer rule that is the implicit OR of all
        // user-defined lexer rules.
        genNextToken();

        // Generate code for each rule in the lexer
        println("");
        println("*** User-defined Lexer rules:");
        tabs++;

        ids = grammar.rules.elements();
        while (ids.hasMoreElements()) {
            RuleSymbol rs = (RuleSymbol)ids.nextElement();
            if (!rs.id.equals("mnextToken")) {
                genRule(rs);
            }
        }

        tabs--;
        println("");
        println("*** End User-defined Lexer rules:");

        // Close the lexer output file
        currentOutput.close();
        currentOutput = null;
        doingLexRules = false;
    
public voidgen(OneOrMoreBlock blk)
Generate code for the given grammar element.

param
blk The (...)+ block to generate

        println("Start ONE-OR-MORE (...)+ block:");
        tabs++;
        genBlockPreamble(blk);
        boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
        if (!ok) {
            println("Warning: This one-or-more block is non-deterministic");
        }
        genCommonBlock(blk);
        tabs--;
        println("End ONE-OR-MORE block.");
    
protected voidgenAlt(Alternative alt)

        for (
            AlternativeElement elem = alt.head;
            !(elem instanceof BlockEndElement);
            elem = elem.next
            ) {
            elem.generate();
        }
        if (alt.getTreeSpecifier() != null) {
            println("AST will be built as: " + alt.getTreeSpecifier().getText());
        }
    
protected voidgenBlockPreamble(AlternativeBlock blk)
Generate the header for a block, which may be a RuleBlock or a plain AlternativeBLock. This generates any variable declarations, init-actions, and syntactic-predicate-testing variables.

blk
The block for which the preamble is to be generated.

        // dump out init action
        if (blk.initAction != null) {
            printAction("Init action: " + blk.initAction);
        }
    
public voidgenCommonBlock(AlternativeBlock blk)
Generate common code for a block of alternatives; return a postscript that needs to be generated at the end of the block. Other routines may append else-clauses and such for error checking before the postfix is generated.

        boolean singleAlt = (blk.alternatives.size() == 1);

        println("Start of an alternative block.");
        tabs++;
        println("The lookahead set for this block is:");
        tabs++;
        genLookaheadSetForBlock(blk);
        tabs--;

        if (singleAlt) {
            println("This block has a single alternative");
            if (blk.getAlternativeAt(0).synPred != null) {
                // Generate a warning if there is one alt and it has a synPred
                println("Warning: you specified a syntactic predicate for this alternative,");
                println("and it is the only alternative of a block and will be ignored.");
            }
        }
        else {
            println("This block has multiple alternatives:");
            tabs++;
        }

        for (int i = 0; i < blk.alternatives.size(); i++) {
            Alternative alt = blk.getAlternativeAt(i);
            AlternativeElement elem = alt.head;

            // Print lookahead set for alternate
            println("");
            if (i != 0) {
                print("Otherwise, ");
            }
            else {
                print("");
            }
            _println("Alternate(" + (i + 1) + ") will be taken IF:");
            println("The lookahead set: ");
            tabs++;
            genLookaheadSetForAlt(alt);
            tabs--;
            if (alt.semPred != null || alt.synPred != null) {
                print("is matched, AND ");
            }
            else {
                println("is matched.");
            }

            // Dump semantic predicates
            if (alt.semPred != null) {
                _println("the semantic predicate:");
                tabs++;
                println(alt.semPred);
                if (alt.synPred != null) {
                    print("is true, AND ");
                }
                else {
                    println("is true.");
                }
            }

            // Dump syntactic predicate
            if (alt.synPred != null) {
                _println("the syntactic predicate:");
                tabs++;
                genSynPred(alt.synPred);
                tabs--;
                println("is matched.");
            }

            // Dump the alternative
            genAlt(alt);
        }
        println("");
        println("OTHERWISE, a NoViableAlt exception will be thrown");
        println("");

        if (!singleAlt) {
            tabs--;
            println("End of alternatives");
        }
        tabs--;
        println("End of alternative block.");
    
public voidgenFollowSetForRuleBlock(RuleBlock blk)
Generate a textual representation of the follow set for a block.

param
blk The rule block of interest

        Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, blk.endNode);
        printSet(grammar.maxk, 1, follow);
    
protected voidgenHeader()
Generate a header that is common to all TXT files

        println("ANTLR-generated file resulting from grammar " + antlrTool.grammarFile);
        println("Diagnostic output");
        println("");
        println("Terence Parr, MageLang Institute");
        println("with John Lilley, Empathy Software");
        println("ANTLR Version " + antlrTool.version + "; 1996,1997");
        println("");
        println("*** Header Action.");
        println("This action will appear at the top of all generated files.");
        tabs++;
        printAction(behavior.getHeaderAction(""));
        tabs--;
        println("*** End of Header Action");
        println("");
    
protected voidgenLookaheadSetForAlt(Alternative alt)
Generate the lookahead set for an alternate.

        if (doingLexRules && alt.cache[1].containsEpsilon()) {
            println("MATCHES ALL");
            return;
        }
        int depth = alt.lookaheadDepth;
        if (depth == GrammarAnalyzer.NONDETERMINISTIC) {
            // if the decision is nondeterministic, do the best we can: LL(k)
            // any predicates that are around will be generated later.
            depth = grammar.maxk;
        }
        for (int i = 1; i <= depth; i++) {
            Lookahead lookahead = alt.cache[i];
            printSet(depth, i, lookahead);
        }
    
public voidgenLookaheadSetForBlock(AlternativeBlock blk)
Generate a textual representation of the lookahead set for a block.

param
blk The block of interest

        // Find the maximal lookahead depth over all alternatives
        int depth = 0;
        for (int i = 0; i < blk.alternatives.size(); i++) {
            Alternative alt = blk.getAlternativeAt(i);
            if (alt.lookaheadDepth == GrammarAnalyzer.NONDETERMINISTIC) {
                depth = grammar.maxk;
                break;
            }
            else if (depth < alt.lookaheadDepth) {
                depth = alt.lookaheadDepth;
            }
        }

        for (int i = 1; i <= depth; i++) {
            Lookahead lookahead = grammar.theLLkAnalyzer.look(i, blk);
            printSet(depth, i, lookahead);
        }
    
public voidgenNextToken()
Generate the nextToken rule. nextToken is a synthetic lexer rule that is the implicit OR of all user-defined lexer rules.

        println("");
        println("*** Lexer nextToken rule:");
        println("The lexer nextToken rule is synthesized from all of the user-defined");
        println("lexer rules.  It logically consists of one big alternative block with");
        println("each user-defined rule being an alternative.");
        println("");

        // Create the synthesized rule block for nextToken consisting
        // of an alternate block containing all the user-defined lexer rules.
        RuleBlock blk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken");

        // Define the nextToken rule symbol
        RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
        nextTokenRs.setDefined();
        nextTokenRs.setBlock(blk);
        nextTokenRs.access = "private";
        grammar.define(nextTokenRs);

        // Analyze the synthesized block
        if (!grammar.theLLkAnalyzer.deterministic(blk)) {
            println("The grammar analyzer has determined that the synthesized");
            println("nextToken rule is non-deterministic (i.e., it has ambiguities)");
            println("This means that there is some overlap of the character");
            println("lookahead for two or more of your lexer rules.");
        }

        genCommonBlock(blk);

        println("*** End of nextToken lexer rule.");
    
public voidgenRule(RuleSymbol s)
Generate code for a named rule block

param
s The RuleSymbol describing the rule to generate

        println("");
        String ruleType = (doingLexRules ? "Lexer" : "Parser");
        println("*** " + ruleType + " Rule: " + s.getId());
        if (!s.isDefined()) {
            println("This rule is undefined.");
            println("This means that the rule was referenced somewhere in the grammar,");
            println("but a definition for the rule was not encountered.");
            println("It is also possible that syntax errors during the parse of");
            println("your grammar file prevented correct processing of the rule.");
            println("*** End " + ruleType + " Rule: " + s.getId());
            return;
        }
        tabs++;

        if (s.access.length() != 0) {
            println("Access: " + s.access);
        }

        // Get rule return type and arguments
        RuleBlock rblk = s.getBlock();

        // Gen method return value(s)
        if (rblk.returnAction != null) {
            println("Return value(s): " + rblk.returnAction);
            if (doingLexRules) {
                println("Error: you specified return value(s) for a lexical rule.");
                println("\tLexical rules have an implicit return type of 'int'.");
            }
        }
        else {
            if (doingLexRules) {
                println("Return value: lexical rule returns an implicit token type");
            }
            else {
                println("Return value: none");
            }
        }

        // Gen arguments
        if (rblk.argAction != null) {
            println("Arguments: " + rblk.argAction);
        }

        // Dump any init-action
        genBlockPreamble(rblk);

        // Analyze the rule
        boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);
        if (!ok) {
            println("Error: This rule is non-deterministic");
        }

        // Dump the alternates of the rule
        genCommonBlock(rblk);

        // Search for an unlabeled exception specification attached to the rule
        ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");

        // Generate user-defined or default catch phrases
        if (unlabeledUserSpec != null) {
            println("You specified error-handler(s) for this rule:");
            tabs++;
            for (int i = 0; i < unlabeledUserSpec.handlers.size(); i++) {
                if (i != 0) {
                    println("");
                }

                ExceptionHandler handler = (ExceptionHandler)unlabeledUserSpec.handlers.elementAt(i);
                println("Error-handler(" + (i + 1) + ") catches [" + handler.exceptionTypeAndName.getText() + "] and executes:");
                printAction(handler.action.getText());
            }
            tabs--;
            println("End error-handlers.");
        }
        else if (!doingLexRules) {
            println("Default error-handling will be generated, which catches all");
            println("parser exceptions and consumes tokens until the follow-set is seen.");
        }

        // Dump the follow set
        // Doesn't seem to work for lexical rules...
        if (!doingLexRules) {
            println("The follow set for this rule is:");
            tabs++;
            genFollowSetForRuleBlock(rblk);
            tabs--;
        }

        tabs--;
        println("*** End " + ruleType + " Rule: " + s.getId());
    
protected voidgenSynPred(SynPredBlock blk)
Generate the syntactic predicate. This basically generates the alternative block, buts tracks if we are inside a synPred

param
blk The syntactic predicate block

        syntacticPredLevel++;
        gen((AlternativeBlock)blk);
        syntacticPredLevel--;
    
protected voidgenTokenTypes(TokenManager tm)
Generate the token types TXT file

        // Open the token output TXT file and set the currentOutput stream
        antlrTool.reportProgress("Generating " + tm.getName() + TokenTypesFileSuffix + TokenTypesFileExt);
        currentOutput = antlrTool.openOutputFile(tm.getName() + TokenTypesFileSuffix + TokenTypesFileExt);
        //SAS: changed for proper text file io
        tabs = 0;

        // Generate the header common to all diagnostic files
        genHeader();

        // Generate a string for each token.  This creates a static
        // array of Strings indexed by token type.
        println("");
        println("*** Tokens used by the parser");
        println("This is a list of the token numeric values and the corresponding");
        println("token identifiers.  Some tokens are literals, and because of that");
        println("they have no identifiers.  Literals are double-quoted.");
        tabs++;

        // Enumerate all the valid token types
        Vector v = tm.getVocabulary();
        for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
            String s = (String)v.elementAt(i);
            if (s != null) {
                println(s + " = " + i);
            }
        }

        // Close the interface
        tabs--;
        println("*** End of tokens used by the parser");

        // Close the tokens output file
        currentOutput.close();
        currentOutput = null;
    
public java.lang.StringgetASTCreateString(persistence.antlr.collections.impl.Vector v)
Get a string for an expression to generate creation of an AST subtree.

param
v A Vector of String, where each element is an expression in the target language yielding an AST node.

        return "***Create an AST from a vector here***" + System.getProperty("line.separator");
    
public java.lang.StringgetASTCreateString(GrammarAtom atom, java.lang.String str)
Get a string for an expression to generate creating of an AST node

param
str The arguments to the AST constructor

        return "[" + str + "]";
    
public java.lang.StringmapTreeId(java.lang.String id, ActionTransInfo tInfo)
Map an identifier to it's corresponding tree-node variable. This is context-sensitive, depending on the rule and alternative being generated

param
id The identifier name to map
param
forInput true if the input tree node variable is to be returned, otherwise the output variable is returned.

        return id;
    
public voidprintSet(int depth, int k, Lookahead lookahead)
Format a lookahead or follow set.

param
depth The depth of the entire lookahead/follow
param
k The lookahead level to print
param
lookahead The lookahead/follow set to print

        int numCols = 5;

        int[] elems = lookahead.fset.toArray();

        if (depth != 1) {
            print("k==" + k + ": {");
        }
        else {
            print("{ ");
        }
        if (elems.length > numCols) {
            _println("");
            tabs++;
            print("");
        }

        int column = 0;
        for (int i = 0; i < elems.length; i++) {
            column++;
            if (column > numCols) {
                _println("");
                print("");
                column = 0;
            }
            if (doingLexRules) {
                _print(charFormatter.literalChar(elems[i]));
            }
            else {
                _print((String)grammar.tokenManager.getVocabulary().elementAt(elems[i]));
            }
            if (i != elems.length - 1) {
                _print(", ");
            }
        }

        if (elems.length > numCols) {
            _println("");
            tabs--;
            print("");
        }
        _println(" }");
    
protected java.lang.StringprocessActionForSpecialSymbols(java.lang.String actionStr, int line, RuleBlock currentRule, ActionTransInfo tInfo)

        return actionStr;