Home | History | Annotate | Download | only in runtime
      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  */
     31 org.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 
     57 org.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