1 package antlr;
2
3 * <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 * 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
83 protected TokenBuffer input;
84
85 protected int guessing = 0;
86
87 protected int exceptionLevel = 0;
88
89 protected String[] tokenNames;
90
91 protected AST returnAST;
92
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
126 public abstract void consume() throws IOException;
127
128 public void consumeUntil(int tokenType) throws IOException {
129 while (LA(1) != Token.EOF_TYPE && LA(1) != tokenType)
130 {
131 consume();
132 }
133 }
134
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 }
143
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 * 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
163 public abstract Token LT(int i) throws IOException;
164 public int mark() {
166 return input.mark();
167 }
168 * 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 consume();
178 }
179 * 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 consume();
189 }
190 public void matchNot(int t) throws MismatchedTokenException, IOException {
191 if ( LA(1)==t )
192 throw new MismatchedTokenException(tokenNames, LT(1), t, true);
194 else
195 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
231 public void reportError(ParserException ex) {
232 System.err.println("Error: " + ex);
233 }
234
235 public void reportError(String s) {
236 System.err.println("Error: " + s);
237 }
238
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 * 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 * 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
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