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 antlr.collections.impl.BitSet;
34	import antlr.collections.AST;
35	import antlr.collections.impl.ASTArray;
36	
37	/**A generic ANTLR parser (LL(k) for k>=1) containing a bunch of
38	 * utility routines useful at any lookahead depth.  We distinguish between
39	 * the LL(1) and LL(k) parsers because of efficiency.  This may not be
40	 * necessary in the near future.
41	 *
42	 * Each parser object contains the state of the parse including a lookahead
43	 * cache (the form of which is determined by the subclass), whether or
44	 * not the parser is in guess mode, where tokens come from, etc...
45	 *
46	 * <p>
47	 * During <b>guess</b> mode, the current lookahead token(s) and token type(s)
48	 * cache must be saved because the token stream may not have been informed
49	 * to save the token (via <tt>mark</tt>) before the <tt>try</tt> block.
50	 * Guessing is started by:
51	 * <ol>
52	 * <li>saving the lookahead cache.
53	 * <li>marking the current position in the TokenBuffer.
54	 * <li>increasing the guessing level.
55	 * </ol>
56	 *
57	 * After guessing, the parser state is restored by:
58	 * <ol>
59	 * <li>restoring the lookahead cache.
60	 * <li>rewinding the TokenBuffer.
61	 * <li>decreasing the guessing level.
62	 * </ol>
63	 *
64	 * @see antlr.Token
65	 * @see antlr.TokenBuffer
66	 * @see antlr.Tokenizer
67	 * @see antlr.LL1Parser
68	 * @see antlr.LLkParser
69	 */
70	
71	import java.io.IOException;
72	
73	import antlr.debug.MessageListener;
74	import antlr.debug.ParserListener;
75	import antlr.debug.ParserMatchListener;
76	import antlr.debug.ParserTokenListener;
77	import antlr.debug.SemanticPredicateListener;
78	import antlr.debug.SyntacticPredicateListener;
79	import antlr.debug.TraceListener;
80	
81	public abstract class Parser {
82		/** Where to get token objects */
83		protected TokenBuffer input;
84		/** Are we guessing (guessing>0)? */
85		protected int guessing = 0;
86		/** Nesting level of registered handlers */
87		protected int exceptionLevel = 0;
88		/** Table of token type to token names */
89		protected String[] tokenNames;
90		/** AST return value for a rule is squirreled away here */
91		protected AST returnAST;
92		/** AST support code; parser and treeparser delegate to this object */
93		protected ASTFactory astFactory = new ASTFactory();
94	
95		private boolean ignoreInvalidDebugCalls = false;
96	
97		public void addMessageListener(MessageListener l) {
98			if (!ignoreInvalidDebugCalls)
99				throw new IllegalArgumentException("addMessageListener() is only valid if parser built for debugging");
100		}
101		public void addParserListener(ParserListener l) {
102			if (!ignoreInvalidDebugCalls)
103				throw new IllegalArgumentException("addParserListener() is only valid if parser built for debugging");
104		}
105		public void addParserMatchListener(ParserMatchListener l) {
106			if (!ignoreInvalidDebugCalls)
107				throw new IllegalArgumentException("addParserMatchListener() is only valid if parser built for debugging");
108		}
109		public void addParserTokenListener(ParserTokenListener l) {
110			if (!ignoreInvalidDebugCalls)
111				throw new IllegalArgumentException("addParserTokenListener() is only valid if parser built for debugging");
112		}
113		public void addSemanticPredicateListener(SemanticPredicateListener l) {
114			if (!ignoreInvalidDebugCalls)
115				throw new IllegalArgumentException("addSemanticPredicateListener() is only valid if parser built for debugging");
116		}
117		public void addSyntacticPredicateListener(SyntacticPredicateListener l) {
118			if (!ignoreInvalidDebugCalls)
119				throw new IllegalArgumentException("addSyntacticPredicateListener() is only valid if parser built for debugging");
120		}
121		public void addTraceListener(TraceListener l) {
122			if (!ignoreInvalidDebugCalls)
123				throw new IllegalArgumentException("addTraceListener() is only valid if parser built for debugging");
124		}
125		/**Get another token object from the token stream */
126		public abstract void consume() throws IOException;
127		/** Consume tokens until one matches the given token */
128		public void consumeUntil(int tokenType) throws IOException {
129			while (LA(1) != Token.EOF_TYPE && LA(1) != tokenType)
130			{
131				consume();
132			}
133		}
134		/** Consume tokens until one matches the given token set */
135		public void consumeUntil(BitSet set) throws IOException {
136			while (LA(1) != Token.EOF_TYPE && !set.member(LA(1))) {
137				consume();
138			}
139		}
140		protected void defaultDebuggingSetup(Tokenizer lexer, TokenBuffer tokBuf) {
141			// by default, do nothing -- we're not debugging
142		}
143		/** Get the AST return value squirreled away in the parser */
144		public AST getAST() {
145			return returnAST;
146		}
147		public ASTFactory getASTFactory() {
148			return astFactory;
149		}
150		public String getTokenName(int num) {
151			return tokenNames[num];
152		}
153		public String[] getTokenNames() {
154			return tokenNames;
155		}
156		public boolean isDebugMode() {return false;}
157		/** Return the token type of the ith token of lookahead where i=1
158		 * is the current token being examined by the parser (i.e., it
159		 * has not been matched yet).
160		 */
161		public abstract int LA(int i) throws IOException;
162		/**Return the ith token of lookahead */
163		public abstract Token LT(int i) throws IOException;
164		// Forwarded to TokenBuffer
165		public int mark() {
166			return input.mark();
167		}
168		/**Make sure current lookahead symbol matches token type <tt>t</tt>.
169		 * Throw an exception upon mismatch, which is catch by either the
170		 * error handler or by the syntactic predicate.
171		 */
172		public void match(int t) throws MismatchedTokenException, IOException {
173			if ( LA(1)!=t )
174				throw new MismatchedTokenException(tokenNames, LT(1), t, false);
175			else
176				// mark token as consumed -- fetch next token deferred until LA/LT
177				consume();
178		}
179		/**Make sure current lookahead symbol matches the given set
180		 * Throw an exception upon mismatch, which is catch by either the
181		 * error handler or by the syntactic predicate.
182		 */
183		public void match(BitSet b) throws MismatchedTokenException, IOException {
184			if ( !b.member(LA(1)) )
185				throw new MismatchedTokenException(tokenNames, LT(1), b, false);
186			else
187				// mark token as consumed -- fetch next token deferred until LA/LT
188				consume();
189		}
190		public void matchNot(int t) throws MismatchedTokenException, IOException {
191			if ( LA(1)==t )
192				// Throws inverted-sense exception
193				throw new MismatchedTokenException(tokenNames, LT(1), t, true);
194			else
195				// mark token as consumed -- fetch next token deferred until LA/LT
196				consume();
197		}
198		public static void panic() {
199			System.err.println("Parser: panic");
200			System.exit(1);
201		}
202		public void removeMessageListener(MessageListener l) {
203			if (!ignoreInvalidDebugCalls)
204				throw new RuntimeException("removeMessageListener() is only valid if parser built for debugging");
205		}
206		public void removeParserListener(ParserListener l) {
207			if (!ignoreInvalidDebugCalls)
208				throw new RuntimeException("removeParserListener() is only valid if parser built for debugging");
209		}
210		public void removeParserMatchListener(ParserMatchListener l) {
211			if (!ignoreInvalidDebugCalls)
212				throw new RuntimeException("removeParserMatchListener() is only valid if parser built for debugging");
213		}
214		public void removeParserTokenListener(ParserTokenListener l) {
215			if (!ignoreInvalidDebugCalls)
216				throw new RuntimeException("removeParserTokenListener() is only valid if parser built for debugging");
217		}
218		public void removeSemanticPredicateListener(SemanticPredicateListener l) {	
219			if (!ignoreInvalidDebugCalls)
220				throw new IllegalArgumentException("removeSemanticPredicateListener() is only valid if parser built for debugging");
221		}
222		public void removeSyntacticPredicateListener(SyntacticPredicateListener l) {
223			if (!ignoreInvalidDebugCalls)
224				throw new IllegalArgumentException("removeSyntacticPredicateListener() is only valid if parser built for debugging");
225		}
226		public void removeTraceListener(TraceListener l) {
227			if (!ignoreInvalidDebugCalls)
228				throw new RuntimeException("removeTraceListener() is only valid if parser built for debugging");
229		}
230		/** Parser error-reporting function can be overridden in subclass */
231		public void reportError(ParserException ex) {
232			System.err.println("Error: " + ex);
233		}
234		/** Parser error-reporting function can be overridden in subclass */
235		public void reportError(String s) {
236			System.err.println("Error: " + s);
237		}
238		/** Parser warning-reporting function can be overridden in subclass */
239		public void reportWarning(String s) {
240			System.err.println("Warning: " + s);
241		}
242		public void rewind(int pos) {
243			input.rewind(pos);
244		}
245		/** Specify an object with support code (shared by
246		 *  Parser and TreeParser.  Normally, the programmer
247		 *  does not play with this, using setASTNodeType instead.
248		 */
249		public void setASTFactory(ASTFactory f) {
250			astFactory = f;
251		}
252	public void setASTNodeClass(String cl) {
253		astFactory.setASTNodeType(cl);
254	}
255	/** Specify the type of node to create during tree building; use setASTNodeClass now
256	 *  to be consistent with Token Object Type accessor.
257	 */
258	public void setASTNodeType (String nodeType) {
259		setASTNodeClass(nodeType);
260	}
261		public void setDebugMode(boolean debugMode) {
262			if (!ignoreInvalidDebugCalls)
263				throw new RuntimeException("setDebugMode() only valid if parser built for debugging");
264		}
265		public void setIgnoreInvalidDebugCalls(boolean value) {
266			ignoreInvalidDebugCalls = value;
267		}
268		/** Set or change the input token buffer */
269		public void setTokenBuffer(TokenBuffer t) { input = t; }
270		public void setTokenObjectClass(String cl) {
271		}
272		public void traceIn(String rname) throws IOException {
273			System.out.println("enter "+rname+"; LA(1)=="+LT(1).getText()+
274				((guessing>0)?" [guessing]":""));
275		}
276		public void traceOut(String rname) throws IOException {
277			System.out.println("exit "+rname+"; LA(1)=="+LT(1).getText()+
278				((guessing>0)?" [guessing]":""));
279		}
280	}
281