start migrating, but 2 tests are failing

This commit is contained in:
Eric Vergnaud 2016-11-29 00:05:13 +08:00
parent 3026c3cc94
commit ec5f64a459
4 changed files with 47 additions and 67 deletions

View File

@ -69,7 +69,7 @@ class ParserInterpreter(Parser):
for state in atn.states: for state in atn.states:
if not isinstance(state, StarLoopEntryState): if not isinstance(state, StarLoopEntryState):
continue continue
if state.precedenceRuleDecision: if state.isPrecedenceDecision:
self.pushRecursionContextStates.add(state.stateNumber) self.pushRecursionContextStates.add(state.stateNumber)
# get atn simulator that knows how to do predictions # get atn simulator that knows how to do predictions
self._interp = ParserATNSimulator(self, atn, self.decisionToDFA, self.sharedContextCache) self._interp = ParserATNSimulator(self, atn, self.decisionToDFA, self.sharedContextCache)

View File

@ -368,7 +368,7 @@ class ATNDeserializer (object):
# #
# Analyze the {@link StarLoopEntryState} states in the specified ATN to set # Analyze the {@link StarLoopEntryState} states in the specified ATN to set
# the {@link StarLoopEntryState#precedenceRuleDecision} field to the # the {@link StarLoopEntryState#isPrecedenceDecision} field to the
# correct value. # correct value.
# #
# @param atn The ATN. # @param atn The ATN.
@ -387,7 +387,7 @@ class ATNDeserializer (object):
if isinstance(maybeLoopEndState, LoopEndState): if isinstance(maybeLoopEndState, LoopEndState):
if maybeLoopEndState.epsilonOnlyTransitions and \ if maybeLoopEndState.epsilonOnlyTransitions and \
isinstance(maybeLoopEndState.transitions[0].target, RuleStopState): isinstance(maybeLoopEndState.transitions[0].target, RuleStopState):
state.precedenceRuleDecision = True state.isPrecedenceDecision = True
def verifyATN(self, atn): def verifyATN(self, atn):
if not self.deserializationOptions.verifyATN: if not self.deserializationOptions.verifyATN:

View File

@ -262,7 +262,7 @@ class StarLoopEntryState(DecisionState):
self.stateType = self.STAR_LOOP_ENTRY self.stateType = self.STAR_LOOP_ENTRY
self.loopBackState = None self.loopBackState = None
# Indicates whether this state can benefit from a precedence DFA during SLL decision making. # Indicates whether this state can benefit from a precedence DFA during SLL decision making.
self.precedenceRuleDecision = None self.isPrecedenceDecision = None
# Mark the end of a * or + loop. # Mark the end of a * or + loop.
class LoopEndState(ATNState): class LoopEndState(ATNState):

View File

