예제 #1
0
    def addDFAEdge(self,
                   from_: DFAState,
                   tk: int,
                   to: DFAState = None,
                   cfgs: ATNConfigSet = None) -> DFAState:

        if to is None and cfgs is not None:
            # leading to this call, ATNConfigSet.hasSemanticContext is used as a
            # marker indicating dynamic predicate evaluation makes this edge
            # dependent on the specific input sequence, so the static edge in the
            # DFA should be omitted. The target DFAState is still created since
            # execATN has the ability to resynchronize with the DFA state cache
            # following the predicate evaluation step.
            #
            # TJP notes: next time through the DFA, we see a pred again and eval.
            # If that gets us to a previously created (but dangling) DFA
            # state, we can continue in pure DFA mode from there.
            #/
            suppressEdge = cfgs.hasSemanticContext
            cfgs.hasSemanticContext = False

            to = self.addDFAState(cfgs)

            if suppressEdge:
                return to

        # add the edge
        if tk < self.MIN_DFA_EDGE or tk > self.MAX_DFA_EDGE:
            # Only track edges within the DFA bounds
            return to

        if self.debug:
            print("EDGE " + str(from_) + " -> " + str(to) + " upon " + chr(tk))

        if from_.edges is None:
            #  make room for tokens 1..n and -1 masquerading as index 0
            from_.edges = [None] * (self.MAX_DFA_EDGE - self.MIN_DFA_EDGE + 1)

        from_.edges[tk - self.MIN_DFA_EDGE] = to  # connect

        return to
예제 #2
0
    def addDFAEdge(self, from_:DFAState, tk:int, to:DFAState=None, cfgs:ATNConfigSet=None) -> DFAState:

        if to is None and cfgs is not None:
            # leading to this call, ATNConfigSet.hasSemanticContext is used as a
            # marker indicating dynamic predicate evaluation makes this edge
            # dependent on the specific input sequence, so the static edge in the
            # DFA should be omitted. The target DFAState is still created since
            # execATN has the ability to resynchronize with the DFA state cache
            # following the predicate evaluation step.
            #
            # TJP notes: next time through the DFA, we see a pred again and eval.
            # If that gets us to a previously created (but dangling) DFA
            # state, we can continue in pure DFA mode from there.
            #/
            suppressEdge = cfgs.hasSemanticContext
            cfgs.hasSemanticContext = False

            to = self.addDFAState(cfgs)

            if suppressEdge:
                return to

        # add the edge
        if tk < self.MIN_DFA_EDGE or tk > self.MAX_DFA_EDGE:
            # Only track edges within the DFA bounds
            return to

        if LexerATNSimulator.debug:
            print("EDGE " + str(from_) + " -> " + str(to) + " upon "+ chr(tk))

        if from_.edges is None:
            #  make room for tokens 1..n and -1 masquerading as index 0
            from_.edges = [ None ] * (self.MAX_DFA_EDGE - self.MIN_DFA_EDGE + 1)

        from_.edges[tk - self.MIN_DFA_EDGE] = to # connect

        return to
예제 #3
0
    def getEpsilonTarget(self, input: InputStream, config: LexerATNConfig,
                         t: Transition, configs: ATNConfigSet,
                         speculative: bool, treatEofAsEpsilon: bool):
        c = None
        if t.serializationType == Transition.RULE:
            newContext = SingletonPredictionContext.create(
                config.context, t.followState.stateNumber)
            c = LexerATNConfig(state=t.target,
                               config=config,
                               context=newContext)

        elif t.serializationType == Transition.PRECEDENCE:
            raise UnsupportedOperationException(
                "Precedence predicates are not supported in lexers.")

        elif t.serializationType == Transition.PREDICATE:
            #  Track traversing semantic predicates. If we traverse,
            # we cannot add a DFA state for this "reach" computation
            # because the DFA would not test the predicate again in the
            # future. Rather than creating collections of semantic predicates
            # like v3 and testing them on prediction, v4 will test them on the
            # fly all the time using the ATN not the DFA. This is slower but
            # semantically it's not used that often. One of the key elements to
            # this predicate mechanism is not adding DFA states that see
            # predicates immediately afterwards in the ATN. For example,

            # a : ID {p1}? | ID {p2}? ;

            # should create the start state for rule 'a' (to save start state
            # competition), but should not create target of ID state. The
            # collection of ATN states the following ID references includes
            # states reached by traversing predicates. Since this is when we
            # test them, we cannot cash the DFA state target of ID.

            if self.debug:
                print("EVAL rule " + str(t.ruleIndex) + ":" + str(t.predIndex))
            configs.hasSemanticContext = True
            if self.evaluatePredicate(input, t.ruleIndex, t.predIndex,
                                      speculative):
                c = LexerATNConfig(state=t.target, config=config)

        elif t.serializationType == Transition.ACTION:
            if config.context is None or config.context.hasEmptyPath():
                # execute actions anywhere in the start rule for a token.
                #
                # TODO: if the entry rule is invoked recursively, some
                # actions may be executed during the recursive call. The
                # problem can appear when hasEmptyPath() is true but
                # isEmpty() is false. In this case, the config needs to be
                # split into two contexts - one with just the empty path
                # and another with everything but the empty path.
                # Unfortunately, the current algorithm does not allow
                # getEpsilonTarget to return two configurations, so
                # additional modifications are needed before we can support
                # the split operation.
                lexerActionExecutor = LexerActionExecutor.append(
                    config.lexerActionExecutor,
                    self.atn.lexerActions[t.actionIndex])
                c = LexerATNConfig(state=t.target,
                                   config=config,
                                   lexerActionExecutor=lexerActionExecutor)

            else:
                # ignore actions in referenced rules
                c = LexerATNConfig(state=t.target, config=config)

        elif t.serializationType == Transition.EPSILON:
            c = LexerATNConfig(state=t.target, config=config)

        elif t.serializationType in [
                Transition.ATOM, Transition.RANGE, Transition.SET
        ]:
            if treatEofAsEpsilon:
                if t.matches(Token.EOF, 0, 0xFFFF):
                    c = LexerATNConfig(state=t.target, config=config)

        return c
