001: /*
002: [The "BSD licence"]
003: Copyright (c) 2005-2007 Terence Parr
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in the
013: documentation and/or other materials provided with the distribution.
014: 3. The name of the author may not be used to endorse or promote products
015: derived from this software without specific prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
018: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
019: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
020: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
021: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028: package org.antlr.runtime.tree;
029:
030: import org.antlr.runtime.*;
031:
032: /** A parser for a stream of tree nodes. "tree grammars" result in a subclass
033: * of this. All the error reporting and recovery is shared with Parser via
034: * the BaseRecognizer superclass.
035: */
036: public class TreeParser extends BaseRecognizer {
037: public static final int DOWN = Token.DOWN;
038: public static final int UP = Token.UP;
039:
040: protected TreeNodeStream input;
041:
042: public TreeParser(TreeNodeStream input) {
043: setTreeNodeStream(input);
044: }
045:
046: public void reset() {
047: super .reset(); // reset all recognizer state variables
048: if (input != null) {
049: input.seek(0); // rewind the input
050: }
051: }
052:
053: /** Set the input stream */
054: public void setTreeNodeStream(TreeNodeStream input) {
055: this .input = input;
056: }
057:
058: public TreeNodeStream getTreeNodeStream() {
059: return input;
060: }
061:
062: /** Match '.' in tree parser has special meaning. Skip node or
063: * entire tree if node has children. If children, scan until
064: * corresponding UP node.
065: */
066: public void matchAny(IntStream ignore) { // ignore stream, copy of this.input
067: errorRecovery = false;
068: failed = false;
069: Object look = input.LT(1);
070: if (input.getTreeAdaptor().getChildCount(look) == 0) {
071: input.consume(); // not subtree, consume 1 node and return
072: return;
073: }
074: // current node is a subtree, skip to corresponding UP.
075: // must count nesting level to get right UP
076: int level = 0;
077: int tokenType = input.getTreeAdaptor().getType(look);
078: while (tokenType != Token.EOF
079: && !(tokenType == UP && level == 0)) {
080: input.consume();
081: look = input.LT(1);
082: tokenType = input.getTreeAdaptor().getType(look);
083: if (tokenType == DOWN) {
084: level++;
085: } else if (tokenType == UP) {
086: level--;
087: }
088: }
089: input.consume(); // consume UP
090: }
091:
092: /** We have DOWN/UP nodes in the stream that have no line info; override.
093: * plus we want to alter the exception type.
094: */
095: protected void mismatch(IntStream input, int ttype, BitSet follow)
096: throws RecognitionException {
097: MismatchedTreeNodeException mte = new MismatchedTreeNodeException(
098: ttype, (TreeNodeStream) input);
099: recoverFromMismatchedToken(input, mte, ttype, follow);
100: }
101:
102: /** Prefix error message with the grammar name because message is
103: * always intended for the programmer because the parser built
104: * the input tree not the user.
105: */
106: public String getErrorHeader(RecognitionException e) {
107: return getGrammarFileName() + ": node from "
108: + (e.approximateLineInfo ? "after " : "") + "line "
109: + e.line + ":" + e.charPositionInLine;
110: }
111:
112: /** Tree parsers parse nodes they usually have a token object as
113: * payload. Set the exception token and do the default behavior.
114: */
115: public String getErrorMessage(RecognitionException e,
116: String[] tokenNames) {
117: if (this instanceof TreeParser) {
118: TreeAdaptor adaptor = ((TreeNodeStream) e.input)
119: .getTreeAdaptor();
120: e.token = adaptor.getToken(e.node);
121: if (e.token == null) { // could be an UP/DOWN node
122: e.token = new CommonToken(adaptor.getType(e.node),
123: adaptor.getText(e.node));
124: }
125: }
126: return super .getErrorMessage(e, tokenNames);
127: }
128:
129: public void traceIn(String ruleName, int ruleIndex) {
130: super .traceIn(ruleName, ruleIndex, input.LT(1));
131: }
132:
133: public void traceOut(String ruleName, int ruleIndex) {
134: super .traceOut(ruleName, ruleIndex, input.LT(1));
135: }
136:
137: }
|