1/** A parser for a stream of tree nodes.  "tree grammars" result in a subclass
2 *  of this.  All the error reporting and recovery is shared with Parser via
3 *  the BaseRecognizer superclass.
4*/
5org.antlr.runtime.tree.TreeParser = function(input) {
6    org.antlr.runtime.tree.TreeParser.superclass.constructor.call(this, arguments[1]);
7    this.setTreeNodeStream(input);
8};
9
10(function(){
11var TP = org.antlr.runtime.tree.TreeParser;
12
13org.antlr.lang.augmentObject(TP, {
14    DOWN: org.antlr.runtime.Token.DOWN,
15    UP: org.antlr.runtime.Token.UP
16});
17
18org.antlr.lang.extend(TP, org.antlr.runtime.BaseRecognizer, {
19    reset: function() {
20        TP.superclass.reset.call(this); // reset all recognizer state variables
21        if ( this.input ) {
22            this.input.seek(0); // rewind the input
23        }
24    },
25
26    /** Set the input stream */
27    setTreeNodeStream: function(input) {
28        this.input = input;
29    },
30
31    getTreeNodeStream: function() {
32        return this.input;
33    },
34
35    getSourceName: function() {
36        return this.input.getSourceName();
37    },
38
39    getCurrentInputSymbol: function(input) {
40        return input.LT(1);
41    },
42
43    getMissingSymbol: function(input, e, expectedTokenType, follow) {
44        var tokenText =
45            "<missing "+this.getTokenNames()[expectedTokenType]+">";
46        return new org.antlr.runtime.tree.CommonTree(new org.antlr.runtime.CommonToken(expectedTokenType, tokenText));
47    },
48
49    /** Match '.' in tree parser has special meaning.  Skip node or
50     *  entire tree if node has children.  If children, scan until
51     *  corresponding UP node.
52     */
53    matchAny: function(ignore) { // ignore stream, copy of this.input
54        this.state.errorRecovery = false;
55        this.state.failed = false;
56        var look = this.input.LT(1);
57        if ( this.input.getTreeAdaptor().getChildCount(look)===0 ) {
58            this.input.consume(); // not subtree, consume 1 node and return
59            return;
60        }
61        // current node is a subtree, skip to corresponding UP.
62        // must count nesting level to get right UP
63        var level=0,
64            tokenType = this.input.getTreeAdaptor().getType(look);
65        while ( tokenType!==org.antlr.runtime.Token.EOF &&
66                !(tokenType===TP.UP && level===0) )
67        {
68            this.input.consume();
69            look = this.input.LT(1);
70            tokenType = this.input.getTreeAdaptor().getType(look);
71            if ( tokenType === TP.DOWN ) {
72                level++;
73            }
74            else if ( tokenType === TP.UP ) {
75                level--;
76            }
77        }
78        this.input.consume(); // consume UP
79    },
80
81    /** We have DOWN/UP nodes in the stream that have no line info; override.
82     *  plus we want to alter the exception type.  Don't try to recover
83     *       *  from tree parser errors inline...
84     */
85    mismatch: function(input, ttype, follow) {
86        throw new org.antlr.runtime.MismatchedTreeNodeException(ttype, input);
87    },
88
89    /** Prefix error message with the grammar name because message is
90     *  always intended for the programmer because the parser built
91     *  the input tree not the user.
92     */
93    getErrorHeader: function(e) {
94        return this.getGrammarFileName()+": node from "+
95               (e.approximateLineInfo?"after ":"")+"line "+e.line+":"+e.charPositionInLine;
96    },
97
98    /** Tree parsers parse nodes they usually have a token object as
99     *  payload. Set the exception token and do the default behavior.
100     */
101    getErrorMessage: function(e, tokenNames) {
102        var adaptor;
103        if ( this instanceof TP ) {
104            adaptor = e.input.getTreeAdaptor();
105            e.token = adaptor.getToken(e.node);
106            if ( !org.antlr.lang.isValue(e.token) ) { // could be an UP/DOWN node
107                e.token = new org.antlr.runtime.CommonToken(
108                        adaptor.getType(e.node),
109                        adaptor.getText(e.node));
110            }
111        }
112        return TP.superclass.getErrorMessage.call(this, e, tokenNames);
113    },
114
115    traceIn: function(ruleName, ruleIndex) {
116        TP.superclass.traceIn.call(this, ruleName, ruleIndex, this.input.LT(1));
117    },
118
119    traceOut: function(ruleName, ruleIndex) {
120        TP.superclass.traceOut.call(this, ruleName, ruleIndex, this.input.LT(1));
121    }
122});
123
124})();
125