📄 parser.java
字号:
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: Parser.java,v 1.2 2005/12/24 21:50:49 robilad Exp $ */import antlr.collections.impl.BitSet;import antlr.collections.AST;import antlr.collections.impl.ASTArray;/**A generic ANTLR parser (LL(k) for k>=1) containing a bunch of * utility routines useful at any lookahead depth. We distinguish between * the LL(1) and LL(k) parsers because of efficiency. This may not be * necessary in the near future. * * Each parser object contains the state of the parse including a lookahead * cache (the form of which is determined by the subclass), whether or * not the parser is in guess mode, where tokens come from, etc... * * <p> * During <b>guess</b> mode, the current lookahead token(s) and token type(s) * cache must be saved because the token stream may not have been informed * to save the token (via <tt>mark</tt>) before the <tt>try</tt> block. * Guessing is started by: * <ol> * <li>saving the lookahead cache. * <li>marking the current position in the TokenBuffer. * <li>increasing the guessing level. * </ol> * * After guessing, the parser state is restored by: * <ol> * <li>restoring the lookahead cache. * <li>rewinding the TokenBuffer. * <li>decreasing the guessing level. * </ol> * * @see antlr.Token * @see antlr.TokenBuffer * @see antlr.LLkParser */import java.io.IOException;import java.util.Hashtable;import antlr.debug.MessageListener;import antlr.debug.ParserListener;import antlr.debug.ParserMatchListener;import antlr.debug.ParserTokenListener;import antlr.debug.SemanticPredicateListener;import antlr.debug.SyntacticPredicateListener;import antlr.debug.TraceListener;public abstract class Parser { protected ParserSharedInputState inputState; /** Nesting level of registered handlers */ // protected int exceptionLevel = 0; /** Table of token type to token names */ protected String[] tokenNames; /** AST return value for a rule is squirreled away here */ protected AST returnAST; /** AST support code; parser delegates to this object. * This is set during parser construction by default * to either "new ASTFactory()" or a ctor that * has a token type to class map for hetero nodes. */ protected ASTFactory astFactory = null; /** Constructed if any AST types specified in tokens{..}. * Maps an Integer->Class object. */ protected Hashtable tokenTypeToASTClassMap = null; private boolean ignoreInvalidDebugCalls = false; /** Used to keep track of indentdepth for traceIn/Out */ protected int traceDepth = 0; public Parser() { this(new ParserSharedInputState()); } public Parser(ParserSharedInputState state) { inputState = state; } /** If the user specifies a tokens{} section with heterogeneous * AST node types, then ANTLR generates code to fill * this mapping. */ public Hashtable getTokenTypeToASTClassMap() { return tokenTypeToASTClassMap; } public void addMessageListener(MessageListener l) { if (!ignoreInvalidDebugCalls) throw new IllegalArgumentException("addMessageListener() is only valid if parser built for debugging"); } public void addParserListener(ParserListener l) { if (!ignoreInvalidDebugCalls) throw new IllegalArgumentException("addParserListener() is only valid if parser built for debugging"); } public void addParserMatchListener(ParserMatchListener l) { if (!ignoreInvalidDebugCalls) throw new IllegalArgumentException("addParserMatchListener() is only valid if parser built for debugging"); } public void addParserTokenListener(ParserTokenListener l) { if (!ignoreInvalidDebugCalls) throw new IllegalArgumentException("addParserTokenListener() is only valid if parser built for debugging"); } public void addSemanticPredicateListener(SemanticPredicateListener l) { if (!ignoreInvalidDebugCalls) throw new IllegalArgumentException("addSemanticPredicateListener() is only valid if parser built for debugging"); } public void addSyntacticPredicateListener(SyntacticPredicateListener l) { if (!ignoreInvalidDebugCalls) throw new IllegalArgumentException("addSyntacticPredicateListener() is only valid if parser built for debugging"); } public void addTraceListener(TraceListener l) { if (!ignoreInvalidDebugCalls) throw new IllegalArgumentException("addTraceListener() is only valid if parser built for debugging"); } /**Get another token object from the token stream */ public abstract void consume() throws TokenStreamException; /** Consume tokens until one matches the given token */ public void consumeUntil(int tokenType) throws TokenStreamException { while (LA(1) != Token.EOF_TYPE && LA(1) != tokenType) { consume(); } } /** Consume tokens until one matches the given token set */ public void consumeUntil(BitSet set) throws TokenStreamException { while (LA(1) != Token.EOF_TYPE && !set.member(LA(1))) { consume(); } } protected void defaultDebuggingSetup(TokenStream lexer, TokenBuffer tokBuf) { // by default, do nothing -- we're not debugging } /** Get the AST return value squirreled away in the parser */ public AST getAST() { return returnAST; } public ASTFactory getASTFactory() { return astFactory; } public String getFilename() { return inputState.filename; } public ParserSharedInputState getInputState() { return inputState; } public void setInputState(ParserSharedInputState state) { inputState = state; } public String getTokenName(int num) { return tokenNames[num]; } public String[] getTokenNames() { return tokenNames; } public boolean isDebugMode() { return false; } /** Return the token type of the ith token of lookahead where i=1 * is the current token being examined by the parser (i.e., it * has not been matched yet). */ public abstract int LA(int i) throws TokenStreamException; /**Return the ith token of lookahead */ public abstract Token LT(int i) throws TokenStreamException; // Forwarded to TokenBuffer public int mark() { return inputState.input.mark(); } /**Make sure current lookahead symbol matches token type <tt>t</tt>. * Throw an exception upon mismatch, which is catch by either the * error handler or by the syntactic predicate. */ public void match(int t) throws MismatchedTokenException, TokenStreamException { if (LA(1) != t) throw new MismatchedTokenException(tokenNames, LT(1), t, false, getFilename()); else // mark token as consumed -- fetch next token deferred until LA/LT consume(); } /**Make sure current lookahead symbol matches the given set * Throw an exception upon mismatch, which is catch by either the * error handler or by the syntactic predicate. */ public void match(BitSet b) throws MismatchedTokenException, TokenStreamException { if (!b.member(LA(1))) throw new MismatchedTokenException(tokenNames, LT(1), b, false, getFilename()); else // mark token as consumed -- fetch next token deferred until LA/LT consume(); } public void matchNot(int t) throws MismatchedTokenException, TokenStreamException { if (LA(1) == t) // Throws inverted-sense exception throw new MismatchedTokenException(tokenNames, LT(1), t, true, getFilename()); else // mark token as consumed -- fetch next token deferred until LA/LT consume(); } /** @deprecated as of 2.7.2. This method calls System.exit() and writes * directly to stderr, which is usually not appropriate when * a parser is embedded into a larger application. Since the method is * <code>static</code>, it cannot be overridden to avoid these problems. * ANTLR no longer uses this method internally or in generated code. */ public static void panic() { System.err.println("Parser: panic"); System.exit(1); } public void removeMessageListener(MessageListener l) { if (!ignoreInvalidDebugCalls) throw new RuntimeException("removeMessageListener() is only valid if parser built for debugging"); } public void removeParserListener(ParserListener l) { if (!ignoreInvalidDebugCalls) throw new RuntimeException("removeParserListener() is only valid if parser built for debugging"); } public void removeParserMatchListener(ParserMatchListener l) { if (!ignoreInvalidDebugCalls) throw new RuntimeException("removeParserMatchListener() is only valid if parser built for debugging"); } public void removeParserTokenListener(ParserTokenListener l) { if (!ignoreInvalidDebugCalls) throw new RuntimeException("removeParserTokenListener() is only valid if parser built for debugging"); } public void removeSemanticPredicateListener(SemanticPredicateListener l) { if (!ignoreInvalidDebugCalls) throw new IllegalArgumentException("removeSemanticPredicateListener() is only valid if parser built for debugging"); } public void removeSyntacticPredicateListener(SyntacticPredicateListener l) { if (!ignoreInvalidDebugCalls) throw new IllegalArgumentException("removeSyntacticPredicateListener() is only valid if parser built for debugging"); } public void removeTraceListener(TraceListener l) { if (!ignoreInvalidDebugCalls) throw new RuntimeException("removeTraceListener() is only valid if parser built for debugging"); } /** Parser error-reporting function can be overridden in subclass */ public void reportError(RecognitionException ex) { System.err.println(ex); } /** Parser error-reporting function can be overridden in subclass */ public void reportError(String s) { if (getFilename() == null) { System.err.println("error: " + s); } else { System.err.println(getFilename() + ": error: " + s); } } /** Parser warning-reporting function can be overridden in subclass */ public void reportWarning(String s) { if (getFilename() == null) { System.err.println("warning: " + s); } else { System.err.println(getFilename() + ": warning: " + s); } } public void recover(RecognitionException ex, BitSet tokenSet) throws TokenStreamException { consume(); consumeUntil(tokenSet); } public void rewind(int pos) { inputState.input.rewind(pos); } /** Specify an object with support code (shared by * Parser and TreeParser. Normally, the programmer * does not play with this, using setASTNodeType instead. */ public void setASTFactory(ASTFactory f) { astFactory = f; } public void setASTNodeClass(String cl) { astFactory.setASTNodeType(cl); } /** Specify the type of node to create during tree building; use setASTNodeClass now * to be consistent with Token Object Type accessor. * @deprecated since 2.7.1 */ public void setASTNodeType(String nodeType) { setASTNodeClass(nodeType); } public void setDebugMode(boolean debugMode) { if (!ignoreInvalidDebugCalls) throw new RuntimeException("setDebugMode() only valid if parser built for debugging"); } public void setFilename(String f) { inputState.filename = f; } public void setIgnoreInvalidDebugCalls(boolean value) { ignoreInvalidDebugCalls = value; } /** Set or change the input token buffer */ public void setTokenBuffer(TokenBuffer t) { inputState.input = t; } public void traceIndent() { for (int i = 0; i < traceDepth; i++) System.out.print(" "); } public void traceIn(String rname) throws TokenStreamException { traceDepth += 1; traceIndent(); System.out.println("> " + rname + "; LA(1)==" + LT(1).getText() + ((inputState.guessing > 0)?" [guessing]":"")); } public void traceOut(String rname) throws TokenStreamException { traceIndent(); System.out.println("< " + rname + "; LA(1)==" + LT(1).getText() + ((inputState.guessing > 0)?" [guessing]":"")); traceDepth -= 1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -