예제 #1
0
  /**
   * From (blk)* build ( blk+ )? with *two* decisions, one for entry and one for choosing alts of
   * blk.
   *
   * <p>|-------------| v | o--[o-blk-o]->o o | ^ -----------------|
   *
   * <p>Note that the optional bypass must jump outside the loop as (A|B)* is not the same thing as
   * (A|B|)+.
   */
  @NotNull
  public Handle star(@NotNull GrammarAST starAST, @NotNull Handle elem) {
    StarBlockStartState blkStart = (StarBlockStartState) elem.left;
    BlockEndState blkEnd = (BlockEndState) elem.right;

    StarLoopEntryState entry = newState(StarLoopEntryState.class, starAST);
    atn.defineDecisionState(entry);
    LoopEndState end = newState(LoopEndState.class, starAST);
    StarLoopbackState loop = newState(StarLoopbackState.class, starAST);
    entry.loopBackState = loop;
    end.loopBackStateNumber = loop.stateNumber;

    BlockAST blkAST = (BlockAST) starAST.getChild(0);
    entry.isGreedy = isGreedy(blkAST);
    if (!g.isLexer() || entry.isGreedy) {
      epsilon(entry, blkStart); // loop enter edge (alt 1)
      epsilon(entry, end); // bypass loop edge (alt 2)
    } else { // only lexers flip entry/exit branches for nongreedy
      // if not greedy, priority to exit branch; make it first
      epsilon(entry, end); // bypass loop edge (alt 1)
      epsilon(entry, blkStart); // loop enter edge (alt 2)
    }
    epsilon(blkEnd, loop); // block end hits loop back
    epsilon(loop, entry); // loop back to entry/exit decision

    starAST.atnState = entry; // decision is to enter/exit; blk is its own decision
    return new Handle(entry, end);
  }
예제 #2
0
  /**
   * From (blk)+ build
   *
   * <p>|---------| v | [o-blk-o]->o->o
   *
   * <p>We add a decision for loop back node to the existing one at blk start.
   */
  @NotNull
  public Handle plus(@NotNull GrammarAST plusAST, @NotNull Handle blk) {
    PlusBlockStartState blkStart = (PlusBlockStartState) blk.left;
    BlockEndState blkEnd = (BlockEndState) blk.right;

    PlusLoopbackState loop = newState(PlusLoopbackState.class, plusAST);
    atn.defineDecisionState(loop);
    LoopEndState end = newState(LoopEndState.class, plusAST);
    blkStart.loopBackState = loop;
    end.loopBackStateNumber = loop.stateNumber;

    plusAST.atnState = blkStart;
    epsilon(blkEnd, loop); // blk can see loop back

    BlockAST blkAST = (BlockAST) plusAST.getChild(0);
    loop.isGreedy = isGreedy(blkAST);
    if (!g.isLexer() || loop.isGreedy) {
      epsilon(loop, blkStart); // loop back to start
      epsilon(loop, end); // or exit
    } else { // only lexers flip entry/exit branches for nongreedy
      // if not greedy, priority to exit branch; make it first
      epsilon(loop, end); // exit
      epsilon(loop, blkStart); // loop back to start
    }

    return new Handle(blkStart, end);
  }