1"""
2 pygments.lexers.purescript
3 ~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5 Lexer for the PureScript language.
6
7 :copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9"""
10
11from pygments.lexer import RegexLexer, bygroups, default
12from pygments.token import Comment, Operator, Keyword, Name, String, \
13 Number, Punctuation, Whitespace
14from pygments import unistring as uni
15
16__all__ = ['PureScriptLexer']
17
18
19class PureScriptLexer(RegexLexer):
20 """
21 A lexer for the PureScript language.
22 """
23 name = 'PureScript'
24 url = 'https://www.purescript.org/'
25 aliases = ['purescript', 'purs']
26 filenames = ['*.purs']
27 mimetypes = ['text/x-purescript']
28 version_added = '2.19'
29
30 reserved = ('ado', 'case', 'class', 'data', 'derive', 'do', 'else',
31 'false', 'forall', 'foreign', 'if', 'in', 'infix[lr]?',
32 'instance', 'let', 'newtype', 'of',
33 'then', 'true', 'type', 'where', '_')
34
35 tokens = {
36 'root': [
37 # Whitespace
38 (r'\s+', Whitespace),
39 # Single-line comments
40 (r'--.*?$', Comment.Single),
41 # Multi-line comments
42 (r'\{-', Comment.Multiline, 'comment'),
43 # Lexemes:
44 # Identifiers
45 (r"\bimport(?!')\b", Keyword.Reserved, 'import'),
46 (r"\bmodule(?!')\b", Keyword.Reserved, 'module'),
47 (r'\b({})(?!\')\b'.format('|'.join(reserved)), Keyword.Reserved),
48 # Typed holes
49 (r'\?\w[\w\']*', Name.Variable),
50 # Character literal (before names to avoid confusion)
51 (r"'[^\\]'", String.Char),
52 # Identifiers
53 (r'^[_' + uni.Ll + r'][\w\']*', Name.Function),
54 (r"[_" + uni.Ll + r"][\w']*", Name),
55 (r'[' + uni.Lu + r'][\w\']*', Keyword.Type),
56 # Backtick operator
57 (r'`', Punctuation),
58 # Operators
59 (r'\\(?![' + uni.Sm + uni.So + uni.Sc +
60 r':!#%&*.\\/?@^-]+)', Name.Function), # lambda
61 # Unicode operators
62 (r'[∀→←⇒∷]', Operator.Word),
63 (r'(<-|::|->|=>|=)(?![' + uni.Sm + uni.So + uni.Sc +
64 r':!#%&*.\\/?@^-]+)', Operator.Word),
65 (r':[' + uni.Sm + uni.So + uni.Sc +
66 r':!#%&*.\\/?@^-]*', Keyword.Type), # Constructor operators
67 (r'[' + uni.Sm + uni.So + uni.Sc +
68 r':!#%&*.\\/?@^-]+', Operator), # Other operators
69 # Numbers
70 (r'\d(_*\d)*_*e[+-]?\d(_*\d)*', Number.Float),
71 (r'\d(_*\d)*\.\d(_*\d)*(_*e[+-]?\d(_*\d)*)?', Number.Float),
72 (r'0x[\da-fA-F]+', Number.Hex),
73 (r'\d(_*\d)*', Number.Integer),
74 # Character/String Literals
75 (r"'", String.Char, 'character'),
76 (r'"""', String, 'rawstring'),
77 (r'"', String, 'string'),
78 # Special
79 (r'[][(),;{}]', Punctuation),
80 ],
81 'import': [
82 (r'\s+', Whitespace),
83 # import X as Y
84 (r'([' + uni.Lu + r'][\w.]*)(\s+)(as)(\s+)([' + uni.Lu + r'][\w.]*)',
85 bygroups(Name.Namespace, Whitespace, Keyword, Whitespace, Name),
86 '#pop'),
87 # import X hiding (functions)
88 (r'([' + uni.Lu + r'][\w.]*)(\s+)(hiding)(\s+)(\()',
89 bygroups(Name.Namespace, Whitespace, Keyword, Whitespace,
90 Punctuation), 'funclist'),
91 # import X (functions)
92 (r'([' + uni.Lu + r'][\w.]*)(\s+)(\()',
93 bygroups(Name.Namespace, Whitespace, Punctuation), 'funclist'),
94 # 'as' after funclist: import X (foo) as Y
95 (r'(as)(\s+)([' + uni.Lu + r'][\w.]*)',
96 bygroups(Keyword, Whitespace, Name), '#pop'),
97 # import X (bare module name, must start with uppercase)
98 (r'[' + uni.Lu + r'][\w.]*', Name.Namespace, '#pop'),
99 # pop when import is done
100 default('#pop'),
101 ],
102 'module': [
103 (r'\s+', Whitespace),
104 (r'([' + uni.Lu + r'][\w.]*)(\s+)(\()',
105 bygroups(Name.Namespace, Whitespace, Punctuation), 'funclist'),
106 (r'[' + uni.Lu + r'][\w.]*', Name.Namespace, '#pop'),
107 default('#pop'),
108 ],
109 'funclist': [
110 (r'\s+', Whitespace),
111 (r'(module)(\s+)([' + uni.Lu + r'][\w.]*)',
112 bygroups(Keyword.Reserved, Whitespace, Name.Namespace)),
113 (r"\b(class|type)(?!')\b", Keyword.Reserved),
114 (r'[' + uni.Lu + r']\w*', Keyword.Type),
115 (r'(_[\w\']+|[' + uni.Ll + r'][\w\']*)', Name.Function),
116 (r'--.*?$', Comment.Single),
117 (r'\{-', Comment.Multiline, 'comment'),
118 (r',', Punctuation),
119 (r'\.\.', Punctuation),
120 (r'[' + uni.Sm + uni.So + uni.Sc +
121 r':!#%&*.\\/?@^-]+', Operator),
122 (r'\(', Punctuation, 'funclist'),
123 (r'\)', Punctuation, '#pop'),
124 ],
125 'comment': [
126 (r'[^-{}]+', Comment.Multiline),
127 (r'\{-', Comment.Multiline, '#push'),
128 (r'-\}', Comment.Multiline, '#pop'),
129 (r'[-{}]', Comment.Multiline),
130 ],
131 'character': [
132 (r"[^\\']'", String.Char, '#pop'),
133 (r"\\", String.Escape, 'escape'),
134 ("'", String.Char, '#pop'),
135 ],
136 'string': [
137 (r'[^\\"]+', String),
138 (r"\\", String.Escape, 'escape'),
139 ('"', String, '#pop'),
140 ],
141 'rawstring': [
142 (r'"""', String, '#pop'),
143 (r'[^"]+', String),
144 (r'"', String),
145 ],
146 'escape': [
147 (r'[nrt"\'\\]', String.Escape, '#pop'),
148 (r'x[\da-fA-F]{1,6}', String.Escape, '#pop'),
149 # String gaps: backslash-whitespace-backslash
150 (r'(\s+)(\\)', bygroups(Whitespace, String.Escape), '#pop'),
151 # Invalid escape: pop back so the next char is handled normally
152 default('#pop'),
153 ],
154 }