/* * [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; /** * 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. * */ 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 { this.input = input; } public TreeParser( ITreeNodeStream input, RecognizerSharedState state ) : base( state ) // share the state object with another parser { this.input = input; } public override void Reset() { base.Reset(); // reset all recognizer state variables if ( input != null ) { input.Seek( 0 ); // rewind the input } } /** Set the input stream */ 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 = ""; ITreeAdaptor adaptor = ((ITreeNodeStream)e.Input).TreeAdaptor; return adaptor.Create(new CommonToken(expectedTokenType, tokenText)); } /** * Match '.' in tree parser has special meaning. Skip node or * entire tree if node has children. If children, scan until * corresponding UP node. * */ 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(); } } } /** * 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... * */ protected override object RecoverFromMismatchedToken( IIntStream input, int ttype, BitSet follow ) { throw new MismatchedTreeNodeException( ttype, (ITreeNodeStream)input ); } /** * 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. * */ public override string GetErrorHeader( RecognitionException e ) { return GrammarFileName + ": node from " + ( e.ApproximateLineInfo ? "after " : "" ) + "line " + e.Line + ":" + e.CharPositionInLine; } /** * Tree parsers parse nodes they usually have a token object as * payload. Set the exception token and do the default behavior. * */ 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 ) ); } } }