fantom.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. # -*- coding: utf-8 -*-
  2. """
  3. pygments.lexers.fantom
  4. ~~~~~~~~~~~~~~~~~~~~~~
  5. Lexer for the Fantom language.
  6. :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS.
  7. :license: BSD, see LICENSE for details.
  8. """
  9. from string import Template
  10. from pygments.lexer import RegexLexer, include, bygroups, using, \
  11. this, default, words
  12. from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
  13. Number, Punctuation, Literal
  14. __all__ = ['FantomLexer']
  15. class FantomLexer(RegexLexer):
  16. """
  17. For Fantom source code.
  18. .. versionadded:: 1.5
  19. """
  20. name = 'Fantom'
  21. aliases = ['fan']
  22. filenames = ['*.fan']
  23. mimetypes = ['application/x-fantom']
  24. # often used regexes
  25. def s(str):
  26. return Template(str).substitute(
  27. dict(
  28. pod=r'[\"\w\.]+',
  29. eos=r'\n|;',
  30. id=r'[a-zA-Z_]\w*',
  31. # all chars which can be part of type definition. Starts with
  32. # either letter, or [ (maps), or | (funcs)
  33. type=r'(?:\[|[a-zA-Z_]|\|)[:\w\[\]|\->?]*?',
  34. )
  35. )
  36. tokens = {
  37. 'comments': [
  38. (r'(?s)/\*.*?\*/', Comment.Multiline), # Multiline
  39. (r'//.*?\n', Comment.Single), # Single line
  40. # TODO: highlight references in fandocs
  41. (r'\*\*.*?\n', Comment.Special), # Fandoc
  42. (r'#.*\n', Comment.Single) # Shell-style
  43. ],
  44. 'literals': [
  45. (r'\b-?[\d_]+(ns|ms|sec|min|hr|day)', Number), # Duration
  46. (r'\b-?[\d_]*\.[\d_]+(ns|ms|sec|min|hr|day)', Number), # Duration with dot
  47. (r'\b-?(\d+)?\.\d+(f|F|d|D)?', Number.Float), # Float/Decimal
  48. (r'\b-?0x[0-9a-fA-F_]+', Number.Hex), # Hex
  49. (r'\b-?[\d_]+', Number.Integer), # Int
  50. (r"'\\.'|'[^\\]'|'\\u[0-9a-f]{4}'", String.Char), # Char
  51. (r'"', Punctuation, 'insideStr'), # Opening quote
  52. (r'`', Punctuation, 'insideUri'), # Opening accent
  53. (r'\b(true|false|null)\b', Keyword.Constant), # Bool & null
  54. (r'(?:(\w+)(::))?(\w+)(<\|)(.*?)(\|>)', # DSL
  55. bygroups(Name.Namespace, Punctuation, Name.Class,
  56. Punctuation, String, Punctuation)),
  57. (r'(?:(\w+)(::))?(\w+)?(#)(\w+)?', # Type/slot literal
  58. bygroups(Name.Namespace, Punctuation, Name.Class,
  59. Punctuation, Name.Function)),
  60. (r'\[,\]', Literal), # Empty list
  61. (s(r'($type)(\[,\])'), # Typed empty list
  62. bygroups(using(this, state='inType'), Literal)),
  63. (r'\[:\]', Literal), # Empty Map
  64. (s(r'($type)(\[:\])'),
  65. bygroups(using(this, state='inType'), Literal)),
  66. ],
  67. 'insideStr': [
  68. (r'\\\\', String.Escape), # Escaped backslash
  69. (r'\\"', String.Escape), # Escaped "
  70. (r'\\`', String.Escape), # Escaped `
  71. (r'\$\w+', String.Interpol), # Subst var
  72. (r'\$\{.*?\}', String.Interpol), # Subst expr
  73. (r'"', Punctuation, '#pop'), # Closing quot
  74. (r'.', String) # String content
  75. ],
  76. 'insideUri': [ # TODO: remove copy/paste str/uri
  77. (r'\\\\', String.Escape), # Escaped backslash
  78. (r'\\"', String.Escape), # Escaped "
  79. (r'\\`', String.Escape), # Escaped `
  80. (r'\$\w+', String.Interpol), # Subst var
  81. (r'\$\{.*?\}', String.Interpol), # Subst expr
  82. (r'`', Punctuation, '#pop'), # Closing tick
  83. (r'.', String.Backtick) # URI content
  84. ],
  85. 'protectionKeywords': [
  86. (r'\b(public|protected|private|internal)\b', Keyword),
  87. ],
  88. 'typeKeywords': [
  89. (r'\b(abstract|final|const|native|facet|enum)\b', Keyword),
  90. ],
  91. 'methodKeywords': [
  92. (r'\b(abstract|native|once|override|static|virtual|final)\b',
  93. Keyword),
  94. ],
  95. 'fieldKeywords': [
  96. (r'\b(abstract|const|final|native|override|static|virtual|'
  97. r'readonly)\b', Keyword)
  98. ],
  99. 'otherKeywords': [
  100. (words((
  101. 'try', 'catch', 'throw', 'finally', 'for', 'if', 'else', 'while',
  102. 'as', 'is', 'isnot', 'switch', 'case', 'default', 'continue',
  103. 'break', 'do', 'return', 'get', 'set'), prefix=r'\b', suffix=r'\b'),
  104. Keyword),
  105. (r'\b(it|this|super)\b', Name.Builtin.Pseudo),
  106. ],
  107. 'operators': [
  108. (r'\+\+|\-\-|\+|\-|\*|/|\|\||&&|<=>|<=|<|>=|>|=|!|\[|\]', Operator)
  109. ],
  110. 'inType': [
  111. (r'[\[\]|\->:?]', Punctuation),
  112. (s(r'$id'), Name.Class),
  113. default('#pop'),
  114. ],
  115. 'root': [
  116. include('comments'),
  117. include('protectionKeywords'),
  118. include('typeKeywords'),
  119. include('methodKeywords'),
  120. include('fieldKeywords'),
  121. include('literals'),
  122. include('otherKeywords'),
  123. include('operators'),
  124. (r'using\b', Keyword.Namespace, 'using'), # Using stmt
  125. (r'@\w+', Name.Decorator, 'facet'), # Symbol
  126. (r'(class|mixin)(\s+)(\w+)', bygroups(Keyword, Text, Name.Class),
  127. 'inheritance'), # Inheritance list
  128. # Type var := val
  129. (s(r'($type)([ \t]+)($id)(\s*)(:=)'),
  130. bygroups(using(this, state='inType'), Text,
  131. Name.Variable, Text, Operator)),
  132. # var := val
  133. (s(r'($id)(\s*)(:=)'),
  134. bygroups(Name.Variable, Text, Operator)),
  135. # .someId( or ->someId( ###
  136. (s(r'(\.|(?:\->))($id)(\s*)(\()'),
  137. bygroups(Operator, Name.Function, Text, Punctuation),
  138. 'insideParen'),
  139. # .someId or ->someId
  140. (s(r'(\.|(?:\->))($id)'),
  141. bygroups(Operator, Name.Function)),
  142. # new makeXXX (
  143. (r'(new)(\s+)(make\w*)(\s*)(\()',
  144. bygroups(Keyword, Text, Name.Function, Text, Punctuation),
  145. 'insideMethodDeclArgs'),
  146. # Type name (
  147. (s(r'($type)([ \t]+)' # Return type and whitespace
  148. r'($id)(\s*)(\()'), # method name + open brace
  149. bygroups(using(this, state='inType'), Text,
  150. Name.Function, Text, Punctuation),
  151. 'insideMethodDeclArgs'),
  152. # ArgType argName,
  153. (s(r'($type)(\s+)($id)(\s*)(,)'),
  154. bygroups(using(this, state='inType'), Text, Name.Variable,
  155. Text, Punctuation)),
  156. # ArgType argName)
  157. # Covered in 'insideParen' state
  158. # ArgType argName -> ArgType|
  159. (s(r'($type)(\s+)($id)(\s*)(\->)(\s*)($type)(\|)'),
  160. bygroups(using(this, state='inType'), Text, Name.Variable,
  161. Text, Punctuation, Text, using(this, state='inType'),
  162. Punctuation)),
  163. # ArgType argName|
  164. (s(r'($type)(\s+)($id)(\s*)(\|)'),
  165. bygroups(using(this, state='inType'), Text, Name.Variable,
  166. Text, Punctuation)),
  167. # Type var
  168. (s(r'($type)([ \t]+)($id)'),
  169. bygroups(using(this, state='inType'), Text,
  170. Name.Variable)),
  171. (r'\(', Punctuation, 'insideParen'),
  172. (r'\{', Punctuation, 'insideBrace'),
  173. (r'.', Text)
  174. ],
  175. 'insideParen': [
  176. (r'\)', Punctuation, '#pop'),
  177. include('root'),
  178. ],
  179. 'insideMethodDeclArgs': [
  180. (r'\)', Punctuation, '#pop'),
  181. (s(r'($type)(\s+)($id)(\s*)(\))'),
  182. bygroups(using(this, state='inType'), Text, Name.Variable,
  183. Text, Punctuation), '#pop'),
  184. include('root'),
  185. ],
  186. 'insideBrace': [
  187. (r'\}', Punctuation, '#pop'),
  188. include('root'),
  189. ],
  190. 'inheritance': [
  191. (r'\s+', Text), # Whitespace
  192. (r':|,', Punctuation),
  193. (r'(?:(\w+)(::))?(\w+)',
  194. bygroups(Name.Namespace, Punctuation, Name.Class)),
  195. (r'\{', Punctuation, '#pop')
  196. ],
  197. 'using': [
  198. (r'[ \t]+', Text), # consume whitespaces
  199. (r'(\[)(\w+)(\])',
  200. bygroups(Punctuation, Comment.Special, Punctuation)), # ffi
  201. (r'(\")?([\w.]+)(\")?',
  202. bygroups(Punctuation, Name.Namespace, Punctuation)), # podname
  203. (r'::', Punctuation, 'usingClass'),
  204. default('#pop')
  205. ],
  206. 'usingClass': [
  207. (r'[ \t]+', Text), # consume whitespaces
  208. (r'(as)(\s+)(\w+)',
  209. bygroups(Keyword.Declaration, Text, Name.Class), '#pop:2'),
  210. (r'[\w$]+', Name.Class),
  211. default('#pop:2') # jump out to root state
  212. ],
  213. 'facet': [
  214. (r'\s+', Text),
  215. (r'\{', Punctuation, 'facetFields'),
  216. default('#pop')
  217. ],
  218. 'facetFields': [
  219. include('comments'),
  220. include('literals'),
  221. include('operators'),
  222. (r'\s+', Text),
  223. (r'(\s*)(\w+)(\s*)(=)', bygroups(Text, Name, Text, Operator)),
  224. (r'\}', Punctuation, '#pop'),
  225. (r'.', Text)
  226. ],
  227. }