1/** The root of the ANTLR exception hierarchy.
2 *
3 *  <p>To avoid English-only error messages and to generally make things
4 *  as flexible as possible, these exceptions are not created with strings,
5 *  but rather the information necessary to generate an error.  Then
6 *  the various reporting methods in Parser and Lexer can be overridden
7 *  to generate a localized error message.  For example, MismatchedToken
8 *  exceptions are built with the expected token type.
9 *  So, don't expect getMessage() to return anything.</p>
10 *
11 *  <p>ANTLR generates code that throws exceptions upon recognition error and
12 *  also generates code to catch these exceptions in each rule.  If you
13 *  want to quit upon first error, you can turn off the automatic error
14 *  handling mechanism using rulecatch action, but you still need to
15 *  override methods mismatch and recoverFromMismatchSet.</p>
16 *
17 *  <p>In general, the recognition exceptions can track where in a grammar a
18 *  problem occurred and/or what was the expected input.  While the parser
19 *  knows its state (such as current input symbol and line info) that
20 *  state can change before the exception is reported so current token index
21 *  is computed and stored at exception time.  From this info, you can
22 *  perhaps print an entire line of input not just a single token, for example.
23 *  Better to just say the recognizer had a problem and then let the parser
24 *  figure out a fancy report.</p>
25 *
26 *  @class
27 *  @param {org.antlr.runtime.CommonTokenStream|org.antlr.runtime.tree.TreeNodeStream|org.antlr.runtime.ANTLRStringStream} input input stream that has an exception.
28 *  @extends Error
29 *
30 */
31org.antlr.runtime.RecognitionException = function(input) {
32    org.antlr.runtime.RecognitionException.superclass.constructor.call(this);
33    this.input = input;
34    this.index = input.index();
35    if ( input instanceof org.antlr.runtime.TokenStream ) {
36        this.token = input.LT(1);
37        this.line = this.token.getLine();
38        this.charPositionInLine = this.token.getCharPositionInLine();
39    }
40    if ( input instanceof org.antlr.runtime.tree.TreeNodeStream ) {
41        this.extractInformationFromTreeNodeStream(input);
42    }
43    else if ( input instanceof org.antlr.runtime.CharStream ) {
44        // Note: removed CharStream from hierarchy in JS port so checking for
45        // StringStream instead
46        this.c = input.LA(1);
47        this.line = input.getLine();
48        this.charPositionInLine = input.getCharPositionInLine();
49    }
50    else {
51        this.c = input.LA(1);
52    }
53
54    this.message = this.toString();
55};
56
57org.antlr.lang.extend(org.antlr.runtime.RecognitionException, Error,
58/** @lends org.antlr.runtime.RecognitionException.prototype */
59{
60	/**
61     * What input stream did the error occur in?
62     */
63    input: null,
64
65    /** What is index of token/char were we looking at when the error occurred?
66     *  @type Number
67     */
68	index: null,
69
70	/** The current Token when an error occurred.  Since not all streams
71	 *  can retrieve the ith Token, we have to track the Token object.
72	 *  For parsers.  Even when it's a tree parser, token might be set.
73     *  @type org.antlr.runtime.CommonToken
74	 */
75	token: null,
76
77	/** If this is a tree parser exception, node is set to the node with
78	 *  the problem.
79     *  @type Object
80	 */
81	node: null,
82
83	/** The current char when an error occurred. For lexers.
84     *  @type Number
85     */
86	c: null,
87
88	/** Track the line at which the error occurred in case this is
89	 *  generated from a lexer.  We need to track this since the
90	 *  unexpected char doesn't carry the line info.
91     *  @type Number
92	 */
93	line: null,
94
95    /** The exception's class name.
96     *  @type String
97     */
98    name: "org.antlr.runtime.RecognitionException",
99
100    /** Position in the line where exception occurred.
101     *  @type Number
102     */
103	charPositionInLine: null,
104
105	/** If you are parsing a tree node stream, you will encounter som
106	 *  imaginary nodes w/o line/col info.  We now search backwards looking
107	 *  for most recent token with line/col info, but notify getErrorHeader()
108	 *  that info is approximate.
109     *  @type Boolean
110	 */
111	approximateLineInfo: null,
112
113    /** Gather exception information from input stream.
114     *  @param {org.antlr.runtime.CommonTokenStream|org.antlr.runtime.tree.TreeNodeStream|org.antlr.runtime.ANTLRStringStream} input input stream that has an exception.
115     */
116	extractInformationFromTreeNodeStream: function(input) {
117		var nodes = input,
118            priorNode,
119            priorPayload,
120            type,
121            text,
122            i;
123
124		this.node = nodes.LT(1);
125		var adaptor = nodes.getTreeAdaptor(),
126		    payload = adaptor.getToken(this.node);
127		if ( payload ) {
128			this.token = payload;
129			if ( payload.getLine()<= 0 ) {
130				// imaginary node; no line/pos info; scan backwards
131				i = -1;
132				priorNode = nodes.LT(i);
133				while ( priorNode ) {
134					priorPayload = adaptor.getToken(priorNode);
135					if ( priorPayload && priorPayload.getLine()>0 ) {
136						// we found the most recent real line / pos info
137						this.line = priorPayload.getLine();
138						this.charPositionInLine = priorPayload.getCharPositionInLine();
139						this.approximateLineInfo = true;
140						break;
141					}
142					--i;
143					priorNode = nodes.LT(i);
144				}
145			}
146			else { // node created from real token
147				this.line = payload.getLine();
148				this.charPositionInLine = payload.getCharPositionInLine();
149			}
150		}
151		else if ( this.node instanceof org.antlr.runtime.tree.Tree) {
152			this.line = this.node.getLine();
153			this.charPositionInLine = this.node.getCharPositionInLine();
154			if ( this.node instanceof org.antlr.runtime.tree.CommonTree) {
155				this.token = this.node.token;
156			}
157		}
158		else {
159			type = adaptor.getType(this.node);
160			text = adaptor.getText(this.node);
161			this.token = new org.antlr.runtime.CommonToken(type, text);
162		}
163	},
164
165	/** Return the token type or char of the unexpected input element
166     *  @return {Number} type of the unexpected input element.
167     */
168    getUnexpectedType: function() {
169		if ( this.input instanceof org.antlr.runtime.TokenStream ) {
170			return this.token.getType();
171		}
172		else if ( this.input instanceof org.antlr.runtime.tree.TreeNodeStream ) {
173			var nodes = this.input;
174			var adaptor = nodes.getTreeAdaptor();
175			return adaptor.getType(this.node);
176		}
177		else {
178			return this.c;
179		}
180	}
181});
182