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 InvalidOperationException = System.InvalidOperationException; 35 36 public class TreePatternParser { 37 protected TreePatternLexer tokenizer; 38 protected int ttype; 39 protected TreeWizard wizard; 40 protected ITreeAdaptor adaptor; 41 42 public TreePatternParser(TreePatternLexer tokenizer, TreeWizard wizard, ITreeAdaptor adaptor) { 43 this.tokenizer = tokenizer; 44 this.wizard = wizard; 45 this.adaptor = adaptor; 46 ttype = tokenizer.NextToken(); // kickstart 47 } 48 49 public virtual object Pattern() { 50 if (ttype == TreePatternLexer.BEGIN) { 51 return ParseTree(); 52 } else if (ttype == TreePatternLexer.ID) { 53 object node = ParseNode(); 54 if (ttype == TreePatternLexer.EOF) { 55 return node; 56 } 57 return null; // extra junk on end 58 } 59 return null; 60 } 61 62 public virtual object ParseTree() { 63 if (ttype != TreePatternLexer.BEGIN) 64 throw new InvalidOperationException("No beginning."); 65 66 ttype = tokenizer.NextToken(); 67 object root = ParseNode(); 68 if (root == null) { 69 return null; 70 } 71 while (ttype == TreePatternLexer.BEGIN || 72 ttype == TreePatternLexer.ID || 73 ttype == TreePatternLexer.PERCENT || 74 ttype == TreePatternLexer.DOT) { 75 if (ttype == TreePatternLexer.BEGIN) { 76 object subtree = ParseTree(); 77 adaptor.AddChild(root, subtree); 78 } else { 79 object child = ParseNode(); 80 if (child == null) { 81 return null; 82 } 83 adaptor.AddChild(root, child); 84 } 85 } 86 87 if (ttype != TreePatternLexer.END) 88 throw new InvalidOperationException("No end."); 89 90 ttype = tokenizer.NextToken(); 91 return root; 92 } 93 94 public virtual object ParseNode() { 95 // "%label:" prefix 96 string label = null; 97 if (ttype == TreePatternLexer.PERCENT) { 98 ttype = tokenizer.NextToken(); 99 if (ttype != TreePatternLexer.ID) { 100 return null; 101 } 102 label = tokenizer.sval.ToString(); 103 ttype = tokenizer.NextToken(); 104 if (ttype != TreePatternLexer.COLON) { 105 return null; 106 } 107 ttype = tokenizer.NextToken(); // move to ID following colon 108 } 109 110 // Wildcard? 111 if (ttype == TreePatternLexer.DOT) { 112 ttype = tokenizer.NextToken(); 113 IToken wildcardPayload = new CommonToken(0, "."); 114 TreeWizard.TreePattern node = 115 new TreeWizard.WildcardTreePattern(wildcardPayload); 116 if (label != null) { 117 node.label = label; 118 } 119 return node; 120 } 121 122 // "ID" or "ID[arg]" 123 if (ttype != TreePatternLexer.ID) { 124 return null; 125 } 126 string tokenName = tokenizer.sval.ToString(); 127 ttype = tokenizer.NextToken(); 128 if (tokenName.Equals("nil")) { 129 return adaptor.Nil(); 130 } 131 string text = tokenName; 132 // check for arg 133 string arg = null; 134 if (ttype == TreePatternLexer.ARG) { 135 arg = tokenizer.sval.ToString(); 136 text = arg; 137 ttype = tokenizer.NextToken(); 138 } 139 140 // create node 141 int treeNodeType = wizard.GetTokenType(tokenName); 142 if (treeNodeType == TokenTypes.Invalid) { 143 return null; 144 } 145 object node2; 146 node2 = adaptor.Create(treeNodeType, text); 147 if (label != null && node2.GetType() == typeof(TreeWizard.TreePattern)) { 148 ((TreeWizard.TreePattern)node2).label = label; 149 } 150 if (arg != null && node2.GetType() == typeof(TreeWizard.TreePattern)) { 151 ((TreeWizard.TreePattern)node2).hasTextArg = true; 152 } 153 return node2; 154 } 155 } 156} 157