protected SemanticContext _getPredicates(NFAState s, NFAState altStartState) { // System.out.println("_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()) { // System.out.println("pred "+transition0.label); p = transition0.label.getSemanticContext(); // ignore backtracking preds not on left edge for this decision if (((SemanticContext.Predicate) p).predicateAST.getType() == ANTLRParser.BACKTRACK_SEMPRED && s == altStartState.transition[0].target) { p = null; // don't count } } // get preds from beyond this state p0 = _getPredicates((NFAState) transition0.target, altStartState); // get preds from other transition Transition transition1 = s.transition[1]; if (transition1 != null) { p1 = _getPredicates((NFAState) transition1.target, altStartState); } // join this&following-right|following-down return SemanticContext.and(p, SemanticContext.or(p0, p1)); }
protected int _detectConfoundingPredicates( NFAState s, Rule enclosingRule, boolean chaseFollowTransitions) { // System.out.println("_detectNonAutobacktrackPredicates("+s+")"); if (!chaseFollowTransitions && s.isAcceptState()) { if (grammar.type == Grammar.LEXER) { // FOLLOW makes no sense (at the moment!) for lexical rules. // assume all char can follow return DETECT_PRED_NOT_FOUND; } return DETECT_PRED_EOR; } if (lookBusy.contains(s)) { // return a copy of an empty set; we may modify set inline return DETECT_PRED_NOT_FOUND; } lookBusy.add(s); Transition transition0 = s.transition[0]; if (transition0 == null) { return DETECT_PRED_NOT_FOUND; } if (!(transition0.label.isSemanticPredicate() || transition0.label.isEpsilon())) { return DETECT_PRED_NOT_FOUND; } if (transition0.label.isSemanticPredicate()) { // System.out.println("pred "+transition0.label); SemanticContext ctx = transition0.label.getSemanticContext(); SemanticContext.Predicate p = (SemanticContext.Predicate) ctx; if (p.predicateAST.getType() != ANTLRParser.BACKTRACK_SEMPRED) { return DETECT_PRED_FOUND; } } /* if ( transition0.label.isSemanticPredicate() ) { System.out.println("pred "+transition0.label); SemanticContext ctx = transition0.label.getSemanticContext(); SemanticContext.Predicate p = (SemanticContext.Predicate)ctx; // if a non-syn-pred found not in enclosingRule, say we found one if ( p.predicateAST.getType() != ANTLRParser.BACKTRACK_SEMPRED && !p.predicateAST.enclosingRuleName.equals(enclosingRule.name) ) { System.out.println("found pred "+p+" not in "+enclosingRule.name); return DETECT_PRED_FOUND; } } */ int result = _detectConfoundingPredicates( (NFAState) transition0.target, enclosingRule, chaseFollowTransitions); if (result == DETECT_PRED_FOUND) { return DETECT_PRED_FOUND; } if (result == DETECT_PRED_EOR) { if (transition0 instanceof RuleClosureTransition) { // we called a rule that found the end of the rule. // That means the rule is nullable and we need to // keep looking at what follows the rule ref. E.g., // a : b A ; where b is nullable means that LOOK(a) // should include A. RuleClosureTransition ruleInvocationTrans = (RuleClosureTransition) transition0; NFAState following = (NFAState) ruleInvocationTrans.followState; int afterRuleResult = _detectConfoundingPredicates(following, enclosingRule, chaseFollowTransitions); if (afterRuleResult == DETECT_PRED_FOUND) { return DETECT_PRED_FOUND; } } } Transition transition1 = s.transition[1]; if (transition1 != null) { int t1Result = _detectConfoundingPredicates( (NFAState) transition1.target, enclosingRule, chaseFollowTransitions); if (t1Result == DETECT_PRED_FOUND) { return DETECT_PRED_FOUND; } } return DETECT_PRED_NOT_FOUND; }
protected LookaheadSet _FIRST(NFAState s, boolean chaseFollowTransitions) { /* System.out.println("_LOOK("+s+") in rule "+s.enclosingRule); if ( s.transition[0] instanceof RuleClosureTransition ) { System.out.println("go to rule "+((NFAState)s.transition[0].target).enclosingRule); } */ if (!chaseFollowTransitions && s.isAcceptState()) { if (grammar.type == Grammar.LEXER) { // FOLLOW makes no sense (at the moment!) for lexical rules. // assume all char can follow return new LookaheadSet(IntervalSet.COMPLETE_SET); } return new LookaheadSet(Label.EOR_TOKEN_TYPE); } if (lookBusy.contains(s)) { // return a copy of an empty set; we may modify set inline return new LookaheadSet(); } lookBusy.add(s); Transition transition0 = s.transition[0]; if (transition0 == null) { return null; } if (transition0.label.isAtom()) { int atom = transition0.label.getAtom(); return new LookaheadSet(atom); } if (transition0.label.isSet()) { IntSet sl = transition0.label.getSet(); return new LookaheadSet(sl); } // compute FIRST of transition 0 LookaheadSet tset = null; // if transition 0 is a rule call and we don't want FOLLOW, check cache if (!chaseFollowTransitions && transition0 instanceof RuleClosureTransition) { LookaheadSet prev = FIRSTCache.get((NFAState) transition0.target); if (prev != null) { tset = new LookaheadSet(prev); } } // if not in cache, must compute if (tset == null) { tset = _FIRST((NFAState) transition0.target, chaseFollowTransitions); // save FIRST cache for transition 0 if rule call if (!chaseFollowTransitions && transition0 instanceof RuleClosureTransition) { FIRSTCache.put((NFAState) transition0.target, tset); } } // did we fall off the end? if (grammar.type != Grammar.LEXER && tset.member(Label.EOR_TOKEN_TYPE)) { if (transition0 instanceof RuleClosureTransition) { // we called a rule that found the end of the rule. // That means the rule is nullable and we need to // keep looking at what follows the rule ref. E.g., // a : b A ; where b is nullable means that LOOK(a) // should include A. RuleClosureTransition ruleInvocationTrans = (RuleClosureTransition) transition0; // remove the EOR and get what follows // tset.remove(Label.EOR_TOKEN_TYPE); NFAState following = (NFAState) ruleInvocationTrans.followState; LookaheadSet fset = _FIRST(following, chaseFollowTransitions); fset.orInPlace(tset); // tset cached; or into new set fset.remove(Label.EOR_TOKEN_TYPE); tset = fset; } } Transition transition1 = s.transition[1]; if (transition1 != null) { LookaheadSet tset1 = _FIRST((NFAState) transition1.target, chaseFollowTransitions); tset1.orInPlace(tset); // tset cached; or into new set tset = tset1; } return tset; }