Recognizer.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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.RuleContext import RuleContext
  7. from antlr4.Token import Token
  8. from antlr4.error.ErrorListener import ProxyErrorListener, ConsoleErrorListener
  9. # need forward delcaration
  10. RecognitionException = None
  11. class Recognizer(object):
  12. __slots__ = ('_listeners', '_interp', '_stateNumber')
  13. tokenTypeMapCache = dict()
  14. ruleIndexMapCache = dict()
  15. def __init__(self):
  16. self._listeners = [ ConsoleErrorListener.INSTANCE ]
  17. self._interp = None
  18. self._stateNumber = -1
  19. def extractVersion(self, version):
  20. pos = version.find(".")
  21. major = version[0:pos]
  22. version = version[pos+1:]
  23. pos = version.find(".")
  24. if pos==-1:
  25. pos = version.find("-")
  26. if pos==-1:
  27. pos = len(version)
  28. minor = version[0:pos]
  29. return major, minor
  30. def checkVersion(self, toolVersion):
  31. runtimeVersion = "4.9.3"
  32. rvmajor, rvminor = self.extractVersion(runtimeVersion)
  33. tvmajor, tvminor = self.extractVersion(toolVersion)
  34. if rvmajor!=tvmajor or rvminor!=tvminor:
  35. print("ANTLR runtime and generated code versions disagree: "+runtimeVersion+"!="+toolVersion)
  36. def addErrorListener(self, listener):
  37. self._listeners.append(listener)
  38. def removeErrorListener(self, listener):
  39. self._listeners.remove(listener)
  40. def removeErrorListeners(self):
  41. self._listeners = []
  42. def getTokenTypeMap(self):
  43. tokenNames = self.getTokenNames()
  44. if tokenNames is None:
  45. from antlr4.error.Errors import UnsupportedOperationException
  46. raise UnsupportedOperationException("The current recognizer does not provide a list of token names.")
  47. result = self.tokenTypeMapCache.get(tokenNames, None)
  48. if result is None:
  49. result = zip( tokenNames, range(0, len(tokenNames)))
  50. result["EOF"] = Token.EOF
  51. self.tokenTypeMapCache[tokenNames] = result
  52. return result
  53. # Get a map from rule names to rule indexes.
  54. #
  55. # <p>Used for XPath and tree pattern compilation.</p>
  56. #
  57. def getRuleIndexMap(self):
  58. ruleNames = self.getRuleNames()
  59. if ruleNames is None:
  60. from antlr4.error.Errors import UnsupportedOperationException
  61. raise UnsupportedOperationException("The current recognizer does not provide a list of rule names.")
  62. result = self.ruleIndexMapCache.get(ruleNames, None)
  63. if result is None:
  64. result = zip( ruleNames, range(0, len(ruleNames)))
  65. self.ruleIndexMapCache[ruleNames] = result
  66. return result
  67. def getTokenType(self, tokenName:str):
  68. ttype = self.getTokenTypeMap().get(tokenName, None)
  69. if ttype is not None:
  70. return ttype
  71. else:
  72. return Token.INVALID_TYPE
  73. # What is the error header, normally line/character position information?#
  74. def getErrorHeader(self, e:RecognitionException):
  75. line = e.getOffendingToken().line
  76. column = e.getOffendingToken().column
  77. return "line "+line+":"+column
  78. # How should a token be displayed in an error message? The default
  79. # is to display just the text, but during development you might
  80. # want to have a lot of information spit out. Override in that case
  81. # to use t.toString() (which, for CommonToken, dumps everything about
  82. # the token). This is better than forcing you to override a method in
  83. # your token objects because you don't have to go modify your lexer
  84. # so that it creates a new Java type.
  85. #
  86. # @deprecated This method is not called by the ANTLR 4 Runtime. Specific
  87. # implementations of {@link ANTLRErrorStrategy} may provide a similar
  88. # feature when necessary. For example, see
  89. # {@link DefaultErrorStrategy#getTokenErrorDisplay}.
  90. #
  91. def getTokenErrorDisplay(self, t:Token):
  92. if t is None:
  93. return "<no token>"
  94. s = t.text
  95. if s is None:
  96. if t.type==Token.EOF:
  97. s = "<EOF>"
  98. else:
  99. s = "<" + str(t.type) + ">"
  100. s = s.replace("\n","\\n")
  101. s = s.replace("\r","\\r")
  102. s = s.replace("\t","\\t")
  103. return "'" + s + "'"
  104. def getErrorListenerDispatch(self):
  105. return ProxyErrorListener(self._listeners)
  106. # subclass needs to override these if there are sempreds or actions
  107. # that the ATN interp needs to execute
  108. def sempred(self, localctx:RuleContext, ruleIndex:int, actionIndex:int):
  109. return True
  110. def precpred(self, localctx:RuleContext , precedence:int):
  111. return True
  112. @property
  113. def state(self):
  114. return self._stateNumber
  115. # Indicate that the recognizer has changed internal state that is
  116. # consistent with the ATN state passed in. This way we always know
  117. # where we are in the ATN as the parser goes along. The rule
  118. # context objects form a stack that lets us see the stack of
  119. # invoking rules. Combine this and we have complete ATN
  120. # configuration information.
  121. @state.setter
  122. def state(self, atnState:int):
  123. self._stateNumber = atnState
  124. del RecognitionException