pawn.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. """
  2. pygments.lexers.pawn
  3. ~~~~~~~~~~~~~~~~~~~~
  4. Lexers for the Pawn languages.
  5. :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS.
  6. :license: BSD, see LICENSE for details.
  7. """
  8. from pygments.lexer import RegexLexer
  9. from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
  10. Number, Punctuation
  11. from pygments.util import get_bool_opt
  12. __all__ = ['SourcePawnLexer', 'PawnLexer']
  13. class SourcePawnLexer(RegexLexer):
  14. """
  15. For SourcePawn source code with preprocessor directives.
  16. """
  17. name = 'SourcePawn'
  18. aliases = ['sp']
  19. filenames = ['*.sp']
  20. mimetypes = ['text/x-sourcepawn']
  21. url = 'https://github.com/alliedmodders/sourcepawn'
  22. version_added = '1.6'
  23. #: optional Comment or Whitespace
  24. _ws = r'(?:\s|//.*?\n|/\*.*?\*/)+'
  25. #: only one /* */ style comment
  26. _ws1 = r'\s*(?:/[*].*?[*]/\s*)*'
  27. tokens = {
  28. 'root': [
  29. # preprocessor directives: without whitespace
  30. (r'^#if\s+0', Comment.Preproc, 'if0'),
  31. ('^#', Comment.Preproc, 'macro'),
  32. # or with whitespace
  33. ('^' + _ws1 + r'#if\s+0', Comment.Preproc, 'if0'),
  34. ('^' + _ws1 + '#', Comment.Preproc, 'macro'),
  35. (r'\n', Text),
  36. (r'\s+', Text),
  37. (r'\\\n', Text), # line continuation
  38. (r'/(\\\n)?/(\n|(.|\n)*?[^\\]\n)', Comment.Single),
  39. (r'/(\\\n)?\*(.|\n)*?\*(\\\n)?/', Comment.Multiline),
  40. (r'[{}]', Punctuation),
  41. (r'L?"', String, 'string'),
  42. (r"L?'(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])'", String.Char),
  43. (r'(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[LlUu]*', Number.Float),
  44. (r'(\d+\.\d*|\.\d+|\d+[fF])[fF]?', Number.Float),
  45. (r'0x[0-9a-fA-F]+[LlUu]*', Number.Hex),
  46. (r'0[0-7]+[LlUu]*', Number.Oct),
  47. (r'\d+[LlUu]*', Number.Integer),
  48. (r'[~!%^&*+=|?:<>/-]', Operator),
  49. (r'[()\[\],.;]', Punctuation),
  50. (r'(case|const|continue|native|'
  51. r'default|else|enum|for|if|new|operator|'
  52. r'public|return|sizeof|static|decl|struct|switch)\b', Keyword),
  53. (r'(bool|Float)\b', Keyword.Type),
  54. (r'(true|false)\b', Keyword.Constant),
  55. (r'[a-zA-Z_]\w*', Name),
  56. ],
  57. 'string': [
  58. (r'"', String, '#pop'),
  59. (r'\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|[0-7]{1,3})', String.Escape),
  60. (r'[^\\"\n]+', String), # all other characters
  61. (r'\\\n', String), # line continuation
  62. (r'\\', String), # stray backslash
  63. ],
  64. 'macro': [
  65. (r'[^/\n]+', Comment.Preproc),
  66. (r'/\*(.|\n)*?\*/', Comment.Multiline),
  67. (r'//.*?\n', Comment.Single, '#pop'),
  68. (r'/', Comment.Preproc),
  69. (r'(?<=\\)\n', Comment.Preproc),
  70. (r'\n', Comment.Preproc, '#pop'),
  71. ],
  72. 'if0': [
  73. (r'^\s*#if.*?(?<!\\)\n', Comment.Preproc, '#push'),
  74. (r'^\s*#endif.*?(?<!\\)\n', Comment.Preproc, '#pop'),
  75. (r'.*?\n', Comment),
  76. ]
  77. }
  78. SM_TYPES = {'Action', 'bool', 'Float', 'Plugin', 'String', 'any',
  79. 'AdminFlag', 'OverrideType', 'OverrideRule', 'ImmunityType',
  80. 'GroupId', 'AdminId', 'AdmAccessMode', 'AdminCachePart',
  81. 'CookieAccess', 'CookieMenu', 'CookieMenuAction', 'NetFlow',
  82. 'ConVarBounds', 'QueryCookie', 'ReplySource',
  83. 'ConVarQueryResult', 'ConVarQueryFinished', 'Function',
  84. 'Action', 'Identity', 'PluginStatus', 'PluginInfo', 'DBResult',
  85. 'DBBindType', 'DBPriority', 'PropType', 'PropFieldType',
  86. 'MoveType', 'RenderMode', 'RenderFx', 'EventHookMode',
  87. 'EventHook', 'FileType', 'FileTimeMode', 'PathType',
  88. 'ParamType', 'ExecType', 'DialogType', 'Handle', 'KvDataTypes',
  89. 'NominateResult', 'MapChange', 'MenuStyle', 'MenuAction',
  90. 'MenuSource', 'RegexError', 'SDKCallType', 'SDKLibrary',
  91. 'SDKFuncConfSource', 'SDKType', 'SDKPassMethod', 'RayType',
  92. 'TraceEntityFilter', 'ListenOverride', 'SortOrder', 'SortType',
  93. 'SortFunc2D', 'APLRes', 'FeatureType', 'FeatureStatus',
  94. 'SMCResult', 'SMCError', 'TFClassType', 'TFTeam', 'TFCond',
  95. 'TFResourceType', 'Timer', 'TopMenuAction', 'TopMenuObjectType',
  96. 'TopMenuPosition', 'TopMenuObject', 'UserMsg'}
  97. def __init__(self, **options):
  98. self.smhighlighting = get_bool_opt(options,
  99. 'sourcemod', True)
  100. self._functions = set()
  101. if self.smhighlighting:
  102. from pygments.lexers._sourcemod_builtins import FUNCTIONS
  103. self._functions.update(FUNCTIONS)
  104. RegexLexer.__init__(self, **options)
  105. def get_tokens_unprocessed(self, text):
  106. for index, token, value in \
  107. RegexLexer.get_tokens_unprocessed(self, text):
  108. if token is Name:
  109. if self.smhighlighting:
  110. if value in self.SM_TYPES:
  111. token = Keyword.Type
  112. elif value in self._functions:
  113. token = Name.Builtin
  114. yield index, token, value
  115. class PawnLexer(RegexLexer):
  116. """
  117. For Pawn source code.
  118. """
  119. name = 'Pawn'
  120. aliases = ['pawn']
  121. filenames = ['*.p', '*.pwn', '*.inc']
  122. mimetypes = ['text/x-pawn']
  123. url = 'https://www.compuphase.com/pawn/pawn.htm'
  124. version_added = '2.0'
  125. #: optional Comment or Whitespace
  126. _ws = r'(?:\s|//.*?\n|/[*][\w\W]*?[*]/)+'
  127. #: only one /* */ style comment
  128. _ws1 = r'\s*(?:/[*].*?[*]/\s*)*'
  129. tokens = {
  130. 'root': [
  131. # preprocessor directives: without whitespace
  132. (r'^#if\s+0', Comment.Preproc, 'if0'),
  133. ('^#', Comment.Preproc, 'macro'),
  134. # or with whitespace
  135. ('^' + _ws1 + r'#if\s+0', Comment.Preproc, 'if0'),
  136. ('^' + _ws1 + '#', Comment.Preproc, 'macro'),
  137. (r'\n', Text),
  138. (r'\s+', Text),
  139. (r'\\\n', Text), # line continuation
  140. (r'/(\\\n)?/(\n|(.|\n)*?[^\\]\n)', Comment.Single),
  141. (r'/(\\\n)?\*[\w\W]*?\*(\\\n)?/', Comment.Multiline),
  142. (r'[{}]', Punctuation),
  143. (r'L?"', String, 'string'),
  144. (r"L?'(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])'", String.Char),
  145. (r'(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[LlUu]*', Number.Float),
  146. (r'(\d+\.\d*|\.\d+|\d+[fF])[fF]?', Number.Float),
  147. (r'0x[0-9a-fA-F]+[LlUu]*', Number.Hex),
  148. (r'0[0-7]+[LlUu]*', Number.Oct),
  149. (r'\d+[LlUu]*', Number.Integer),
  150. (r'[~!%^&*+=|?:<>/-]', Operator),
  151. (r'[()\[\],.;]', Punctuation),
  152. (r'(switch|case|default|const|new|static|char|continue|break|'
  153. r'if|else|for|while|do|operator|enum|'
  154. r'public|return|sizeof|tagof|state|goto)\b', Keyword),
  155. (r'(bool|Float)\b', Keyword.Type),
  156. (r'(true|false)\b', Keyword.Constant),
  157. (r'[a-zA-Z_]\w*', Name),
  158. ],
  159. 'string': [
  160. (r'"', String, '#pop'),
  161. (r'\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|[0-7]{1,3})', String.Escape),
  162. (r'[^\\"\n]+', String), # all other characters
  163. (r'\\\n', String), # line continuation
  164. (r'\\', String), # stray backslash
  165. ],
  166. 'macro': [
  167. (r'[^/\n]+', Comment.Preproc),
  168. (r'/\*(.|\n)*?\*/', Comment.Multiline),
  169. (r'//.*?\n', Comment.Single, '#pop'),
  170. (r'/', Comment.Preproc),
  171. (r'(?<=\\)\n', Comment.Preproc),
  172. (r'\n', Comment.Preproc, '#pop'),
  173. ],
  174. 'if0': [
  175. (r'^\s*#if.*?(?<!\\)\n', Comment.Preproc, '#push'),
  176. (r'^\s*#endif.*?(?<!\\)\n', Comment.Preproc, '#pop'),
  177. (r'.*?\n', Comment),
  178. ]
  179. }
  180. def analyse_text(text):
  181. """This is basically C. There is a keyword which doesn't exist in C
  182. though and is nearly unique to this language."""
  183. if 'tagof' in text:
  184. return 0.01