예제 #4
0
    def getEpsilonTarget(self, input:InputStream, config:LexerATNConfig, t:Transition, configs:ATNConfigSet,
                                           speculative:bool, treatEofAsEpsilon:bool):
        c = None
        if t.serializationType==Transition.RULE:
                newContext = SingletonPredictionContext.create(config.context, t.followState.stateNumber)
                c = LexerATNConfig(state=t.target, config=config, context=newContext)

        elif t.serializationType==Transition.PRECEDENCE:
                raise UnsupportedOperationException("Precedence predicates are not supported in lexers.")

        elif t.serializationType==Transition.PREDICATE:
                #  Track traversing semantic predicates. If we traverse,
                # we cannot add a DFA state for this "reach" computation
                # because the DFA would not test the predicate again in the
                # future. Rather than creating collections of semantic predicates
                # like v3 and testing them on prediction, v4 will test them on the
                # fly all the time using the ATN not the DFA. This is slower but
                # semantically it's not used that often. One of the key elements to
                # this predicate mechanism is not adding DFA states that see
                # predicates immediately afterwards in the ATN. For example,

                # a : ID {p1}? | ID {p2}? ;

                # should create the start state for rule 'a' (to save start state
                # competition), but should not create target of ID state. The
                # collection of ATN states the following ID references includes
                # states reached by traversing predicates. Since this is when we
                # test them, we cannot cash the DFA state target of ID.

                if LexerATNSimulator.debug:
                    print("EVAL rule "+ str(t.ruleIndex) + ":" + str(t.predIndex))
                configs.hasSemanticContext = True
                if self.evaluatePredicate(input, t.ruleIndex, t.predIndex, speculative):
                    c = LexerATNConfig(state=t.target, config=config)

        elif t.serializationType==Transition.ACTION:
                if config.context is None or config.context.hasEmptyPath():
                    # execute actions anywhere in the start rule for a token.
                    #
                    # TODO: if the entry rule is invoked recursively, some
                    # actions may be executed during the recursive call. The
                    # problem can appear when hasEmptyPath() is true but
                    # isEmpty() is false. In this case, the config needs to be
                    # split into two contexts - one with just the empty path
                    # and another with everything but the empty path.
                    # Unfortunately, the current algorithm does not allow
                    # getEpsilonTarget to return two configurations, so
                    # additional modifications are needed before we can support
                    # the split operation.
                    lexerActionExecutor = LexerActionExecutor.append(config.lexerActionExecutor,
                                    self.atn.lexerActions[t.actionIndex])
                    c = LexerATNConfig(state=t.target, config=config, lexerActionExecutor=lexerActionExecutor)

                else:
                    # ignore actions in referenced rules
                    c = LexerATNConfig(state=t.target, config=config)

        elif t.serializationType==Transition.EPSILON:
            c = LexerATNConfig(state=t.target, config=config)

        elif t.serializationType in [ Transition.ATOM, Transition.RANGE, Transition.SET ]:
            if treatEofAsEpsilon:
                if t.matches(Token.EOF, 0, 0xFFFF):
                    c = LexerATNConfig(state=t.target, config=config)

        return c