@ -347,7 +347,7 @@ class ParserATNSimulator(ATNSimulator):
# should continue or complete. # should continue or complete.
# #
if not dfa.precedenceDfa and isinstance(dfa.atnStartState, StarLoopEntryState): if not dfa.precedenceDfa and isinstance(dfa.atnStartState, StarLoopEntryState):
if dfa.atnStartState.precedenceRuleDecision: if dfa.atnStartState.isPrecedenceDecision:
dfa.setPrecedenceDfa(True) dfa.setPrecedenceDfa(True)
fullCtx = False fullCtx = False
@ -1300,15 +1300,16 @@ class ParserATNSimulator(ATNSimulator):
# @since 4.6 # @since 4.6
# #
def canDropLoopEntryEdgeInLeftRecursiveRule(self, config): def canDropLoopEntryEdgeInLeftRecursiveRule(self, config):
# return False
p = config.state p = config.state
# First check to see if we are in StarLoopEntryState generated during # First check to see if we are in StarLoopEntryState generated during
# left-recursion elimination. For efficiency, also check if # left-recursion elimination. For efficiency, also check if
# the context has an empty stack case. If so, it would mean # the context has an empty stack case. If so, it would mean
# global FOLLOW so we can't perform optimization # global FOLLOW so we can't perform optimization
# Are we the special loop entry/exit state? or SLL wildcard # Are we the special loop entry/exit state? or SLL wildcard
if p.getStateType() != ATNState.STAR_LOOP_ENTRY \ if p.stateType != ATNState.STAR_LOOP_ENTRY \
or not p.isPrecedenceDecision \ or not p.isPrecedenceDecision \
or config.context.isEmpty() \ or config.context.isEmpty() \
or config.context.hasEmptyPath(): or config.context.hasEmptyPath():
return False return False
@ -1316,72 +1317,51 @@ class ParserATNSimulator(ATNSimulator):
# that p is in. # that p is in.
numCtxs = len(config.context) numCtxs = len(config.context)
for i in range(0, numCtxs): # for each stack context for i in range(0, numCtxs): # for each stack context
returnState = atn.states.get(config.context.getReturnState(i)); returnState = self.atn.states[config.context.getReturnState(i)]
if (returnState.ruleIndex != p.ruleIndex) return false; if returnState.ruleIndex != p.ruleIndex:
return False
decisionStartState = p.transitions[0].target
blockEndStateNum = decisionStartState.endState.stateNumber
blockEndState = self.atn.states[blockEndStateNum]
# Verify that the top of each stack context leads to loop entry/exit
# state through epsilon edges and w/o leaving rule.
for i in range(0, numCtxs): # for each stack context
returnStateNumber = config.context.getReturnState(i)
returnState = self.atn.states[returnStateNumber]
# all states must have single outgoing epsilon edge
if len(returnState.transitions) != 1 or not returnState.transitions[0].isEpsilon:
return False
} # Look for prefix op case like 'not expr', (' type ')' expr
returnStateTarget = returnState.transitions[0].target
if returnState.stateType == ATNState.BLOCK_END and returnStateTarget is p:
continue
BlockStartState # Look for 'expr op expr' or case where expr's return state is block end
decisionStartState = (BlockStartState) # of (...)* internal block; the block end points to loop back
p.transition(0).target; # which points to p but we don't need to check that
int if returnState is blockEndState:
blockEndStateNum = decisionStartState.endState.stateNumber; continue
BlockEndState
blockEndState = (BlockEndState)
atn.states.get(blockEndStateNum);
# Verify that the top of each stack context leads to loop entry/exit # Look for ternary expr ? expr : expr. The return state points at block end,
# state through epsilon edges and w/o leaving rule. # which points at loop entry state
for (int if returnStateTarget is blockEndState:
i = 0; continue
i < numCtxs;
i + +) { # for each stack context
int
returnStateNumber = config.context.getReturnState(i);
ATNState
returnState = atn.states.get(returnStateNumber);
# all states must have single outgoing epsilon edge
if (returnState.getNumberOfTransitions() != 1 | |
!returnState.transition(0).isEpsilon() )
{
return false;
}
# Look for prefix op case like 'not expr', (' type ')' expr
ATNState
returnStateTarget = returnState.transition(0).target;
if (returnState.getStateType() == BLOCK_END & & returnStateTarget == p)
{
continue;
}
# Look for 'expr op expr' or case where expr's return state is block end
# of (...)* internal block; the block end points to loop back
# which points to p but we don't need to check that
if (returnState == blockEndState) {
continue;
}
# Look for ternary expr ? expr : expr. The return state points at block end,
# which points at loop entry state
if (returnStateTarget == blockEndState) {
continue;
}
# Look for complex prefix 'between expr and expr' case where 2nd expr's
# return state points at block end state of (...)* internal block
if (returnStateTarget.getStateType() == BLOCK_END & &
returnStateTarget.getNumberOfTransitions() == 1 & &
returnStateTarget.transition(0).isEpsilon() & &
returnStateTarget.transition(0).target == p )
{
continue;
}
# anything else ain't conforming # Look for complex prefix 'between expr and expr' case where 2nd expr's
return false; # return state points at block end state of (...)* internal block
} if returnStateTarget.stateType == ATNState.BLOCK_END \
and len(returnStateTarget.transitions) == 1 \
and returnStateTarget.transitions[0].isEpsilon \
and returnStateTarget.transitions[0].target is p:
continue
return true; # anything else ain't conforming
} return False
return True
def getRuleName(self, index): def getRuleName(self, index):