1"""
2 pygments.lexers.clean
3 ~~~~~~~~~~~~~~~~~~~~~
4
5 Lexer for the Clean language.
6
7 :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9"""
10
11from pygments.lexer import ExtendedRegexLexer, words, default, include, bygroups
12from pygments.token import Comment, Error, Keyword, Literal, Name, Number, \
13 Operator, Punctuation, String, Whitespace
14
15__all__ = ['CleanLexer']
16
17
18class CleanLexer(ExtendedRegexLexer):
19 """
20 Lexer for the general purpose, state-of-the-art, pure and lazy functional
21 programming language Clean.
22
23 .. versionadded: 2.2
24 """
25 name = 'Clean'
26 url = 'http://clean.cs.ru.nl/Clean'
27 aliases = ['clean']
28 filenames = ['*.icl', '*.dcl']
29 version_added = ''
30
31 keywords = (
32 'case', 'ccall', 'class', 'code', 'code inline', 'derive', 'export',
33 'foreign', 'generic', 'if', 'in', 'infix', 'infixl', 'infixr',
34 'instance', 'let', 'of', 'otherwise', 'special', 'stdcall', 'where',
35 'with')
36
37 modulewords = ('implementation', 'definition', 'system')
38
39 lowerId = r'[a-z`][\w`]*'
40 upperId = r'[A-Z`][\w`]*'
41 funnyId = r'[~@#$%\^?!+\-*<>\\/|&=:]+'
42 scoreUpperId = r'_' + upperId
43 scoreLowerId = r'_' + lowerId
44 moduleId = r'[a-zA-Z_][a-zA-Z0-9_.`]+'
45 classId = '|'.join([lowerId, upperId, funnyId])
46
47 tokens = {
48 'root': [
49 include('comments'),
50 include('keywords'),
51 include('module'),
52 include('import'),
53 include('whitespace'),
54 include('literals'),
55 include('operators'),
56 include('delimiters'),
57 include('names'),
58 ],
59 'whitespace': [
60 (r'\s+', Whitespace),
61 ],
62 'comments': [
63 (r'//.*\n', Comment.Single),
64 (r'/\*', Comment.Multiline, 'comments.in'),
65 (r'/\*\*', Comment.Special, 'comments.in'),
66 ],
67 'comments.in': [
68 (r'\*\/', Comment.Multiline, '#pop'),
69 (r'/\*', Comment.Multiline, '#push'),
70 (r'[^*/]+', Comment.Multiline),
71 (r'\*(?!/)', Comment.Multiline),
72 (r'/', Comment.Multiline),
73 ],
74 'keywords': [
75 (words(keywords, prefix=r'\b', suffix=r'\b'), Keyword),
76 ],
77 'module': [
78 (words(modulewords, prefix=r'\b', suffix=r'\b'), Keyword.Namespace),
79 (r'\bmodule\b', Keyword.Namespace, 'module.name'),
80 ],
81 'module.name': [
82 include('whitespace'),
83 (moduleId, Name.Class, '#pop'),
84 ],
85 'import': [
86 (r'\b(import)\b(\s*)', bygroups(Keyword, Whitespace), 'import.module'),
87 (r'\b(from)\b(\s*)\b(' + moduleId + r')\b(\s*)\b(import)\b',
88 bygroups(Keyword, Whitespace, Name.Class, Whitespace, Keyword),
89 'import.what'),
90 ],
91 'import.module': [
92 (r'\b(qualified)\b(\s*)', bygroups(Keyword, Whitespace)),
93 (r'(\s*)\b(as)\b', bygroups(Whitespace, Keyword), ('#pop', 'import.module.as')),
94 (moduleId, Name.Class),
95 (r'(\s*)(,)(\s*)', bygroups(Whitespace, Punctuation, Whitespace)),
96 (r'\s+', Whitespace),
97 default('#pop'),
98 ],
99 'import.module.as': [
100 include('whitespace'),
101 (lowerId, Name.Class, '#pop'),
102 (upperId, Name.Class, '#pop'),
103 ],
104 'import.what': [
105 (r'\b(class)\b(\s+)(' + classId + r')',
106 bygroups(Keyword, Whitespace, Name.Class), 'import.what.class'),
107 (r'\b(instance)(\s+)(' + classId + r')(\s+)',
108 bygroups(Keyword, Whitespace, Name.Class, Whitespace), 'import.what.instance'),
109 (r'(::)(\s*)\b(' + upperId + r')\b',
110 bygroups(Punctuation, Whitespace, Name.Class), 'import.what.type'),
111 (r'\b(generic)\b(\s+)\b(' + lowerId + '|' + upperId + r')\b',
112 bygroups(Keyword, Whitespace, Name)),
113 include('names'),
114 (r'(,)(\s+)', bygroups(Punctuation, Whitespace)),
115 (r'$', Whitespace, '#pop'),
116 include('whitespace'),
117 ],
118 'import.what.class': [
119 (r',', Punctuation, '#pop'),
120 (r'\(', Punctuation, 'import.what.class.members'),
121 (r'$', Whitespace, '#pop:2'),
122 include('whitespace'),
123 ],
124 'import.what.class.members': [
125 (r',', Punctuation),
126 (r'\.\.', Punctuation),
127 (r'\)', Punctuation, '#pop'),
128 include('names'),
129 ],
130 'import.what.instance': [
131 (r'[,)]', Punctuation, '#pop'),
132 (r'\(', Punctuation, 'import.what.instance'),
133 (r'$', Whitespace, '#pop:2'),
134 include('whitespace'),
135 include('names'),
136 ],
137 'import.what.type': [
138 (r',', Punctuation, '#pop'),
139 (r'[({]', Punctuation, 'import.what.type.consesandfields'),
140 (r'$', Whitespace, '#pop:2'),
141 include('whitespace'),
142 ],
143 'import.what.type.consesandfields': [
144 (r',', Punctuation),
145 (r'\.\.', Punctuation),
146 (r'[)}]', Punctuation, '#pop'),
147 include('names'),
148 ],
149 'literals': [
150 (r'\'([^\'\\]|\\(x[\da-fA-F]+|\d+|.))\'', Literal.Char),
151 (r'[+~-]?0[0-7]+\b', Number.Oct),
152 (r'[+~-]?\d+\.\d+(E[+-]?\d+)?', Number.Float),
153 (r'[+~-]?\d+\b', Number.Integer),
154 (r'[+~-]?0x[\da-fA-F]+\b', Number.Hex),
155 (r'True|False', Literal),
156 (r'"', String.Double, 'literals.stringd'),
157 ],
158 'literals.stringd': [
159 (r'[^\\"\n]+', String.Double),
160 (r'"', String.Double, '#pop'),
161 (r'\\.', String.Double),
162 (r'[$\n]', Error, '#pop'),
163 ],
164 'operators': [
165 (r'[-~@#$%\^?!+*<>\\/|&=:.]+', Operator),
166 (r'\b_+\b', Operator),
167 ],
168 'delimiters': [
169 (r'[,;(){}\[\]]', Punctuation),
170 (r'(\')([\w`.]+)(\')',
171 bygroups(Punctuation, Name.Class, Punctuation)),
172 ],
173 'names': [
174 (lowerId, Name),
175 (scoreLowerId, Name),
176 (funnyId, Name.Function),
177 (upperId, Name.Class),
178 (scoreUpperId, Name.Class),
179 ]
180 }