1*37748cd8SNickeau<?php 2*37748cd8SNickeau 3*37748cd8SNickeaudeclare(strict_types=1); 4*37748cd8SNickeau 5*37748cd8SNickeaunamespace Antlr\Antlr4\Runtime\Atn\SemanticContexts; 6*37748cd8SNickeau 7*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Comparison\Hashable; 8*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Recognizer; 9*37748cd8SNickeauuse Antlr\Antlr4\Runtime\RuleContext; 10*37748cd8SNickeauuse Antlr\Antlr4\Runtime\Utils\Set; 11*37748cd8SNickeau 12*37748cd8SNickeau/** 13*37748cd8SNickeau * A tree structure used to record the semantic context in which 14*37748cd8SNickeau * an ATN configuration is valid. It's either a single predicate, 15*37748cd8SNickeau * a conjunction `p1&&p2`, or a sum of products `p1 || p2`. 16*37748cd8SNickeau * 17*37748cd8SNickeau * I have scoped the {@see AndOperator}, {@see OrOperator}, and 18*37748cd8SNickeau * {@see PrecedencePredicate} subclasses of {@see SemanticContext} within 19*37748cd8SNickeau * the scope of this outer class. 20*37748cd8SNickeau */ 21*37748cd8SNickeauabstract class SemanticContext implements Hashable 22*37748cd8SNickeau{ 23*37748cd8SNickeau /** 24*37748cd8SNickeau * The default {@see SemanticContext}, which is semantically equivalent to 25*37748cd8SNickeau * a predicate of the form `{true}?`. 26*37748cd8SNickeau */ 27*37748cd8SNickeau public static function none() : Predicate 28*37748cd8SNickeau { 29*37748cd8SNickeau static $none; 30*37748cd8SNickeau 31*37748cd8SNickeau return $none = $none ?? new Predicate(); 32*37748cd8SNickeau } 33*37748cd8SNickeau 34*37748cd8SNickeau public static function andContext(?self $a, ?self $b) : ?self 35*37748cd8SNickeau { 36*37748cd8SNickeau if ($a === null || $a === self::none()) { 37*37748cd8SNickeau return $b; 38*37748cd8SNickeau } 39*37748cd8SNickeau 40*37748cd8SNickeau if ($b === null || $b === self::none()) { 41*37748cd8SNickeau return $a; 42*37748cd8SNickeau } 43*37748cd8SNickeau 44*37748cd8SNickeau $result = new AndOperator($a, $b); 45*37748cd8SNickeau 46*37748cd8SNickeau return \count($result->operands) === 1 ? $result->operands[0] : $result; 47*37748cd8SNickeau } 48*37748cd8SNickeau 49*37748cd8SNickeau public static function orContext(?self $a, ?self $b) : ?self 50*37748cd8SNickeau { 51*37748cd8SNickeau if ($a === null) { 52*37748cd8SNickeau return $b; 53*37748cd8SNickeau } 54*37748cd8SNickeau 55*37748cd8SNickeau if ($b === null) { 56*37748cd8SNickeau return $a; 57*37748cd8SNickeau } 58*37748cd8SNickeau 59*37748cd8SNickeau if ($a === self::none() || $b === self::none()) { 60*37748cd8SNickeau return self::none(); 61*37748cd8SNickeau } 62*37748cd8SNickeau 63*37748cd8SNickeau $result = new OrOperator($a, $b); 64*37748cd8SNickeau 65*37748cd8SNickeau return \count($result->operand) === 1 ? $result->operand[0] : $result; 66*37748cd8SNickeau } 67*37748cd8SNickeau 68*37748cd8SNickeau /** 69*37748cd8SNickeau * For context independent predicates, we evaluate them without a local 70*37748cd8SNickeau * context (i.e., null context). That way, we can evaluate them without 71*37748cd8SNickeau * having to create proper rule-specific context during prediction (as 72*37748cd8SNickeau * opposed to the parser, which creates them naturally). In a practical 73*37748cd8SNickeau * sense, this avoids a cast exception from RuleContext to myruleContext. 74*37748cd8SNickeau * 75*37748cd8SNickeau * For context dependent predicates, we must pass in a local context so that 76*37748cd8SNickeau * references such as $arg evaluate properly as _localctx.arg. We only 77*37748cd8SNickeau * capture context dependent predicates in the context in which we begin 78*37748cd8SNickeau * prediction, so we passed in the outer context here in case of context 79*37748cd8SNickeau * dependent predicate evaluation. 80*37748cd8SNickeau */ 81*37748cd8SNickeau abstract public function eval(Recognizer $parser, RuleContext $parserCallStack); 82*37748cd8SNickeau 83*37748cd8SNickeau /** 84*37748cd8SNickeau * Evaluate the precedence predicates for the context and reduce the result. 85*37748cd8SNickeau * 86*37748cd8SNickeau * @param Recognizer $parser The parser instance. 87*37748cd8SNickeau * 88*37748cd8SNickeau * @return self|null The simplified semantic context after precedence predicates 89*37748cd8SNickeau * are evaluated, which will be one of the following values. 90*37748cd8SNickeau * 91*37748cd8SNickeau * - {@see self::NONE()}: if the predicate simplifies to 92*37748cd8SNickeau * `true` after precedence predicates are evaluated. 93*37748cd8SNickeau * - `null`: if the predicate simplifies to `false` after 94*37748cd8SNickeau * precedence predicates are evaluated. 95*37748cd8SNickeau * - `this`: if the semantic context is not changed 96*37748cd8SNickeau * as a result of precedence predicate evaluation. 97*37748cd8SNickeau * - A non-`null` {@see SemanticContext}: if the new simplified 98*37748cd8SNickeau * semantic context after precedence predicates are evaluated. 99*37748cd8SNickeau */ 100*37748cd8SNickeau public function evalPrecedence(Recognizer $parser, RuleContext $parserCallStack) : ?self 101*37748cd8SNickeau { 102*37748cd8SNickeau return $this; 103*37748cd8SNickeau } 104*37748cd8SNickeau 105*37748cd8SNickeau /** 106*37748cd8SNickeau * @return array<PrecedencePredicate> 107*37748cd8SNickeau */ 108*37748cd8SNickeau public static function filterPrecedencePredicates(Set $set) : array 109*37748cd8SNickeau { 110*37748cd8SNickeau $result = []; 111*37748cd8SNickeau foreach ($set->getValues() as $context) { 112*37748cd8SNickeau if ($context instanceof PrecedencePredicate) { 113*37748cd8SNickeau $result[] = $context; 114*37748cd8SNickeau } 115*37748cd8SNickeau } 116*37748cd8SNickeau 117*37748cd8SNickeau return $result; 118*37748cd8SNickeau } 119*37748cd8SNickeau 120*37748cd8SNickeau abstract public function __toString() : string; 121*37748cd8SNickeau} 122