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.6/antlr/Grammar.java#1 $
*/
import java.util.Hashtable;
import java.util.Enumeration;
import java.io.IOException;
import antlr.collections.impl.BitSet;
import antlr.collections.impl.Vector;
/**A Grammar holds a set of rules (which are stored
* in a symbol table). Most of the time a grammar
* needs a code generator and an LLkAnalyzer too.
*/
public abstract class Grammar {
protected Tool antlrTool;
protected CodeGenerator generator;
protected LLkGrammarAnalyzer theLLkAnalyzer;
protected Hashtable symbols;
protected boolean buildAST = false;
protected boolean analyzerDebug = false;
protected boolean interactive = false;
protected String superClass = null;
/** The token manager associated with the grammar, if any.
// The token manager is responsible for maintaining the set of valid tokens, and
// is conceptually shared between the lexer and parser. This may be either a
// LexerGrammar or a ImportVocabTokenManager.
*/
protected TokenManager tokenManager;
/** The name of the export vocabulary...used to generate the output
* token types interchange file.
*/
protected String exportVocab = null;
/** The name of the import vocabulary. "Initial conditions"
*/
protected String importVocab = null;
// Mapping from String keys to Token option values
protected Hashtable options;
// Vector of RuleSymbol entries
protected Vector rules;
protected Token preambleAction = new CommonToken(Token.INVALID_TYPE, "");
protected String className = null;
protected String fileName = null;
protected Token classMemberAction = new CommonToken(Token.INVALID_TYPE, "");
protected boolean hasSyntacticPredicate = false;
protected boolean hasUserErrorHandling = false;
// max lookahead that can be attempted for this parser.
protected int maxk = 1;
// options
protected boolean traceRules = false;
protected boolean debuggingOutput = false;
protected boolean defaultErrorHandler = true;
protected String comment = null; // javadoc comment
public Grammar(String className_, Tool tool_, String superClass) {
className = className_;
antlrTool = tool_;
symbols = new Hashtable();
options = new Hashtable();
rules = new Vector(100);
this.superClass = superClass;
}
/** Define a rule */
public void define(RuleSymbol rs) {
rules.appendElement(rs);
// add the symbol to the rules hash table
symbols.put(rs.getId(), rs);
}
/** Top-level call to generate the code for this grammar */
public abstract void generate() throws IOException;
protected String getClassName() {
return className;
}
/* Does this grammar have a default error handler? */
public boolean getDefaultErrorHandler() {
return defaultErrorHandler;
}
public String getFilename() {
return fileName;
}
/** Get an integer option. Given the name of the option find its
* associated integer value. If the associated value is not an integer or
* is not in the table, then throw an exception of type NumberFormatException.
* @param key The name of the option
* @return The value associated with the key.
*/
public int getIntegerOption(String key) throws NumberFormatException {
Token t = (Token)options.get(key);
if (t == null || t.getType() != ANTLRTokenTypes.INT) {
throw new NumberFormatException();
}
else {
return Integer.parseInt(t.getText());
}
}
/** Get an option. Given the name of the option find its associated value.
* @param key The name of the option
* @return The value associated with the key, or null if the key has not been set.
*/
public Token getOption(String key) {
return (Token)options.get(key);
}
// Get name of class from which generated parser/lexer inherits
protected abstract String getSuperClass();
public GrammarSymbol getSymbol(String s) {
return (GrammarSymbol)symbols.get(s);
}
public Enumeration getSymbols() {
return symbols.elements();
}
/** Check the existence of an option in the table
* @param key The name of the option
* @return true if the option is in the table
*/
public boolean hasOption(String key) {
return options.containsKey(key);
}
/** Is a rule symbol defined? (not used for tokens) */
public boolean isDefined(String s) {
return symbols.containsKey(s);
}
/**Process command line arguments. Implemented in subclasses */
public abstract void processArguments(String[] args);
public void setCodeGenerator(CodeGenerator gen) {
generator = gen;
}
public void setFilename(String s) {
fileName = s;
}
public void setGrammarAnalyzer(LLkGrammarAnalyzer a) {
theLLkAnalyzer = a;
}
/** Set a generic option.
* This associates a generic option key with a Token value.
* No validation is performed by this method, although users of the value
* (code generation and/or analysis) may require certain formats.
* The value is stored as a token so that the location of an error
* can be reported.
* @param key The name of the option.
* @param value The value to associate with the key.
* @return true if the option was a valid generic grammar option, false o/w
*/
public boolean setOption(String key, Token value) {
options.put(key, value);
String s = value.getText();
int i;
if (key.equals("k")) {
try {
maxk = getIntegerOption("k");
if ( maxk<=0 ) {
antlrTool.error("option 'k' must be greater than 0 (was " +
value.getText() + ")",
getFilename(),
value.getLine(),
value.getColumn());
maxk = 1;
}
}
catch (NumberFormatException e) {
antlrTool.error("option 'k' must be an integer (was " + value.getText() + ")", getFilename(), value.getLine(), value.getColumn());
}
return true;
}
if (key.equals("codeGenMakeSwitchThreshold")) {
try {
i = getIntegerOption("codeGenMakeSwitchThreshold");
}
catch (NumberFormatException e) {
antlrTool.error("option 'codeGenMakeSwitchThreshold' must be an integer", getFilename(), value.getLine(), value.getColumn());
}
return true;
}
if (key.equals("codeGenBitsetTestThreshold")) {
try {
i = getIntegerOption("codeGenBitsetTestThreshold");
}
catch (NumberFormatException e) {
antlrTool.error("option 'codeGenBitsetTestThreshold' must be an integer", getFilename(), value.getLine(), value.getColumn());
}
return true;
}
if (key.equals("defaultErrorHandler")) {
if (s.equals("true")) {
defaultErrorHandler = true;
}
else if (s.equals("false")) {
defaultErrorHandler = false;
}
else {
antlrTool.error("Value for defaultErrorHandler must be true or false", getFilename(), value.getLine(), value.getColumn());
}
return true;
}
if (key.equals("analyzerDebug")) {
if (s.equals("true")) {
analyzerDebug = true;
}
else if (s.equals("false")) {
analyzerDebug = false;
}
else {
antlrTool.error("option 'analyzerDebug' must be true or false", getFilename(), value.getLine(), value.getColumn());
}
return true;
}
if (key.equals("codeGenDebug")) {
if (s.equals("true")) {
analyzerDebug = true;
}
else if (s.equals("false")) {
analyzerDebug = false;
}
else {
antlrTool.error("option 'codeGenDebug' must be true or false", getFilename(), value.getLine(), value.getColumn());
}
return true;
}
if (key.equals("classHeaderSuffix")) {
return true;
}
if (key.equals("classHeaderPrefix")) {
return true;
}
if (key.equals("namespaceAntlr")) {
return true;
}
if (key.equals("namespaceStd")) {
return true;
}
if (key.equals("genHashLines")) {
return true;
}
if (key.equals("noConstructors")) {
return true;
}
return false;
}
public void setTokenManager(TokenManager tokenManager_) {
tokenManager = tokenManager_;
}
/** Print out the grammar without actions */
public String toString() {
StringBuffer buf = new StringBuffer(20000);
Enumeration ids = rules.elements();
while (ids.hasMoreElements()) {
RuleSymbol rs = (RuleSymbol)ids.nextElement();
if (!rs.id.equals("mnextToken")) {
buf.append(rs.getBlock().toString());
buf.append("\n\n");
}
}
return buf.toString();
}
}