fantom.py 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. """
  2. pygments.lexers.fantom
  3. ~~~~~~~~~~~~~~~~~~~~~~
  4. Lexer for the Fantom language.
  5. :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS.
  6. :license: BSD, see LICENSE for details.
  7. """
  8. from string import Template
  9. from pygments.lexer import RegexLexer, include, bygroups, using, \
  10. this, default, words
  11. from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
  12. Number, Punctuation, Literal, Whitespace
  13. __all__ = ['FantomLexer']
  14. class FantomLexer(RegexLexer):
  15. """
  16. For Fantom source code.
  17. """
  18. name = 'Fantom'
  19. aliases = ['fan']
  20. filenames = ['*.fan']
  21. mimetypes = ['application/x-fantom']
  22. url = 'https://www.fantom.org'
  23. version_added = '1.5'
  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'//.*?$', Comment.Single), # Single line
  40. # TODO: highlight references in fandocs
  41. (r'\*\*.*?$', Comment.Special), # Fandoc
  42. (r'#.*$', 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, Whitespace, Name.Class),
  127. 'inheritance'), # Inheritance list
  128. # Type var := val
  129. (s(r'($type)([ \t]+)($id)(\s*)(:=)'),
  130. bygroups(using(this, state='inType'), Whitespace,
  131. Name.Variable, Whitespace, Operator)),
  132. # var := val
  133. (s(r'($id)(\s*)(:=)'),
  134. bygroups(Name.Variable, Whitespace, Operator)),
  135. # .someId( or ->someId( ###
  136. (s(r'(\.|(?:\->))($id)(\s*)(\()'),
  137. bygroups(Operator, Name.Function, Whitespace, 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, Whitespace, Name.Function, Whitespace, 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'), Whitespace,
  150. Name.Function, Whitespace, Punctuation),
  151. 'insideMethodDeclArgs'),
  152. # ArgType argName,
  153. (s(r'($type)(\s+)($id)(\s*)(,)'),
  154. bygroups(using(this, state='inType'), Whitespace, Name.Variable,
  155. Whitespace, 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'), Whitespace, Name.Variable,
  161. Whitespace, Punctuation, Whitespace, using(this, state='inType'),
  162. Punctuation)),
  163. # ArgType argName|
  164. (s(r'($type)(\s+)($id)(\s*)(\|)'),
  165. bygroups(using(this, state='inType'), Whitespace, Name.Variable,
  166. Whitespace, Punctuation)),
  167. # Type var
  168. (s(r'($type)([ \t]+)($id)'),
  169. bygroups(using(this, state='inType'), Whitespace,
  170. Name.Variable)),
  171. (r'\(', Punctuation, 'insideParen'),
  172. (r'\{', Punctuation, 'insideBrace'),
  173. (r'\s+', Whitespace),
  174. (r'.', Text)
  175. ],
  176. 'insideParen': [
  177. (r'\)', Punctuation, '#pop'),
  178. include('root'),
  179. ],
  180. 'insideMethodDeclArgs': [
  181. (r'\)', Punctuation, '#pop'),
  182. (s(r'($type)(\s+)($id)(\s*)(\))'),
  183. bygroups(using(this, state='inType'), Whitespace, Name.Variable,
  184. Whitespace, Punctuation), '#pop'),
  185. include('root'),
  186. ],
  187. 'insideBrace': [
  188. (r'\}', Punctuation, '#pop'),
  189. include('root'),
  190. ],
  191. 'inheritance': [
  192. (r'\s+', Whitespace), # Whitespace
  193. (r':|,', Punctuation),
  194. (r'(?:(\w+)(::))?(\w+)',
  195. bygroups(Name.Namespace, Punctuation, Name.Class)),
  196. (r'\{', Punctuation, '#pop')
  197. ],
  198. 'using': [
  199. (r'[ \t]+', Whitespace), # consume whitespaces
  200. (r'(\[)(\w+)(\])',
  201. bygroups(Punctuation, Comment.Special, Punctuation)), # ffi
  202. (r'(\")?([\w.]+)(\")?',
  203. bygroups(Punctuation, Name.Namespace, Punctuation)), # podname
  204. (r'::', Punctuation, 'usingClass'),
  205. default('#pop')
  206. ],
  207. 'usingClass': [
  208. (r'[ \t]+', Whitespace), # consume whitespaces
  209. (r'(as)(\s+)(\w+)',
  210. bygroups(Keyword.Declaration, Whitespace, Name.Class), '#pop:2'),
  211. (r'[\w$]+', Name.Class),
  212. default('#pop:2') # jump out to root state
  213. ],
  214. 'facet': [
  215. (r'\s+', Whitespace),
  216. (r'\{', Punctuation, 'facetFields'),
  217. default('#pop')
  218. ],
  219. 'facetFields': [
  220. include('comments'),
  221. include('literals'),
  222. include('operators'),
  223. (r'\s+', Whitespace),
  224. (r'(\s*)(\w+)(\s*)(=)', bygroups(Whitespace, Name, Whitespace, Operator)),
  225. (r'\}', Punctuation, '#pop'),
  226. (r'\s+', Whitespace),
  227. (r'.', Text)
  228. ],
  229. }