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