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