1 /*
2  * [The "BSD license"]
3  * Copyright (c) 2013 Terence Parr
4  * Copyright (c) 2013 Sam Harwell
5  * Copyright (c) 2017 Egbert Voigt
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 module antlr.v4.runtime.tree.pattern.ParseTreePattern;
33 
34 import antlr.v4.runtime.tree.ParseTree;
35 import antlr.v4.runtime.tree.pattern.ParseTreeMatch;
36 import antlr.v4.runtime.tree.pattern.ParseTreePatternMatcher;
37 import antlr.v4.runtime.tree.xpath.XPath;
38 
39 /**
40  * @uml
41  * A pattern like {@code <ID> = <expr>;} converted to a {@link ParseTree} by
42  * {@link ParseTreePatternMatcher#compile(String, int)}.
43  */
44 class ParseTreePattern
45 {
46 
47     /**
48      * @uml
49      * This is the backing field for {@link #getPatternRuleIndex()}.
50      * @final
51      */
52     private int patternRuleIndex;
53 
54     /**
55      * @uml
56      * This is the backing field for {@link #getPattern()}.
57      * @final
58      */
59     private string pattern;
60 
61     /**
62      * @uml
63      * This is the backing field for {@link #getPatternTree()}.
64      */
65     public ParseTree patternTree;
66 
67     /**
68      * @uml
69      * This is the backing field for {@link #getMatcher()}.
70      */
71     public ParseTreePatternMatcher matcher;
72 
73     /**
74      * @uml
75      * Construct a new instance of the {@link ParseTreePattern} class.
76      *
77      *  @param matcher The {@link ParseTreePatternMatcher} which created this
78      *  tree pattern.
79      *  @param pattern The tree pattern in concrete syntax form.
80      *  @param patternRuleIndex The parser rule which serves as the root of the
81      *  tree pattern.
82      *  @param patternTree The tree pattern in {@link ParseTree} form.
83      */
84     public this(ParseTreePatternMatcher matcher, string pattern, int patternRuleIndex, ParseTree patternTree)
85     {
86         this.matcher = matcher;
87         this.patternRuleIndex = patternRuleIndex;
88         this.pattern = pattern;
89         this.patternTree = patternTree;
90     }
91 
92     /**
93      * @uml
94      * Match a specific parse tree against this tree pattern.
95      *
96      *  @param tree The parse tree to match against this tree pattern.
97      *  @return A {@link ParseTreeMatch} object describing the result of the
98      * match operation. The {@link ParseTreeMatch#succeeded()} method can be
99      * used to determine whether or not the match was successful.
100      */
101     public ParseTreeMatch match(ParseTree tree)
102     {
103         return matcher.match(tree, this);
104     }
105 
106     /**
107      * @uml
108      * Determine whether or not a parse tree matches this tree pattern.
109      *
110      *  @param tree The parse tree to match against this tree pattern.
111      *  @return {@code true} if {@code tree} is a match for the current tree
112      * pattern; otherwise, {@code false}.
113      */
114     public bool matches(ParseTree tree)
115     {
116         return matcher.match(tree, this).succeeded();
117     }
118 
119     /**
120      * @uml
121      * Find all nodes using XPath and then try to match those subtrees against
122      *  this tree pattern.
123      *
124      *  @param tree The {@link ParseTree} to match against this pattern.
125      *  @param xpath An expression matching the nodes
126      *
127      *  @return A collection of {@link ParseTreeMatch} objects describing the
128      * successful matches. Unsuccessful matches are omitted from the result,
129      * regardless of the reason for the failure.
130      */
131     public ParseTreeMatch[] findAll(ParseTree tree, string xpath)
132     {
133         ParseTree[] subtrees = XPath.findAll(tree, xpath, matcher.getParser());
134         ParseTreeMatch[] matches;
135         foreach (ParseTree t; subtrees) {
136             ParseTreeMatch match = match(t);
137             if ( match.succeeded() ) {
138                 matches ~= match;
139             }
140         }
141         return matches;
142     }
143 
144     /**
145      * @uml
146      * et the {@link ParseTreePatternMatcher} which created this tree pattern.
147      *
148      *  @return The {@link ParseTreePatternMatcher} which created this tree
149      * pattern.
150      */
151     public ParseTreePatternMatcher getMatcher()
152     {
153         return matcher;
154     }
155 
156     /**
157      * @uml
158      * Get the tree pattern in concrete syntax form.
159      *
160      *  @return The tree pattern in concrete syntax form.
161      */
162     public string getPattern()
163     {
164         return pattern;
165     }
166 
167     /**
168      * @uml
169      * Get the parser rule which serves as the outermost rule for the tree
170      * pattern.
171      *
172      *  @return The parser rule which serves as the outermost rule for the tree
173      * pattern.
174      */
175     public int getPatternRuleIndex()
176     {
177         return patternRuleIndex;
178     }
179 
180     /**
181      * @uml
182      * Get the tree pattern as a {@link ParseTree}. The rule and token tags from
183      * the pattern are present in the parse tree as terminal nodes with a symbol
184      * of type {@link RuleTagToken} or {@link TokenTagToken}.
185      *
186      *  @return The tree pattern as a {@link ParseTree}.
187      */
188     public ParseTree getPatternTree()
189     {
190         return patternTree;
191     }
192 
193 }