/** For gated productions, we need an OR'd list of all predicates for the * target of an edge so we can gate the edge based upon the predicates * associated with taking that path (if any). * * For syntactic predicates, we only want to generate predicate * evaluations as it transitions to an accept state; waste to * do it earlier. So, only add gated preds derived from manually- * specified syntactic predicates if this is an accept state. * * Also, since configurations w/o gated predicates are like true * gated predicates, finding a configuration whose alt has no gated * predicate implies we should evaluate the predicate to true. This * means the whole edge has to be ungated. Consider: * * X : ('a' | {p}?=> 'a') * | 'a' 'b' * ; * * Here, you 'a' gets you from s0 to s1 but you can't test p because * plain 'a' is ok. It's also ok for starting alt 2. Hence, you can't * test p. Even on the edge going to accept state for alt 1 of X, you * can't test p. You can get to the same place with and w/o the context. * Therefore, it is never ok to test p in this situation. * * TODO: cache this as it's called a lot; or at least set bit if >1 present in state */ public virtual SemanticContext GetGatedPredicatesInNFAConfigurations() { SemanticContext unionOfPredicatesFromAllAlts = null; int numConfigs = _nfaConfigurations.Count; for (int i = 0; i < numConfigs; i++) { NFAConfiguration configuration = (NFAConfiguration)_nfaConfigurations[i]; SemanticContext gatedPredExpr = configuration.SemanticContext.GatedPredicateContext; if (gatedPredExpr == null) { // if we ever find a configuration w/o a gated predicate // (even if it's a nongated predicate), we cannot gate // the indident edges. return(null); } else if (IsAcceptState || !configuration.SemanticContext.IsSyntacticPredicate) { // at this point we have a gated predicate and, due to elseif, // we know it's an accept or not a syn pred. In this case, // it's safe to add the gated predicate to the union. We // only want to add syn preds if it's an accept state. Other // gated preds can be used with edges leading to accept states. if (unionOfPredicatesFromAllAlts == null) { unionOfPredicatesFromAllAlts = gatedPredExpr; } else { unionOfPredicatesFromAllAlts = SemanticContext.Or(unionOfPredicatesFromAllAlts, gatedPredExpr); } } } if (unionOfPredicatesFromAllAlts is SemanticContext.TruePredicate) { return(null); } return(unionOfPredicatesFromAllAlts); }
protected virtual SemanticContext GetPredicatesCore(NFAState s, NFAState altStartState) { //[email protected]("_getPredicates("+s+")"); if (s.IsAcceptState) { return(null); } // avoid infinite loops from (..)* etc... if (_lookBusy.Contains(s)) { return(null); } _lookBusy.Add(s); Transition transition0 = s.transition[0]; // no transitions if (transition0 == null) { return(null); } // not a predicate and not even an epsilon if (!(transition0.label.IsSemanticPredicate || transition0.label.IsEpsilon)) { return(null); } SemanticContext p = null; SemanticContext p0 = null; SemanticContext p1 = null; if (transition0.label.IsSemanticPredicate) { //[email protected]("pred "+transition0.label); p = transition0.label.SemanticContext; // ignore backtracking preds not on left edge for this decision if (((SemanticContext.Predicate)p).predicateAST.Type == ANTLRParser.BACKTRACK_SEMPRED && s == altStartState.transition[0].target) { p = null; // don't count } } // get preds from beyond this state p0 = GetPredicatesCore((NFAState)transition0.target, altStartState); // get preds from other transition Transition transition1 = s.transition[1]; if (transition1 != null) { p1 = GetPredicatesCore((NFAState)transition1.target, altStartState); } // join this&following-right|following-down return(SemanticContext.And(p, SemanticContext.Or(p0, p1))); }