blob: 9c9860592c5e5a94b56045fe122c1476648bf730 [file] [log] [blame]
/** The root of the ANTLR exception hierarchy.
*
* <p>To avoid English-only error messages and to generally make things
* as flexible as possible, these exceptions are not created with strings,
* but rather the information necessary to generate an error. Then
* the various reporting methods in Parser and Lexer can be overridden
* to generate a localized error message. For example, MismatchedToken
* exceptions are built with the expected token type.
* So, don't expect getMessage() to return anything.</p>
*
* <p>ANTLR generates code that throws exceptions upon recognition error and
* also generates code to catch these exceptions in each rule. If you
* want to quit upon first error, you can turn off the automatic error
* handling mechanism using rulecatch action, but you still need to
* override methods mismatch and recoverFromMismatchSet.</p>
*
* <p>In general, the recognition exceptions can track where in a grammar a
* problem occurred and/or what was the expected input. While the parser
* knows its state (such as current input symbol and line info) that
* state can change before the exception is reported so current token index
* is computed and stored at exception time. From this info, you can
* perhaps print an entire line of input not just a single token, for example.
* Better to just say the recognizer had a problem and then let the parser
* figure out a fancy report.</p>
*
* @class
* @param {org.antlr.runtime.CommonTokenStream|org.antlr.runtime.tree.TreeNodeStream|org.antlr.runtime.ANTLRStringStream} input input stream that has an exception.
* @extends Error
*
*/
org.antlr.runtime.RecognitionException = function(input) {
org.antlr.runtime.RecognitionException.superclass.constructor.call(this);
this.input = input;
this.index = input.index();
if ( input instanceof org.antlr.runtime.TokenStream ) {
this.token = input.LT(1);
this.line = this.token.getLine();
this.charPositionInLine = this.token.getCharPositionInLine();
}
if ( input instanceof org.antlr.runtime.tree.TreeNodeStream ) {
this.extractInformationFromTreeNodeStream(input);
}
else if ( input instanceof org.antlr.runtime.CharStream ) {
// Note: removed CharStream from hierarchy in JS port so checking for
// StringStream instead
this.c = input.LA(1);
this.line = input.getLine();
this.charPositionInLine = input.getCharPositionInLine();
}
else {
this.c = input.LA(1);
}
this.message = this.toString();
};
org.antlr.lang.extend(org.antlr.runtime.RecognitionException, Error,
/** @lends org.antlr.runtime.RecognitionException.prototype */
{
/**
* What input stream did the error occur in?
*/
input: null,
/** What is index of token/char were we looking at when the error occurred?
* @type Number
*/
index: null,
/** The current Token when an error occurred. Since not all streams
* can retrieve the ith Token, we have to track the Token object.
* For parsers. Even when it's a tree parser, token might be set.
* @type org.antlr.runtime.CommonToken
*/
token: null,
/** If this is a tree parser exception, node is set to the node with
* the problem.
* @type Object
*/
node: null,
/** The current char when an error occurred. For lexers.
* @type Number
*/
c: null,
/** Track the line at which the error occurred in case this is
* generated from a lexer. We need to track this since the
* unexpected char doesn't carry the line info.
* @type Number
*/
line: null,
/** The exception's class name.
* @type String
*/
name: "org.antlr.runtime.RecognitionException",
/** Position in the line where exception occurred.
* @type Number
*/
charPositionInLine: null,
/** If you are parsing a tree node stream, you will encounter som
* imaginary nodes w/o line/col info. We now search backwards looking
* for most recent token with line/col info, but notify getErrorHeader()
* that info is approximate.
* @type Boolean
*/
approximateLineInfo: null,
/** Gather exception information from input stream.
* @param {org.antlr.runtime.CommonTokenStream|org.antlr.runtime.tree.TreeNodeStream|org.antlr.runtime.ANTLRStringStream} input input stream that has an exception.
*/
extractInformationFromTreeNodeStream: function(input) {
var nodes = input,
priorNode,
priorPayload,
type,
text,
i;
this.node = nodes.LT(1);
var adaptor = nodes.getTreeAdaptor(),
payload = adaptor.getToken(this.node);
if ( payload ) {
this.token = payload;
if ( payload.getLine()<= 0 ) {
// imaginary node; no line/pos info; scan backwards
i = -1;
priorNode = nodes.LT(i);
while ( priorNode ) {
priorPayload = adaptor.getToken(priorNode);
if ( priorPayload && priorPayload.getLine()>0 ) {
// we found the most recent real line / pos info
this.line = priorPayload.getLine();
this.charPositionInLine = priorPayload.getCharPositionInLine();
this.approximateLineInfo = true;
break;
}
--i;
priorNode = nodes.LT(i);
}
}
else { // node created from real token
this.line = payload.getLine();
this.charPositionInLine = payload.getCharPositionInLine();
}
}
else if ( this.node instanceof org.antlr.runtime.tree.Tree) {
this.line = this.node.getLine();
this.charPositionInLine = this.node.getCharPositionInLine();
if ( this.node instanceof org.antlr.runtime.tree.CommonTree) {
this.token = this.node.token;
}
}
else {
type = adaptor.getType(this.node);
text = adaptor.getText(this.node);
this.token = new org.antlr.runtime.CommonToken(type, text);
}
},
/** Return the token type or char of the unexpected input element
* @return {Number} type of the unexpected input element.
*/
getUnexpectedType: function() {
if ( this.input instanceof org.antlr.runtime.TokenStream ) {
return this.token.getType();
}
else if ( this.input instanceof org.antlr.runtime.tree.TreeNodeStream ) {
var nodes = this.input;
var adaptor = nodes.getTreeAdaptor();
return adaptor.getType(this.node);
}
else {
return this.c;
}
}
});