TreePatternParser.cs revision 324c4644fee44b9898524c09511bd33c3f12e2df
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{
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
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
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
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
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