Home | History | Annotate | Download | only in Antlr.Runtime.Tree
      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     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