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 // Class ParseTreePattern
40 /**
41  * @uml
42  * A pattern like {@code <ID> = <expr>;} converted to a {@link ParseTree} by
43  * {@link ParseTreePatternMatcher#compile(String, int)}.
44  */
45 class ParseTreePattern
46 {
47 
48     /**
49      * @uml
50      * This is the backing field for {@link #getPatternRuleIndex()}.
51      * @final
52      */
53     private int patternRuleIndex;
54 
55     /**
56      * @uml
57      * This is the backing field for {@link #getPattern()}.
58      * @final
59      */
60     private string pattern;
61 
62     /**
63      * @uml
64      * This is the backing field for {@link #getPatternTree()}.
65      */
66     public ParseTree patternTree;
67 
68     /**
69      * @uml
70      * This is the backing field for {@link #getMatcher()}.
71      */
72     public ParseTreePatternMatcher matcher;
73 
74     /**
75      * @uml
76      * Construct a new instance of the {@link ParseTreePattern} class.
77      *
78      *  @param matcher The {@link ParseTreePatternMatcher} which created this
79      *  tree pattern.
80      *  @param pattern The tree pattern in concrete syntax form.
81      *  @param patternRuleIndex The parser rule which serves as the root of the
82      *  tree pattern.
83      *  @param patternTree The tree pattern in {@link ParseTree} form.
84      */
85     public this(ParseTreePatternMatcher matcher, string pattern, int patternRuleIndex, ParseTree patternTree)
86     {
87         this.matcher = matcher;
88         this.patternRuleIndex = patternRuleIndex;
89         this.pattern = pattern;
90         this.patternTree = patternTree;
91     }
92 
93     /**
94      * @uml
95      * Match a specific parse tree against this tree pattern.
96      *
97      *  @param tree The parse tree to match against this tree pattern.
98      *  @return A {@link ParseTreeMatch} object describing the result of the
99      * match operation. The {@link ParseTreeMatch#succeeded()} method can be
100      * used to determine whether or not the match was successful.
101      */
102     public ParseTreeMatch match(ParseTree tree)
103     {
104         return matcher.match(tree, this);
105     }
106 
107     /**
108      * @uml
109      * Determine whether or not a parse tree matches this tree pattern.
110      *
111      *  @param tree The parse tree to match against this tree pattern.
112      *  @return {@code true} if {@code tree} is a match for the current tree
113      * pattern; otherwise, {@code false}.
114      */
115     public bool matches(ParseTree tree)
116     {
117         return matcher.match(tree, this).succeeded();
118     }
119 
120     /**
121      * @uml
122      * Find all nodes using XPath and then try to match those subtrees against
123      *  this tree pattern.
124      *
125      *  @param tree The {@link ParseTree} to match against this pattern.
126      *  @param xpath An expression matching the nodes
127      *
128      *  @return A collection of {@link ParseTreeMatch} objects describing the
129      * successful matches. Unsuccessful matches are omitted from the result,
130      * regardless of the reason for the failure.
131      */
132     public ParseTreeMatch[] findAll(ParseTree tree, string xpath)
133     {
134         ParseTree[] subtrees = XPath.findAll(tree, xpath, matcher.getParser());
135         ParseTreeMatch[] matches;
136         foreach (ParseTree t; subtrees) {
137             ParseTreeMatch match = match(t);
138             if ( match.succeeded() ) {
139                 matches ~= match;
140             }
141         }
142         return matches;
143     }
144 
145     /**
146      * @uml
147      * et the {@link ParseTreePatternMatcher} which created this tree pattern.
148      *
149      *  @return The {@link ParseTreePatternMatcher} which created this tree
150      * pattern.
151      */
152     public ParseTreePatternMatcher getMatcher()
153     {
154         return matcher;
155     }
156 
157     /**
158      * @uml
159      * Get the tree pattern in concrete syntax form.
160      *
161      *  @return The tree pattern in concrete syntax form.
162      */
163     public string getPattern()
164     {
165         return pattern;
166     }
167 
168     /**
169      * @uml
170      * Get the parser rule which serves as the outermost rule for the tree
171      * pattern.
172      *
173      *  @return The parser rule which serves as the outermost rule for the tree
174      * pattern.
175      */
176     public int getPatternRuleIndex()
177     {
178         return patternRuleIndex;
179     }
180 
181     /**
182      * @uml
183      * Get the tree pattern as a {@link ParseTree}. The rule and token tags from
184      * the pattern are present in the parse tree as terminal nodes with a symbol
185      * of type {@link RuleTagToken} or {@link TokenTagToken}.
186      *
187      *  @return The tree pattern as a {@link ParseTree}.
188      */
189     public ParseTree getPatternTree()
190     {
191         return patternTree;
192     }
193 
194 }