1 /* 2 * [The "BSD licence"] 3 * Copyright (c) 2005-2008 Terence Parr 4 * All rights reserved. 5 * 6 * Conversion to C#: 7 * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 namespace Antlr.Runtime.Tree 34 { 35 using ConditionalAttribute = System.Diagnostics.ConditionalAttribute; 36 using Regex = System.Text.RegularExpressions.Regex; 37 using RegexOptions = System.Text.RegularExpressions.RegexOptions; 38 39 /** <summary> 40 * A parser for a stream of tree nodes. "tree grammars" result in a subclass 41 * of this. All the error reporting and recovery is shared with Parser via 42 * the BaseRecognizer superclass. 43 * </summary> 44 */ 45 public class TreeParser : BaseRecognizer 46 { 47 public const int DOWN = TokenTypes.Down; 48 public const int UP = TokenTypes.Up; 49 50 // precompiled regex used by inContext 51 static string dotdot = ".*[^.]\\.\\.[^.].*"; 52 static string doubleEtc = ".*\\.\\.\\.\\s+\\.\\.\\..*"; 53 static Regex dotdotPattern = new Regex( dotdot, RegexOptions.Compiled ); 54 static Regex doubleEtcPattern = new Regex( doubleEtc, RegexOptions.Compiled ); 55 56 protected ITreeNodeStream input; 57 TreeParser( ITreeNodeStream input )58 public TreeParser( ITreeNodeStream input ) 59 : base() // highlight that we go to super to set state object 60 { 61 SetTreeNodeStream( input ); 62 } 63 TreeParser( ITreeNodeStream input, RecognizerSharedState state )64 public TreeParser( ITreeNodeStream input, RecognizerSharedState state ) 65 : base( state ) // share the state object with another parser 66 { 67 SetTreeNodeStream( input ); 68 } 69 Reset()70 public override void Reset() 71 { 72 base.Reset(); // reset all recognizer state variables 73 if ( input != null ) 74 { 75 input.Seek( 0 ); // rewind the input 76 } 77 } 78 79 /** <summary>Set the input stream</summary> */ SetTreeNodeStream( ITreeNodeStream input )80 public virtual void SetTreeNodeStream( ITreeNodeStream input ) 81 { 82 this.input = input; 83 } 84 GetTreeNodeStream()85 public virtual ITreeNodeStream GetTreeNodeStream() 86 { 87 return input; 88 } 89 90 public override string SourceName 91 { 92 get 93 { 94 return input.SourceName; 95 } 96 } 97 GetCurrentInputSymbol( IIntStream input )98 protected override object GetCurrentInputSymbol( IIntStream input ) 99 { 100 return ( (ITreeNodeStream)input ).LT( 1 ); 101 } 102 GetMissingSymbol( IIntStream input, RecognitionException e, int expectedTokenType, BitSet follow )103 protected override object GetMissingSymbol( IIntStream input, 104 RecognitionException e, 105 int expectedTokenType, 106 BitSet follow ) 107 { 108 string tokenText = 109 "<missing " + TokenNames[expectedTokenType] + ">"; 110 ITreeAdaptor adaptor = ((ITreeNodeStream)e.Input).TreeAdaptor; 111 return adaptor.Create(new CommonToken(expectedTokenType, tokenText)); 112 } 113 114 /** <summary> 115 * Match '.' in tree parser has special meaning. Skip node or 116 * entire tree if node has children. If children, scan until 117 * corresponding UP node. 118 * </summary> 119 */ MatchAny( IIntStream ignore )120 public override void MatchAny( IIntStream ignore ) 121 { 122 state.errorRecovery = false; 123 state.failed = false; 124 // always consume the current node 125 input.Consume(); 126 // if the next node is DOWN, then the current node is a subtree: 127 // skip to corresponding UP. must count nesting level to get right UP 128 int look = input.LA( 1 ); 129 if ( look == DOWN ) 130 { 131 input.Consume(); 132 int level = 1; 133 while ( level > 0 ) 134 { 135 switch ( input.LA( 1 ) ) 136 { 137 case DOWN: 138 level++; 139 break; 140 case UP: 141 level--; 142 break; 143 case TokenTypes.EndOfFile: 144 return; 145 default: 146 break; 147 } 148 input.Consume(); 149 } 150 } 151 } 152 153 /** <summary> 154 * We have DOWN/UP nodes in the stream that have no line info; override. 155 * plus we want to alter the exception type. Don't try to recover 156 * from tree parser errors inline... 157 * </summary> 158 */ RecoverFromMismatchedToken( IIntStream input, int ttype, BitSet follow )159 protected override object RecoverFromMismatchedToken( IIntStream input, int ttype, BitSet follow ) 160 { 161 throw new MismatchedTreeNodeException( ttype, (ITreeNodeStream)input ); 162 } 163 164 /** <summary> 165 * Prefix error message with the grammar name because message is 166 * always intended for the programmer because the parser built 167 * the input tree not the user. 168 * </summary> 169 */ GetErrorHeader( RecognitionException e )170 public override string GetErrorHeader( RecognitionException e ) 171 { 172 return GrammarFileName + ": node from " + 173 ( e.ApproximateLineInfo ? "after " : "" ) + "line " + e.Line + ":" + e.CharPositionInLine; 174 } 175 176 /** <summary> 177 * Tree parsers parse nodes they usually have a token object as 178 * payload. Set the exception token and do the default behavior. 179 * </summary> 180 */ GetErrorMessage( RecognitionException e, string[] tokenNames )181 public override string GetErrorMessage( RecognitionException e, string[] tokenNames ) 182 { 183 if ( this is TreeParser ) 184 { 185 ITreeAdaptor adaptor = ( (ITreeNodeStream)e.Input ).TreeAdaptor; 186 e.Token = adaptor.GetToken( e.Node ); 187 if ( e.Token == null ) 188 { // could be an UP/DOWN node 189 e.Token = new CommonToken( adaptor.GetType( e.Node ), 190 adaptor.GetText( e.Node ) ); 191 } 192 } 193 return base.GetErrorMessage( e, tokenNames ); 194 } 195 196 [Conditional("ANTLR_TRACE")] TraceIn( string ruleName, int ruleIndex )197 public virtual void TraceIn( string ruleName, int ruleIndex ) 198 { 199 base.TraceIn( ruleName, ruleIndex, input.LT( 1 ) ); 200 } 201 202 [Conditional("ANTLR_TRACE")] TraceOut( string ruleName, int ruleIndex )203 public virtual void TraceOut( string ruleName, int ruleIndex ) 204 { 205 base.TraceOut( ruleName, ruleIndex, input.LT( 1 ) ); 206 } 207 208 } 209 } 210