Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pygments/lexers/csound.py: 81%

48 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-01 06:54 +0000

1""" 

2 pygments.lexers.csound 

3 ~~~~~~~~~~~~~~~~~~~~~~ 

4 

5 Lexers for Csound languages. 

6 

7 :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. 

8 :license: BSD, see LICENSE for details. 

9""" 

10 

11import re 

12 

13from pygments.lexer import RegexLexer, bygroups, default, include, using, words 

14from pygments.token import Comment, Error, Keyword, Name, Number, Operator, Punctuation, \ 

15 String, Text, Whitespace 

16from pygments.lexers._csound_builtins import OPCODES, DEPRECATED_OPCODES, REMOVED_OPCODES 

17from pygments.lexers.html import HtmlLexer 

18from pygments.lexers.python import PythonLexer 

19from pygments.lexers.scripting import LuaLexer 

20 

21__all__ = ['CsoundScoreLexer', 'CsoundOrchestraLexer', 'CsoundDocumentLexer'] 

22 

23newline = (r'((?:(?:;|//).*)*)(\n)', bygroups(Comment.Single, Text)) 

24 

25 

26class CsoundLexer(RegexLexer): 

27 url = 'https://csound.com/' 

28 

29 tokens = { 

30 'whitespace': [ 

31 (r'[ \t]+', Whitespace), 

32 (r'/[*](?:.|\n)*?[*]/', Comment.Multiline), 

33 (r'(?:;|//).*$', Comment.Single), 

34 (r'(\\)(\n)', bygroups(Text, Whitespace)) 

35 ], 

36 

37 'preprocessor directives': [ 

38 (r'#(?:e(?:nd(?:if)?|lse)\b|##)|@@?[ \t]*\d+', Comment.Preproc), 

39 (r'#includestr', Comment.Preproc, 'includestr directive'), 

40 (r'#include', Comment.Preproc, 'include directive'), 

41 (r'#[ \t]*define', Comment.Preproc, 'define directive'), 

42 (r'#(?:ifn?def|undef)\b', Comment.Preproc, 'macro directive') 

43 ], 

44 

45 'include directive': [ 

46 include('whitespace'), 

47 (r'([^ \t]).*?\1', String, '#pop') 

48 ], 

49 'includestr directive': [ 

50 include('whitespace'), 

51 (r'"', String, ('#pop', 'quoted string')) 

52 ], 

53 

54 'define directive': [ 

55 (r'\n', Whitespace), 

56 include('whitespace'), 

57 (r'([A-Z_a-z]\w*)(\()', bygroups(Comment.Preproc, Punctuation), 

58 ('#pop', 'macro parameter name list')), 

59 (r'[A-Z_a-z]\w*', Comment.Preproc, ('#pop', 'before macro body')) 

60 ], 

61 'macro parameter name list': [ 

62 include('whitespace'), 

63 (r'[A-Z_a-z]\w*', Comment.Preproc), 

64 (r"['#]", Punctuation), 

65 (r'\)', Punctuation, ('#pop', 'before macro body')) 

66 ], 

67 'before macro body': [ 

68 (r'\n', Whitespace), 

69 include('whitespace'), 

70 (r'#', Punctuation, ('#pop', 'macro body')) 

71 ], 

72 'macro body': [ 

73 (r'(?:\\(?!#)|[^#\\]|\n)+', Comment.Preproc), 

74 (r'\\#', Comment.Preproc), 

75 (r'(?<!\\)#', Punctuation, '#pop') 

76 ], 

77 

78 'macro directive': [ 

79 include('whitespace'), 

80 (r'[A-Z_a-z]\w*', Comment.Preproc, '#pop') 

81 ], 

82 

83 'macro uses': [ 

84 (r'(\$[A-Z_a-z]\w*\.?)(\()', bygroups(Comment.Preproc, Punctuation), 

85 'macro parameter value list'), 

86 (r'\$[A-Z_a-z]\w*(?:\.|\b)', Comment.Preproc) 

87 ], 

88 'macro parameter value list': [ 

89 (r'(?:[^\'#"{()]|\{(?!\{))+', Comment.Preproc), 

90 (r"['#]", Punctuation), 

91 (r'"', String, 'macro parameter value quoted string'), 

92 (r'\{\{', String, 'macro parameter value braced string'), 

93 (r'\(', Comment.Preproc, 'macro parameter value parenthetical'), 

94 (r'\)', Punctuation, '#pop') 

95 ], 

96 'macro parameter value quoted string': [ 

97 (r"\\[#'()]", Comment.Preproc), 

98 (r"[#'()]", Error), 

99 include('quoted string') 

100 ], 

101 'macro parameter value braced string': [ 

102 (r"\\[#'()]", Comment.Preproc), 

103 (r"[#'()]", Error), 

104 include('braced string') 

105 ], 

106 'macro parameter value parenthetical': [ 

107 (r'(?:[^\\()]|\\\))+', Comment.Preproc), 

108 (r'\(', Comment.Preproc, '#push'), 

109 (r'\)', Comment.Preproc, '#pop') 

110 ], 

111 

112 'whitespace and macro uses': [ 

113 include('whitespace'), 

114 include('macro uses') 

115 ], 

116 

117 'numbers': [ 

118 (r'\d+[Ee][+-]?\d+|(\d+\.\d*|\d*\.\d+)([Ee][+-]?\d+)?', Number.Float), 

119 (r'(0[Xx])([0-9A-Fa-f]+)', bygroups(Keyword.Type, Number.Hex)), 

120 (r'\d+', Number.Integer) 

121 ], 

122 

123 'quoted string': [ 

124 (r'"', String, '#pop'), 

125 (r'[^"$]+', String), 

126 include('macro uses'), 

127 (r'[$]', String) 

128 ], 

129 

130 'braced string': [ 

131 # Do nothing. This must be defined in subclasses. 

132 ] 

133 } 

