1"""
2 pygments.lexers.dotnet
3 ~~~~~~~~~~~~~~~~~~~~~~
4
5 Lexers for .net languages.
6
7 :copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9"""
10import re
11
12from pygments.lexer import RegexLexer, DelegatingLexer, bygroups, include, \
13 using, this, default, words
14from pygments.token import Punctuation, Text, Comment, Operator, Keyword, \
15 Name, String, Number, Literal, Other, Whitespace
16from pygments.util import get_choice_opt
17from pygments import unistring as uni
18
19from pygments.lexers.html import XmlLexer
20
21__all__ = ['CSharpLexer', 'NemerleLexer', 'BooLexer', 'VbNetLexer',
22 'CSharpAspxLexer', 'VbNetAspxLexer', 'FSharpLexer', 'XppLexer']
23
24
25class CSharpLexer(RegexLexer):
26 """
27 For C# source code.
28
29 Additional options accepted:
30
31 `unicodelevel`
32 Determines which Unicode characters this lexer allows for identifiers.
33 The possible values are:
34
35 * ``none`` -- only the ASCII letters and numbers are allowed. This
36 is the fastest selection.
37 * ``basic`` -- all Unicode characters from the specification except
38 category ``Lo`` are allowed.
39 * ``full`` -- all Unicode characters as specified in the C# specs
40 are allowed. Note that this means a considerable slowdown since the
41 ``Lo`` category has more than 40,000 characters in it!
42
43 The default value is ``basic``.
44
45 .. versionadded:: 0.8
46 """
47
48 name = 'C#'
49 url = 'https://docs.microsoft.com/en-us/dotnet/csharp/'
50 aliases = ['csharp', 'c#', 'cs']
51 filenames = ['*.cs']
52 mimetypes = ['text/x-csharp'] # inferred
53 version_added = ''
54
55 flags = re.MULTILINE | re.DOTALL
56
57 # for the range of allowed unicode characters in identifiers, see
58 # http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf
59
60 levels = {
61 'none': r'@?[_a-zA-Z]\w*',
62 'basic': ('@?[_' + uni.combine('Lu', 'Ll', 'Lt', 'Lm', 'Nl') + ']' +
63 '[' + uni.combine('Lu', 'Ll', 'Lt', 'Lm', 'Nl', 'Nd', 'Pc',
64 'Cf', 'Mn', 'Mc') + ']*'),
65 'full': ('@?(?:_|[^' +
66 uni.allexcept('Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl') + '])' +
67 '[^' + uni.allexcept('Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl',
68 'Nd', 'Pc', 'Cf', 'Mn', 'Mc') + ']*'),
69 }
70
71 tokens = {}
72 token_variants = True
73
74 for levelname, cs_ident in levels.items():
75 tokens[levelname] = {
76 'root': [
77 include('numbers'),
78 # method names
79 (r'^([ \t]*)((?:' + cs_ident + r'(?:\[\])?\s+)+?)' # return type
80 r'(' + cs_ident + ')' # method name
81 r'(\s*)(\()', # signature start
82 bygroups(Whitespace, using(this), Name.Function, Whitespace,
83 Punctuation)),
84 (r'^(\s*)(\[.*?\])', bygroups(Whitespace, Name.Attribute)),
85 (r'[^\S\n]+', Whitespace),
86 (r'(\\)(\n)', bygroups(Text, Whitespace)), # line continuation
87 (r'//.*?\n', Comment.Single),
88 (r'/[*].*?[*]/', Comment.Multiline),
89 (r'\n', Whitespace),
90 (words((
91 '>>>=', '>>=', '<<=', '<=', '>=', '+=', '-=', '*=', '/=',
92 '%=', '&=', '|=', '^=', '??=', '=>', '??', '?.', '!=', '==',
93 '&&', '||', '>>>', '>>', '<<', '++', '--', '+', '-', '*',
94 '/', '%', '&', '|', '^', '<', '>', '?', '!', '~', '=',
95 )), Operator),
96 (r'=~|!=|==|<<|>>|[-+/*%=<>&^|]', Operator),
97 (r'[()\[\];:,.]', Punctuation),
98 (r'[{}]', Punctuation),
99 (r'\$*"{3,}.*?"{3,}', String),
100 (r'(?:\$@|@\$)"(""|[^"])*"', String),
101 (r'@"(""|[^"])*"', String),
102 (r'\$?"(\\\\|\\[^\\]|[^"\\\n])*["\n]', String),
103 (r"'\\.'|'[^\\]'", String.Char),
104 (r"[0-9]+(\.[0-9]*)?([eE][+-][0-9]+)?"
105 r"[flFLdD]?|0[xX][0-9a-fA-F]+[Ll]?", Number),
106 (r'(#)([ \t]*)(if|endif|else|elif|define|undef|'
107 r'line|error|warning|region|endregion|pragma)\b(.*?)(\n)',
108 bygroups(Comment.Preproc, Whitespace, Comment.Preproc,
109 Comment.Preproc, Whitespace)),
110 (r'\b(extern)(\s+)(alias)\b', bygroups(Keyword, Whitespace,
111 Keyword)),
112 (words((
113 'abstract', 'as', 'async', 'await', 'base', 'break', 'by',
114 'case', 'catch', 'checked', 'const', 'continue', 'default',
115 'delegate', 'do', 'else', 'enum', 'event', 'explicit',
116 'extern', 'false', 'finally', 'fixed', 'for', 'foreach',
117 'goto', 'if', 'implicit', 'in', 'interface', 'internal',
118 'is', 'let', 'lock', 'new', 'null', 'on', 'operator',
119 'out', 'override', 'params', 'private', 'protected',
120 'public', 'readonly', 'ref', 'return', 'sealed', 'sizeof',
121 'stackalloc', 'static', 'switch', 'this', 'throw', 'true',
122 'try', 'typeof', 'unchecked', 'unsafe', 'virtual', 'void',
123 'while', 'get', 'set', 'new', 'partial', 'yield', 'add',
124 'remove', 'value', 'alias', 'ascending', 'descending',
125 'from', 'group', 'into', 'orderby', 'select', 'thenby',
126 'where', 'join', 'equals', 'record', 'allows',
127 'and', 'init', 'managed', 'nameof', 'nint', 'not',
128 'notnull', 'nuint', 'or', 'scoped', 'unmanaged', 'when',
129 'with'
130 ), suffix=r'\b'), Keyword),
131 # version 1: assumes that 'file' is the only contextual keyword
132 # that is a class modifier
133 (r'(file)(\s+)(record|class|abstract|enum|new|sealed|static)\b',
134 bygroups(Keyword, Whitespace, Keyword)),
135 (r'(global)(::)', bygroups(Keyword, Punctuation)),
136 (r'(bool|byte|char|decimal|double|dynamic|float|int|long|object|'
137 r'sbyte|short|string|uint|ulong|ushort|var)\b\??', Keyword.Type),
138 (r'(class|struct|union)(\s+)', bygroups(Keyword, Whitespace), 'class'),
139 (r'(namespace|using)(\s+)', bygroups(Keyword, Whitespace), 'namespace'),
140 (cs_ident, Name),
141 ],
142 'numbers_int': [
143 (r"0[xX][0-9a-fA-F]+(([uU][lL]?)|[lL][uU]?)?", Number.Hex),
144 (r"0[bB][01]+(([uU][lL]?)|[lL][uU]?)?", Number.Bin),
145 (r"[0-9]+(([uU][lL]?)|[lL][uU]?)?", Number.Integer),
146 ],
147 'numbers_float': [
148 (r"([0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fFdDmM]?)|"
149 r"(\.[0-9]+([eE][+-]?[0-9]+)?[fFdDmM]?)|"
150 r"([0-9]+([eE][+-]?[0-9]+)[fFdDmM]?)|"
151 r"([0-9]+[fFdDmM])", Number.Float),
152 ],
153 'numbers': [
154 include('numbers_float'),
155 include('numbers_int'),
156 ],
157 'class': [
158 (cs_ident, Name.Class, '#pop'),
159 default('#pop'),
160 ],
161 'namespace': [
162 (r'(?=\()', Text, '#pop'), # using (resource)
163 ('(' + cs_ident + r'|\.)+', Name.Namespace, '#pop'),
164 ]
165 }
166
167 def __init__(self, **options):
168 level = get_choice_opt(options, 'unicodelevel', list(self.tokens), 'basic')
169 if level not in self._all_tokens:
170 # compile the regexes now
171 self._tokens = self.__class__.process_tokendef(level)
172 else:
173 self._tokens = self._all_tokens[level]
174
175 RegexLexer.__init__(self, **options)
176
177
178class NemerleLexer(RegexLexer):
179 """
180 For Nemerle source code.
181
182 Additional options accepted:
183
184 `unicodelevel`
185 Determines which Unicode characters this lexer allows for identifiers.
186 The possible values are:
187
188 * ``none`` -- only the ASCII letters and numbers are allowed. This
189 is the fastest selection.
190 * ``basic`` -- all Unicode characters from the specification except
191 category ``Lo`` are allowed.
192 * ``full`` -- all Unicode characters as specified in the C# specs
193 are allowed. Note that this means a considerable slowdown since the
194 ``Lo`` category has more than 40,000 characters in it!
195
196 The default value is ``basic``.
197 """
198
199 name = 'Nemerle'
200 url = 'http://nemerle.org'
201 aliases = ['nemerle']
202 filenames = ['*.n']
203 mimetypes = ['text/x-nemerle'] # inferred
204 version_added = '1.5'
205
206 flags = re.MULTILINE | re.DOTALL
207
208 # for the range of allowed unicode characters in identifiers, see
209 # http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf
210
211 levels = {
212 'none': r'@?[_a-zA-Z]\w*',
213 'basic': ('@?[_' + uni.combine('Lu', 'Ll', 'Lt', 'Lm', 'Nl') + ']' +
214 '[' + uni.combine('Lu', 'Ll', 'Lt', 'Lm', 'Nl', 'Nd', 'Pc',
215 'Cf', 'Mn', 'Mc') + ']*'),
216 'full': ('@?(?:_|[^' +
217 uni.allexcept('Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl') + '])' +
218 '[^' + uni.allexcept('Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl',
219 'Nd', 'Pc', 'Cf', 'Mn', 'Mc') + ']*'),
220 }
221
222 tokens = {}
223 token_variants = True
224
225 for levelname, cs_ident in levels.items():
226 tokens[levelname] = {
227 'root': [
228 # method names
229 (r'^([ \t]*)((?:' + cs_ident + r'(?:\[\])?\s+)+?)' # return type
230 r'(' + cs_ident + ')' # method name
231 r'(\s*)(\()', # signature start
232 bygroups(Whitespace, using(this), Name.Function, Whitespace, \
233 Punctuation)),
234 (r'^(\s*)(\[.*?\])', bygroups(Whitespace, Name.Attribute)),
235 (r'[^\S\n]+', Whitespace),
236 (r'(\\)(\n)', bygroups(Text, Whitespace)), # line continuation
237 (r'//.*?\n', Comment.Single),
238 (r'/[*].*?[*]/', Comment.Multiline),
239 (r'\n', Whitespace),
240 (r'(\$)(\s*)(")', bygroups(String, Whitespace, String),
241 'splice-string'),
242 (r'(\$)(\s*)(<#)', bygroups(String, Whitespace, String),
243 'splice-string2'),
244 (r'<#', String, 'recursive-string'),
245
246 (r'(<\[)(\s*)(' + cs_ident + ':)?',
247 bygroups(Keyword, Whitespace, Keyword)),
248 (r'\]\>', Keyword),
249
250 # quasiquotation only
251 (r'\$' + cs_ident, Name),
252 (r'(\$)(\()', bygroups(Name, Punctuation),
253 'splice-string-content'),
254
255 (r'[~!%^&*()+=|\[\]:;,.<>/?-]', Punctuation),
256 (r'[{}]', Punctuation),
257 (r'@"(""|[^"])*"', String),
258 (r'"(\\\\|\\[^\\]|[^"\\\n])*["\n]', String),
259 (r"'\\.'|'[^\\]'", String.Char),
260 (r"0[xX][0-9a-fA-F]+[Ll]?", Number),
261 (r"[0-9](\.[0-9]*)?([eE][+-][0-9]+)?[flFLdD]?", Number),
262 (r'(#)([ \t]*)(if|endif|else|elif|define|undef|'
263 r'line|error|warning|region|endregion|pragma)\b',
264 bygroups(Comment.Preproc, Whitespace, Comment.Preproc), 'preproc'),
265 (r'\b(extern)(\s+)(alias)\b', bygroups(Keyword, Whitespace, Keyword)),
266 (words(('abstract', 'and', 'as', 'base', 'catch', 'def', 'delegate',
267 'enum', 'event', 'extern', 'false',
268 'finally', 'fun', 'implements', 'interface',
269 'internal', 'is', 'macro', 'match',
270 'matches', 'module', 'mutable', 'new',
271 'null', 'out', 'override', 'params',
272 'partial', 'private', 'protected', 'public',
273 'ref', 'sealed', 'static', 'syntax', 'this',
274 'throw', 'true', 'try', 'type', 'typeof',
275 'virtual', 'volatile', 'when', 'where',
276 'with', 'assert', 'assert2', 'async',
277 'break', 'checked', 'continue', 'do',
278 'else', 'ensures', 'for', 'foreach', 'if',
279 'late', 'lock', 'new', 'nolate',
280 'otherwise', 'regexp', 'repeat', 'requires',
281 'return', 'surroundwith', 'unchecked',
282 'unless', 'using', 'while', 'yield'), suffix=r'\b'), Keyword),
283 (r'(global)(::)', bygroups(Keyword, Punctuation)),
284 (r'(bool|byte|char|decimal|double|float|int|long|object|sbyte|'
285 r'short|string|uint|ulong|ushort|void|array|list)\b\??',
286 Keyword.Type),
287 (r'(:>?)(\s*)(' + cs_ident + r'\??)',
288 bygroups(Punctuation, Whitespace, Keyword.Type)),
289 (r'(class|struct|variant|module)(\s+)',
290 bygroups(Keyword, Whitespace), 'class'),
291 (r'(namespace|using)(\s+)', bygroups(Keyword, Whitespace),
292 'namespace'),
293 (cs_ident, Name),
294 ],
295 'class': [
296 (cs_ident, Name.Class, '#pop')
297 ],
298 'preproc': [
299 (r'\w+', Comment.Preproc),
300 (r'[ \t]+', Whitespace),
301 (r'\n', Whitespace, '#pop')
302 ],
303 'namespace': [
304 (r'(?=\()', Text, '#pop'), # using (resource)
305 ('(' + cs_ident + r'|\.)+', Name.Namespace, '#pop')
306 ],
307 'splice-string': [
308 (r'[^"$]', String),
309 (r'\$' + cs_ident, Name),
310 (r'(\$)(\()', bygroups(Name, Punctuation),
311 'splice-string-content'),
312 (r'\\"', String),
313 (r'"', String, '#pop')
314 ],
315 'splice-string2': [
316 (r'[^#<>$]', String),
317 (r'\$' + cs_ident, Name),
318 (r'(\$)(\()', bygroups(Name, Punctuation),
319 'splice-string-content'),
320 (r'<#', String, '#push'),
321 (r'#>', String, '#pop')
322 ],
323 'recursive-string': [
324 (r'[^#<>]', String),
325 (r'<#', String, '#push'),
326 (r'#>', String, '#pop')
327 ],
328 'splice-string-content': [
329 (r'if|match', Keyword),
330 (r'[~!%^&*+=|\[\]:;,.<>/?-\\"$ ]', Punctuation),
331 (cs_ident, Name),
332 (r'\d+', Number),
333 (r'\(', Punctuation, '#push'),
334 (r'\)', Punctuation, '#pop')
335 ]
336 }
337
338 def __init__(self, **options):
339 level = get_choice_opt(options, 'unicodelevel', list(self.tokens),
340 'basic')
341 if level not in self._all_tokens:
342 # compile the regexes now
343 self._tokens = self.__class__.process_tokendef(level)
344 else:
345 self._tokens = self._all_tokens[level]
346
347 RegexLexer.__init__(self, **options)
348
349 def analyse_text(text):
350 """Nemerle is quite similar to Python, but @if is relatively uncommon
351 elsewhere."""
352 result = 0
353
354 if '@if' in text:
355 result += 0.1
356
357 return result
358
359
360class BooLexer(RegexLexer):
361 """
362 For Boo source code.
363 """
364
365 name = 'Boo'
366 url = 'https://github.com/boo-lang/boo'
367 aliases = ['boo']
368 filenames = ['*.boo']
369 mimetypes = ['text/x-boo']
370 version_added = ''
371
372 tokens = {
373 'root': [
374 (r'\s+', Whitespace),
375 (r'(#|//).*$', Comment.Single),
376 (r'/[*]', Comment.Multiline, 'comment'),
377 (r'[]{}:(),.;[]', Punctuation),
378 (r'(\\)(\n)', bygroups(Text, Whitespace)),
379 (r'\\', Text),
380 (r'(in|is|and|or|not)\b', Operator.Word),
381 (r'/(\\\\|\\[^\\]|[^/\\\s])/', String.Regex),
382 (r'@/(\\\\|\\[^\\]|[^/\\])*/', String.Regex),
383 (r'=~|!=|==|<<|>>|[-+/*%=<>&^|]', Operator),
384 (words(('as', 'abstract', 'callable', 'constructor', 'destructor',
385 'do', 'import', 'enum', 'event', 'final',
386 'get', 'interface', 'internal', 'of',
387 'override', 'partial', 'private',
388 'protected', 'public', 'return', 'set',
389 'static', 'struct', 'transient', 'virtual',
390 'yield', 'super', 'and', 'break', 'cast',
391 'continue', 'elif', 'else', 'ensure',
392 'except', 'for', 'given', 'goto', 'if',
393 'in', 'is', 'isa', 'not', 'or', 'otherwise',
394 'pass', 'raise', 'ref', 'try', 'unless',
395 'when', 'while', 'from'), suffix=r'\b'), Keyword),
396 (r'def(?=\s+\(.*?\))', Keyword),
397 (r'(def)(\s+)', bygroups(Keyword, Whitespace), 'funcname'),
398 (r'(class)(\s+)', bygroups(Keyword, Whitespace), 'classname'),
399 (r'(namespace)(\s+)', bygroups(Keyword, Whitespace), 'namespace'),
400 (r'(?<!\.)(true|false|null|self|__eval__|__switch__|array|'
401 r'assert|checked|enumerate|filter|getter|len|lock|map|'
402 r'matrix|max|min|normalArrayIndexing|print|property|range|'
403 r'rawArrayIndexing|required|typeof|unchecked|using|'
404 r'yieldAll|zip)\b', Name.Builtin),
405 (r'"""(\\\\|\\"|.*?)"""', String.Double),
406 (r'"(\\\\|\\[^\\]|[^"\\])*"', String.Double),
407 (r"'(\\\\|\\[^\\]|[^'\\])*'", String.Single),
408 (r'[a-zA-Z_]\w*', Name),
409 (r'(\d+\.\d*|\d*\.\d+)([fF][+-]?[0-9]+)?', Number.Float),
410 (r'[0-9][0-9.]*(ms?|d|h|s)', Number),
411 (r'0\d+', Number.Oct),
412 (r'0x[a-fA-F0-9]+', Number.Hex),
413 (r'\d+L', Number.Integer.Long),
414 (r'\d+', Number.Integer),
415 ],
416 'comment': [
417 ('/[*]', Comment.Multiline, '#push'),
418 ('[*]/', Comment.Multiline, '#pop'),
419 ('[^/*]', Comment.Multiline),
420 ('[*/]', Comment.Multiline)
421 ],
422 'funcname': [
423 (r'[a-zA-Z_]\w*', Name.Function, '#pop')
424 ],
425 'classname': [
426 (r'[a-zA-Z_]\w*', Name.Class, '#pop')
427 ],
428 'namespace': [
429 (r'[a-zA-Z_][\w.]*', Name.Namespace, '#pop')
430 ]
431 }
432
433
434class VbNetLexer(RegexLexer):
435 """
436 For Visual Basic.NET source code.
437 Also LibreOffice Basic, OpenOffice Basic, and StarOffice Basic.
438 """
439
440 name = 'VB.net'
441 url = 'https://docs.microsoft.com/en-us/dotnet/visual-basic/'
442 aliases = ['vb.net', 'vbnet', 'lobas', 'oobas', 'sobas', 'visual-basic', 'visualbasic']
443 filenames = ['*.vb', '*.bas']
444 mimetypes = ['text/x-vbnet', 'text/x-vba'] # (?)
445 version_added = ''
446
447 uni_name = '[_' + uni.combine('Ll', 'Lt', 'Lm', 'Nl') + ']' + \
448 '[' + uni.combine('Ll', 'Lt', 'Lm', 'Nl', 'Nd', 'Pc',
449 'Cf', 'Mn', 'Mc') + ']*'
450
451 flags = re.MULTILINE | re.IGNORECASE
452 tokens = {
453 'root': [
454 (r'^\s*<.*?>', Name.Attribute),
455 (r'\s+', Whitespace),
456 (r'\n', Whitespace),
457 (r'(rem\b.*?)(\n)', bygroups(Comment, Whitespace)),
458 (r"('.*?)(\n)", bygroups(Comment, Whitespace)),
459 (r'#If\s.*?\sThen|#ElseIf\s.*?\sThen|#Else|#End\s+If|#Const|'
460 r'#ExternalSource.*?\n|#End\s+ExternalSource|'
461 r'#Region.*?\n|#End\s+Region|#ExternalChecksum',
462 Comment.Preproc),
463 (r'[(){}!#,.:]', Punctuation),
464 (r'(Option)(\s+)(Strict|Explicit|Compare)(\s+)'
465 r'(On|Off|Binary|Text)',
466 bygroups(Keyword.Declaration, Whitespace, Keyword.Declaration,
467 Whitespace, Keyword.Declaration)),
468 (words((
469 'AddHandler', 'Alias', 'ByRef', 'ByVal', 'Call', 'Case',
470 'Catch', 'CBool', 'CByte', 'CChar', 'CDate', 'CDec', 'CDbl',
471 'CInt', 'CLng', 'CObj', 'Continue', 'CSByte', 'CShort', 'CSng',
472 'CStr', 'CType', 'CUInt', 'CULng', 'CUShort', 'Declare',
473 'Default', 'Delegate', 'DirectCast', 'Do', 'Each', 'Else',
474 'ElseIf', 'EndIf', 'Erase', 'Error', 'Event', 'Exit', 'False',
475 'Finally', 'For', 'Friend', 'Get', 'Global', 'GoSub', 'GoTo',
476 'Handles', 'If', 'Implements', 'Inherits', 'Interface', 'Let',
477 'Lib', 'Loop', 'Me', 'MustInherit', 'MustOverride', 'MyBase',
478 'MyClass', 'Narrowing', 'New', 'Next', 'Not', 'Nothing',
479 'NotInheritable', 'NotOverridable', 'Of', 'On', 'Operator',
480 'Option', 'Optional', 'Overloads', 'Overridable', 'Overrides',
481 'ParamArray', 'Partial', 'Private', 'Protected', 'Public',
482 'RaiseEvent', 'ReadOnly', 'ReDim', 'RemoveHandler', 'Resume',
483 'Return', 'Select', 'Set', 'Shadows', 'Shared', 'Single',
484 'Static', 'Step', 'Stop', 'SyncLock', 'Then', 'Throw', 'To',
485 'True', 'Try', 'TryCast', 'Wend', 'Using', 'When', 'While',
486 'Widening', 'With', 'WithEvents', 'WriteOnly'),
487 prefix=r'(?<!\.)', suffix=r'\b'), Keyword),
488 (r'(?<!\.)End\b', Keyword, 'end'),
489 (r'(?<!\.)(Dim|Const)\b', Keyword, 'dim'),
490 (r'(?<!\.)(Function|Sub|Property)(\s+)',
491 bygroups(Keyword, Whitespace), 'funcname'),
492 (r'(?<!\.)(Class|Structure|Enum)(\s+)',
493 bygroups(Keyword, Whitespace), 'classname'),
494 (r'(?<!\.)(Module|Namespace|Imports)(\s+)',
495 bygroups(Keyword, Whitespace), 'namespace'),
496 (r'(?<!\.)(Boolean|Byte|Char|Date|Decimal|Double|Integer|Long|'
497 r'Object|SByte|Short|Single|String|Variant|UInteger|ULong|'
498 r'UShort)\b', Keyword.Type),
499 (r'(?<!\.)(AddressOf|And|AndAlso|As|GetType|In|Is|IsNot|Like|Mod|'
500 r'Or|OrElse|TypeOf|Xor)\b', Operator.Word),
501 (r'&=|[*]=|/=|\\=|\^=|\+=|-=|<<=|>>=|<<|>>|:=|'
502 r'<=|>=|<>|[-&*/\\^+=<>\[\]]',
503 Operator),
504 ('"', String, 'string'),
505 (r'(_)(\n)', bygroups(Text, Whitespace)), # Line continuation (must be before Name)
506 (uni_name + '[%&@!#$]?', Name),
507 ('#.*?#', Literal.Date),
508 (r'(\d+\.\d*|\d*\.\d+)(F[+-]?[0-9]+)?', Number.Float),
509 (r'\d+([SILDFR]|US|UI|UL)?', Number.Integer),
510 (r'&H[0-9a-f]+([SILDFR]|US|UI|UL)?', Number.Integer),
511 (r'&O[0-7]+([SILDFR]|US|UI|UL)?', Number.Integer),
512 ],
513 'string': [
514 (r'""', String),
515 (r'"C?', String, '#pop'),
516 (r'[^"]+', String),
517 ],
518 'dim': [
519 (uni_name, Name.Variable, '#pop'),
520 default('#pop'), # any other syntax
521 ],
522 'funcname': [
523 (uni_name, Name.Function, '#pop'),
524 ],
525 'classname': [
526 (uni_name, Name.Class, '#pop'),
527 ],
528 'namespace': [
529 (uni_name, Name.Namespace),
530 (r'\.', Name.Namespace),
531 default('#pop'),
532 ],
533 'end': [
534 (r'\s+', Whitespace),
535 (words(('Function', 'Sub', 'Property', 'Class', 'Structure', 'Enum',
536 'Module', 'Namespace'), suffix=r'\b'),
537 Keyword, '#pop'),
538 default('#pop'),
539 ]
540 }
541
542 def analyse_text(text):
543 if re.search(r'^\s*(#If|Module|Namespace)', text, re.MULTILINE):
544 return 0.5
545
546
547class GenericAspxLexer(RegexLexer):
548 """
549 Lexer for ASP.NET pages.
550 """
551
552 name = 'aspx-gen'
553 filenames = []
554 mimetypes = []
555 url = 'https://dotnet.microsoft.com/en-us/apps/aspnet'
556
557 flags = re.DOTALL
558
559 tokens = {
560 'root': [
561 (r'(<%[@=#]?)(.*?)(%>)', bygroups(Name.Tag, Other, Name.Tag)),
562 (r'(<script.*?>)(.*?)(</script>)', bygroups(using(XmlLexer),
563 Other,
564 using(XmlLexer))),
565 (r'(.+?)(?=<)', using(XmlLexer)),
566 (r'.+', using(XmlLexer)),
567 ],
568 }
569
570
571# TODO support multiple languages within the same source file
572class CSharpAspxLexer(DelegatingLexer):
573 """
574 Lexer for highlighting C# within ASP.NET pages.
575 """
576
577 name = 'aspx-cs'
578 aliases = ['aspx-cs']
579 filenames = ['*.aspx', '*.asax', '*.ascx', '*.ashx', '*.asmx', '*.axd']
580 mimetypes = []
581 url = 'https://dotnet.microsoft.com/en-us/apps/aspnet'
582 version_added = ''
583
584 def __init__(self, **options):
585 super().__init__(CSharpLexer, GenericAspxLexer, **options)
586
587 def analyse_text(text):
588 if re.search(r'Page\s*Language="C#"', text, re.I) is not None:
589 return 0.2
590 elif re.search(r'script[^>]+language=["\']C#', text, re.I) is not None:
591 return 0.15
592
593
594class VbNetAspxLexer(DelegatingLexer):
595 """
596 Lexer for highlighting Visual Basic.net within ASP.NET pages.
597 """
598
599 name = 'aspx-vb'
600 aliases = ['aspx-vb']
601 filenames = ['*.aspx', '*.asax', '*.ascx', '*.ashx', '*.asmx', '*.axd']
602 mimetypes = []
603 url = 'https://dotnet.microsoft.com/en-us/apps/aspnet'
604 version_added = ''
605
606 def __init__(self, **options):
607 super().__init__(VbNetLexer, GenericAspxLexer, **options)
608
609 def analyse_text(text):
610 if re.search(r'Page\s*Language="Vb"', text, re.I) is not None:
611 return 0.2
612 elif re.search(r'script[^>]+language=["\']vb', text, re.I) is not None:
613 return 0.15
614
615
616# Very close to functional.OcamlLexer
617class FSharpLexer(RegexLexer):
618 """
619 For the F# language (version 3.0).
620 """
621
622 name = 'F#'
623 url = 'https://fsharp.org/'
624 aliases = ['fsharp', 'f#']
625 filenames = ['*.fs', '*.fsi', '*.fsx']
626 mimetypes = ['text/x-fsharp']
627 version_added = '1.5'
628
629 keywords = [
630 'abstract', 'as', 'assert', 'base', 'begin', 'class', 'default',
631 'delegate', 'do!', 'do', 'done', 'downcast', 'downto', 'elif', 'else',
632 'end', 'exception', 'extern', 'false', 'finally', 'for', 'function',
633 'fun', 'global', 'if', 'inherit', 'inline', 'interface', 'internal',
634 'in', 'lazy', 'let!', 'let', 'match', 'member', 'module', 'mutable',
635 'namespace', 'new', 'null', 'of', 'open', 'override', 'private', 'public',
636 'rec', 'return!', 'return', 'select', 'static', 'struct', 'then', 'to',
637 'true', 'try', 'type', 'upcast', 'use!', 'use', 'val', 'void', 'when',
638 'while', 'with', 'yield!', 'yield',
639 ]
640 # Reserved words; cannot hurt to color them as keywords too.
641 keywords += [
642 'atomic', 'break', 'checked', 'component', 'const', 'constraint',
643 'constructor', 'continue', 'eager', 'event', 'external', 'fixed',
644 'functor', 'include', 'method', 'mixin', 'object', 'parallel',
645 'process', 'protected', 'pure', 'sealed', 'tailcall', 'trait',
646 'virtual', 'volatile',
647 ]
648 keyopts = [
649 '!=', '#', '&&', '&', r'\(', r'\)', r'\*', r'\+', ',', r'-\.',
650 '->', '-', r'\.\.', r'\.', '::', ':=', ':>', ':', ';;', ';', '<-',
651 r'<\]', '<', r'>\]', '>', r'\?\?', r'\?', r'\[<', r'\[\|', r'\[', r'\]',
652 '_', '`', r'\{', r'\|\]', r'\|', r'\}', '~', '<@@', '<@', '=', '@>', '@@>',
653 ]
654
655 operators = r'[!$%&*+\./:<=>?@^|~-]'
656 word_operators = ['and', 'or', 'not']
657 prefix_syms = r'[!?~]'
658 infix_syms = r'[=<>@^|&+\*/$%-]'
659 primitives = [
660 'sbyte', 'byte', 'char', 'nativeint', 'unativeint', 'float32', 'single',
661 'float', 'double', 'int8', 'uint8', 'int16', 'uint16', 'int32',
662 'uint32', 'int64', 'uint64', 'decimal', 'unit', 'bool', 'string',
663 'list', 'exn', 'obj', 'enum',
664 ]
665
666 # See http://msdn.microsoft.com/en-us/library/dd233181.aspx and/or
667 # http://fsharp.org/about/files/spec.pdf for reference. Good luck.
668
669 tokens = {
670 'escape-sequence': [
671 (r'\\[\\"\'ntbrafv]', String.Escape),
672 (r'\\[0-9]{3}', String.Escape),
673 (r'\\u[0-9a-fA-F]{4}', String.Escape),
674 (r'\\U[0-9a-fA-F]{8}', String.Escape),
675 ],
676 'root': [
677 (r'\s+', Whitespace),
678 (r'\(\)|\[\]', Name.Builtin.Pseudo),
679 (r'\b(?<!\.)([A-Z][\w\']*)(?=\s*\.)',
680 Name.Namespace, 'dotted'),
681 (r'\b([A-Z][\w\']*)', Name),
682 (r'(///.*?)(\n)', bygroups(String.Doc, Whitespace)),
683 (r'(//.*?)(\n)', bygroups(Comment.Single, Whitespace)),
684 (r'\(\*(?!\))', Comment, 'comment'),
685
686 (r'@"', String, 'lstring'),
687 (r'"""', String, 'tqs'),
688 (r'"', String, 'string'),
689
690 (r'\b(open|module)(\s+)([\w.]+)',
691 bygroups(Keyword, Whitespace, Name.Namespace)),
692 (r'\b(let!?)(\s+)(\w+)',
693 bygroups(Keyword, Whitespace, Name.Variable)),
694 (r'\b(type)(\s+)(\w+)',
695 bygroups(Keyword, Whitespace, Name.Class)),
696 (r'\b(member|override)(\s+)(\w+)(\.)(\w+)',
697 bygroups(Keyword, Whitespace, Name, Punctuation, Name.Function)),
698 (r'\b({})\b'.format('|'.join(keywords)), Keyword),
699 (r'``([^`\n\r\t]|`[^`\n\r\t])+``', Name),
700 (r'({})'.format('|'.join(keyopts)), Operator),
701 (rf'({infix_syms}|{prefix_syms})?{operators}', Operator),
702 (r'\b({})\b'.format('|'.join(word_operators)), Operator.Word),
703 (r'\b({})\b'.format('|'.join(primitives)), Keyword.Type),
704 (r'(#)([ \t]*)(if|endif|else|line|nowarn|light|\d+)\b(.*?)(\n)',
705 bygroups(Comment.Preproc, Whitespace, Comment.Preproc,
706 Comment.Preproc, Whitespace)),
707
708 (r"[^\W\d][\w']*", Name),
709
710 (r'\d[\d_]*[uU]?[yslLnQRZINGmM]?', Number.Integer),
711 (r'0[xX][\da-fA-F][\da-fA-F_]*[uU]?[yslLn]?[fF]?', Number.Hex),
712 (r'0[oO][0-7][0-7_]*[uU]?[yslLn]?', Number.Oct),
713 (r'0[bB][01][01_]*[uU]?[yslLn]?', Number.Bin),
714 (r'-?\d[\d_]*(.[\d_]*)?([eE][+\-]?\d[\d_]*)[fFmM]?',
715 Number.Float),
716
717 (r"'(?:(\\[\\\"'ntbr ])|(\\[0-9]{3})|(\\x[0-9a-fA-F]{2}))'B?",
718 String.Char),
719 (r"'.'", String.Char),
720 (r"'", Keyword), # a stray quote is another syntax element
721
722 (r'@?"', String.Double, 'string'),
723
724 (r'[~?][a-z][\w\']*:', Name.Variable),
725 ],
726 'dotted': [
727 (r'\s+', Whitespace),
728 (r'\.', Punctuation),
729 (r'[A-Z][\w\']*(?=\s*\.)', Name.Namespace),
730 (r'[A-Z][\w\']*', Name, '#pop'),
731 (r'[a-z_][\w\']*', Name, '#pop'),
732 # e.g. dictionary index access
733 default('#pop'),
734 ],
735 'comment': [
736 (r'[^(*)@"]+', Comment),
737 (r'\(\*', Comment, '#push'),
738 (r'\*\)', Comment, '#pop'),
739 # comments cannot be closed within strings in comments
740 (r'@"', String, 'lstring'),
741 (r'"""', String, 'tqs'),
742 (r'"', String, 'string'),
743 (r'[(*)@]', Comment),
744 ],
745 'string': [
746 (r'[^\\"]+', String),
747 include('escape-sequence'),
748 (r'\\\n', String),
749 (r'\n', String), # newlines are allowed in any string
750 (r'"B?', String, '#pop'),
751 ],
752 'lstring': [
753 (r'[^"]+', String),
754 (r'\n', String),
755 (r'""', String),
756 (r'"B?', String, '#pop'),
757 ],
758 'tqs': [
759 (r'[^"]+', String),
760 (r'\n', String),
761 (r'"""B?', String, '#pop'),
762 (r'"', String),
763 ],
764 }
765
766 def analyse_text(text):
767 """F# doesn't have that many unique features -- |> and <| are weak
768 indicators."""
769 result = 0
770 if '|>' in text:
771 result += 0.05
772 if '<|' in text:
773 result += 0.05
774
775 return result
776
777
778class XppLexer(RegexLexer):
779
780 """
781 For X++ source code. This is based loosely on the CSharpLexer
782 """
783
784 name = 'X++'
785 url = 'https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-ref/xpp-language-reference'
786 aliases = ['xpp', 'x++']
787 filenames = ['*.xpp']
788 version_added = '2.15'
789
790 flags = re.MULTILINE
791
792 XPP_CHARS = ('@?(?:_|[^' +
793 uni.allexcept('Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl') + '])' +
794 '[^' + uni.allexcept('Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl',
795 'Nd', 'Pc', 'Cf', 'Mn', 'Mc') + ']*')
796 # Temporary, see
797 # https://github.com/thatch/regexlint/pull/49
798 XPP_CHARS = XPP_CHARS.replace('\x00', '\x01')
799
800 OPERATORS = (
801 '<=', '>=', '+=', '-=', '*=', '/=', '!=', '==',
802 '&&', '||', '>>', '<<', '++', '--', '+', '-', '*',
803 '/', '%', '&', '|', '^', '<', '>', '?', '!', '~', '=',
804 )
805 KEYWORDS = ('abstract','anytype','as','async','asc','at','avg','break','breakpoint','by','byref','case','catch',
806 'changecompany','client','container','continue','count','crosscompany','default','delegate',
807 'delete_from','desc','display','div','do','edit','else','element','eventhandler','exists','false','final',
808 'firstfast','firstonly','firstonly10','firstonly100','firstonly1000','flush','for','forceliterals',
809 'forcenestedloop','forceplaceholders','forceselectorder','forupdate','from','group','if','insert_recordset',
810 'interface','is','join','like','maxof','minof','mod','new','next','nofetch','notexists','null','optimisticlock','order',
811 'outer','pause','pessimisticlock','print','private','protected','public','repeatableread','retry','return',
812 'reverse','select','server','setting','static','sum','super','switch','tablelock','this','throw','true','try','ttsabort','ttsbegin',
813 'ttscommit','update_recordset','validtimestate','void','where','while','window')
814 RUNTIME_FUNCTIONS = ('_duration','abs','acos','any2Date','any2Enum','any2Guid','any2Int','any2Int64','any2Real','any2Str','anytodate',
815 'anytoenum','anytoguid','anytoint','anytoint64','anytoreal','anytostr','asin','atan','beep','cTerm','char2Num','classIdGet',
816 'corrFlagGet','corrFlagSet','cos','cosh','curExt','curUserId','date2Num','date2Str','datetime2Str','dayName','dayOfMth',
817 'dayOfWk','dayOfYr','ddb','decRound','dg','dimOf','endMth','enum2str','exp','exp10','fV','fieldId2Name','fieldId2PName',
818 'fieldName2Id','frac','funcName','getCurrentPartition','getCurrentPartitionRecId','getPrefix','guid2Str','idg','indexId2Name',
819 'indexName2Id','int2Str','int642Str','intvMax','intvName','intvNo','intvNorm','log10','logN','match','max','min','mkDate','mthName',
820 'mthOfYr','newGuid','nextMth','nextQtr','nextYr','num2Char','num2Date','num2Str','pmt','power','prevMth','prevQtr','prevYr',
821 'prmIsDefault','pt','pv','rate','refPrintAll','round','runAs','sessionId','setPrefix','sin','sinh','sleep','sln','str2Date',
822 'str2Datetime','str2Enum','str2Guid','str2Int','str2Int64','str2Num','str2Time','strAlpha','strCmp','strColSeq','strDel',
823 'strFind','strFmt','strIns','strKeep','strLTrim','strLen','strLine','strLwr','strNFind','strPoke','strPrompt','strRTrim',
824 'strRem','strRep','strScan','strUpr','subStr','syd','systemDateGet','systemDateSet','tableId2Name',
825 'tableId2PName','tableName2Id','tan','tanh','term','time2Str','timeNow','today','trunc','typeOf','uint2Str','wkOfYr','year')
826 COMPILE_FUNCTIONS = ('attributeStr','classNum','classStr','configurationKeyNum','configurationKeyStr','dataEntityDataSourceStr','delegateStr',
827 'dimensionHierarchyLevelStr','dimensionHierarchyStr','dimensionReferenceStr','dutyStr','enumCnt','enumLiteralStr','enumNum','enumStr',
828 'extendedTypeNum','extendedTypeStr','fieldNum','fieldPName','fieldStr','formControlStr','formDataFieldStr','formDataSourceStr',
829 'formMethodStr','formStr','identifierStr','indexNum','indexStr','licenseCodeNum','licenseCodeStr','literalStr','maxDate','maxInt',
830 'measureStr','measurementStr','menuItemActionStr','menuItemDisplayStr','menuItemOutputStr','menuStr','methodStr','minInt','privilegeStr',
831 'queryDatasourceStr','queryMethodStr','queryStr','reportStr','resourceStr','roleStr','ssrsReportStr','staticDelegateStr','staticMethodStr',
832 'tableCollectionStr','tableFieldGroupStr','tableMethodStr','tableNum','tablePName','tableStaticMethodStr','tableStr','tileStr','varStr',
833 'webActionItemStr','webDisplayContentItemStr','webFormStr','webMenuStr','webOutputContentItemStr','webReportStr','webSiteTempStr',
834 'webStaticFileStr','webUrlItemStr','webWebPartStr','webletItemStr','webpageDefStr','websiteDefStr','workflowApprovalStr',
835 'workflowCategoryStr','workflowTaskStr','workflowTypeStr')
836
837 tokens = {}
838
839 tokens = {
840 'root': [
841 # method names
842 (r'(\s*)\b(else|if)\b([^\n])', bygroups(Whitespace, Keyword, using(this))), # ensure that if is not treated like a function
843 (r'^([ \t]*)((?:' + XPP_CHARS + r'(?:\[\])?\s+)+?)' # return type
844 r'(' + XPP_CHARS + ')' # method name
845 r'(\s*)(\()', # signature start
846 bygroups(Whitespace, using(this), Name.Function, Whitespace,
847 Punctuation)),
848 (r'^(\s*)(\[)([^\n]*?)(\])', bygroups(Whitespace, Name.Attribute, Name.Variable.Class, Name.Attribute)),
849 (r'[^\S\n]+', Whitespace),
850 (r'(\\)(\n)', bygroups(Text, Whitespace)), # line continuation
851 (r'//[^\n]*?\n', Comment.Single),
852 (r'/[*][^\n]*?[*]/', Comment.Multiline),
853 (r'\n', Whitespace),
854 (words(OPERATORS), Operator),
855 (r'=~|!=|==|<<|>>|[-+/*%=<>&^|]', Operator),
856 (r'[()\[\];:,.#@]', Punctuation),
857 (r'[{}]', Punctuation),
858 (r'@"(""|[^"])*"', String),
859 (r'\$?"(\\\\|\\[^\\]|[^"\\\n])*["\n]', String),
860 (r"'\\.'|'[^\\]'", String.Char),
861 (r"[0-9]+(\.[0-9]*)?([eE][+-][0-9]+)?"
862 r"[flFLdD]?|0[xX][0-9a-fA-F]+[Ll]?", Number),
863 (words(KEYWORDS, suffix=r'\b'), Keyword),
864 (r'(boolean|int|int64|str|real|guid|date)\b\??', Keyword.Type),
865 (r'(class|struct|extends|implements)(\s+)', bygroups(Keyword, Whitespace), 'class'),
866 (r'('+XPP_CHARS+')(::)', bygroups(Name.Variable.Class, Punctuation)),
867 (r'(\s*)(\w+)(\s+\w+(,|=)?[^\n]*;)', bygroups(Whitespace, Name.Variable.Class, using(this))), # declaration
868 # x++ specific function to get field should highlight the classname
869 (r'(fieldNum\()('+XPP_CHARS+r')(\s*,\s*)('+XPP_CHARS+r')(\s*\))',
870 bygroups(using(this), Name.Variable.Class, using(this), Name.Property, using(this))),
871 # x++ specific function to get table should highlight the classname
872 (r'(tableNum\()('+XPP_CHARS+r')(\s*\))',
873 bygroups(using(this), Name.Variable.Class, using(this))),
874 (words(RUNTIME_FUNCTIONS, suffix=r'(?=\()'), Name.Function.Magic),
875 (words(COMPILE_FUNCTIONS, suffix=r'(?=\()'), Name.Function.Magic),
876 (XPP_CHARS, Name),
877 ],
878 'class': [
879 (XPP_CHARS, Name.Class, '#pop'),
880 default('#pop'),
881 ],
882 'namespace': [
883 (r'(?=\()', Text, '#pop'), # using (resource)
884 ('(' + XPP_CHARS + r'|\.)+', Name.Namespace, '#pop'),
885 ]
886 }