1 /* 2 * Copyright (c) 2012-2018 The ANTLR Project. All rights reserved. 3 * Use of this file is governed by the BSD 3-clause license that 4 * can be found in the LICENSE.txt file in the project root. 5 */ 6 7 module antlr.v4.runtime.atn.AND; 8 9 import antlr.v4.runtime.InterfaceRecognizer; 10 import antlr.v4.runtime.RuleContext; 11 import antlr.v4.runtime.Token; 12 import antlr.v4.runtime.atn.Operator; 13 import antlr.v4.runtime.atn.SemanticContext; 14 import antlr.v4.runtime.misc.MurmurHash; 15 import std.algorithm.comparison; 16 import std.algorithm.iteration; 17 import std.algorithm.searching; 18 import std.conv; 19 20 /** 21 * A semantic context which is true whenever none of the contained contexts 22 * is false. 23 24 */ 25 class AND : Operator 26 { 27 28 public SemanticContext[] opnds; 29 30 public this(SemanticContext a, SemanticContext b) 31 { 32 SemanticContext[] operands; 33 if (cast(AND)a) operands ~= (cast(AND)a).opnds; 34 else operands ~= a; 35 if (cast(AND)b) operands ~= (cast(AND)b).opnds; 36 else operands ~= b; 37 38 SemanticContext.PrecedencePredicate[] precedencePredicates = 39 filterPrecedencePredicates(operands); 40 if (precedencePredicates.length) { 41 // interested in the transition with the lowest precedence 42 SemanticContext.PrecedencePredicate reduced = minElement(precedencePredicates); 43 operands ~= reduced; 44 } 45 this.opnds = operands; 46 } 47 48 /** 49 * @uml 50 * @override 51 */ 52 public override SemanticContext[] getOperands() 53 { 54 return opnds; 55 } 56 57 /** 58 * @uml 59 * @override 60 */ 61 public override bool opEquals(Object obj) 62 { 63 if (this is obj) 64 return true; 65 if (!cast(AND)obj) 66 return false; 67 AND other = cast(AND)obj; 68 return equal(this.opnds, other.opnds); 69 } 70 71 /** 72 * @uml 73 * @override 74 * @trusted 75 */ 76 public override size_t toHash() @trusted 77 { 78 return MurmurHash.hashCode(opnds, this.toHash); 79 } 80 81 /** 82 * @uml 83 * @override 84 */ 85 public override bool eval(InterfaceRecognizer parser, RuleContext parserCallStack) 86 { 87 foreach (SemanticContext opnd; opnds) { 88 if (!opnd.eval(parser, parserCallStack)) 89 return false; 90 } 91 return true; 92 } 93 94 /** 95 * @uml 96 * @override 97 */ 98 public override SemanticContext evalPrecedence(InterfaceRecognizer parser, RuleContext parserCallStack) 99 { 100 bool differs = false; 101 SemanticContext[] operands; 102 foreach (SemanticContext context; opnds) { 103 SemanticContext evaluated = context.evalPrecedence(parser, parserCallStack); 104 differs |= (evaluated != context); 105 if (evaluated is null) { 106 // The AND context is false if any element is false 107 return null; 108 } 109 else if (evaluated != NONE) { 110 // Reduce the result by skipping true elements 111 operands ~= evaluated; 112 } 113 } 114 115 if (!differs) { 116 return this; 117 } 118 119 if (operands.length == 0) { 120 // all elements were true, so the AND context is true 121 return NONE; 122 } 123 124 SemanticContext result = operands[0]; 125 for (int i = 1; i < operands.length; i++) { 126 result = SemanticContext.and(result, operands[i]); 127 } 128 129 return result; 130 131 } 132 133 /** 134 * @uml 135 * @override 136 */ 137 public override string toString() 138 { 139 return to!string(map!(n => n.toString)(opnds).joiner(" && ")); 140 } 141 142 }