134 

135 

136class CsoundScoreLexer(CsoundLexer): 

137 """ 

138 For `Csound <https://csound.com>`_ scores. 

139 

140 .. versionadded:: 2.1 

141 """ 

142 

143 name = 'Csound Score' 

144 aliases = ['csound-score', 'csound-sco'] 

145 filenames = ['*.sco'] 

146 

147 tokens = { 

148 'root': [ 

149 (r'\n', Whitespace), 

150 include('whitespace and macro uses'), 

151 include('preprocessor directives'), 

152 

153 (r'[aBbCdefiqstvxy]', Keyword), 

154 # There is also a w statement that is generated internally and should not be 

155 # used; see https://github.com/csound/csound/issues/750. 

156 

157 (r'z', Keyword.Constant), 

158 # z is a constant equal to 800,000,000,000. 800 billion seconds is about 

159 # 25,367.8 years. See also 

160 # https://csound.com/docs/manual/ScoreTop.html and 

161 # https://github.com/csound/csound/search?q=stof+path%3AEngine+filename%3Asread.c. 

162 

163 (r'([nNpP][pP])(\d+)', bygroups(Keyword, Number.Integer)), 

164 

165 (r'[mn]', Keyword, 'mark statement'), 

166 

167 include('numbers'), 

168 (r'[!+\-*/^%&|<>#~.]', Operator), 

169 (r'[()\[\]]', Punctuation), 

170 (r'"', String, 'quoted string'), 

171 (r'\{', Comment.Preproc, 'loop after left brace'), 

172 ], 

173 

174 'mark statement': [ 

175 include('whitespace and macro uses'), 

176 (r'[A-Z_a-z]\w*', Name.Label), 

177 (r'\n', Whitespace, '#pop') 

178 ], 

179 

180 'loop after left brace': [ 

181 include('whitespace and macro uses'), 

182 (r'\d+', Number.Integer, ('#pop', 'loop after repeat count')), 

183 ], 

184 'loop after repeat count': [ 

185 include('whitespace and macro uses'), 

186 (r'[A-Z_a-z]\w*', Comment.Preproc, ('#pop', 'loop')) 

187 ], 

188 'loop': [ 

189 (r'\}', Comment.Preproc, '#pop'), 

190 include('root') 

191 ], 

192 

193 # Braced strings are not allowed in Csound scores, but this is needed because the 

194 # superclass includes it. 

195 'braced string': [ 

196 (r'\}\}', String, '#pop'), 

197 (r'[^}]|\}(?!\})', String) 

198 ] 

199 } 

200 

201 

