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