summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Hammerschmidt <florianh89@gmail.com>2020-02-29 15:47:15 +0100
committerGitHub <noreply@github.com>2020-02-29 15:47:15 +0100
commit0922530959cebfdb3a75dcae244d50e12a1b2052 (patch)
tree22ffff7cb00ecbe9119c0b9c1042b0d71b13d3e9
parent35544e2fc6eed0ce4a27ec7285aac71ff0ddc473 (diff)
downloadpygments-git-0922530959cebfdb3a75dcae244d50e12a1b2052.tar.gz
Add ReasonML lexer. (#1386)
-rw-r--r--doc/languages.rst1
-rw-r--r--pygments/lexers/_mapping.py1
-rw-r--r--pygments/lexers/ml.py94
-rw-r--r--tests/examplefiles/test.re70
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