1	package antlr;
2	
3	/**
4	 * <b>SOFTWARE RIGHTS</b>
5	 * <p>
6	 * ANTLR 2.5.0 MageLang Institute, 1998
7	 * <p>
8	 * We reserve no legal rights to the ANTLR--it is fully in the
9	 * public domain. An individual or company may do whatever
10	 * they wish with source code distributed with ANTLR or the
11	 * code generated by ANTLR, including the incorporation of
12	 * ANTLR, or its output, into commerical software.
13	 * <p>
14	 * We encourage users to develop software with ANTLR. However,
15	 * we do ask that credit is given to us for developing
16	 * ANTLR. By "credit", we mean that if you use ANTLR or
17	 * incorporate any source code into one of your programs
18	 * (commercial product, research project, or otherwise) that
19	 * you acknowledge this fact somewhere in the documentation,
20	 * research report, etc... If you like ANTLR and have
21	 * developed a nice tool with the output, please mention that
22	 * you developed it using ANTLR. In addition, we ask that the
23	 * headers remain intact in our source code. As long as these
24	 * guidelines are kept, we expect to continue enhancing this
25	 * system and expect to make other tools available as they are
26	 * completed.
27	 * <p>
28	 * The ANTLR gang:
29	 * @version ANTLR 2.5.0 MageLang Institute, 1998
30	 * @author Terence Parr, <a href=http://www.MageLang.com>MageLang Institute</a>
31	 * @author <br>John Lilley, <a href=http://www.Empathy.com>Empathy Software</a>
32	 */
33	import java.util.Hashtable;
34	import java.util.Enumeration;
35	import java.io.IOException;
36	import antlr.collections.impl.BitSet;
37	import antlr.collections.impl.Vector;
38	
39	/**A Grammar holds a set of rules (which are stored
40	 * in a symbol table).  Most of the time a grammar
41	 * needs a code generator and an LLkAnalyzer too.
42	 */
43	public abstract class Grammar {
44		protected Tool tool;
45		protected CodeGenerator generator;
46		protected LLkGrammarAnalyzer theLLkAnalyzer;
47		protected Hashtable symbols;
48		protected boolean buildAST = false;
49		protected boolean analyzerDebug = false;
50		protected boolean interactive = false;
51		protected String superClass = null;
52	
53		// The token manager associated with the grammar, if any.
54		// The token manager is responsible for maintaining the set of valid tokens, and
55		// is conceptually shared between the lexer and parser.  This may be either a
56		// LexerGrammar or a TokdefTokenManager.
57		protected TokenManager tokenManager;
58	
59		// Mapping from String keys to Token option values
60		protected Hashtable options;
61		// Vector of RuleSymbol entries
62		protected Vector rules;
63	
64		protected String preambleAction = null;
65		protected String className = null;
66		protected String classMemberAction = null;
67		protected boolean hasSyntacticPredicate = false;
68		protected boolean hasUserErrorHandling = false;
69	
70		// max lookahead that can be attempted for this parser.
71		protected int maxk=1;
72	
73		// options
74		protected boolean traceRules = false;
75		protected boolean debuggingOutput = false;
76		protected boolean defaultErrorHandler = true;
77	
78		protected String comment = null; // javadoc comment
79	
80		public Grammar(String className_, Tool tool_, String superClass) {
81			className = className_;
82			tool = tool_;
83			symbols = new Hashtable();
84			options = new Hashtable();
85			rules = new Vector(100);
86			this.superClass = superClass;
87		}
88		/** Define a rule */
89		public void define(RuleSymbol rs) {
90			rules.appendElement(rs);
91			// add the symbol to the rules hash table
92			symbols.put(rs.getId(), rs);
93		}
94		/** Top-level call to generate the code for this grammar */
95		public abstract void generate() throws IOException;
96		protected String getClassName() { return className; }
97		/* Does this grammar have a default error handler? */
98		public boolean getDefaultErrorHandler() {
99			return defaultErrorHandler;
100		}
101		/** Get an integer option.  Given the name of the option find its 
102		 * associated integer value.  If the associated value is not an integer or
103		 * is not in the table, then throw an exception of type NumberFormatException.
104		 * @param key The name of the option
105		 * @return The value associated with the key.
106		 */
107		public int getIntegerOption(String key) throws NumberFormatException {
108			Token t = (Token)options.get(key);
109			if (t == null || t.getType() != ANTLRTokenTypes.INT) {
110				throw new NumberFormatException();
111			}
112			else {
113				return Integer.parseInt(t.getText());
114			}
115		}
116		/** Get an option.  Given the name of the option find its associated value.
117		 * @param key The name of the option
118		 * @return The value associated with the key, or null if the key has not been set.
119		 */
120		public Token getOption(String key) {
121			return (Token)options.get(key);
122		}
123		// Get name of class from which generated parser/lexer inherits
124		protected abstract String getSuperClass();
125		public GrammarSymbol getSymbol(String s) {
126			return (GrammarSymbol) symbols.get(s);
127		}
128		public Enumeration getSymbols() {
129			return symbols.elements();
130		}
131		/** Check the existence of an option in the table
132		 * @param key The name of the option
133		 * @return true if the option is in the table
134		 */
135		public boolean hasOption(String key) {
136			return options.containsKey(key);
137		}
138		/** Is a rule symbol defined? (not used for tokens) */
139		public boolean isDefined(String s) {
140			return symbols.containsKey(s);
141		}
142		/**Process command line arguments.  Implemented in subclasses */
143		public abstract void processArguments(String[] args);
144		public void setCodeGenerator(CodeGenerator gen) {
145			generator = gen;
146		}
147		public void setGrammarAnalyzer(LLkGrammarAnalyzer a) {
148			theLLkAnalyzer = a;
149		}
150		/** Set a generic option.
151		 * This associates a generic option key with a Token value.
152		 * No validation is performed by this method, although users of the value
153		 * (code generation and/or analysis) may require certain formats.
154		 * The value is stored as a token so that the location of an error
155		 * can be reported.
156		 * @param key The name of the option.
157		 * @param value The value to associate with the key.
158		 * @return true if the option was a valid generic grammar option, false o/w
159		 */
160		public boolean setOption(String key, Token value) {
161			options.put(key, value);
162			String s = value.getText();
163			int i;
164			if (key.equals("k")) {
165				try {
166					maxk = getIntegerOption("k");
167					//System.out.println("setting lookahead to " + maxk);
168				} catch (NumberFormatException e) {
169					tool.error("option 'k' must be an integer (was "+value.getText()+")", value.getLine());
170				}
171				return true;
172			}
173			if (key.equals("codeGenMakeSwitchThreshold")) {
174				try {
175					i = getIntegerOption("codeGenMakeSwitchThreshold");
176				} catch (NumberFormatException e) {
177					tool.error("option 'codeGenMakeSwitchThreshold' must be an integer", value.getLine());
178				}
179				return true;
180			}
181			if (key.equals("codeGenBitsetTestThreshold")) {
182				try {
183					i = getIntegerOption("codeGenBitsetTestThreshold");
184				} catch (NumberFormatException e) {
185					tool.error("option 'codeGenBitsetTestThreshold' must be an integer", value.getLine());
186				}
187				return true;
188			}
189			if (key.equals("defaultErrorHandler")) {
190				if (s.equals("true")) {
191					defaultErrorHandler = true;
192				} else if (s.equals("false")) {
193					defaultErrorHandler = false;
194				} else {
195					tool.error("Value for defaultErrorHandler must be true or false", value.getLine());
196				}
197				return true;
198			}
199			if (key.equals("analyzerDebug")) {
200				if (s.equals("true")) {
201					analyzerDebug = true;
202				}
203				else if (s.equals("false")) {
204					analyzerDebug = false;
205				}
206				else {
207					tool.error("option 'analyzerDebug' must be true or false", value.getLine());
208				}
209				return true;
210			}
211			if (key.equals("codeGenDebug")) {
212				if (s.equals("true")) {
213					analyzerDebug = true;
214				}
215				else if (s.equals("false")) {
216					analyzerDebug = false;
217				}
218				else {
219					tool.error("option 'codeGenDebug' must be true or false", value.getLine());
220				}
221				return true;
222			}
223			if (key.equals("classHeaderSuffix")) {
224				return true;
225			}
226			return false;
227		}
228		public void setTokenManager(TokenManager tokenManager_) {
229			tokenManager = tokenManager_;
230		}
231	}
232