ThirdParty/Pygments/pygments/lexers/csound.py

changeset 4697
c2e9bf425554
child 5713
6762afd9f963
equal deleted inserted replaced
4696:bf4d19a7cade 4697:c2e9bf425554
1 # -*- coding: utf-8 -*-
2 """
3 pygments.lexers.csound
4 ~~~~~~~~~~~~~~~~~~~~~~
5
6 Lexers for CSound languages.
7
8 :copyright: Copyright 2006-2015 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details.
10 """
11
12 import copy, re
13
14 from pygments.lexer import RegexLexer, bygroups, default, include, using, words
15 from pygments.token import Comment, Keyword, Name, Number, Operator, Punctuation, \
16 String, Text
17 from pygments.lexers._csound_builtins import 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 # Subclasses must define a 'single-line string' state.
29 tokens = {
30 'whitespace': [
31 (r'[ \t]+', Text),
32 (r'\\\n', Text),
33 (r'/[*](.|\n)*?[*]/', Comment.Multiline)
34 ],
35
36 'macro call': [
37 (r'(\$\w+\.?)(\()', bygroups(Comment.Preproc, Punctuation),
38 'function macro call'),
39 (r'\$\w+(\.|\b)', Comment.Preproc)
40 ],
41 'function macro call': [
42 (r"((?:\\['\)]|[^'\)])+)(')", bygroups(Comment.Preproc, Punctuation)),
43 (r"([^'\)]+)(\))", bygroups(Comment.Preproc, Punctuation), '#pop')
44 ],
45
46 'whitespace or macro call': [
47 include('whitespace'),
48 include('macro call')
49 ],
50
51 'preprocessor directives': [
52 (r'#(e(nd(if)?|lse)|ifn?def|undef)\b|##', Comment.Preproc),
53 (r'#include\b', Comment.Preproc, 'include'),
54 (r'#[ \t]*define\b', Comment.Preproc, 'macro name'),
55 (r'@+[ \t]*\d*', Comment.Preproc)
56 ],
57
58 'include': [
59 include('whitespace'),
60 (r'"', String, 'single-line string')
61 ],
62
63 'macro name': [
64 include('whitespace'),
65 (r'(\w+)(\()', bygroups(Comment.Preproc, Text),
66 'function macro argument list'),
67 (r'\w+', Comment.Preproc, 'object macro definition after name')
68 ],
69 'object macro definition after name': [
70 include('whitespace'),
71 (r'#', Punctuation, 'object macro replacement text')
72 ],
73 'object macro replacement text': [
74 (r'(\\#|[^#])+', Comment.Preproc),
75 (r'#', Punctuation, '#pop:3')
76 ],
77 'function macro argument list': [
78 (r"(\w+)(['#])", bygroups(Comment.Preproc, Punctuation)),
79 (r'(\w+)(\))', bygroups(Comment.Preproc, Punctuation),
80 'function macro definition after name')
81 ],
82 'function macro definition after name': [
83 (r'[ \t]+', Text),
84 (r'#', Punctuation, 'function macro replacement text')
85 ],
86 'function macro replacement text': [
87 (r'(\\#|[^#])+', Comment.Preproc),
88 (r'#', Punctuation, '#pop:4')
89 ]
90 }
91
92
93 class CsoundScoreLexer(CsoundLexer):
94 """
95 For `Csound <http://csound.github.io>`_ scores.
96
97 .. versionadded:: 2.1
98 """
99
100 name = 'Csound Score'
101 aliases = ['csound-score', 'csound-sco']
102 filenames = ['*.sco']
103
104 tokens = {
105 'partial statement': [
106 include('preprocessor directives'),
107 (r'\d+e[+-]?\d+|(\d+\.\d*|\d*\.\d+)(e[+-]?\d+)?', Number.Float),
108 (r'0[xX][a-fA-F0-9]+', Number.Hex),
109 (r'\d+', Number.Integer),
110 (r'"', String, 'single-line string'),
111 (r'[+\-*/%^!=<>|&#~.]', Operator),
112 (r'[]()[]', Punctuation),
113 (r'\w+', Comment.Preproc)
114 ],
115
116 'statement': [
117 include('whitespace or macro call'),
118 newline + ('#pop',),
119 include('partial statement')
120 ],
121
122 'root': [
123 newline,
124 include('whitespace or macro call'),
125 (r'[{}]', Punctuation, 'statement'),
126 (r'[abefimq-tv-z]|[nN][pP]?', Keyword, 'statement')
127 ],
128
129 'single-line string': [
130 (r'"', String, '#pop'),
131 (r'[^\\"]+', String)
132 ]
133 }
134
135
136 class CsoundOrchestraLexer(CsoundLexer):
137 """
138 For `Csound <http://csound.github.io>`_ orchestras.
139
140 .. versionadded:: 2.1
141 """
142
143 name = 'Csound Orchestra'
144 aliases = ['csound', 'csound-orc']
145 filenames = ['*.orc']
146
147 user_defined_opcodes = set()
148
149 def opcode_name_callback(lexer, match):
150 opcode = match.group(0)
151 lexer.user_defined_opcodes.add(opcode)
152 yield match.start(), Name.Function, opcode
153
154 def name_callback(lexer, match):
155 name = match.group(0)
156 if re.match('p\d+$', name) or name in OPCODES:
157 yield match.start(), Name.Builtin, name
158 elif name in lexer.user_defined_opcodes:
159 yield match.start(), Name.Function, name
160 else:
161 nameMatch = re.search(r'^(g?[aikSw])(\w+)', name)
162 if nameMatch:
163 yield nameMatch.start(1), Keyword.Type, nameMatch.group(1)
164 yield nameMatch.start(2), Name, nameMatch.group(2)
165 else:
166 yield match.start(), Name, name
167
168 tokens = {
169 'label': [
170 (r'\b(\w+)(:)', bygroups(Name.Label, Punctuation))
171 ],
172
173 'partial expression': [
174 include('preprocessor directives'),
175 (r'\b(0dbfs|k(r|smps)|nchnls(_i)?|sr)\b', Name.Variable.Global),
176 (r'\d+e[+-]?\d+|(\d+\.\d*|\d*\.\d+)(e[+-]?\d+)?', Number.Float),
177 (r'0[xX][a-fA-F0-9]+', Number.Hex),
178 (r'\d+', Number.Integer),
179 (r'"', String, 'single-line string'),
180 (r'{{', String, 'multi-line string'),
181 (r'[+\-*/%^!=&|<>#~¬]', Operator),
182 (r'[](),?:[]', Punctuation),
183 (words((
184 # Keywords
185 'do', 'else', 'elseif', 'endif', 'enduntil', 'fi', 'if', 'ithen', 'kthen',
186 'od', 'then', 'until', 'while',
187 # Opcodes that act as control structures
188 'return', 'timout'
189 ), prefix=r'\b', suffix=r'\b'), Keyword),
190 (words(('goto', 'igoto', 'kgoto', 'rigoto', 'tigoto'),
191 prefix=r'\b', suffix=r'\b'), Keyword, 'goto label'),
192 (words(('cggoto', 'cigoto', 'cingoto', 'ckgoto', 'cngoto'),
193 prefix=r'\b', suffix=r'\b'), Keyword,
194 ('goto label', 'goto expression')),
195 (words(('loop_ge', 'loop_gt', 'loop_le', 'loop_lt'),
196 prefix=r'\b', suffix=r'\b'), Keyword,
197 ('goto label', 'goto expression', 'goto expression', 'goto expression')),
198 (r'\bscoreline(_i)?\b', Name.Builtin, 'scoreline opcode'),
199 (r'\bpyl?run[it]?\b', Name.Builtin, 'python opcode'),
200 (r'\blua_(exec|opdef)\b', Name.Builtin, 'lua opcode'),
201 (r'\b[a-zA-Z_]\w*\b', name_callback)
202 ],
203
204 'expression': [
205 include('whitespace or macro call'),
206 newline + ('#pop',),
207 include('partial expression')
208 ],
209
210 'root': [
211 newline,
212 include('whitespace or macro call'),
213 (r'\binstr\b', Keyword, ('instrument block', 'instrument name list')),
214 (r'\bopcode\b', Keyword, ('opcode block', 'opcode parameter list',
215 'opcode types', 'opcode types', 'opcode name')),
216 include('label'),
217 default('expression')
218 ],
219
220 'instrument name list': [
221 include('whitespace or macro call'),
222 (r'\d+|\+?[a-zA-Z_]\w*', Name.Function),
223 (r',', Punctuation),
224 newline + ('#pop',)
225 ],
226 'instrument block': [
227 newline,
228 include('whitespace or macro call'),
229 (r'\bendin\b', Keyword, '#pop'),
230 include('label'),
231 default('expression')
232 ],
233
234 'opcode name': [
235 include('whitespace or macro call'),
236 (r'[a-zA-Z_]\w*', opcode_name_callback, '#pop')
237 ],
238 'opcode types': [
239 include('whitespace or macro call'),
240 (r'0|[]afijkKoOpPStV[]+', Keyword.Type, '#pop'),
241 (r',', Punctuation)
242 ],
243 'opcode parameter list': [
244 include('whitespace or macro call'),
245 newline + ('#pop',)
246 ],
247 'opcode block': [
248 newline,
249 include('whitespace or macro call'),
250 (r'\bendop\b', Keyword, '#pop'),
251 include('label'),
252 default('expression')
253 ],
254
255 'goto label': [
256 include('whitespace or macro call'),
257 (r'\w+', Name.Label, '#pop'),
258 default('#pop')
259 ],
260 'goto expression': [
261 include('whitespace or macro call'),
262 (r',', Punctuation, '#pop'),
263 include('partial expression')
264 ],
265
266 'single-line string': [
267 include('macro call'),
268 (r'"', String, '#pop'),
269 # From https://github.com/csound/csound/blob/develop/Opcodes/fout.c#L1405
270 (r'%\d*(\.\d+)?[cdhilouxX]', String.Interpol),
271 (r'%[!%nNrRtT]|[~^]|\\([\\aAbBnNrRtT"]|[0-7]{1,3})', String.Escape),
272 (r'[^\\"~$%\^\n]+', String),
273 (r'[\\"~$%\^\n]', String)
274 ],
275 'multi-line string': [
276 (r'}}', String, '#pop'),
277 (r'[^\}]+|\}(?!\})', String)
278 ],
279
280 'scoreline opcode': [
281 include('whitespace or macro call'),
282 (r'{{', String, 'scoreline'),
283 default('#pop')
284 ],
285 'scoreline': [
286 (r'}}', String, '#pop'),
287 (r'([^\}]+)|\}(?!\})', using(CsoundScoreLexer))
288 ],
289
290 'python opcode': [
291 include('whitespace or macro call'),
292 (r'{{', String, 'python'),
293 default('#pop')
294 ],
295 'python': [
296 (r'}}', String, '#pop'),
297 (r'([^\}]+)|\}(?!\})', using(PythonLexer))
298 ],
299
300 'lua opcode': [
301 include('whitespace or macro call'),
302 (r'"', String, 'single-line string'),
303 (r'{{', String, 'lua'),
304 (r',', Punctuation),
305 default('#pop')
306 ],
307 'lua': [
308 (r'}}', String, '#pop'),
309 (r'([^\}]+)|\}(?!\})', using(LuaLexer))
310 ]
311 }
312
313
314 class CsoundDocumentLexer(RegexLexer):
315 """
316 For `Csound <http://csound.github.io>`_ documents.
317
318
319 """
320
321 name = 'Csound Document'
322 aliases = ['csound-document', 'csound-csd']
323 filenames = ['*.csd']
324
325 # These tokens are based on those in XmlLexer in pygments/lexers/html.py. Making
326 # CsoundDocumentLexer a subclass of XmlLexer rather than RegexLexer may seem like a
327 # better idea, since Csound Document files look like XML files. However, Csound
328 # Documents can contain Csound comments (preceded by //, for example) before and
329 # after the root element, unescaped bitwise AND & and less than < operators, etc. In
330 # other words, while Csound Document files look like XML files, they may not actually
331 # be XML files.
332 tokens = {
333 'root': [
334 newline,
335 (r'/[*](.|\n)*?[*]/', Comment.Multiline),
336 (r'[^<&;/]+', Text),
337 (r'<\s*CsInstruments', Name.Tag, ('orchestra', 'tag')),
338 (r'<\s*CsScore', Name.Tag, ('score', 'tag')),
339 (r'<\s*[hH][tT][mM][lL]', Name.Tag, ('HTML', 'tag')),
340 (r'<\s*[\w:.-]+', Name.Tag, 'tag'),
341 (r'<\s*/\s*[\w:.-]+\s*>', Name.Tag)
342 ],
343 'orchestra': [
344 (r'<\s*/\s*CsInstruments\s*>', Name.Tag, '#pop'),
345 (r'(.|\n)+?(?=<\s*/\s*CsInstruments\s*>)', using(CsoundOrchestraLexer))
346 ],
347 'score': [
348 (r'<\s*/\s*CsScore\s*>', Name.Tag, '#pop'),
349 (r'(.|\n)+?(?=<\s*/\s*CsScore\s*>)', using(CsoundScoreLexer))
350 ],
351 'HTML': [
352 (r'<\s*/\s*[hH][tT][mM][lL]\s*>', Name.Tag, '#pop'),
353 (r'(.|\n)+?(?=<\s*/\s*[hH][tT][mM][lL]\s*>)', using(HtmlLexer))
354 ],
355 'tag': [
356 (r'\s+', Text),
357 (r'[\w.:-]+\s*=', Name.Attribute, 'attr'),
358 (r'/?\s*>', Name.Tag, '#pop')
359 ],
360 'attr': [
361 (r'\s+', Text),
362 (r'".*?"', String, '#pop'),
363 (r"'.*?'", String, '#pop'),
364 (r'[^\s>]+', String, '#pop')
365 ]
366 }

eric ide

mercurial