diff options
Diffstat (limited to 'runtime/CSharp3/Sources/Antlr3.Runtime/RecognitionException.cs')
-rw-r--r-- | runtime/CSharp3/Sources/Antlr3.Runtime/RecognitionException.cs | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/RecognitionException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/RecognitionException.cs new file mode 100644 index 0000000..f0c5662 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/RecognitionException.cs @@ -0,0 +1,404 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace Antlr.Runtime +{ + using Antlr.Runtime.Tree; + + using ArgumentException = System.ArgumentException; + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary>The root of the ANTLR exception hierarchy.</summary> + * + * <remarks> + * 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. + * + * Note that as of Java 1.4, you can access the stack trace, which means + * that you can compute the complete trace of rules from the start symbol. + * This gives you considerable context information with which to generate + * useful error messages. + * + * 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. + * + * 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. + * </remarks> + */ + [System.Serializable] + public class RecognitionException : Exception + { + /** <summary>What input stream did the error occur in?</summary> */ + private IIntStream _input; + + /** <summary>What is index of token/char were we looking at when the error occurred?</summary> */ + private int _index; + + /** <summary> + * 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. + * </summary> + */ + private IToken _token; + + /** <summary> + * If this is a tree parser exception, node is set to the node with + * the problem. + * </summary> + */ + private object _node; + + /** <summary>The current char when an error occurred. For lexers.</summary> */ + private int _c; + + /** <summary> + * Track the line (1-based) 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. + * </summary> + */ + private int _line; + + /// <summary> + /// The 0-based index into the line where the error occurred. + /// </summary> + private int _charPositionInLine; + + /** <summary> + * 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. + * </summary> + */ + private bool _approximateLineInfo; + + /** <summary>Used for remote debugger deserialization</summary> */ + public RecognitionException() + : this("A recognition error occurred.", null, null) + { + } + + public RecognitionException( IIntStream input ) + : this("A recognition error occurred.", input, null) + { + } + + public RecognitionException(string message) + : this(message, null, null) + { + } + + public RecognitionException(string message, IIntStream input) + : this(message, input, null) + { + } + + public RecognitionException(string message, Exception innerException) + : this(message, null, innerException) + { + } + + public RecognitionException(string message, IIntStream input, Exception innerException) + : base(message, innerException) + { + this._input = input; + if (input != null) + { + this._index = input.Index; + if (input is ITokenStream) + { + this._token = ((ITokenStream)input).LT(1); + this._line = _token.Line; + this._charPositionInLine = _token.CharPositionInLine; + } + + ITreeNodeStream tns = input as ITreeNodeStream; + if (tns != null) + { + ExtractInformationFromTreeNodeStream(tns); + } + else + { + ICharStream charStream = input as ICharStream; + if (charStream != null) + { + this._c = input.LA(1); + this._line = ((ICharStream)input).Line; + this._charPositionInLine = ((ICharStream)input).CharPositionInLine; + } + else + { + this._c = input.LA(1); + } + } + } + } + + protected RecognitionException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + _index = info.GetInt32("Index"); + _c = info.GetInt32("C"); + _line = info.GetInt32("Line"); + _charPositionInLine = info.GetInt32("CharPositionInLine"); + _approximateLineInfo = info.GetBoolean("ApproximateLineInfo"); + } + + /** <summary>Return the token type or char of the unexpected input element</summary> */ + public virtual int UnexpectedType + { + get + { + if ( _input is ITokenStream ) + { + return _token.Type; + } + + ITreeNodeStream treeNodeStream = _input as ITreeNodeStream; + if ( treeNodeStream != null ) + { + ITreeAdaptor adaptor = treeNodeStream.TreeAdaptor; + return adaptor.GetType( _node ); + } + + return _c; + } + } + + public bool ApproximateLineInfo + { + get + { + return _approximateLineInfo; + } + protected set + { + _approximateLineInfo = value; + } + } + + public IIntStream Input + { + get + { + return _input; + } + protected set + { + _input = value; + } + } + + public IToken Token + { + get + { + return _token; + } + set + { + _token = value; + } + } + + public object Node + { + get + { + return _node; + } + protected set + { + _node = value; + } + } + + public int Character + { + get + { + return _c; + } + protected set + { + _c = value; + } + } + + public int Index + { + get + { + return _index; + } + protected set + { + _index = value; + } + } + + public int Line + { + get + { + return _line; + } + set + { + _line = value; + } + } + + public int CharPositionInLine + { + get + { + return _charPositionInLine; + } + set + { + _charPositionInLine = value; + } + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("Index", _index); + info.AddValue("C", _c); + info.AddValue("Line", _line); + info.AddValue("CharPositionInLine", _charPositionInLine); + info.AddValue("ApproximateLineInfo", _approximateLineInfo); + } + + protected virtual void ExtractInformationFromTreeNodeStream(ITreeNodeStream input) + { + this._node = input.LT(1); + ITokenStreamInformation streamInformation = input as ITokenStreamInformation; + if (streamInformation != null) + { + IToken lastToken = streamInformation.LastToken; + IToken lastRealToken = streamInformation.LastRealToken; + if (lastRealToken != null) + { + this._token = lastRealToken; + this._line = lastRealToken.Line; + this._charPositionInLine = lastRealToken.CharPositionInLine; + this._approximateLineInfo = lastRealToken.Equals(lastToken); + } + } + else + { + ITreeAdaptor adaptor = input.TreeAdaptor; + IToken payload = adaptor.GetToken(_node); + if (payload != null) + { + this._token = payload; + if (payload.Line <= 0) + { + // imaginary node; no line/pos info; scan backwards + int i = -1; + object priorNode = input.LT(i); + while (priorNode != null) + { + IToken priorPayload = adaptor.GetToken(priorNode); + if (priorPayload != null && priorPayload.Line > 0) + { + // we found the most recent real line / pos info + this._line = priorPayload.Line; + this._charPositionInLine = priorPayload.CharPositionInLine; + this._approximateLineInfo = true; + break; + } + --i; + try + { + priorNode = input.LT(i); + } + catch (ArgumentException) + { + priorNode = null; + } + } + } + else + { + // node created from real token + this._line = payload.Line; + this._charPositionInLine = payload.CharPositionInLine; + } + } + else if (this._node is Tree.ITree) + { + this._line = ((Tree.ITree)this._node).Line; + this._charPositionInLine = ((Tree.ITree)this._node).CharPositionInLine; + if (this._node is CommonTree) + { + this._token = ((CommonTree)this._node).Token; + } + } + else + { + int type = adaptor.GetType(this._node); + string text = adaptor.GetText(this._node); + this._token = new CommonToken(type, text); + } + } + } + } +} |