| /* |
| * [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.Tree { |
| using ConditionalAttribute = System.Diagnostics.ConditionalAttribute; |
| using Regex = System.Text.RegularExpressions.Regex; |
| using RegexOptions = System.Text.RegularExpressions.RegexOptions; |
| |
| /** <summary> |
| * A parser for a stream of tree nodes. "tree grammars" result in a subclass |
| * of this. All the error reporting and recovery is shared with Parser via |
| * the BaseRecognizer superclass. |
| * </summary> |
| */ |
| public class TreeParser : BaseRecognizer { |
| public const int DOWN = TokenTypes.Down; |
| public const int UP = TokenTypes.Up; |
| |
| // precompiled regex used by inContext |
| static string dotdot = ".*[^.]\\.\\.[^.].*"; |
| static string doubleEtc = ".*\\.\\.\\.\\s+\\.\\.\\..*"; |
| static Regex dotdotPattern = new Regex(dotdot, RegexOptions.Compiled); |
| static Regex doubleEtcPattern = new Regex(doubleEtc, RegexOptions.Compiled); |
| |
| protected ITreeNodeStream input; |
| |
| public TreeParser(ITreeNodeStream input) |
| : base() // highlight that we go to super to set state object |
| { |
| SetTreeNodeStream(input); |
| } |
| |
| public TreeParser(ITreeNodeStream input, RecognizerSharedState state) |
| : base(state) // share the state object with another parser |
| { |
| SetTreeNodeStream(input); |
| } |
| |
| public override void Reset() { |
| base.Reset(); // reset all recognizer state variables |
| if (input != null) { |
| input.Seek(0); // rewind the input |
| } |
| } |
| |
| /** <summary>Set the input stream</summary> */ |
| public virtual void SetTreeNodeStream(ITreeNodeStream input) { |
| this.input = input; |
| } |
| |
| public virtual ITreeNodeStream GetTreeNodeStream() { |
| return input; |
| } |
| |
| public override string SourceName { |
| get { |
| return input.SourceName; |
| } |
| } |
| |
| protected override object GetCurrentInputSymbol(IIntStream input) { |
| return ((ITreeNodeStream)input).LT(1); |
| } |
| |
| protected override object GetMissingSymbol(IIntStream input, |
| RecognitionException e, |
| int expectedTokenType, |
| BitSet follow) { |
| string tokenText = |
| "<missing " + TokenNames[expectedTokenType] + ">"; |
| ITreeAdaptor adaptor = ((ITreeNodeStream)e.Input).TreeAdaptor; |
| return adaptor.Create(new CommonToken(expectedTokenType, tokenText)); |
| } |
| |
| /** <summary> |
| * Match '.' in tree parser has special meaning. Skip node or |
| * entire tree if node has children. If children, scan until |
| * corresponding UP node. |
| * </summary> |
| */ |
| public override void MatchAny(IIntStream ignore) { |
| state.errorRecovery = false; |
| state.failed = false; |
| // always consume the current node |
| input.Consume(); |
| // if the next node is DOWN, then the current node is a subtree: |
| // skip to corresponding UP. must count nesting level to get right UP |
| int look = input.LA(1); |
| if (look == DOWN) { |
| input.Consume(); |
| int level = 1; |
| while (level > 0) { |
| switch (input.LA(1)) { |
| case DOWN: |
| level++; |
| break; |
| case UP: |
| level--; |
| break; |
| case TokenTypes.EndOfFile: |
| return; |
| default: |
| break; |
| } |
| input.Consume(); |
| } |
| } |
| } |
| |
| /** <summary> |
| * We have DOWN/UP nodes in the stream that have no line info; override. |
| * plus we want to alter the exception type. Don't try to recover |
| * from tree parser errors inline... |
| * </summary> |
| */ |
| protected override object RecoverFromMismatchedToken(IIntStream input, int ttype, BitSet follow) { |
| throw new MismatchedTreeNodeException(ttype, (ITreeNodeStream)input); |
| } |
| |
| /** <summary> |
| * Prefix error message with the grammar name because message is |
| * always intended for the programmer because the parser built |
| * the input tree not the user. |
| * </summary> |
| */ |
| public override string GetErrorHeader(RecognitionException e) { |
| return GrammarFileName + ": node from " + |
| (e.ApproximateLineInfo ? "after " : "") + "line " + e.Line + ":" + e.CharPositionInLine; |
| } |
| |
| /** <summary> |
| * Tree parsers parse nodes they usually have a token object as |
| * payload. Set the exception token and do the default behavior. |
| * </summary> |
| */ |
| public override string GetErrorMessage(RecognitionException e, string[] tokenNames) { |
| if (this is TreeParser) { |
| ITreeAdaptor adaptor = ((ITreeNodeStream)e.Input).TreeAdaptor; |
| e.Token = adaptor.GetToken(e.Node); |
| if (e.Token == null) { // could be an UP/DOWN node |
| e.Token = new CommonToken(adaptor.GetType(e.Node), |
| adaptor.GetText(e.Node)); |
| } |
| } |
| return base.GetErrorMessage(e, tokenNames); |
| } |
| |
| [Conditional("ANTLR_TRACE")] |
| public virtual void TraceIn(string ruleName, int ruleIndex) { |
| base.TraceIn(ruleName, ruleIndex, input.LT(1)); |
| } |
| |
| [Conditional("ANTLR_TRACE")] |
| public virtual void TraceOut(string ruleName, int ruleIndex) { |
| base.TraceOut(ruleName, ruleIndex, input.LT(1)); |
| } |
| |
| } |
| } |