package antlr;
/* ANTLR Translator Generator
* Project led by Terence Parr at http://www.cs.usfca.edu
* Software rights: http://www.antlr.org/license.html
*
* $Id: //depot/code/org.antlr/release/antlr-2.7.7/antlr/DiagnosticCodeGenerator.java#2 $
*/
import java.util.
Enumeration;
import antlr.collections.impl.
BitSet;
import antlr.collections.impl.
Vector;
import java.io.
PrintWriter; //SAS: changed for proper text file io
import java.io.
IOException;
import java.io.
FileWriter;
/**Generate MyParser.txt, MyLexer.txt and MyParserTokenTypes.txt */
public class
DiagnosticCodeGenerator extends
CodeGenerator {
/** non-zero if inside syntactic predicate generation */
protected int
syntacticPredLevel = 0;
/** true during lexer generation, false during parser generation */
protected boolean
doingLexRules = false;
/** Create a Diagnostic code-generator using the given Grammar
* The caller must still call setTool, setBehavior, and setAnalyzer
* before generating code.
*/
public
DiagnosticCodeGenerator() {
super();
charFormatter = new
JavaCharFormatter();
}
/**Generate the parser, lexer, and token types documentation */
public void
gen() {
// 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);
}
}
/** Generate code for the given grammar element.
* @param blk The {...} action to generate
*/
public void
gen(
ActionElement action) {
if (
action.
isSemPred) {
// handled elsewhere
}
else {
print("ACTION: ");
_printAction(
action.
actionText);
}
}
/** Generate code for the given grammar element.
* @param blk The "x|y|z|..." block to generate
*/
public void
gen(
AlternativeBlock blk) {
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--;
}
/** 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.
*/
public void
gen(
BlockEndElement end) {
// no-op
}
/** Generate code for the given grammar element.
* @param blk The character literal reference to generate
*/
public void
gen(
CharLiteralElement atom) {
print("Match character ");
if (
atom.
not) {
_print("NOT ");
}
_print(
atom.
atomText);
if (
atom.
label != null) {
_print(", label=" +
atom.
label);
}
_println("");
}
/** Generate code for the given grammar element.
* @param blk The character-range reference to generate
*/
public void
gen(
CharRangeElement r) {
print("Match character range: " +
r.
beginText + ".." +
r.
endText);
if (
r.
label != null) {
_print(", label = " +
r.
label);
}
_println("");
}
/** Generate the lexer TXT file */
public void
gen(
LexerGrammar g) throws
IOException {
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;
}
/** Generate code for the given grammar element.
* @param blk The (...)+ block to generate
*/
public void
gen(
OneOrMoreBlock blk) {
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.");
}
/** Generate the parser TXT file */
public void
gen(
ParserGrammar g) throws
IOException {
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;
}
/** Generate code for the given grammar element.
* @param blk The rule-reference to generate
*/
public void
gen(
RuleRefElement rr) {
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.");
}
}
/** Generate code for the given grammar element.
* @param blk The string-literal reference to generate
*/
public void
gen(
StringLiteralElement atom) {
print("Match string literal ");
_print(
atom.
atomText);
if (
atom.
label != null) {
_print(", label=" +
atom.
label);
}
_println("");
}
/** Generate code for the given grammar element.
* @param blk The token-range reference to generate
*/
public void
gen(
TokenRangeElement r) {
print("Match token range: " +
r.
beginText + ".." +
r.
endText);
if (
r.
label != null) {
_print(", label = " +
r.
label);
}
_println("");
}
/** Generate code for the given grammar element.
* @param blk The token-reference to generate
*/
public void
gen(
TokenRefElement atom) {
print("Match token ");
if (
atom.
not) {
_print("NOT ");
}
_print(
atom.
atomText);
if (
atom.
label != null) {
_print(", label=" +
atom.
label);
}
_println("");
}
public void
gen(
TreeElement t) {
print("Tree reference: " +
t);
}
/** Generate the tree-walker TXT file */
public void
gen(
TreeWalkerGrammar g) throws
IOException {
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;
}
/** Generate a wildcard element */
public void
gen(
WildcardElement wc) {
print("Match wildcard");
if (
wc.
getLabel() != null) {
_print(", label = " +
wc.
getLabel());
}
_println("");
}
/** Generate code for the given grammar element.
* @param blk The (...)* block to generate
*/
public void
gen(
ZeroOrMoreBlock blk) {
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.");
}
protected void
genAlt(
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());
}
}
/** 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.
*/
protected void
genBlockPreamble(
AlternativeBlock blk) {
// dump out init action
if (
blk.
initAction != null) {
printAction("Init action: " +
blk.
initAction);
}
}
/**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.
*/
public void
genCommonBlock(
AlternativeBlock blk) {
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.");
}
/** Generate a textual representation of the follow set
* for a block.
* @param blk The rule block of interest
*/
public void
genFollowSetForRuleBlock(
RuleBlock blk) {
Lookahead follow =
grammar.
theLLkAnalyzer.
FOLLOW(1,
blk.
endNode);
printSet(
grammar.
maxk, 1,
follow);
}
/** Generate a header that is common to all TXT files */
protected void
genHeader() {
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 + "; 1989-2005");
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("");
}
/**Generate the lookahead set for an alternate. */
protected void
genLookaheadSetForAlt(
Alternative alt) {
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);
}
}
/** Generate a textual representation of the lookahead set
* for a block.
* @param blk The block of interest
*/
public void
genLookaheadSetForBlock(
AlternativeBlock blk) {
// 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);
}
}
/** Generate the nextToken rule.
* nextToken is a synthetic lexer rule that is the implicit OR of all
* user-defined lexer rules.
*/
public void
genNextToken() {
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.");
}
/** Generate code for a named rule block
* @param s The RuleSymbol describing the rule to generate
*/
public void
genRule(
RuleSymbol s) {
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());
}
/** Generate the syntactic predicate. This basically generates
* the alternative block, buts tracks if we are inside a synPred
* @param blk The syntactic predicate block
*/
protected void
genSynPred(
SynPredBlock blk) {
syntacticPredLevel++;
gen((
AlternativeBlock)
blk);
syntacticPredLevel--;
}
/** Generate the token types TXT file */
protected void
genTokenTypes(
TokenManager tm) throws
IOException {
// 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;
}
/** 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.
*/
public
String getASTCreateString(
Vector v) {
return "***Create an AST from a vector here***" +
System.
getProperty("line.separator");
}
/** Get a string for an expression to generate creating of an AST node
* @param str The arguments to the AST constructor
*/
public
String getASTCreateString(
GrammarAtom atom,
String str) {
return "[" +
str + "]";
}
/// unused.
protected
String processActionForSpecialSymbols(
String actionStr,
int
line,
RuleBlock currentRule,
ActionTransInfo tInfo) {
return
actionStr;
}
/** 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.
*/
public
String mapTreeId(
String id,
ActionTransInfo tInfo) {
return
id;
}
/** 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
*/
public void
printSet(int
depth, int
k,
Lookahead lookahead) {
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(" }");
}
}