17 |
17 |
18 from pygments.lexers.python import PythonLexer |
18 from pygments.lexers.python import PythonLexer |
19 |
19 |
20 __all__ = ['SchemeLexer', 'CommonLispLexer', 'HyLexer', 'RacketLexer', |
20 __all__ = ['SchemeLexer', 'CommonLispLexer', 'HyLexer', 'RacketLexer', |
21 'NewLispLexer', 'EmacsLispLexer', 'ShenLexer', 'CPSALexer', |
21 'NewLispLexer', 'EmacsLispLexer', 'ShenLexer', 'CPSALexer', |
22 'XtlangLexer'] |
22 'XtlangLexer', 'FennelLexer'] |
23 |
23 |
24 |
24 |
25 class SchemeLexer(RegexLexer): |
25 class SchemeLexer(RegexLexer): |
26 """ |
26 """ |
27 A Scheme lexer, parsing a stream and outputting the tokens |
27 A Scheme lexer, parsing a stream and outputting the tokens |
137 # '(this is syntactic sugar) |
137 # '(this is syntactic sugar) |
138 (r"(?<='\()" + valid_name, Name.Variable), |
138 (r"(?<='\()" + valid_name, Name.Variable), |
139 (r"(?<=#\()" + valid_name, Name.Variable), |
139 (r"(?<=#\()" + valid_name, Name.Variable), |
140 |
140 |
141 # highlight the builtins |
141 # highlight the builtins |
142 ("(?<=\()(%s)" % '|'.join(re.escape(entry) + ' ' for entry in builtins), |
142 (r"(?<=\()(%s)" % '|'.join(re.escape(entry) + ' ' for entry in builtins), |
143 Name.Builtin), |
143 Name.Builtin), |
144 |
144 |
145 # the remaining functions |
145 # the remaining functions |
146 (r'(?<=\()' + valid_name, Name.Function), |
146 (r'(?<=\()' + valid_name, Name.Function), |
147 # find the remaining variables |
147 # find the remaining variables |
331 |
331 |
332 # special constants |
332 # special constants |
333 (r'(t|nil)' + terminated, Name.Constant), |
333 (r'(t|nil)' + terminated, Name.Constant), |
334 |
334 |
335 # functions and variables |
335 # functions and variables |
336 (r'\*' + symbol + '\*', Name.Variable.Global), |
336 (r'\*' + symbol + r'\*', Name.Variable.Global), |
337 (symbol, Name.Variable), |
337 (symbol, Name.Variable), |
338 |
338 |
339 # parentheses |
339 # parentheses |
340 (r'\(', Punctuation, 'body'), |
340 (r'\(', Punctuation, 'body'), |
341 (r'\)', Punctuation, '#pop'), |
341 (r'\)', Punctuation, '#pop'), |
1247 ) |
1247 ) |
1248 |
1248 |
1249 _opening_parenthesis = r'[([{]' |
1249 _opening_parenthesis = r'[([{]' |
1250 _closing_parenthesis = r'[)\]}]' |
1250 _closing_parenthesis = r'[)\]}]' |
1251 _delimiters = r'()[\]{}",\'`;\s' |
1251 _delimiters = r'()[\]{}",\'`;\s' |
1252 _symbol = r'(?u)(?:\|[^|]*\||\\[\w\W]|[^|\\%s]+)+' % _delimiters |
1252 _symbol = r'(?:\|[^|]*\||\\[\w\W]|[^|\\%s]+)+' % _delimiters |
1253 _exact_decimal_prefix = r'(?:#e)?(?:#d)?(?:#e)?' |
1253 _exact_decimal_prefix = r'(?:#e)?(?:#d)?(?:#e)?' |
1254 _exponent = r'(?:[defls][-+]?\d+)' |
1254 _exponent = r'(?:[defls][-+]?\d+)' |
1255 _inexact_simple_no_hashes = r'(?:\d+(?:/\d+|\.\d*)?|\.\d+)' |
1255 _inexact_simple_no_hashes = r'(?:\d+(?:/\d+|\.\d*)?|\.\d+)' |
1256 _inexact_simple = (r'(?:%s|(?:\d+#+(?:\.#*|/\d+#*)?|\.\d+#+|' |
1256 _inexact_simple = (r'(?:%s|(?:\d+#+(?:\.#*|/\d+#*)?|\.\d+#+|' |
1257 r'\d+(?:\.\d*#+|/\d+#+)))' % _inexact_simple_no_hashes) |
1257 r'\d+(?:\.\d*#+|/\d+#+)))' % _inexact_simple_no_hashes) |
1299 # The remaining extflonums |
1299 # The remaining extflonums |
1300 (r'(?i)(([-+]?%st[-+]?\d+)|[-+](inf|nan)\.t)(?=[%s])' % |
1300 (r'(?i)(([-+]?%st[-+]?\d+)|[-+](inf|nan)\.t)(?=[%s])' % |
1301 (_inexact_simple, _delimiters), Number.Float, '#pop'), |
1301 (_inexact_simple, _delimiters), Number.Float, '#pop'), |
1302 |
1302 |
1303 # #b |
1303 # #b |
1304 (r'(?i)(#[ei])?#b%s' % _symbol, Number.Bin, '#pop'), |
1304 (r'(?iu)(#[ei])?#b%s' % _symbol, Number.Bin, '#pop'), |
1305 |
1305 |
1306 # #o |
1306 # #o |
1307 (r'(?i)(#[ei])?#o%s' % _symbol, Number.Oct, '#pop'), |
1307 (r'(?iu)(#[ei])?#o%s' % _symbol, Number.Oct, '#pop'), |
1308 |
1308 |
1309 # #x |
1309 # #x |
1310 (r'(?i)(#[ei])?#x%s' % _symbol, Number.Hex, '#pop'), |
1310 (r'(?iu)(#[ei])?#x%s' % _symbol, Number.Hex, '#pop'), |
1311 |
1311 |
1312 # #i is always inexact, i.e. float |
1312 # #i is always inexact, i.e. float |
1313 (r'(?i)(#d)?#i%s' % _symbol, Number.Float, '#pop'), |
1313 (r'(?iu)(#d)?#i%s' % _symbol, Number.Float, '#pop'), |
1314 |
1314 |
1315 # Strings and characters |
1315 # Strings and characters |
1316 (r'#?"', String.Double, ('#pop', 'string')), |
1316 (r'#?"', String.Double, ('#pop', 'string')), |
1317 (r'#<<(.+)\n(^(?!\1$).*$\n)*^\1$', String.Heredoc, '#pop'), |
1317 (r'#<<(.+)\n(^(?!\1$).*$\n)*^\1$', String.Heredoc, '#pop'), |
1318 (r'#\\(u[\da-fA-F]{1,4}|U[\da-fA-F]{1,8})', String.Char, '#pop'), |
1318 (r'#\\(u[\da-fA-F]{1,4}|U[\da-fA-F]{1,8})', String.Char, '#pop'), |
1321 |
1321 |
1322 # Constants |
1322 # Constants |
1323 (r'#(true|false|[tTfF])', Name.Constant, '#pop'), |
1323 (r'#(true|false|[tTfF])', Name.Constant, '#pop'), |
1324 |
1324 |
1325 # Keyword argument names (e.g. #:keyword) |
1325 # Keyword argument names (e.g. #:keyword) |
1326 (r'#:%s' % _symbol, Keyword.Declaration, '#pop'), |
1326 (r'(?u)#:%s' % _symbol, Keyword.Declaration, '#pop'), |
1327 |
1327 |
1328 # Reader extensions |
1328 # Reader extensions |
1329 (r'(#lang |#!)(\S+)', |
1329 (r'(#lang |#!)(\S+)', |
1330 bygroups(Keyword.Namespace, Name.Namespace)), |
1330 bygroups(Keyword.Namespace, Name.Namespace)), |
1331 (r'#reader', Keyword.Namespace, 'quoted-datum'), |
1331 (r'#reader', Keyword.Namespace, 'quoted-datum'), |
2152 |
2152 |
2153 # special constants |
2153 # special constants |
2154 (r'(t|nil)' + terminated, Name.Constant), |
2154 (r'(t|nil)' + terminated, Name.Constant), |
2155 |
2155 |
2156 # functions and variables |
2156 # functions and variables |
2157 (r'\*' + symbol + '\*', Name.Variable.Global), |
2157 (r'\*' + symbol + r'\*', Name.Variable.Global), |
2158 (symbol, Name.Variable), |
2158 (symbol, Name.Variable), |
2159 |
2159 |
2160 # parentheses |
2160 # parentheses |
2161 (r'#\(', Operator, 'body'), |
2161 (r'#\(', Operator, 'body'), |
2162 (r'\(', Punctuation, 'body'), |
2162 (r'\(', Punctuation, 'body'), |
2325 yield index, token, value |
2325 yield index, token, value |
2326 else: |
2326 else: |
2327 token = Name.Function if token == Literal else token |
2327 token = Name.Function if token == Literal else token |
2328 yield index, token, value |
2328 yield index, token, value |
2329 |
2329 |
2330 raise StopIteration |
2330 return |
2331 |
2331 |
2332 def _process_signature(self, tokens): |
2332 def _process_signature(self, tokens): |
2333 for index, token, value in tokens: |
2333 for index, token, value in tokens: |
2334 if token == Literal and value == '}': |
2334 if token == Literal and value == '}': |
2335 yield index, Punctuation, value |
2335 yield index, Punctuation, value |
2336 raise StopIteration |
2336 return |
2337 elif token in (Literal, Name.Function): |
2337 elif token in (Literal, Name.Function): |
2338 token = Name.Variable if value.istitle() else Keyword.Type |
2338 token = Name.Variable if value.istitle() else Keyword.Type |
2339 yield index, token, value |
2339 yield index, token, value |
2340 |
2340 |
2341 |
2341 |
2617 Keyword, 'xtlang'), |
2617 Keyword, 'xtlang'), |
2618 |
2618 |
2619 include('scheme') |
2619 include('scheme') |
2620 ], |
2620 ], |
2621 } |
2621 } |
|
2622 |
|
2623 |
|
2624 class FennelLexer(RegexLexer): |
|
2625 """A lexer for the `Fennel programming language <https://fennel-lang.org>`_. |
|
2626 |
|
2627 Fennel compiles to Lua, so all the Lua builtins are recognized as well |
|
2628 as the special forms that are particular to the Fennel compiler. |
|
2629 |
|
2630 .. versionadded:: 2.3 |
|
2631 """ |
|
2632 name = 'Fennel' |
|
2633 aliases = ['fennel', 'fnl'] |
|
2634 filenames = ['*.fnl'] |
|
2635 |
|
2636 # these two lists are taken from fennel-mode.el: |
|
2637 # https://gitlab.com/technomancy/fennel-mode |
|
2638 # this list is current as of Fennel version 0.1.0. |
|
2639 special_forms = ( |
|
2640 u'require-macros', u'eval-compiler', |
|
2641 u'do', u'values', u'if', u'when', u'each', u'for', u'fn', u'lambda', |
|
2642 u'λ', u'set', u'global', u'var', u'local', u'let', u'tset', u'doto', |
|
2643 u'set-forcibly!', u'defn', u'partial', u'while', u'or', u'and', u'true', |
|
2644 u'false', u'nil', u'.', u'+', u'..', u'^', u'-', u'*', u'%', u'/', u'>', |
|
2645 u'<', u'>=', u'<=', u'=', u'~=', u'#', u'...', u':', u'->', u'->>', |
|
2646 ) |
|
2647 |
|
2648 # Might be nicer to use the list from _lua_builtins.py but it's unclear how? |
|
2649 builtins = ( |
|
2650 u'_G', u'_VERSION', u'arg', u'assert', u'bit32', u'collectgarbage', |
|
2651 u'coroutine', u'debug', u'dofile', u'error', u'getfenv', |
|
2652 u'getmetatable', u'io', u'ipairs', u'load', u'loadfile', u'loadstring', |
|
2653 u'math', u'next', u'os', u'package', u'pairs', u'pcall', u'print', |
|
2654 u'rawequal', u'rawget', u'rawlen', u'rawset', u'require', u'select', |
|
2655 u'setfenv', u'setmetatable', u'string', u'table', u'tonumber', |
|
2656 u'tostring', u'type', u'unpack', u'xpcall' |
|
2657 ) |
|
2658 |
|
2659 # based on the scheme definition, but disallowing leading digits and commas |
|
2660 valid_name = r'[a-zA-Z_!$%&*+/:<=>?@^~|-][\w!$%&*+/:<=>?@^~|\.-]*' |
|
2661 |
|
2662 tokens = { |
|
2663 'root': [ |
|
2664 # the only comment form is a semicolon; goes to the end of the line |
|
2665 (r';.*$', Comment.Single), |
|
2666 |
|
2667 (r'[,\s]+', Text), |
|
2668 (r'-?\d+\.\d+', Number.Float), |
|
2669 (r'-?\d+', Number.Integer), |
|
2670 |
|
2671 (r'"(\\\\|\\"|[^"])*"', String), |
|
2672 (r"'(\\\\|\\'|[^'])*'", String), |
|
2673 |
|
2674 # these are technically strings, but it's worth visually |
|
2675 # distinguishing them because their intent is different |
|
2676 # from regular strings. |
|
2677 (r':' + valid_name, String.Symbol), |
|
2678 |
|
2679 # special forms are keywords |
|
2680 (words(special_forms, suffix=' '), Keyword), |
|
2681 # lua standard library are builtins |
|
2682 (words(builtins, suffix=' '), Name.Builtin), |
|
2683 # special-case the vararg symbol |
|
2684 (r'\.\.\.', Name.Variable), |
|
2685 # regular identifiers |
|
2686 (valid_name, Name.Variable), |
|
2687 |
|
2688 # all your normal paired delimiters for your programming enjoyment |
|
2689 (r'(\(|\))', Punctuation), |
|
2690 (r'(\[|\])', Punctuation), |
|
2691 (r'(\{|\})', Punctuation), |
|
2692 ] |
|
2693 } |