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 33namespace Antlr.Runtime.Tree { 34 using ConditionalAttribute = System.Diagnostics.ConditionalAttribute; 35 using Regex = System.Text.RegularExpressions.Regex; 36 using RegexOptions = System.Text.RegularExpressions.RegexOptions; 37 38 /** <summary> 39 * A parser for a stream of tree nodes. "tree grammars" result in a subclass 40 * of this. All the error reporting and recovery is shared with Parser via 41 * the BaseRecognizer superclass. 42 * </summary> 43 */ 44 public class TreeParser : BaseRecognizer { 45 public const int DOWN = TokenTypes.Down; 46 public const int UP = TokenTypes.Up; 47 48 // precompiled regex used by inContext 49 static string dotdot = ".*[^.]\\.\\.[^.].*"; 50 static string doubleEtc = ".*\\.\\.\\.\\s+\\.\\.\\..*"; 51 static Regex dotdotPattern = new Regex(dotdot, RegexOptions.Compiled); 52 static Regex doubleEtcPattern = new Regex(doubleEtc, RegexOptions.Compiled); 53 54 protected ITreeNodeStream input; 55 56 public TreeParser(ITreeNodeStream input) 57 : base() // highlight that we go to super to set state object 58 { 59 SetTreeNodeStream(input); 60 } 61 62 public TreeParser(ITreeNodeStream input, RecognizerSharedState state) 63 : base(state) // share the state object with another parser 64 { 65 SetTreeNodeStream(input); 66 } 67 68 public override void Reset() { 69 base.Reset(); // reset all recognizer state variables 70 if (input != null) { 71 input.Seek(0); // rewind the input 72 } 73 } 74 75 /** <summary>Set the input stream</summary> */ 76 public virtual void SetTreeNodeStream(ITreeNodeStream input) { 77 this.input = input; 78 } 79 80 public virtual ITreeNodeStream GetTreeNodeStream() { 81 return input; 82 } 83 84 public override string SourceName { 85 get { 86 return input.SourceName; 87 } 88 } 89 90 protected override object GetCurrentInputSymbol(IIntStream input) { 91 return ((ITreeNodeStream)input).LT(1); 92 } 93 94 protected override object GetMissingSymbol(IIntStream input, 95 RecognitionException e, 96 int expectedTokenType, 97 BitSet follow) { 98 string tokenText = 99 "<missing " + TokenNames[expectedTokenType] + ">"; 100 ITreeAdaptor adaptor = ((ITreeNodeStream)e.Input).TreeAdaptor; 101 return adaptor.Create(new CommonToken(expectedTokenType, tokenText)); 102 } 103 104 /** <summary> 105 * Match '.' in tree parser has special meaning. Skip node or 106 * entire tree if node has children. If children, scan until 107 * corresponding UP node. 108 * </summary> 109 */ 110 public override void MatchAny(IIntStream ignore) { 111 state.errorRecovery = false; 112 state.failed = false; 113 // always consume the current node 114 input.Consume(); 115 // if the next node is DOWN, then the current node is a subtree: 116 // skip to corresponding UP. must count nesting level to get right UP 117 int look = input.LA(1); 118 if (look == DOWN) { 119 input.Consume(); 120 int level = 1; 121 while (level > 0) { 122 switch (input.LA(1)) { 123 case DOWN: 124 level++; 125 break; 126 case UP: 127 level--; 128 break; 129 case TokenTypes.EndOfFile: 130 return; 131 default: 132 break; 133 } 134 input.Consume(); 135 } 136 } 137 } 138 139 /** <summary> 140 * We have DOWN/UP nodes in the stream that have no line info; override. 141 * plus we want to alter the exception type. Don't try to recover 142 * from tree parser errors inline... 143 * </summary> 144 */ 145 protected override object RecoverFromMismatchedToken(IIntStream input, int ttype, BitSet follow) { 146 throw new MismatchedTreeNodeException(ttype, (ITreeNodeStream)input); 147 } 148 149 /** <summary> 150 * Prefix error message with the grammar name because message is 151 * always intended for the programmer because the parser built 152 * the input tree not the user. 153 * </summary> 154 */ 155 public override string GetErrorHeader(RecognitionException e) { 156 return GrammarFileName + ": node from " + 157 (e.ApproximateLineInfo ? "after " : "") + "line " + e.Line + ":" + e.CharPositionInLine; 158 } 159 160 /** <summary> 161 * Tree parsers parse nodes they usually have a token object as 162 * payload. Set the exception token and do the default behavior. 163 * </summary> 164 */ 165 public override string GetErrorMessage(RecognitionException e, string[] tokenNames) { 166 if (this is TreeParser) { 167 ITreeAdaptor adaptor = ((ITreeNodeStream)e.Input).TreeAdaptor; 168 e.Token = adaptor.GetToken(e.Node); 169 if (e.Token == null) { // could be an UP/DOWN node 170 e.Token = new CommonToken(adaptor.GetType(e.Node), 171 adaptor.GetText(e.Node)); 172 } 173 } 174 return base.GetErrorMessage(e, tokenNames); 175 } 176 177 [Conditional("ANTLR_TRACE")] 178 public virtual void TraceIn(string ruleName, int ruleIndex) { 179 base.TraceIn(ruleName, ruleIndex, input.LT(1)); 180 } 181 182 [Conditional("ANTLR_TRACE")] 183 public virtual void TraceOut(string ruleName, int ruleIndex) { 184 base.TraceOut(ruleName, ruleIndex, input.LT(1)); 185 } 186 187 } 188} 189