1"""
2 pygments.lexers.felix
3 ~~~~~~~~~~~~~~~~~~~~~
4
5 Lexer for the Felix 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 RegexLexer, include, bygroups, default, words, \
12 combined
13from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
14 Number, Punctuation, Whitespace
15
16__all__ = ['FelixLexer']
17
18
19class FelixLexer(RegexLexer):
20 """
21 For Felix source code.
22 """
23
24 name = 'Felix'
25 url = 'http://www.felix-lang.org'
26 aliases = ['felix', 'flx']
27 filenames = ['*.flx', '*.flxh']
28 mimetypes = ['text/x-felix']
29 version_added = '1.2'
30
31 preproc = (
32 'elif', 'else', 'endif', 'if', 'ifdef', 'ifndef',
33 )
34
35 keywords = (
36 '_', '_deref', 'all', 'as',
37 'assert', 'attempt', 'call', 'callback', 'case', 'caseno', 'cclass',
38 'code', 'compound', 'ctypes', 'do', 'done', 'downto', 'elif', 'else',
39 'endattempt', 'endcase', 'endif', 'endmatch', 'enum', 'except',
40 'exceptions', 'expect', 'finally', 'for', 'forall', 'forget', 'fork',
41 'functor', 'goto', 'ident', 'if', 'incomplete', 'inherit', 'instance',
42 'interface', 'jump', 'lambda', 'loop', 'match', 'module', 'namespace',
43 'new', 'noexpand', 'nonterm', 'obj', 'of', 'open', 'parse', 'raise',
44 'regexp', 'reglex', 'regmatch', 'rename', 'return', 'the', 'then',
45 'to', 'type', 'typecase', 'typedef', 'typematch', 'typeof', 'upto',
46 'when', 'whilst', 'with', 'yield',
47 )
48
49 keyword_directives = (
50 '_gc_pointer', '_gc_type', 'body', 'comment', 'const', 'export',
51 'header', 'inline', 'lval', 'macro', 'noinline', 'noreturn',
52 'package', 'private', 'pod', 'property', 'public', 'publish',
53 'requires', 'todo', 'virtual', 'use',
54 )
55
56 keyword_declarations = (
57 'def', 'let', 'ref', 'val', 'var',
58 )
59
60 keyword_types = (
61 'unit', 'void', 'any', 'bool',
62 'byte', 'offset',
63 'address', 'caddress', 'cvaddress', 'vaddress',
64 'tiny', 'short', 'int', 'long', 'vlong',
65 'utiny', 'ushort', 'vshort', 'uint', 'ulong', 'uvlong',
66 'int8', 'int16', 'int32', 'int64',
67 'uint8', 'uint16', 'uint32', 'uint64',
68 'float', 'double', 'ldouble',
69 'complex', 'dcomplex', 'lcomplex',
70 'imaginary', 'dimaginary', 'limaginary',
71 'char', 'wchar', 'uchar',
72 'charp', 'charcp', 'ucharp', 'ucharcp',
73 'string', 'wstring', 'ustring',
74 'cont',
75 'array', 'varray', 'list',
76 'lvalue', 'opt', 'slice',
77 )
78
79 keyword_constants = (
80 'false', 'true',
81 )
82
83 operator_words = (
84 'and', 'not', 'in', 'is', 'isin', 'or', 'xor',
85 )
86
87 name_builtins = (
88 '_svc', 'while',
89 )
90
91 name_pseudo = (
92 'root', 'self', 'this',
93 )
94
95 decimal_suffixes = '([tTsSiIlLvV]|ll|LL|([iIuU])(8|16|32|64))?'
96
97 tokens = {
98 'root': [
99 include('whitespace'),
100
101 # Keywords
102 (words(('axiom', 'ctor', 'fun', 'gen', 'proc', 'reduce',
103 'union'), suffix=r'\b'),
104 Keyword, 'funcname'),
105 (words(('class', 'cclass', 'cstruct', 'obj', 'struct'), suffix=r'\b'),
106 Keyword, 'classname'),
107 (r'(instance|module|typeclass)\b', Keyword, 'modulename'),
108
109 (words(keywords, suffix=r'\b'), Keyword),
110 (words(keyword_directives, suffix=r'\b'), Name.Decorator),
111 (words(keyword_declarations, suffix=r'\b'), Keyword.Declaration),
112 (words(keyword_types, suffix=r'\b'), Keyword.Type),
113 (words(keyword_constants, suffix=r'\b'), Keyword.Constant),
114
115 # Operators
116 include('operators'),
117
118 # Float Literal
119 # -- Hex Float
120 (r'0[xX]([0-9a-fA-F_]*\.[0-9a-fA-F_]+|[0-9a-fA-F_]+)'
121 r'[pP][+\-]?[0-9_]+[lLfFdD]?', Number.Float),
122 # -- DecimalFloat
123 (r'[0-9_]+(\.[0-9_]+[eE][+\-]?[0-9_]+|'
124 r'\.[0-9_]*|[eE][+\-]?[0-9_]+)[lLfFdD]?', Number.Float),
125 (r'\.(0|[1-9][0-9_]*)([eE][+\-]?[0-9_]+)?[lLfFdD]?',
126 Number.Float),
127
128 # IntegerLiteral
129 # -- Binary
130 (rf'0[Bb][01_]+{decimal_suffixes}', Number.Bin),
131 # -- Octal
132 (rf'0[0-7_]+{decimal_suffixes}', Number.Oct),
133 # -- Hexadecimal
134 (rf'0[xX][0-9a-fA-F_]+{decimal_suffixes}', Number.Hex),
135 # -- Decimal
136 (rf'(0|[1-9][0-9_]*){decimal_suffixes}', Number.Integer),
137
138 # Strings
139 ('([rR][cC]?|[cC][rR])"""', String, 'tdqs'),
140 ("([rR][cC]?|[cC][rR])'''", String, 'tsqs'),
141 ('([rR][cC]?|[cC][rR])"', String, 'dqs'),
142 ("([rR][cC]?|[cC][rR])'", String, 'sqs'),
143 ('[cCfFqQwWuU]?"""', String, combined('stringescape', 'tdqs')),
144 ("[cCfFqQwWuU]?'''", String, combined('stringescape', 'tsqs')),
145 ('[cCfFqQwWuU]?"', String, combined('stringescape', 'dqs')),
146 ("[cCfFqQwWuU]?'", String, combined('stringescape', 'sqs')),
147
148 # Punctuation
149 (r'[\[\]{}:(),;?]', Punctuation),
150
151 # Labels
152 (r'[a-zA-Z_]\w*:>', Name.Label),
153
154 # Identifiers
155 (r'({})\b'.format('|'.join(name_builtins)), Name.Builtin),
156 (r'({})\b'.format('|'.join(name_pseudo)), Name.Builtin.Pseudo),
157 (r'[a-zA-Z_]\w*', Name),
158 ],
159 'whitespace': [
160 (r'\s+', Whitespace),
161
162 include('comment'),
163
164 # Preprocessor
165 (r'(#)(\s*)(if)(\s+)(0)',
166 bygroups(Comment.Preproc, Whitespace, Comment.Preproc,
167 Whitespace, Comment.Preproc), 'if0'),
168 (r'#', Comment.Preproc, 'macro'),
169 ],
170 'operators': [
171 (r'({})\b'.format('|'.join(operator_words)), Operator.Word),
172 (r'!=|==|<<|>>|\|\||&&|[-~+/*%=<>&^|.$]', Operator),
173 ],
174 'comment': [
175 (r'//(.*?)$', Comment.Single),
176 (r'/[*]', Comment.Multiline, 'comment2'),
177 ],
178 'comment2': [
179 (r'[^/*]', Comment.Multiline),
180 (r'/[*]', Comment.Multiline, '#push'),
181 (r'[*]/', Comment.Multiline, '#pop'),
182 (r'[/*]', Comment.Multiline),
183 ],
184 'if0': [
185 (r'^(\s*)(#if.*?(?<!\\))(\n)',
186 bygroups(Whitespace, Comment, Whitespace), '#push'),
187 (r'^(\s*)(#endif.*?(?<!\\))(\n)',
188 bygroups(Whitespace, Comment, Whitespace), '#pop'),
189 (r'(.*?)(\n)', bygroups(Comment, Whitespace)),
190 ],
191 'macro': [
192 include('comment'),
193 (r'(import|include)(\s+)(<[^>]*?>)',
194 bygroups(Comment.Preproc, Whitespace, String), '#pop'),
195 (r'(import|include)(\s+)("[^"]*?")',
196 bygroups(Comment.Preproc, Whitespace, String), '#pop'),
197 (r"(import|include)(\s+)('[^']*?')",
198 bygroups(Comment.Preproc, Whitespace, String), '#pop'),
199 (r'[^/\n]+', Comment.Preproc),
200 # (r'/[*](.|\n)*?[*]/', Comment),
201 # (r'//.*?\n', Comment, '#pop'),
202 (r'/', Comment.Preproc),
203 (r'(?<=\\)\n', Comment.Preproc),
204 (r'\n', Whitespace, '#pop'),
205 ],
206 'funcname': [
207 include('whitespace'),
208 (r'[a-zA-Z_]\w*', Name.Function, '#pop'),
209 # anonymous functions
210 (r'(?=\()', Text, '#pop'),
211 ],
212 'classname': [
213 include('whitespace'),
214 (r'[a-zA-Z_]\w*', Name.Class, '#pop'),
215 # anonymous classes
216 (r'(?=\{)', Text, '#pop'),
217 ],
218 'modulename': [
219 include('whitespace'),
220 (r'\[', Punctuation, ('modulename2', 'tvarlist')),
221 default('modulename2'),
222 ],
223 'modulename2': [
224 include('whitespace'),
225 (r'([a-zA-Z_]\w*)', Name.Namespace, '#pop:2'),
226 ],
227 'tvarlist': [
228 include('whitespace'),
229 include('operators'),
230 (r'\[', Punctuation, '#push'),
231 (r'\]', Punctuation, '#pop'),
232 (r',', Punctuation),
233 (r'(with|where)\b', Keyword),
234 (r'[a-zA-Z_]\w*', Name),
235 ],
236 'stringescape': [
237 (r'\\([\\abfnrtv"\']|\n|N\{.*?\}|u[a-fA-F0-9]{4}|'
238 r'U[a-fA-F0-9]{8}|x[a-fA-F0-9]{2}|[0-7]{1,3})', String.Escape)
239 ],
240 'strings': [
241 (r'%(\([a-zA-Z0-9]+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?'
242 '[hlL]?[E-GXc-giorsux%]', String.Interpol),
243 (r'[^\\\'"%\n]+', String),
244 # quotes, percents and backslashes must be parsed one at a time
245 (r'[\'"\\]', String),
246 # unhandled string formatting sign
247 (r'%', String)
248 # newlines are an error (use "nl" state)
249 ],
250 'nl': [
251 (r'\n', String)
252 ],
253 'dqs': [
254 (r'"', String, '#pop'),
255 # included here again for raw strings
256 (r'\\\\|\\"|\\\n', String.Escape),
257 include('strings')
258 ],
259 'sqs': [
260 (r"'", String, '#pop'),
261 # included here again for raw strings
262 (r"\\\\|\\'|\\\n", String.Escape),
263 include('strings')
264 ],
265 'tdqs': [
266 (r'"""', String, '#pop'),
267 include('strings'),
268 include('nl')
269 ],
270 'tsqs': [
271 (r"'''", String, '#pop'),
272 include('strings'),
273 include('nl')
274 ],
275 }