LexerAction.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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 enum import IntEnum
  7. # need forward declaration
  8. Lexer = None
  9. class LexerActionType(IntEnum):
  10. CHANNEL = 0 #The type of a {@link LexerChannelAction} action.
  11. CUSTOM = 1 #The type of a {@link LexerCustomAction} action.
  12. MODE = 2 #The type of a {@link LexerModeAction} action.
  13. MORE = 3 #The type of a {@link LexerMoreAction} action.
  14. POP_MODE = 4 #The type of a {@link LexerPopModeAction} action.
  15. PUSH_MODE = 5 #The type of a {@link LexerPushModeAction} action.
  16. SKIP = 6 #The type of a {@link LexerSkipAction} action.
  17. TYPE = 7 #The type of a {@link LexerTypeAction} action.
  18. class LexerAction(object):
  19. __slots__ = ('actionType', 'isPositionDependent')
  20. def __init__(self, action:LexerActionType):
  21. self.actionType = action
  22. self.isPositionDependent = False
  23. def __hash__(self):
  24. return hash(self.actionType)
  25. def __eq__(self, other):
  26. return self is other
  27. #
  28. # Implements the {@code skip} lexer action by calling {@link Lexer#skip}.
  29. #
  30. # <p>The {@code skip} command does not have any parameters, so this action is
  31. # implemented as a singleton instance exposed by {@link #INSTANCE}.</p>
  32. class LexerSkipAction(LexerAction):
  33. # Provides a singleton instance of this parameterless lexer action.
  34. INSTANCE = None
  35. def __init__(self):
  36. super().__init__(LexerActionType.SKIP)
  37. def execute(self, lexer:Lexer):
  38. lexer.skip()
  39. def __str__(self):
  40. return "skip"
  41. LexerSkipAction.INSTANCE = LexerSkipAction()
  42. # Implements the {@code type} lexer action by calling {@link Lexer#setType}
  43. # with the assigned type.
  44. class LexerTypeAction(LexerAction):
  45. __slots__ = 'type'
  46. def __init__(self, type:int):
  47. super().__init__(LexerActionType.TYPE)
  48. self.type = type
  49. def execute(self, lexer:Lexer):
  50. lexer.type = self.type
  51. def __hash__(self):
  52. return hash((self.actionType, self.type))
  53. def __eq__(self, other):
  54. if self is other:
  55. return True
  56. elif not isinstance(other, LexerTypeAction):
  57. return False
  58. else:
  59. return self.type == other.type
  60. def __str__(self):
  61. return "type(" + str(self.type) + ")"
  62. # Implements the {@code pushMode} lexer action by calling
  63. # {@link Lexer#pushMode} with the assigned mode.
  64. class LexerPushModeAction(LexerAction):
  65. __slots__ = 'mode'
  66. def __init__(self, mode:int):
  67. super().__init__(LexerActionType.PUSH_MODE)
  68. self.mode = mode
  69. # <p>This action is implemented by calling {@link Lexer#pushMode} with the
  70. # value provided by {@link #getMode}.</p>
  71. def execute(self, lexer:Lexer):
  72. lexer.pushMode(self.mode)
  73. def __hash__(self):
  74. return hash((self.actionType, self.mode))
  75. def __eq__(self, other):
  76. if self is other:
  77. return True
  78. elif not isinstance(other, LexerPushModeAction):
  79. return False
  80. else:
  81. return self.mode == other.mode
  82. def __str__(self):
  83. return "pushMode(" + str(self.mode) + ")"
  84. # Implements the {@code popMode} lexer action by calling {@link Lexer#popMode}.
  85. #
  86. # <p>The {@code popMode} command does not have any parameters, so this action is
  87. # implemented as a singleton instance exposed by {@link #INSTANCE}.</p>
  88. class LexerPopModeAction(LexerAction):
  89. INSTANCE = None
  90. def __init__(self):
  91. super().__init__(LexerActionType.POP_MODE)
  92. # <p>This action is implemented by calling {@link Lexer#popMode}.</p>
  93. def execute(self, lexer:Lexer):
  94. lexer.popMode()
  95. def __str__(self):
  96. return "popMode"
  97. LexerPopModeAction.INSTANCE = LexerPopModeAction()
  98. # Implements the {@code more} lexer action by calling {@link Lexer#more}.
  99. #
  100. # <p>The {@code more} command does not have any parameters, so this action is
  101. # implemented as a singleton instance exposed by {@link #INSTANCE}.</p>
  102. class LexerMoreAction(LexerAction):
  103. INSTANCE = None
  104. def __init__(self):
  105. super().__init__(LexerActionType.MORE)
  106. # <p>This action is implemented by calling {@link Lexer#popMode}.</p>
  107. def execute(self, lexer:Lexer):
  108. lexer.more()
  109. def __str__(self):
  110. return "more"
  111. LexerMoreAction.INSTANCE = LexerMoreAction()
  112. # Implements the {@code mode} lexer action by calling {@link Lexer#mode} with
  113. # the assigned mode.
  114. class LexerModeAction(LexerAction):
  115. __slots__ = 'mode'
  116. def __init__(self, mode:int):
  117. super().__init__(LexerActionType.MODE)
  118. self.mode = mode
  119. # <p>This action is implemented by calling {@link Lexer#mode} with the
  120. # value provided by {@link #getMode}.</p>
  121. def execute(self, lexer:Lexer):
  122. lexer.mode(self.mode)
  123. def __hash__(self):
  124. return hash((self.actionType, self.mode))
  125. def __eq__(self, other):
  126. if self is other:
  127. return True
  128. elif not isinstance(other, LexerModeAction):
  129. return False
  130. else:
  131. return self.mode == other.mode
  132. def __str__(self):
  133. return "mode(" + str(self.mode) + ")"
  134. # Executes a custom lexer action by calling {@link Recognizer#action} with the
  135. # rule and action indexes assigned to the custom action. The implementation of
  136. # a custom action is added to the generated code for the lexer in an override
  137. # of {@link Recognizer#action} when the grammar is compiled.
  138. #
  139. # <p>This class may represent embedded actions created with the <code>{...}</code>
  140. # syntax in ANTLR 4, as well as actions created for lexer commands where the
  141. # command argument could not be evaluated when the grammar was compiled.</p>
  142. class LexerCustomAction(LexerAction):
  143. __slots__ = ('ruleIndex', 'actionIndex')
  144. # Constructs a custom lexer action with the specified rule and action
  145. # indexes.
  146. #
  147. # @param ruleIndex The rule index to use for calls to
  148. # {@link Recognizer#action}.
  149. # @param actionIndex The action index to use for calls to
  150. # {@link Recognizer#action}.
  151. #/
  152. def __init__(self, ruleIndex:int, actionIndex:int):
  153. super().__init__(LexerActionType.CUSTOM)
  154. self.ruleIndex = ruleIndex
  155. self.actionIndex = actionIndex
  156. self.isPositionDependent = True
  157. # <p>Custom actions are implemented by calling {@link Lexer#action} with the
  158. # appropriate rule and action indexes.</p>
  159. def execute(self, lexer:Lexer):
  160. lexer.action(None, self.ruleIndex, self.actionIndex)
  161. def __hash__(self):
  162. return hash((self.actionType, self.ruleIndex, self.actionIndex))
  163. def __eq__(self, other):
  164. if self is other:
  165. return True
  166. elif not isinstance(other, LexerCustomAction):
  167. return False
  168. else:
  169. return self.ruleIndex == other.ruleIndex and self.actionIndex == other.actionIndex
  170. # Implements the {@code channel} lexer action by calling
  171. # {@link Lexer#setChannel} with the assigned channel.
  172. class LexerChannelAction(LexerAction):
  173. __slots__ = 'channel'
  174. # Constructs a new {@code channel} action with the specified channel value.
  175. # @param channel The channel value to pass to {@link Lexer#setChannel}.
  176. def __init__(self, channel:int):
  177. super().__init__(LexerActionType.CHANNEL)
  178. self.channel = channel
  179. # <p>This action is implemented by calling {@link Lexer#setChannel} with the
  180. # value provided by {@link #getChannel}.</p>
  181. def execute(self, lexer:Lexer):
  182. lexer._channel = self.channel
  183. def __hash__(self):
  184. return hash((self.actionType, self.channel))
  185. def __eq__(self, other):
  186. if self is other:
  187. return True
  188. elif not isinstance(other, LexerChannelAction):
  189. return False
  190. else:
  191. return self.channel == other.channel
  192. def __str__(self):
  193. return "channel(" + str(self.channel) + ")"
  194. # This implementation of {@link LexerAction} is used for tracking input offsets
  195. # for position-dependent actions within a {@link LexerActionExecutor}.
  196. #
  197. # <p>This action is not serialized as part of the ATN, and is only required for
  198. # position-dependent lexer actions which appear at a location other than the
  199. # end of a rule. For more information about DFA optimizations employed for
  200. # lexer actions, see {@link LexerActionExecutor#append} and
  201. # {@link LexerActionExecutor#fixOffsetBeforeMatch}.</p>
  202. class LexerIndexedCustomAction(LexerAction):
  203. __slots__ = ('offset', 'action')
  204. # Constructs a new indexed custom action by associating a character offset
  205. # with a {@link LexerAction}.
  206. #
  207. # <p>Note: This class is only required for lexer actions for which
  208. # {@link LexerAction#isPositionDependent} returns {@code true}.</p>
  209. #
  210. # @param offset The offset into the input {@link CharStream}, relative to
  211. # the token start index, at which the specified lexer action should be
  212. # executed.
  213. # @param action The lexer action to execute at a particular offset in the
  214. # input {@link CharStream}.
  215. def __init__(self, offset:int, action:LexerAction):
  216. super().__init__(action.actionType)
  217. self.offset = offset
  218. self.action = action
  219. self.isPositionDependent = True
  220. # <p>This method calls {@link #execute} on the result of {@link #getAction}
  221. # using the provided {@code lexer}.</p>
  222. def execute(self, lexer:Lexer):
  223. # assume the input stream position was properly set by the calling code
  224. self.action.execute(lexer)
  225. def __hash__(self):
  226. return hash((self.actionType, self.offset, self.action))
  227. def __eq__(self, other):
  228. if self is other:
  229. return True
  230. elif not isinstance(other, LexerIndexedCustomAction):
  231. return False
  232. else:
  233. return self.offset == other.offset and self.action == other.action