diff options
author | Florian Hammerschmidt <florianh89@gmail.com> | 2020-02-29 15:47:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-29 15:47:15 +0100 |
commit | 0922530959cebfdb3a75dcae244d50e12a1b2052 (patch) | |
tree | 22ffff7cb00ecbe9119c0b9c1042b0d71b13d3e9 | |
parent | 35544e2fc6eed0ce4a27ec7285aac71ff0ddc473 (diff) | |
download | pygments-git-0922530959cebfdb3a75dcae244d50e12a1b2052.tar.gz |
Add ReasonML lexer. (#1386)
-rw-r--r-- | doc/languages.rst | 1 | ||||
-rw-r--r-- | pygments/lexers/_mapping.py | 1 | ||||
-rw-r--r-- | pygments/lexers/ml.py | 94 | ||||
-rw-r--r-- | tests/examplefiles/test.re | 70 |
4 files changed, 164 insertions, 2 deletions
diff --git a/doc/languages.rst b/doc/languages.rst index de2e93c9..9fc0093e 100644 --- a/doc/languages.rst +++ b/doc/languages.rst @@ -134,6 +134,7 @@ Programming languages * QBasic * `Racket <https://racket-lang.org/>`_ * `Raku <https://www.raku.org/>`_ a.k.a. Perl 6 +* `ReasonML <https://reasonml.github.io/>`_ * `REBOL <http://www.rebol.com>`_ * `Red <https://www.red-lang.org>`_ * Redcode diff --git a/pygments/lexers/_mapping.py b/pygments/lexers/_mapping.py index f16b9a87..5178b70a 100644 --- a/pygments/lexers/_mapping.py +++ b/pygments/lexers/_mapping.py @@ -369,6 +369,7 @@ LEXERS = { 'RagelRubyLexer': ('pygments.lexers.parsers', 'Ragel in Ruby Host', ('ragel-ruby', 'ragel-rb'), ('*.rl',), ()), 'RawTokenLexer': ('pygments.lexers.special', 'Raw token data', ('raw',), (), ('application/x-pygments-tokens',)), 'RdLexer': ('pygments.lexers.r', 'Rd', ('rd',), ('*.Rd',), ('text/x-r-doc',)), + 'ReasonLexer': ('pygments.lexers.ml', 'ReasonML', ('reason', 'reasonml'), ('*.re', '*.rei'), ('text/x-reasonml',)), 'RebolLexer': ('pygments.lexers.rebol', 'REBOL', ('rebol',), ('*.r', '*.r3', '*.reb'), ('text/x-rebol',)), 'RedLexer': ('pygments.lexers.rebol', 'Red', ('red', 'red/system'), ('*.red', '*.reds'), ('text/x-red', 'text/x-red-system')), 'RedcodeLexer': ('pygments.lexers.esoteric', 'Redcode', ('redcode',), ('*.cw',), ()), diff --git a/pygments/lexers/ml.py b/pygments/lexers/ml.py index 461af881..c052de7a 100644 --- a/pygments/lexers/ml.py +++ b/pygments/lexers/ml.py @@ -15,7 +15,7 @@ from pygments.lexer import RegexLexer, include, bygroups, default, words from pygments.token import Text, Comment, Operator, Keyword, Name, String, \ Number, Punctuation, Error -__all__ = ['SMLLexer', 'OcamlLexer', 'OpaLexer'] +__all__ = ['SMLLexer', 'OcamlLexer', 'OpaLexer', 'ReasonLexer'] class SMLLexer(RegexLexer): @@ -445,7 +445,6 @@ class OcamlLexer(RegexLexer): ], } - class OpaLexer(RegexLexer): """ Lexer for the Opa language (http://opalang.org). @@ -767,3 +766,94 @@ class OpaLexer(RegexLexer): (r'[^\-]+|-', Comment), ], } + +class ReasonLexer(RegexLexer): + """ + For the ReasonML language (https://reasonml.github.io/). + + .. versionadded:: 2.6 + """ + + name = 'ReasonML' + aliases = ['reason', "reasonml"] + filenames = ['*.re', '*.rei'] + mimetypes = ['text/x-reasonml'] + + keywords = ( + 'as', 'assert', 'begin', 'class', 'constraint', 'do', 'done', 'downto', + 'else', 'end', 'exception', 'external', 'false', 'for', 'fun', 'esfun', + 'function', 'functor', 'if', 'in', 'include', 'inherit', 'initializer', 'lazy', + 'let', 'switch', 'module', 'pub', 'mutable', 'new', 'nonrec', 'object', 'of', + 'open', 'pri', 'rec', 'sig', 'struct', 'then', 'to', 'true', 'try', + 'type', 'val', 'virtual', 'when', 'while', 'with' + ) + keyopts = ( + '!=', '#', '&', '&&', r'\(', r'\)', r'\*', r'\+', ',', '-', + r'-\.', '=>', r'\.', r'\.\.', r'\.\.\.', ':', '::', ':=', ':>', ';', ';;', '<', + '<-', '=', '>', '>]', r'>\}', r'\?', r'\?\?', r'\[', r'\[<', r'\[>', + r'\[\|', ']', '_', '`', r'\{', r'\{<', r'\|\|', r'\|', r'\|]', r'\}', '~' + ) + + operators = r'[!$%&*+\./:<=>?@^|~-]' + word_operators = ('and', 'asr', 'land', 'lor', 'lsl', 'lsr', 'lxor', 'mod', 'or') + prefix_syms = r'[!?~]' + infix_syms = r'[=<>@^|&+\*/$%-]' + primitives = ('unit', 'int', 'float', 'bool', 'string', 'char', 'list', 'array') + + tokens = { + 'escape-sequence': [ + (r'\\[\\"\'ntbr]', String.Escape), + (r'\\[0-9]{3}', String.Escape), + (r'\\x[0-9a-fA-F]{2}', String.Escape), + ], + 'root': [ + (r'\s+', Text), + (r'false|true|\(\)|\[\]', Name.Builtin.Pseudo), + (r'\b([A-Z][\w\']*)(?=\s*\.)', Name.Namespace, 'dotted'), + (r'\b([A-Z][\w\']*)', Name.Class), + (r'//.*?\n', Comment.Single), + (r'\/\*(?![\/])', Comment.Multiline, 'comment'), + (r'\b(%s)\b' % '|'.join(keywords), Keyword), + (r'(%s)' % '|'.join(keyopts[::-1]), Operator.Word), + (r'(%s|%s)?%s' % (infix_syms, prefix_syms, operators), Operator), + (r'\b(%s)\b' % '|'.join(word_operators), Operator.Word), + (r'\b(%s)\b' % '|'.join(primitives), Keyword.Type), + + (r"[^\W\d][\w']*", Name), + + (r'-?\d[\d_]*(.[\d_]*)?([eE][+\-]?\d[\d_]*)', Number.Float), + (r'0[xX][\da-fA-F][\da-fA-F_]*', Number.Hex), + (r'0[oO][0-7][0-7_]*', Number.Oct), + (r'0[bB][01][01_]*', Number.Bin), + (r'\d[\d_]*', Number.Integer), + + (r"'(?:(\\[\\\"'ntbr ])|(\\[0-9]{3})|(\\x[0-9a-fA-F]{2}))'", + String.Char), + (r"'.'", String.Char), + (r"'", Keyword), + + (r'"', String.Double, 'string'), + + (r'[~?][a-z][\w\']*:', Name.Variable), + ], + 'comment': [ + (r'[^\/*]+', Comment.Multiline), + (r'\/\*', Comment.Multiline, '#push'), + (r'\*\/', Comment.Multiline, '#pop'), + (r'[\*]', Comment.Multiline), + ], + 'string': [ + (r'[^\\"]+', String.Double), + include('escape-sequence'), + (r'\\\n', String.Double), + (r'"', String.Double, '#pop'), + ], + 'dotted': [ + (r'\s+', Text), + (r'\.', Punctuation), + (r'[A-Z][\w\']*(?=\s*\.)', Name.Namespace), + (r'[A-Z][\w\']*', Name.Class, '#pop'), + (r'[a-z_][\w\']*', Name, '#pop'), + default('#pop'), + ], + } diff --git a/tests/examplefiles/test.re b/tests/examplefiles/test.re new file mode 100644 index 00000000..8f74ff4a --- /dev/null +++ b/tests/examplefiles/test.re @@ -0,0 +1,70 @@ +// This is a single line comment. +/* A multi line comment, in a single line... */ +/* This is a multi line comment + Second Line... +*/ +/* This is a nested comment + /* Nested Line... */ +*/ + +module Process_Bind_Without_Do = + (W: Monad_Bind with type m('a) = writer(string, 'a)) => { + let process = s => W.(up_case(s) >>= (up_str => to_words(up_str))); +}; + +let a = 1 or 2; +let b = 1 || 2; +let c = 1 && 2; + +let str = "Hello, Lexer!"; + +let chr = 'a'; + +type test; + +open Belt; + +include Pervasives; + +let test: unit => Map.String.t(string) = () => Map.String.empty; + +let tup = (1: int, 2: int); + +let myRec = {x: 0, y: 10}; + +let myFuncs = { + myFun: (x) => x + 1, + your: (a, b) => a + b +}; + +let lst = [1, 2, 3]; + +let logRest = (lst) => + switch (lst) { + | [] => Js.log("no entry") + | [hd, ...rest] => Js.log2("Rest: ", rest); + }; + +let arr = [|1, 2, 3|]; + +let res = (x) => + switch (x) { + | HasNothing => 0 + | HasSingleInt(x) => 0 + | HasSingleTuple((x, y)) => 0 + | HasMultipleInts(x, y) => 0 + | HasMultipleTuples((x, y), (q, r)) => 0 + }; + +module View = { + [@react.component] + let make = () => { + <div className="view"> + <ul> + <li> React.string("Hello, World!") </li> + <li> "pipe"->React.string </li> + <li> <span> "nested"->React.string </span> </li> + </ul> + </div> + } +}
\ No newline at end of file |