202class CsoundOrchestraLexer(CsoundLexer): 

203 """ 

204 For `Csound <https://csound.com>`_ orchestras. 

205 

206 .. versionadded:: 2.1 

207 """ 

208 

209 name = 'Csound Orchestra' 

210 aliases = ['csound', 'csound-orc'] 

211 filenames = ['*.orc', '*.udo'] 

212 

213 user_defined_opcodes = set() 

214 

215 def opcode_name_callback(lexer, match): 

216 opcode = match.group(0) 

217 lexer.user_defined_opcodes.add(opcode) 

218 yield match.start(), Name.Function, opcode 

219 

220 def name_callback(lexer, match): 

221 type_annotation_token = Keyword.Type 

222 

223 name = match.group(1) 

224 if name in OPCODES or name in DEPRECATED_OPCODES or name in REMOVED_OPCODES: 

225 yield match.start(), Name.Builtin, name 

226 elif name in lexer.user_defined_opcodes: 

227 yield match.start(), Name.Function, name 

228 else: 

229 type_annotation_token = Name 

230 name_match = re.search(r'^(g?[afikSw])(\w+)', name) 

231 if name_match: 

232 yield name_match.start(1), Keyword.Type, name_match.group(1) 

233 yield name_match.start(2), Name, name_match.group(2) 

234 else: 

235 yield match.start(), Name, name 

236 

237 if match.group(2): 

238 yield match.start(2), Punctuation, match.group(2) 

239 yield match.start(3), type_annotation_token, match.group(3) 

240 

