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.OR; 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 at least one of the contained 22 * contexts is true. 23 */ 24 class OR : Operator 25 { 26 27 public SemanticContext[] opnds; 28 29 public this(SemanticContext a, SemanticContext b) 30 { 31 SemanticContext[] operands; 32 if (cast(OR)a) operands ~= (cast(OR)a).opnds; 33 else operands ~= a; 34 if (cast(OR)b) operands ~= (cast(OR)b).opnds; 35 else operands ~= b; 36 37 SemanticContext.PrecedencePredicate[] precedencePredicates = 38 filterPrecedencePredicates(operands); 39 if (precedencePredicates.length) { 40 // interested in the transition with the highest precedence 41 SemanticContext.PrecedencePredicate reduced = maxElement(precedencePredicates); 42 operands ~= reduced; 43 } 44 this.opnds = operands; 45 } 46 47 /** 48 * @uml 49 * @override 50 */ 51 public override SemanticContext[] getOperands() 52 { 53 return opnds; 54 } 55 56 /** 57 * @uml 58 * @override 59 */ 60 public override bool opEquals(Object obj) 61 { 62 if (this is obj) 63 return true; 64 if (!cast(OR)obj) 65 return false; 66 return this.opnds == (cast(OR)obj).opnds; 67 } 68 69 /** 70 * @uml 71 * @override 72 * @trusted 73 */ 74 public override size_t toHash() @trusted 75 { 76 return MurmurHash.hashCode(opnds, this.toHash); 77 } 78 79 /** 80 * @uml 81 * @override 82 */ 83 public override bool eval(InterfaceRecognizer parser, RuleContext parserCallStack) 84 { 85 foreach (SemanticContext opnd; opnds) { 86 if (opnd.eval(parser, parserCallStack)) 87 return true; 88 } 89 return false; 90 } 91 92 /** 93 * @uml 94 * @override 95 */ 96 public override SemanticContext evalPrecedence(InterfaceRecognizer parser, RuleContext parserCallStack) 97 { 98 bool differs = false; 99 SemanticContext[] operands; 100 foreach (SemanticContext context; opnds) { 101 SemanticContext evaluated = context.evalPrecedence(parser, parserCallStack); 102 differs |= (evaluated != context); 103 if (evaluated == NONE) { 104 // The OR context is true if any element is true 105 return NONE; 106 } 107 else if (evaluated !is null) { 108 // Reduce the result by skipping false elements 109 operands ~= evaluated; 110 } 111 } 112 113 if (!differs) { 114 return this; 115 } 116 117 if (operands.length == 0) { 118 // all elements were false, so the OR context is false 119 return null; 120 } 121 122 SemanticContext result = operands[0]; 123 for (int i = 1; i < operands.length; i++) { 124 result = SemanticContext.or(result, operands[i]); 125 } 126 return result; 127 } 128 129 /** 130 * @uml 131 * @override 132 */ 133 public override string toString() 134 { 135 return to!string(map!(n => n.toString)(opnds).joiner(" || ")); 136 } 137 138 }