package antlr.debug; /* ANTLR Translator Generator * Project led by Terence Parr at http://www.cs.usfca.edu * Software rights: http://www.antlr.org/license.html */ import antlr.*; import antlr.collections.impl.BitSet; import java.util.Stack; /** Override the standard matching and rule entry/exit routines * to build parse trees. This class is useful for 2.7.3 where * you can specify a superclass like * * class TinyCParser extends Parser(ParseTreeDebugParser); */ public class ParseTreeDebugParser extends LLkParser { /** Each new rule invocation must have it's own subtree. Tokens * are added to the current root so we must have a stack of subtree roots. */ protected Stack currentParseTreeRoot = new Stack(); /** Track most recently created parse subtree so that when parsing * is finished, we can get to the root. */ protected ParseTreeRule mostRecentParseTreeRoot = null; /** For every rule replacement with a production, we bump up count. */ protected int numberOfDerivationSteps = 1; // n replacements plus step 0 public ParseTreeDebugParser(int k_) { super(k_); } public ParseTreeDebugParser(ParserSharedInputState state, int k_) { super(state,k_); } public ParseTreeDebugParser(TokenBuffer tokenBuf, int k_) { super(tokenBuf, k_); } public ParseTreeDebugParser(TokenStream lexer, int k_) { super(lexer,k_); } public ParseTree getParseTree() { return mostRecentParseTreeRoot; } public int getNumberOfDerivationSteps() { return numberOfDerivationSteps; } public void match(int i) throws MismatchedTokenException, TokenStreamException { addCurrentTokenToParseTree(); super.match(i); } public void match(BitSet bitSet) throws MismatchedTokenException, TokenStreamException { addCurrentTokenToParseTree(); super.match(bitSet); } public void matchNot(int i) throws MismatchedTokenException, TokenStreamException { addCurrentTokenToParseTree(); super.matchNot(i); } /** This adds LT(1) to the current parse subtree. Note that the match() * routines add the node before checking for correct match. This means * that, upon mismatched token, there will a token node in the tree * corresponding to where that token was expected. For no viable * alternative errors, no node will be in the tree as nothing was * matched() (the lookahead failed to predict an alternative). */ protected void addCurrentTokenToParseTree() throws TokenStreamException { if (inputState.guessing>0) { return; } ParseTreeRule root = (ParseTreeRule)currentParseTreeRoot.peek(); ParseTreeToken tokenNode = null; if ( LA(1)==Token.EOF_TYPE ) { tokenNode = new ParseTreeToken(new antlr.CommonToken("EOF")); } else { tokenNode = new ParseTreeToken(LT(1)); } root.addChild(tokenNode); } /** Create a rule node, add to current tree, and make it current root */ public void traceIn(String s) throws TokenStreamException { if (inputState.guessing>0) { return; } ParseTreeRule subRoot = new ParseTreeRule(s); if ( currentParseTreeRoot.size()>0 ) { ParseTreeRule oldRoot = (ParseTreeRule)currentParseTreeRoot.peek(); oldRoot.addChild(subRoot); } currentParseTreeRoot.push(subRoot); numberOfDerivationSteps++; } /** Pop current root; back to adding to old root */ public void traceOut(String s) throws TokenStreamException { if (inputState.guessing>0) { return; } mostRecentParseTreeRoot = (ParseTreeRule)currentParseTreeRoot.pop(); } }