LL1Analyzer.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #
  2. # Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
  3. # Use of this file is governed by the BSD 3-clause license that
  4. # can be found in the LICENSE.txt file in the project root.
  5. #/
  6. from antlr4.IntervalSet import IntervalSet
  7. from antlr4.Token import Token
  8. from antlr4.PredictionContext import PredictionContext, SingletonPredictionContext, PredictionContextFromRuleContext
  9. from antlr4.RuleContext import RuleContext
  10. from antlr4.atn.ATN import ATN
  11. from antlr4.atn.ATNConfig import ATNConfig
  12. from antlr4.atn.ATNState import ATNState, RuleStopState
  13. from antlr4.atn.Transition import WildcardTransition, NotSetTransition, AbstractPredicateTransition, RuleTransition
  14. class LL1Analyzer (object):
  15. __slots__ = 'atn'
  16. #* Special value added to the lookahead sets to indicate that we hit
  17. # a predicate during analysis if {@code seeThruPreds==false}.
  18. #/
  19. HIT_PRED = Token.INVALID_TYPE
  20. def __init__(self, atn:ATN):
  21. self.atn = atn
  22. #*
  23. # Calculates the SLL(1) expected lookahead set for each outgoing transition
  24. # of an {@link ATNState}. The returned array has one element for each
  25. # outgoing transition in {@code s}. If the closure from transition
  26. # <em>i</em> leads to a semantic predicate before matching a symbol, the
  27. # element at index <em>i</em> of the result will be {@code null}.
  28. #
  29. # @param s the ATN state
  30. # @return the expected symbols for each outgoing transition of {@code s}.
  31. #/
  32. def getDecisionLookahead(self, s:ATNState):
  33. if s is None:
  34. return None
  35. count = len(s.transitions)
  36. look = [] * count
  37. for alt in range(0, count):
  38. look[alt] = set()
  39. lookBusy = set()
  40. seeThruPreds = False # fail to get lookahead upon pred
  41. self._LOOK(s.transition(alt).target, None, PredictionContext.EMPTY,
  42. look[alt], lookBusy, set(), seeThruPreds, False)
  43. # Wipe out lookahead for this alternative if we found nothing
  44. # or we had a predicate when we !seeThruPreds
  45. if len(look[alt])==0 or self.HIT_PRED in look[alt]:
  46. look[alt] = None
  47. return look
  48. #*
  49. # Compute set of tokens that can follow {@code s} in the ATN in the
  50. # specified {@code ctx}.
  51. #
  52. # <p>If {@code ctx} is {@code null} and the end of the rule containing
  53. # {@code s} is reached, {@link Token#EPSILON} is added to the result set.
  54. # If {@code ctx} is not {@code null} and the end of the outermost rule is
  55. # reached, {@link Token#EOF} is added to the result set.</p>
  56. #
  57. # @param s the ATN state
  58. # @param stopState the ATN state to stop at. This can be a
  59. # {@link BlockEndState} to detect epsilon paths through a closure.
  60. # @param ctx the complete parser context, or {@code null} if the context
  61. # should be ignored
  62. #
  63. # @return The set of tokens that can follow {@code s} in the ATN in the
  64. # specified {@code ctx}.
  65. #/
  66. def LOOK(self, s:ATNState, stopState:ATNState=None, ctx:RuleContext=None):
  67. r = IntervalSet()
  68. seeThruPreds = True # ignore preds; get all lookahead
  69. lookContext = PredictionContextFromRuleContext(s.atn, ctx) if ctx is not None else None
  70. self._LOOK(s, stopState, lookContext, r, set(), set(), seeThruPreds, True)
  71. return r
  72. #*
  73. # Compute set of tokens that can follow {@code s} in the ATN in the
  74. # specified {@code ctx}.
  75. #
  76. # <p>If {@code ctx} is {@code null} and {@code stopState} or the end of the
  77. # rule containing {@code s} is reached, {@link Token#EPSILON} is added to
  78. # the result set. If {@code ctx} is not {@code null} and {@code addEOF} is
  79. # {@code true} and {@code stopState} or the end of the outermost rule is
  80. # reached, {@link Token#EOF} is added to the result set.</p>
  81. #
  82. # @param s the ATN state.
  83. # @param stopState the ATN state to stop at. This can be a
  84. # {@link BlockEndState} to detect epsilon paths through a closure.
  85. # @param ctx The outer context, or {@code null} if the outer context should
  86. # not be used.
  87. # @param look The result lookahead set.
  88. # @param lookBusy A set used for preventing epsilon closures in the ATN
  89. # from causing a stack overflow. Outside code should pass
  90. # {@code new HashSet<ATNConfig>} for this argument.
  91. # @param calledRuleStack A set used for preventing left recursion in the
  92. # ATN from causing a stack overflow. Outside code should pass
  93. # {@code new BitSet()} for this argument.
  94. # @param seeThruPreds {@code true} to true semantic predicates as
  95. # implicitly {@code true} and "see through them", otherwise {@code false}
  96. # to treat semantic predicates as opaque and add {@link #HIT_PRED} to the
  97. # result if one is encountered.
  98. # @param addEOF Add {@link Token#EOF} to the result if the end of the
  99. # outermost context is reached. This parameter has no effect if {@code ctx}
  100. # is {@code null}.
  101. #/
  102. def _LOOK(self, s:ATNState, stopState:ATNState , ctx:PredictionContext, look:IntervalSet, lookBusy:set,
  103. calledRuleStack:set, seeThruPreds:bool, addEOF:bool):
  104. c = ATNConfig(s, 0, ctx)
  105. if c in lookBusy:
  106. return
  107. lookBusy.add(c)
  108. if s == stopState:
  109. if ctx is None:
  110. look.addOne(Token.EPSILON)
  111. return
  112. elif ctx.isEmpty() and addEOF:
  113. look.addOne(Token.EOF)
  114. return
  115. if isinstance(s, RuleStopState ):
  116. if ctx is None:
  117. look.addOne(Token.EPSILON)
  118. return
  119. elif ctx.isEmpty() and addEOF:
  120. look.addOne(Token.EOF)
  121. return
  122. if ctx != PredictionContext.EMPTY:
  123. removed = s.ruleIndex in calledRuleStack
  124. try:
  125. calledRuleStack.discard(s.ruleIndex)
  126. # run thru all possible stack tops in ctx
  127. for i in range(0, len(ctx)):
  128. returnState = self.atn.states[ctx.getReturnState(i)]
  129. self._LOOK(returnState, stopState, ctx.getParent(i), look, lookBusy, calledRuleStack, seeThruPreds, addEOF)
  130. finally:
  131. if removed:
  132. calledRuleStack.add(s.ruleIndex)
  133. return
  134. for t in s.transitions:
  135. if type(t) == RuleTransition:
  136. if t.target.ruleIndex in calledRuleStack:
  137. continue
  138. newContext = SingletonPredictionContext.create(ctx, t.followState.stateNumber)
  139. try:
  140. calledRuleStack.add(t.target.ruleIndex)
  141. self._LOOK(t.target, stopState, newContext, look, lookBusy, calledRuleStack, seeThruPreds, addEOF)
  142. finally:
  143. calledRuleStack.remove(t.target.ruleIndex)
  144. elif isinstance(t, AbstractPredicateTransition ):
  145. if seeThruPreds:
  146. self._LOOK(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF)
  147. else:
  148. look.addOne(self.HIT_PRED)
  149. elif t.isEpsilon:
  150. self._LOOK(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF)
  151. elif type(t) == WildcardTransition:
  152. look.addRange( range(Token.MIN_USER_TOKEN_TYPE, self.atn.maxTokenType + 1) )
  153. else:
  154. set_ = t.label
  155. if set_ is not None:
  156. if isinstance(t, NotSetTransition):
  157. set_ = set_.complement(Token.MIN_USER_TOKEN_TYPE, self.atn.maxTokenType)
  158. look.addSet(set_)