241 tokens = { 

242 'root': [ 

243 (r'\n', Whitespace), 

244 

245 (r'^([ \t]*)(\w+)(:)([ \t]+|$)', bygroups(Whitespace, Name.Label, Punctuation, Whitespace)), 

246 

247 include('whitespace and macro uses'), 

248 include('preprocessor directives'), 

249 

250 (r'\binstr\b', Keyword.Declaration, 'instrument numbers and identifiers'), 

251 (r'\bopcode\b', Keyword.Declaration, 'after opcode keyword'), 

252 (r'\b(?:end(?:in|op))\b', Keyword.Declaration), 

253 

254 include('partial statements') 

255 ], 

256 

257 'partial statements': [ 

258 (r'\b(?:0dbfs|A4|k(?:r|smps)|nchnls(?:_i)?|sr)\b', Name.Variable.Global), 

259 

260 include('numbers'), 

261 

262 (r'\+=|-=|\*=|/=|<<|>>|<=|>=|==|!=|&&|\|\||[~¬]|[=!+\-*/^%&|<>#?:]', Operator), 

263 (r'[(),\[\]]', Punctuation), 

264 

265 (r'"', String, 'quoted string'), 

266 (r'\{\{', String, 'braced string'), 

267 

268 (words(( 

269 'do', 'else', 'elseif', 'endif', 'enduntil', 'fi', 'if', 'ithen', 'kthen', 

270 'od', 'then', 'until', 'while', 

271 ), prefix=r'\b', suffix=r'\b'), Keyword), 

272 (words(('return', 'rireturn'), prefix=r'\b', suffix=r'\b'), Keyword.Pseudo), 

273 

274 (r'\b[ik]?goto\b', Keyword, 'goto label'), 

275 (r'\b(r(?:einit|igoto)|tigoto)(\(|\b)', bygroups(Keyword.Pseudo, Punctuation), 

276 'goto label'), 

277 (r'\b(c(?:g|in?|k|nk?)goto)(\(|\b)', bygroups(Keyword.Pseudo, Punctuation), 

278 ('goto label', 'goto argument')), 

279 (r'\b(timout)(\(|\b)', bygroups(Keyword.Pseudo, Punctuation), 

280 ('goto label', 'goto argument', 'goto argument')), 

281 (r'\b(loop_[gl][et])(\(|\b)', bygroups(Keyword.Pseudo, Punctuation), 

282 ('goto label', 'goto argument', 'goto argument', 'goto argument')), 

283 

284 (r'\bprintk?s\b', Name.Builtin, 'prints opcode'), 

285 (r'\b(?:readscore|scoreline(?:_i)?)\b', Name.Builtin, 'Csound score opcode'), 

286 (r'\bpyl?run[it]?\b', Name.Builtin, 'Python opcode'), 

287 (r'\blua_(?:exec|opdef)\b', Name.Builtin, 'Lua opcode'), 

288 (r'\bp\d+\b', Name.Variable.Instance), 

289 (r'\b([A-Z_a-z]\w*)(?:(:)([A-Za-z]))?\b', name_callback) 

290 ], 

291 

292 'instrument numbers and identifiers': [ 

293 include('whitespace and macro uses'), 

294 (r'\d+|[A-Z_a-z]\w*', Name.Function), 

295 (r'[+,]', Punctuation), 

296 (r'\n', Whitespace, '#pop') 

297 ], 

298 

299 'after opcode keyword': [ 

300 include('whitespace and macro uses'), 

301 (r'[A-Z_a-z]\w*', opcode_name_callback, ('#pop', 'opcode type signatures')), 

302 (r'\n', Whitespace, '#pop') 

303 ], 

304 'opcode type signatures': [ 

305 include('whitespace and macro uses'), 

306 

307 # https://github.com/csound/csound/search?q=XIDENT+path%3AEngine+filename%3Acsound_orc.lex 

308 (r'0|[afijkKoOpPStV\[\]]+', Keyword.Type), 

309 

310 (r',', Punctuation), 

311 (r'\n', Whitespace, '#pop') 

312 ], 

313 

314 'quoted string': [ 

315 (r'"', String, '#pop'), 

316 (r'[^\\"$%)]+', String), 

317 include('macro uses'), 

318 include('escape sequences'), 

319 include('format specifiers'), 

320 (r'[\\$%)]', String) 

321 ], 

322 'braced string': [ 

323 (r'\}\}', String, '#pop'), 

324 (r'(?:[^\\%)}]|\}(?!\}))+', String), 

325 include('escape sequences'), 

326 include('format specifiers'), 

327 (r'[\\%)]', String) 

328 ], 

329 'escape sequences': [ 

330 # https://github.com/csound/csound/search?q=unquote_string+path%3AEngine+filename%3Acsound_orc_compile.c 

331 (r'\\(?:[\\abnrt"]|[0-7]{1,3})', String.Escape) 

332 ], 

333 # Format specifiers are highlighted in all strings, even though only 

334 # fprintks https://csound.com/docs/manual/fprintks.html 

335 # fprints https://csound.com/docs/manual/fprints.html 

336 # printf/printf_i https://csound.com/docs/manual/printf.html 

337 # printks https://csound.com/docs/manual/printks.html 

338 # prints https://csound.com/docs/manual/prints.html 

339 # sprintf https://csound.com/docs/manual/sprintf.html 

340 # sprintfk https://csound.com/docs/manual/sprintfk.html 

341 # work with strings that contain format specifiers. In addition, these opcodes’ 

342 # handling of format specifiers is inconsistent: 

343 # - fprintks and fprints accept %a and %A specifiers, and accept %s specifiers 

344 # starting in Csound 6.15.0. 

345 # - printks and prints accept %a and %A specifiers, but don’t accept %s 

346 # specifiers. 

347 # - printf, printf_i, sprintf, and sprintfk don’t accept %a and %A specifiers, 

348 # but accept %s specifiers. 

349 # See https://github.com/csound/csound/issues/747 for more information. 

350 'format specifiers': [ 

351 (r'%[#0\- +]*\d*(?:\.\d+)?[AE-GXac-giosux]', String.Interpol), 

352 (r'%%', String.Escape) 

353 ], 

354 

355 'goto argument': [ 

356 include('whitespace and macro uses'), 

357 (r',', Punctuation, '#pop'), 

358 include('partial statements') 

359 ], 

360 'goto label': [ 

361 include('whitespace and macro uses'), 

362 (r'\w+', Name.Label, '#pop'), 

363 default('#pop') 

364 ], 

365 

366 'prints opcode': [ 

367 include('whitespace and macro uses'), 

368 (r'"', String, 'prints quoted string'), 

369 default('#pop') 

370 ], 

371 'prints quoted string': [ 

372 (r'\\\\[aAbBnNrRtT]', String.Escape), 

373 (r'%[!nNrRtT]|[~^]{1,2}', String.Escape), 

374 include('quoted string') 

375 ], 

376 

377 'Csound score opcode': [ 

378 include('whitespace and macro uses'), 

379 (r'"', String, 'quoted string'), 

380 (r'\{\{', String, 'Csound score'), 

381 (r'\n', Whitespace, '#pop') 

382 ], 

383 'Csound score': [ 

384 (r'\}\}', String, '#pop'), 

385 (r'([^}]+)|\}(?!\})', using(CsoundScoreLexer)) 

386 ], 

387 

388 'Python opcode': [ 

389 include('whitespace and macro uses'), 

390 (r'"', String, 'quoted string'), 

391 (r'\{\{', String, 'Python'), 

392 (r'\n', Whitespace, '#pop') 

393 ], 

394 'Python': [ 

395 (r'\}\}', String, '#pop'), 

396 (r'([^}]+)|\}(?!\})', using(PythonLexer)) 

397 ], 

398 

399 'Lua opcode': [ 

400 include('whitespace and macro uses'), 

401 (r'"', String, 'quoted string'), 

402 (r'\{\{', String, 'Lua'), 

403 (r'\n', Whitespace, '#pop') 

404 ], 

405 'Lua': [ 

406 (r'\}\}', String, '#pop'), 

407 (r'([^}]+)|\}(?!\})', using(LuaLexer)) 

408 ] 

409 } 

