1 module antlr.v4.runtime.atn.AND;
2 
3 import std.conv;
4 import std.algorithm.comparison;
5 import std.algorithm.iteration;
6 import antlr.v4.runtime.InterfaceRecognizer;
7 import antlr.v4.runtime.Token;
8 import antlr.v4.runtime.atn.Operator;
9 import antlr.v4.runtime.RuleContext;
10 import antlr.v4.runtime.atn.SemanticContext;
11 import antlr.v4.runtime.misc.MurmurHash;
12 
13 // Class AND
14 /**
15  * TODO add class description
16  */
17 class AND : Operator
18 {
19 
20     public SemanticContext[] opnds;
21 
22     public this(SemanticContext a, SemanticContext b)
23     {
24     }
25 
26     /**
27      * @uml
28      * @override
29      */
30     public override SemanticContext[] getOperands()
31     {
32         return opnds;
33     }
34 
35     /**
36      * @uml
37      * @override
38      */
39     public override bool opEquals(Object obj)
40     {
41 	if (this is obj) return true;
42         if (obj.classinfo != AND.classinfo) return false;
43         AND other = cast(AND)obj;
44         return equal(this.opnds, other.opnds);
45     }
46 
47     /**
48      * @uml
49      * @override
50      * @trusted
51      */
52     public override size_t toHash() @trusted
53     {
54         return MurmurHash.hashCode(opnds, this.toHash);
55     }
56 
57     /**
58      * @uml
59      * @override
60      */
61     public override bool eval(InterfaceRecognizer parser, RuleContext parserCallStack)
62     {
63 	foreach (SemanticContext opnd; opnds) {
64             if (!opnd.eval(parser, parserCallStack)) return false;
65         }
66         return true;
67     }
68 
69     /**
70      * @uml
71      * @override
72      */
73     public override SemanticContext evalPrecedence(InterfaceRecognizer parser, RuleContext parserCallStack)
74     {
75 	bool differs = false;
76         SemanticContext[] operands;
77         foreach (SemanticContext context; opnds) {
78             SemanticContext evaluated = context.evalPrecedence(parser, parserCallStack);
79             differs |= (evaluated != context);
80             if (evaluated is null) {
81                 // The AND context is false if any element is false
82                 return null;
83             }
84             else if (evaluated != NONE) {
85                 // Reduce the result by skipping true elements
86                 operands ~= evaluated;
87             }
88         }
89 
90         if (!differs) {
91             return this;
92         }
93 
94         if (operands.length == 0) {
95             // all elements were true, so the AND context is true
96             return NONE;
97         }
98 
99         SemanticContext result = operands[0];
100         for (int i = 1; i < operands.length; i++) {
101             result = SemanticContext.and(result, operands[i]);
102         }
103 
104         return result;
105 	
106     }
107 
108     /**
109      * @uml
110      * @override
111      */
112     public override string toString()
113     {
114         return to!string(map!(n => n.toString)(opnds).joiner(" && "));
115     }
116 
117 }