eric6/ThirdParty/Pygments/pygments/lexers/csound.py

changeset 8258
82b608e352ec
parent 8257
28146736bbfc
child 8259
2bbec88047dd
equal deleted inserted replaced
8257:28146736bbfc 8258:82b608e352ec
1 # -*- coding: utf-8 -*-
2 """
3 pygments.lexers.csound
4 ~~~~~~~~~~~~~~~~~~~~~~
5
6 Lexers for Csound languages.
7
8 :copyright: Copyright 2006-2021 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details.
10 """
11
12 import re
13
14 from pygments.lexer import RegexLexer, bygroups, default, include, using, words
15 from pygments.token import Comment, Error, Keyword, Name, Number, Operator, Punctuation, \
16 String, Text, Whitespace
17 from pygments.lexers._csound_builtins import OPCODES, DEPRECATED_OPCODES
18 from pygments.lexers.html import HtmlLexer
19 from pygments.lexers.python import PythonLexer
20 from pygments.lexers.scripting import LuaLexer
21
22 __all__ = ['CsoundScoreLexer', 'CsoundOrchestraLexer', 'CsoundDocumentLexer']
23
24 newline = (r'((?:(?:;|//).*)*)(\n)', bygroups(Comment.Single, Text))
25
26
27 class CsoundLexer(RegexLexer):
28 tokens = {
29 'whitespace': [
30 (r'[ \t]+', Text),
31 (r'/[*](?:.|\n)*?[*]/', Comment.Multiline),
32 (r'(?:;|//).*$', Comment.Single),
33 (r'(\\)(\n)', bygroups(Whitespace, Text))
34 ],
35
36 'preprocessor directives': [
37 (r'#(?:e(?:nd(?:if)?|lse)\b|##)|@@?[ \t]*\d+', Comment.Preproc),
38 (r'#includestr', Comment.Preproc, 'includestr directive'),
39 (r'#include', Comment.Preproc, 'include directive'),
40 (r'#[ \t]*define', Comment.Preproc, 'define directive'),
41 (r'#(?:ifn?def|undef)\b', Comment.Preproc, 'macro directive')
42 ],
43
44 'include directive': [
45 include('whitespace'),
46 (r'([^ \t]).*?\1', String, '#pop')
47 ],
48 'includestr directive': [
49 include('whitespace'),
50 (r'"', String, ('#pop', 'quoted string'))
51 ],
52
53 'define directive': [
54 (r'\n', Text),
55 include('whitespace'),
56 (r'([A-Z_a-z]\w*)(\()', bygroups(Comment.Preproc, Punctuation),
57 ('#pop', 'macro parameter name list')),
58 (r'[A-Z_a-z]\w*', Comment.Preproc, ('#pop', 'before macro body'))
59 ],
60 'macro parameter name list': [
61 include('whitespace'),
62 (r'[A-Z_a-z]\w*', Comment.Preproc),
63 (r"['#]", Punctuation),
64 (r'\)', Punctuation, ('#pop', 'before macro body'))
65 ],
66 'before macro body': [
67 (r'\n', Text),
68 include('whitespace'),
69 (r'#', Punctuation, ('#pop', 'macro body'))
70 ],
71 'macro body': [
72 (r'(?:\\(?!#)|[^#\\]|\n)+', Comment.Preproc),
73 (r'\\#', Comment.Preproc),
74 (r'(?<!\\)#', Punctuation, '#pop')
75 ],
76
77 'macro directive': [
78 include('whitespace'),
79 (r'[A-Z_a-z]\w*', Comment.Preproc, '#pop')
80 ],
81
82 'macro uses': [
83 (r'(\$[A-Z_a-z]\w*\.?)(\()', bygroups(Comment.Preproc, Punctuation),
84 'macro parameter value list'),
85 (r'\$[A-Z_a-z]\w*(?:\.|\b)', Comment.Preproc)
86 ],
87 'macro parameter value list': [
88 (r'(?:[^\'#"{()]|\{(?!\{))+', Comment.Preproc),
89 (r"['#]", Punctuation),
90 (r'"', String, 'macro parameter value quoted string'),
91 (r'\{\{', String, 'macro parameter value braced string'),
92 (r'\(', Comment.Preproc, 'macro parameter value parenthetical'),
93 (r'\)', Punctuation, '#pop')
94 ],
95 'macro parameter value quoted string': [
96 (r"\\[#'()]", Comment.Preproc),
97 (r"[#'()]", Error),
98 include('quoted string')
99 ],
100 'macro parameter value braced string': [
101 (r"\\[#'()]", Comment.Preproc),
102 (r"[#'()]", Error),
103 include('braced string')
104 ],
105 'macro parameter value parenthetical': [
106 (r'(?:[^\\()]|\\\))+', Comment.Preproc),
107 (r'\(', Comment.Preproc, '#push'),
108 (r'\)', Comment.Preproc, '#pop')
109 ],
110
111 'whitespace and macro uses': [
112 include('whitespace'),
113 include('macro uses')
114 ],
115
116 'numbers': [
117 (r'\d+[Ee][+-]?\d+|(\d+\.\d*|\d*\.\d+)([Ee][+-]?\d+)?', Number.Float),
118 (r'(0[Xx])([0-9A-Fa-f]+)', bygroups(Keyword.Type, Number.Hex)),
119 (r'\d+', Number.Integer)
120 ],
121
122 'quoted string': [
123 (r'"', String, '#pop'),
124 (r'[^"$]+', String),
125 include('macro uses'),
126 (r'[$]', String)
127 ],
128
129 'braced string': [
130 # Do nothing. This must be defined in subclasses.
131 ]
132 }
133
134
135 class CsoundScoreLexer(CsoundLexer):
136 """
137 For `Csound <https://csound.com>`_ scores.
138
139 .. versionadded:: 2.1
140 """
141
142 name = 'Csound Score'
143 aliases = ['csound-score', 'csound-sco']
144 filenames = ['*.sco']
145
146 tokens = {
147 'root': [
148 (r'\n', Text),
149 include('whitespace and macro uses'),
150 include('preprocessor directives'),
151
152 (r'[aBbCdefiqstvxy]', Keyword),
153 # There is also a w statement that is generated internally and should not be
154 # used; see https://github.com/csound/csound/issues/750.
155
156 (r'z', Keyword.Constant),
157 # z is a constant equal to 800,000,000,000. 800 billion seconds is about
158 # 25,367.8 years. See also
159 # https://csound.com/docs/manual/ScoreTop.html and
160 # https://github.com/csound/csound/search?q=stof+path%3AEngine+filename%3Asread.c.
161
162 (r'([nNpP][pP])(\d+)', bygroups(Keyword, Number.Integer)),
163
164 (r'[mn]', Keyword, 'mark statement'),
165
166 include('numbers'),
167 (r'[!+\-*/^%&|<>#~.]', Operator),
168 (r'[()\[\]]', Punctuation),
169 (r'"', String, 'quoted string'),
170 (r'\{', Comment.Preproc, 'loop after left brace'),
171 ],
172
173 'mark statement': [
174 include('whitespace and macro uses'),
175 (r'[A-Z_a-z]\w*', Name.Label),
176 (r'\n', Text, '#pop')
177 ],
178
179 'loop after left brace': [
180 include('whitespace and macro uses'),
181 (r'\d+', Number.Integer, ('#pop', 'loop after repeat count')),
182 ],
183 'loop after repeat count': [
184 include('whitespace and macro uses'),
185 (r'[A-Z_a-z]\w*', Comment.Preproc, ('#pop', 'loop'))
186 ],
187 'loop': [
188 (r'\}', Comment.Preproc, '#pop'),
189 include('root')
190 ],
191
192 # Braced strings are not allowed in Csound scores, but this is needed because the
193 # superclass includes it.
194 'braced string': [
195 (r'\}\}', String, '#pop'),
196 (r'[^}]|\}(?!\})', String)
197 ]
198 }
199
200
201 class CsoundOrchestraLexer(CsoundLexer):
202 """
203 For `Csound <https://csound.com>`_ orchestras.
204
205 .. versionadded:: 2.1
206 """
207
208 name = 'Csound Orchestra'
209 aliases = ['csound', 'csound-orc']
210 filenames = ['*.orc', '*.udo']
211
212 user_defined_opcodes = set()
213
214 def opcode_name_callback(lexer, match):
215 opcode = match.group(0)
216 lexer.user_defined_opcodes.add(opcode)
217 yield match.start(), Name.Function, opcode
218
219 def name_callback(lexer, match):
220 type_annotation_token = Keyword.Type
221
222 name = match.group(1)
223 if name in OPCODES or name in DEPRECATED_OPCODES:
224 yield match.start(), Name.Builtin, name
225 elif name in lexer.user_defined_opcodes:
226 yield match.start(), Name.Function, name
227 else:
228 type_annotation_token = Name
229 name_match = re.search(r'^(g?[afikSw])(\w+)', name)
230 if name_match:
231 yield name_match.start(1), Keyword.Type, name_match.group(1)
232 yield name_match.start(2), Name, name_match.group(2)
233 else:
234 yield match.start(), Name, name
235
236 if match.group(2):
237 yield match.start(2), Punctuation, match.group(2)
238 yield match.start(3), type_annotation_token, match.group(3)
239
240 tokens = {
241 'root': [
242 (r'\n', Text),
243
244 (r'^([ \t]*)(\w+)(:)([ \t]+|$)', bygroups(Text, Name.Label, Punctuation, Text)),
245
246 include('whitespace and macro uses'),
247 include('preprocessor directives'),
248
249 (r'\binstr\b', Keyword.Declaration, 'instrument numbers and identifiers'),
250 (r'\bopcode\b', Keyword.Declaration, 'after opcode keyword'),
251 (r'\b(?:end(?:in|op))\b', Keyword.Declaration),
252
253 include('partial statements')
254 ],
255
256 'partial statements': [
257 (r'\b(?:0dbfs|A4|k(?:r|smps)|nchnls(?:_i)?|sr)\b', Name.Variable.Global),
258
259 include('numbers'),
260
261 (r'\+=|-=|\*=|/=|<<|>>|<=|>=|==|!=|&&|\|\||[~¬]|[=!+\-*/^%&|<>#?:]', Operator),
262 (r'[(),\[\]]', Punctuation),
263
264 (r'"', String, 'quoted string'),
265 (r'\{\{', String, 'braced string'),
266
267 (words((
268 'do', 'else', 'elseif', 'endif', 'enduntil', 'fi', 'if', 'ithen', 'kthen',
269 'od', 'then', 'until', 'while',
270 ), prefix=r'\b', suffix=r'\b'), Keyword),
271 (words(('return', 'rireturn'), prefix=r'\b', suffix=r'\b'), Keyword.Pseudo),
272
273 (r'\b[ik]?goto\b', Keyword, 'goto label'),
274 (r'\b(r(?:einit|igoto)|tigoto)(\(|\b)', bygroups(Keyword.Pseudo, Punctuation),
275 'goto label'),
276 (r'\b(c(?:g|in?|k|nk?)goto)(\(|\b)', bygroups(Keyword.Pseudo, Punctuation),
277 ('goto label', 'goto argument')),
278 (r'\b(timout)(\(|\b)', bygroups(Keyword.Pseudo, Punctuation),
279 ('goto label', 'goto argument', 'goto argument')),
280 (r'\b(loop_[gl][et])(\(|\b)', bygroups(Keyword.Pseudo, Punctuation),
281 ('goto label', 'goto argument', 'goto argument', 'goto argument')),
282
283 (r'\bprintk?s\b', Name.Builtin, 'prints opcode'),
284 (r'\b(?:readscore|scoreline(?:_i)?)\b', Name.Builtin, 'Csound score opcode'),
285 (r'\bpyl?run[it]?\b', Name.Builtin, 'Python opcode'),
286 (r'\blua_(?:exec|opdef)\b', Name.Builtin, 'Lua opcode'),
287 (r'\bp\d+\b', Name.Variable.Instance),
288 (r'\b([A-Z_a-z]\w*)(?:(:)([A-Za-z]))?\b', name_callback)
289 ],
290
291 'instrument numbers and identifiers': [
292 include('whitespace and macro uses'),
293 (r'\d+|[A-Z_a-z]\w*', Name.Function),
294 (r'[+,]', Punctuation),
295 (r'\n', Text, '#pop')
296 ],
297
298 'after opcode keyword': [
299 include('whitespace and macro uses'),
300 (r'[A-Z_a-z]\w*', opcode_name_callback, ('#pop', 'opcode type signatures')),
301 (r'\n', Text, '#pop')
302 ],
303 'opcode type signatures': [
304 include('whitespace and macro uses'),
305
306 # https://github.com/csound/csound/search?q=XIDENT+path%3AEngine+filename%3Acsound_orc.lex
307 (r'0|[afijkKoOpPStV\[\]]+', Keyword.Type),
308
309 (r',', Punctuation),
310 (r'\n', Text, '#pop')
311 ],
312
313 'quoted string': [
314 (r'"', String, '#pop'),
315 (r'[^\\"$%)]+', String),
316 include('macro uses'),
317 include('escape sequences'),
318 include('format specifiers'),
319 (r'[\\$%)]', String)
320 ],
321 'braced string': [
322 (r'\}\}', String, '#pop'),
323 (r'(?:[^\\%)}]|\}(?!\}))+', String),
324 include('escape sequences'),
325 include('format specifiers'),
326 (r'[\\%)]', String)
327 ],
328 'escape sequences': [
329 # https://github.com/csound/csound/search?q=unquote_string+path%3AEngine+filename%3Acsound_orc_compile.c
330 (r'\\(?:[\\abnrt"]|[0-7]{1,3})', String.Escape)
331 ],
332 # Format specifiers are highlighted in all strings, even though only
333 # fprintks https://csound.com/docs/manual/fprintks.html
334 # fprints https://csound.com/docs/manual/fprints.html
335 # printf/printf_i https://csound.com/docs/manual/printf.html
336 # printks https://csound.com/docs/manual/printks.html
337 # prints https://csound.com/docs/manual/prints.html
338 # sprintf https://csound.com/docs/manual/sprintf.html
339 # sprintfk https://csound.com/docs/manual/sprintfk.html
340 # work with strings that contain format specifiers. In addition, these opcodes’
341 # handling of format specifiers is inconsistent:
342 # - fprintks and fprints accept %a and %A specifiers, and accept %s specifiers
343 # starting in Csound 6.15.0.
344 # - printks and prints accept %a and %A specifiers, but don’t accept %s
345 # specifiers.
346 # - printf, printf_i, sprintf, and sprintfk don’t accept %a and %A specifiers,
347 # but accept %s specifiers.
348 # See https://github.com/csound/csound/issues/747 for more information.
349 'format specifiers': [
350 (r'%[#0\- +]*\d*(?:\.\d+)?[AE-GXac-giosux]', String.Interpol),
351 (r'%%', String.Escape)
352 ],
353
354 'goto argument': [
355 include('whitespace and macro uses'),
356 (r',', Punctuation, '#pop'),
357 include('partial statements')
358 ],
359 'goto label': [
360 include('whitespace and macro uses'),
361 (r'\w+', Name.Label, '#pop'),
362 default('#pop')
363 ],
364
365 'prints opcode': [
366 include('whitespace and macro uses'),
367 (r'"', String, 'prints quoted string'),
368 default('#pop')
369 ],
370 'prints quoted string': [
371 (r'\\\\[aAbBnNrRtT]', String.Escape),
372 (r'%[!nNrRtT]|[~^]{1,2}', String.Escape),
373 include('quoted string')
374 ],
375
376 'Csound score opcode': [
377 include('whitespace and macro uses'),
378 (r'"', String, 'quoted string'),
379 (r'\{\{', String, 'Csound score'),
380 (r'\n', Text, '#pop')
381 ],
382 'Csound score': [
383 (r'\}\}', String, '#pop'),
384 (r'([^}]+)|\}(?!\})', using(CsoundScoreLexer))
385 ],
386
387 'Python opcode': [
388 include('whitespace and macro uses'),
389 (r'"', String, 'quoted string'),
390 (r'\{\{', String, 'Python'),
391 (r'\n', Text, '#pop')
392 ],
393 'Python': [
394 (r'\}\}', String, '#pop'),
395 (r'([^}]+)|\}(?!\})', using(PythonLexer))
396 ],
397
398 'Lua opcode': [
399 include('whitespace and macro uses'),
400 (r'"', String, 'quoted string'),
401 (r'\{\{', String, 'Lua'),
402 (r'\n', Text, '#pop')
403 ],
404 'Lua': [
405 (r'\}\}', String, '#pop'),
406 (r'([^}]+)|\}(?!\})', using(LuaLexer))
407 ]
408 }
409
410
411 class CsoundDocumentLexer(RegexLexer):
412 """
413 For `Csound <https://csound.com>`_ documents.
414
415 .. versionadded:: 2.1
416 """
417
418 name = 'Csound Document'
419 aliases = ['csound-document', 'csound-csd']
420 filenames = ['*.csd']
421
422 # These tokens are based on those in XmlLexer in pygments/lexers/html.py. Making
423 # CsoundDocumentLexer a subclass of XmlLexer rather than RegexLexer may seem like a
424 # better idea, since Csound Document files look like XML files. However, Csound
425 # Documents can contain Csound comments (preceded by //, for example) before and
426 # after the root element, unescaped bitwise AND & and less than < operators, etc. In
427 # other words, while Csound Document files look like XML files, they may not actually
428 # be XML files.
429 tokens = {
430 'root': [
431 (r'/[*](.|\n)*?[*]/', Comment.Multiline),
432 (r'(?:;|//).*$', Comment.Single),
433 (r'[^/;<]+|/(?!/)', Text),
434
435 (r'<\s*CsInstruments', Name.Tag, ('orchestra', 'tag')),
436 (r'<\s*CsScore', Name.Tag, ('score', 'tag')),
437 (r'<\s*[Hh][Tt][Mm][Ll]', Name.Tag, ('HTML', 'tag')),
438
439 (r'<\s*[\w:.-]+', Name.Tag, 'tag'),
440 (r'<\s*/\s*[\w:.-]+\s*>', Name.Tag)
441 ],
442
443 'orchestra': [
444 (r'<\s*/\s*CsInstruments\s*>', Name.Tag, '#pop'),
445 (r'(.|\n)+?(?=<\s*/\s*CsInstruments\s*>)', using(CsoundOrchestraLexer))
446 ],
447 'score': [
448 (r'<\s*/\s*CsScore\s*>', Name.Tag, '#pop'),
449 (r'(.|\n)+?(?=<\s*/\s*CsScore\s*>)', using(CsoundScoreLexer))
450 ],
451 'HTML': [
452 (r'<\s*/\s*[Hh][Tt][Mm][Ll]\s*>', Name.Tag, '#pop'),
453 (r'(.|\n)+?(?=<\s*/\s*[Hh][Tt][Mm][Ll]\s*>)', using(HtmlLexer))
454 ],
455
456 'tag': [
457 (r'\s+', Text),
458 (r'[\w.:-]+\s*=', Name.Attribute, 'attr'),
459 (r'/?\s*>', Name.Tag, '#pop')
460 ],
461 'attr': [
462 (r'\s+', Text),
463 (r'".*?"', String, '#pop'),
464 (r"'.*?'", String, '#pop'),
465 (r'[^\s>]+', String, '#pop')
466 ]
467 }

eric ide

mercurial