1 /*
2  * [The "BSD license"]
3  *  Copyright (c) 2016 Terence Parr
4  *  Copyright (c) 2016 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.atn.SemanticContext;
33 
34 import std.conv;
35 import antlr.v4.runtime.RuleContext;
36 import antlr.v4.runtime.InterfaceRecognizer;
37 import antlr.v4.runtime.atn.AND;
38 import antlr.v4.runtime.atn.OR;
39 import antlr.v4.runtime.misc.MurmurHash;
40 
41 
42 /**
43  * @uml
44  * A tree structure used to record the semantic context in which
45  * an ATN configuration is valid.  It's either a single predicate,
46  * a conjunction {@code p1&&p2}, or a sum of products {@code p1||p2}.
47  *
48  * <p>I have scoped the {@link AND}, {@link OR}, and {@link Predicate} subclasses of
49  * {@link SemanticContext} within the scope of this outer class.</p>
50  */
51 class SemanticContext
52 {
53     public bool eval(InterfaceRecognizer parser, RuleContext parserCallStack)
54     {
55         return true;
56     }
57     /**
58      * @uml
59      * The default {@link SemanticContext}, which is semantically equivalent to
60      * a predicate of the form {@code {true}?}.
61      */
62     public static SemanticContext NONE;
63 
64 
65     /**
66      * @uml
67      * For context independent predicates, we evaluate them without a local
68      * context (i.e., null context). That way, we can evaluate them without
69      * having to create proper rule-specific context during prediction (as
70      * opposed to the parser, which creates them naturally). In a practical
71      * sense, this avoids a cast exception from RuleContext to myruleContext.
72      *
73      * <p>For context dependent predicates, we must pass in a local context so that
74      * references such as $arg evaluate properly as _localctx.arg. We only
75      * capture context dependent predicates in the context in which we begin
76      * prediction, so we passed in the outer context here in case of context
77      * dependent predicate evaluation.</p>
78      */
79     //abstract public bool eval(InterfaceRecognizer parser, RuleContext parserCallStack);
80 
81     /**
82      * @uml
83      * Evaluate the precedence predicates for the context and reduce the result.
84      *
85      *  @param parser The parser instance.
86      *  @param parserCallStack
87      *  @return The simplified semantic context after precedence predicates are
88      *  evaluated, which will be one of the following values.
89      * <ul>
90      *  <li>{@link #NONE}: if the predicate simplifies to {@code true} after
91      *  precedence predicates are evaluated.</li>
92      *  <li>{@code null}: if the predicate simplifies to {@code false} after
93      *  precedence predicates are evaluated.</li>
94      *  <li>{@code this}: if the semantic context is not changed as a result of
95      *  precedence predicate evaluation.</li>
96      *  <li>A non-{@code null} {@link SemanticContext}: the new simplified
97      *  semantic context after precedence predicates are evaluated.</li>
98      * </ul>
99      */
100     public SemanticContext evalPrecedence(InterfaceRecognizer parser, RuleContext parserCallStack)
101     {
102         return this;
103     }
104     // Class Predicate
105     /**
106      * TODO add class description
107      */
108     class Predicate : SemanticContext
109     {
110         /**
111          * The single instance of LexerMoreAction.
112          */
113         private static __gshared Predicate instance_;
114 
115         public int ruleIndex;
116 
117         public int predIndex;
118 
119         /**
120          * @uml
121          * e.g., $i ref in pred
122          */
123         public bool isCtxDependent;
124 
125         public this()
126         {
127             this.ruleIndex = -1;
128             this.predIndex = -1;
129             this.isCtxDependent = false;
130         }
131 
132         public this(int ruleIndex, int predIndex, bool isCtxDependent)
133         {
134             this.ruleIndex = ruleIndex;
135             this.predIndex = predIndex;
136             this.isCtxDependent = isCtxDependent;
137         }
138 
139         /**
140          * @uml
141          * @override
142          */
143         public override bool eval(InterfaceRecognizer parser, RuleContext parserCallStack)
144         {
145             RuleContext localctx = isCtxDependent ? parserCallStack : null;
146             return parser.sempred(localctx, ruleIndex, predIndex);
147         }
148 
149         /**
150          * @uml
151          * @override
152          * @safe
153          * @nothrow
154          */
155         public override size_t toHash() @safe nothrow
156         {
157             size_t hashCode = MurmurHash.initialize();
158             hashCode = MurmurHash.update(hashCode, ruleIndex);
159             hashCode = MurmurHash.update(hashCode, predIndex);
160             hashCode = MurmurHash.update(hashCode, isCtxDependent ? 1 : 0);
161             hashCode = MurmurHash.finish(hashCode, 3);
162             return hashCode;
163         }
164 
165         /**
166          * @uml
167          * @override
168          */
169         public override bool opEquals(Object obj)
170         {
171             if (typeid(typeof(obj)) != typeid(Predicate*)) return false;
172             if ( this is obj ) return true;
173             Predicate p = cast(Predicate)obj;
174             return this.ruleIndex == p.ruleIndex &&
175                 this.predIndex == p.predIndex &&
176                 this.isCtxDependent == p.isCtxDependent;
177         }
178 
179         /**
180          * @uml
181          * @override
182          */
183         public override string toString()
184         {
185             return "{" ~ to!string(ruleIndex) ~ ":" ~ to!string(predIndex) ~ "}?";
186         }
187 
188         // /**
189         //  * Creates the single instance of Predicate.
190         //  */
191         // private shared static this()
192         // {
193         //     instance_ = new Predicate;
194         // }
195 
196         // /**
197         //  * Returns: A single instance of LexerMoreAction.
198         //  */
199         // public static Predicate instance()
200         // {
201         //     return instance_;
202         // }
203 
204     }
205     // Class PrecedencePredicate
206     /**
207      * TODO add class description
208      */
209     class PrecedencePredicate : SemanticContext
210     {
211 
212         /**
213          * @uml
214          * @final
215          */
216         public int precedence;
217 
218         protected this()
219         {
220             this.precedence = 0;
221         }
222 
223         public this(int precedence)
224         {
225             this.precedence = precedence;
226         }
227 
228         /**
229          * @uml
230          * @override
231          */
232         public override bool eval(InterfaceRecognizer parser, RuleContext parserCallStack)
233         {
234             return parser.precpred(parserCallStack, precedence);
235         }
236 
237         /**
238          * @uml
239          * @override
240          */
241         public override SemanticContext evalPrecedence(InterfaceRecognizer parser, RuleContext parserCallStack)
242         {
243             if (parser.precpred(parserCallStack, precedence)) {
244                 if (!SemanticContext.NONE)
245                     SemanticContext.NONE = new Predicate;
246                 return SemanticContext.NONE;
247             }
248             else {
249                 return null;
250             }
251         }
252 
253         /**
254          * @uml
255          * @override
256          */
257         public override int opCmp(Object o)
258         {
259             return precedence - (cast(PrecedencePredicate)o).precedence;
260         }
261 
262         /**
263          * @uml
264          * @override
265          * @safe
266          * @nothrow
267          */
268         public override size_t toHash() @safe nothrow
269         {
270             int hashCode = 1;
271             hashCode = 31 * hashCode + precedence;
272             return hashCode;
273         }
274 
275         /**
276          * @uml
277          * @override
278          */
279         public override bool opEquals(Object obj)
280         {
281             if (! cast(PrecedencePredicate)obj) {
282                 return false;
283             }
284 
285             if (this is obj) {
286                 return true;
287             }
288 
289             PrecedencePredicate other = cast(PrecedencePredicate)obj;
290             return this.precedence == other.precedence;
291         }
292 
293         /**
294          * @uml
295          * @override
296          * precedence >= _precedenceStack.peek()
297          */
298         public override string toString()
299         {
300             return "{" ~ to!string(precedence) ~ ">=prec}?";
301         }
302 
303     }
304 
305     /**
306      * @uml
307      * @safe
308      * @nothrow
309      * @override
310      */
311     public override size_t toHash() @safe nothrow
312     {
313         return 1;
314     }
315 
316     public static SemanticContext and(SemanticContext a, SemanticContext b)
317     {
318         if (a is null || a == NONE )
319             return b;
320         if (b is null || b == NONE )
321             return a;
322         AND result = new AND(a, b);
323         if (result.opnds.length == 1) {
324             return result.opnds[0];
325         }
326         return result;
327     }
328 
329     public static SemanticContext or(SemanticContext a, SemanticContext b)
330     {
331         if (a is null )
332             return b;
333         if (b is null )
334             return a;
335         if (a == NONE || b == NONE ) return NONE;
336         OR result = new OR(a, b);
337         if (result.opnds.length == 1) {
338             return result.opnds[0];
339         }
340         return result;
341     }
342 
343     public PrecedencePredicate[] filterPrecedencePredicates(SemanticContext[] collection)
344     {
345         PrecedencePredicate[] result;
346         foreach (context; collection) {
347             if (cast(PrecedencePredicate)context) {
348                 result ~= cast(PrecedencePredicate)context;
349             }
350         }
351         return result;
352     }
353 
354 }