410 

411 

412class CsoundDocumentLexer(RegexLexer): 

413 """ 

414 For `Csound <https://csound.com>`_ documents. 

415 

416 .. versionadded:: 2.1 

417 """ 

418 

419 name = 'Csound Document' 

420 aliases = ['csound-document', 'csound-csd'] 

421 filenames = ['*.csd'] 

422 

423 # These tokens are based on those in XmlLexer in pygments/lexers/html.py. Making 

424 # CsoundDocumentLexer a subclass of XmlLexer rather than RegexLexer may seem like a 

425 # better idea, since Csound Document files look like XML files. However, Csound 

426 # Documents can contain Csound comments (preceded by //, for example) before and 

427 # after the root element, unescaped bitwise AND & and less than < operators, etc. In 

428 # other words, while Csound Document files look like XML files, they may not actually 

429 # be XML files. 

430 tokens = { 

431 'root': [ 

432 (r'/[*](.|\n)*?[*]/', Comment.Multiline), 

433 (r'(?:;|//).*$', Comment.Single), 

434 (r'[^/;<]+|/(?!/)', Text), 

435 

436 (r'<\s*CsInstruments', Name.Tag, ('orchestra', 'tag')), 

437 (r'<\s*CsScore', Name.Tag, ('score', 'tag')), 

438 (r'<\s*[Hh][Tt][Mm][Ll]', Name.Tag, ('HTML', 'tag')), 

439 

440 (r'<\s*[\w:.-]+', Name.Tag, 'tag'), 

441 (r'<\s*/\s*[\w:.-]+\s*>', Name.Tag) 

442 ], 

443 

444 'orchestra': [ 

445 (r'<\s*/\s*CsInstruments\s*>', Name.Tag, '#pop'), 

446 (r'(.|\n)+?(?=<\s*/\s*CsInstruments\s*>)', using(CsoundOrchestraLexer)) 

447 ], 

448 'score': [ 

449 (r'<\s*/\s*CsScore\s*>', Name.Tag, '#pop'), 

450 (r'(.|\n)+?(?=<\s*/\s*CsScore\s*>)', using(CsoundScoreLexer)) 

451 ], 

452 'HTML': [ 

453 (r'<\s*/\s*[Hh][Tt][Mm][Ll]\s*>', Name.Tag, '#pop'), 

454 (r'(.|\n)+?(?=<\s*/\s*[Hh][Tt][Mm][Ll]\s*>)', using(HtmlLexer)) 

455 ], 

456 

457 'tag': [ 

458 (r'\s+', Whitespace), 

459 (r'[\w.:-]+\s*=', Name.Attribute, 'attr'), 

460 (r'/?\s*>', Name.Tag, '#pop') 

461 ], 

462 'attr': [ 

463 (r'\s+', Whitespace), 

464 (r'".*?"', String, '#pop'), 

465 (r"'.*?'", String, '#pop'), 

466 (r'[^\s>]+', String, '#pop') 

467 ] 

468 }