001: package antlr.debug;
002:
003: /* ANTLR Translator Generator
004: * Project led by Terence Parr at http://www.cs.usfca.edu
005: * Software rights: http://www.antlr.org/license.html
006: */
007:
008: import antlr.*;
009: import antlr.collections.impl.BitSet;
010:
011: import java.util.Stack;
012:
013: /** Override the standard matching and rule entry/exit routines
014: * to build parse trees. This class is useful for 2.7.3 where
015: * you can specify a superclass like
016: *
017: * class TinyCParser extends Parser(ParseTreeDebugParser);
018: */
019: public class ParseTreeDebugParser extends LLkParser {
020: /** Each new rule invocation must have it's own subtree. Tokens
021: * are added to the current root so we must have a stack of subtree roots.
022: */
023: protected Stack currentParseTreeRoot = new Stack();
024:
025: /** Track most recently created parse subtree so that when parsing
026: * is finished, we can get to the root.
027: */
028: protected ParseTreeRule mostRecentParseTreeRoot = null;
029:
030: /** For every rule replacement with a production, we bump up count. */
031: protected int numberOfDerivationSteps = 1; // n replacements plus step 0
032:
033: public ParseTreeDebugParser(int k_) {
034: super (k_);
035: }
036:
037: public ParseTreeDebugParser(ParserSharedInputState state, int k_) {
038: super (state, k_);
039: }
040:
041: public ParseTreeDebugParser(TokenBuffer tokenBuf, int k_) {
042: super (tokenBuf, k_);
043: }
044:
045: public ParseTreeDebugParser(TokenStream lexer, int k_) {
046: super (lexer, k_);
047: }
048:
049: public ParseTree getParseTree() {
050: return mostRecentParseTreeRoot;
051: }
052:
053: public int getNumberOfDerivationSteps() {
054: return numberOfDerivationSteps;
055: }
056:
057: public void match(int i) throws MismatchedTokenException {
058: addCurrentTokenToParseTree();
059: super .match(i);
060: }
061:
062: public void match(BitSet bitSet) throws MismatchedTokenException {
063: addCurrentTokenToParseTree();
064: super .match(bitSet);
065: }
066:
067: public void matchNot(int i) throws MismatchedTokenException {
068: addCurrentTokenToParseTree();
069: super .matchNot(i);
070: }
071:
072: /** This adds LT(1) to the current parse subtree. Note that the match()
073: * routines add the node before checking for correct match. This means
074: * that, upon mismatched token, there will a token node in the tree
075: * corresponding to where that token was expected. For no viable
076: * alternative errors, no node will be in the tree as nothing was
077: * matched() (the lookahead failed to predict an alternative).
078: */
079: protected void addCurrentTokenToParseTree() {
080: if (inputState.guessing > 0) {
081: return;
082: }
083: ParseTreeRule root = (ParseTreeRule) currentParseTreeRoot
084: .peek();
085: ParseTreeToken tokenNode = null;
086: if (LA(1) == Token.EOF_TYPE) {
087: tokenNode = new ParseTreeToken(new antlr.CommonToken("EOF"));
088: } else {
089: tokenNode = new ParseTreeToken(LT(1));
090: }
091: root.addChild(tokenNode);
092: }
093:
094: /** Create a rule node, add to current tree, and make it current root */
095: public void traceIn(String s) {
096: if (inputState.guessing > 0) {
097: return;
098: }
099: ParseTreeRule subRoot = new ParseTreeRule(s);
100: if (currentParseTreeRoot.size() > 0) {
101: ParseTreeRule oldRoot = (ParseTreeRule) currentParseTreeRoot
102: .peek();
103: oldRoot.addChild(subRoot);
104: }
105: currentParseTreeRoot.push(subRoot);
106: numberOfDerivationSteps++;
107: }
108:
109: /** Pop current root; back to adding to old root */
110: public void traceOut(String s) {
111: if (inputState.guessing > 0) {
112: return;
113: }
114: mostRecentParseTreeRoot = (ParseTreeRule) currentParseTreeRoot
115: .pop();
116: }
117:
118: }
|