@Override protected void visitState(ATNState p) { super.visitState(p); if (p.getNumberOfTransitions() > 1) { return; } Transition transition = p.transition(0); if (transition instanceof RuleTransition) { // rule transition created a new context associatedTransitions.put(_ctx, transition); } else if (!p.onlyHasEpsilonTransitions()) { // match transition created a new terminal or error node associatedTransitions.put(_ctx.getChild(_ctx.getChildCount() - 1), transition); } }
@Override public void visitState(ATNState p) { if (p.getStateType() == ATNState.BASIC && p.getNumberOfTransitions() == 1) { ATNState q = p.transition(0).target; if (p.transition(0) instanceof RuleTransition) { q = ((RuleTransition) p.transition(0)).followState; } if (q.getStateType() == ATNState.BASIC) { // we have p-x->q for x in {rule, action, pred, token, ...} // if edge out of q is single epsilon to block end // we can strip epsilon p-x->q-eps->r Transition trans = q.transition(0); if (q.getNumberOfTransitions() == 1 && trans instanceof EpsilonTransition) { ATNState r = trans.target; if (r instanceof BlockEndState || r instanceof PlusLoopbackState || r instanceof StarLoopbackState) { // skip over q if (p.transition(0) instanceof RuleTransition) { ((RuleTransition) p.transition(0)).followState = r; } else { p.transition(0).target = r; } _atn.removeState(q); } } } } }
public void visit_(ATNState s, Set<Integer> visited) { if ( !visited.add(s.stateNumber) ) return; visited.add(s.stateNumber); visitState(s); int n = s.getNumberOfTransitions(); for (int i=0; i<n; i++) { Transition t = s.transition(i); visit_(t.target, visited); } }
public Handle elemList(List<Handle> els) { int n = els.size(); for (int i = 0; i < n - 1; i++) { // hook up elements (visit all but last) Handle el = els.get(i); // if el is of form o-x->o for x in {rule, action, pred, token, ...} // and not last in alt Transition tr = null; if ( el.left.getNumberOfTransitions()==1 ) tr = el.left.transition(0); boolean isRuleTrans = tr instanceof RuleTransition; if ( el.left.getStateType() == ATNState.BASIC && el.right.getStateType()== ATNState.BASIC && tr!=null && (isRuleTrans && ((RuleTransition)tr).followState == el.right || tr.target == el.right) ) { // we can avoid epsilon edge to next el if ( isRuleTrans ) ((RuleTransition)tr).followState = els.get(i+1).left; else tr.target = els.get(i+1).left; atn.removeState(el.right); // we skipped over this state } else { // need epsilon if previous block's right end node is complicated epsilon(el.right, els.get(i+1).left); } } Handle first = els.get(0); Handle last = els.get(n -1); if ( first==null || last==null ) { g.tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, "element list has first|last == null"); } return new Handle(first.left, last.right); }
/** Add an EOF transition to any rule end ATNState that points to nothing * (i.e., for all those rules not invoked by another rule). These * are start symbols then. * * Return the number of grammar entry points; i.e., how many rules are * not invoked by another rule (they can only be invoked from outside). * These are the start rules. */ public int addEOFTransitionToStartRules() { int n = 0; ATNState eofTarget = newState(null); // one unique EOF target for all rules for (Rule r : g.rules.values()) { ATNState stop = atn.ruleToStopState[r.index]; if ( stop.getNumberOfTransitions()>0 ) continue; n++; Transition t = new AtomTransition(eofTarget, Token.EOF); stop.addTransition(t); } return n; }
/** From state s, look for any transition to a rule that is currently * being traced. When tracing r, visitedPerRuleCheck has r * initially. If you reach a rule stop state, return but notify the * invoking rule that the called rule is nullable. This implies that * invoking rule must look at follow transition for that invoking state. * * The visitedStates tracks visited states within a single rule so * we can avoid epsilon-loop-induced infinite recursion here. Keep * filling the cycles in listOfRecursiveCycles and also, as a * side-effect, set leftRecursiveRules. */ public boolean check(Rule enclosingRule, ATNState s, Set<ATNState> visitedStates) { if ( s instanceof RuleStopState) return true; if ( visitedStates.contains(s) ) return false; visitedStates.add(s); //System.out.println("visit "+s); int n = s.getNumberOfTransitions(); boolean stateReachesStopState = false; for (int i=0; i<n; i++) { Transition t = s.transition(i); if ( t instanceof RuleTransition ) { RuleTransition rt = (RuleTransition) t; Rule r = g.getRule(rt.ruleIndex); if ( rulesVisitedPerRuleCheck.contains((RuleStartState)t.target) ) { addRulesToCycle(enclosingRule, r); } else { // must visit if not already visited; mark target, pop when done rulesVisitedPerRuleCheck.add((RuleStartState)t.target); // send new visitedStates set per rule invocation boolean nullable = check(r, t.target, new HashSet<ATNState>()); // we're back from visiting that rule rulesVisitedPerRuleCheck.remove((RuleStartState)t.target); if ( nullable ) { stateReachesStopState |= check(enclosingRule, rt.followState, visitedStates); } } } else if ( t.isEpsilon() ) { stateReachesStopState |= check(enclosingRule, t.target, visitedStates); } // else ignore non-epsilon transitions } return stateReachesStopState; }
private static Transition createSetTransition(ATNState target, IntervalSet set) { if (set.getIntervals().size() == 1) { Interval interval = set.getIntervals().get(0); if (interval.a == interval.b) { return new AtomTransition(target, interval.a); } else { return new RangeTransition(target, interval.a, interval.b); } } else { return new SetTransition(target, set); } }
@Override public ATNState getReachableTarget(ATNConfig source, Transition trans, int ttype) { if (trans instanceof RuleTransition) { IntervalSet suppressed = getSuppressedSet(startIndex); if (suppressed.contains(((RuleTransition)trans).ruleIndex)) { return null; } } return super.getReachableTarget(source, trans, ttype); }
public ParserDebuggerParseTreeNode(@NonNull ParseTree tree, @NullAllowed List<String> ruleNames, Set<ParseTree> errorNodes, Map<ParseTree, Transition> associatedTransitions) { super(tree, ruleNames); this.errorNodes = errorNodes; this.associatedTransitions = associatedTransitions; }
@RuleDependencies({ @RuleDependency(recognizer=GrammarParser.class, rule=GrammarParser.RULE_lexerCommandName, version=0, dependents=Dependents.SELF), @RuleDependency(recognizer=GrammarParser.class, rule=GrammarParser.RULE_id, version=6, dependents=Dependents.PARENTS), }) private void analyzeKeywords(Map<RuleContext, CaretReachedException> parseTrees, Map<String, CompletionItem> intermediateResults) { boolean maybeLexerCommand = false; IntervalSet remainingKeywords = new IntervalSet(KeywordCompletionItem.KEYWORD_TYPES); for (Map.Entry<RuleContext, CaretReachedException> entry : parseTrees.entrySet()) { CaretReachedException caretReachedException = entry.getValue(); if (caretReachedException == null || caretReachedException.getTransitions() == null) { continue; } RuleContext finalContext = caretReachedException.getFinalContext(); if (finalContext.getRuleIndex() == GrammarParser.RULE_id) { RuleContext parent = finalContext.getParent(); if (parent != null && parent.getRuleIndex() == GrammarParser.RULE_lexerCommandName) { maybeLexerCommand = true; } continue; } Map<ATNConfig, List<Transition>> transitions = caretReachedException.getTransitions(); for (List<Transition> transitionList : transitions.values()) { for (Transition transition : transitionList) { if (transition.isEpsilon() || transition instanceof WildcardTransition || transition instanceof NotSetTransition) { continue; } IntervalSet label = transition.label(); if (label == null) { continue; } for (int keyword : remainingKeywords.toArray()) { if (label.contains(keyword)) { remainingKeywords.remove(keyword); KeywordCompletionItem item = KeywordCompletionItem.KEYWORD_ITEMS.get(keyword); intermediateResults.put(item.getInsertPrefix().toString(), item); } } } } } if (maybeLexerCommand) { addLexerCommands(intermediateResults); } }
public Map<ATNConfig, List<Transition>> getCaretTransitions() { return caretTransitions; }
@Override public ATNState getReachableTarget(ATNConfig source, Transition trans, int ttype) { if (ttype == CaretToken.CARET_TOKEN_TYPE) { ATNState target = null; if (trans instanceof AtomTransition) { AtomTransition at = (AtomTransition)trans; if (getWordlikeTokenTypes().contains(at.label)) { target = at.target; } } else if (trans instanceof SetTransition) { SetTransition st = (SetTransition)trans; boolean not = trans instanceof NotSetTransition; // TODO: this could probably be done with an intersects method? for (int t : getWordlikeTokenTypes().toArray()) { if (!not && st.set.contains(t) || not && !st.set.contains(t)) { target = st.target; break; } } } else if (trans instanceof RangeTransition) { RangeTransition rt = (RangeTransition)trans; // TODO: there must be a better algorithm here :) int[] wordlikeTokenTypes = getWordlikeTokenTypes().toArray(); int lb = Arrays.binarySearch(wordlikeTokenTypes, rt.from); int ub = Arrays.binarySearch(wordlikeTokenTypes, rt.to); if (lb >= 0 || ub >= 0 || lb != ub) { target = rt.target; } } else if (trans instanceof WildcardTransition) { target = trans.target; } if (caretTransitions == null) { caretTransitions = new LinkedHashMap<>(); } List<Transition> configTransitions = caretTransitions.get(source); if (configTransitions == null) { configTransitions = new ArrayList<>(); caretTransitions.put(source, configTransitions); } configTransitions.add(trans); return target; } return super.getReachableTarget(source, trans, ttype); }
public CaretReachedException(RuleContext finalContext, CaretToken caretToken, Map<ATNConfig, List<Transition>> transitions, RecognitionException cause) { super(cause); this.finalContext = finalContext; this.caretToken = caretToken; this.transitions = transitions; }
public Map<ATNConfig, List<Transition>> getTransitions() { return transitions; }