]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexCsound.cxx
1 // Scintilla source code edit control
2 /** @file LexCsound.cxx
3 ** Lexer for Csound (Orchestra & Score)
4 ** Written by Georg Ritter - <ritterfuture A T gmail D O T com>
6 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
17 #include "Scintilla.h"
21 #include "LexAccessor.h"
23 #include "StyleContext.h"
24 #include "CharacterSet.h"
25 #include "LexerModule.h"
28 using namespace Scintilla
;
31 static inline bool IsAWordChar(const int ch
) {
32 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' ||
33 ch
== '_' || ch
== '?');
36 static inline bool IsAWordStart(const int ch
) {
37 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_' || ch
== '.' ||
38 ch
== '%' || ch
== '@' || ch
== '$' || ch
== '?');
41 static inline bool IsCsoundOperator(char ch
) {
42 if (isascii(ch
) && isalnum(ch
))
44 // '.' left out as it is used to make up numbers
45 if (ch
== '*' || ch
== '/' || ch
== '-' || ch
== '+' ||
46 ch
== '(' || ch
== ')' || ch
== '=' || ch
== '^' ||
47 ch
== '[' || ch
== ']' || ch
== '<' || ch
== '&' ||
48 ch
== '>' || ch
== ',' || ch
== '|' || ch
== '~' ||
49 ch
== '%' || ch
== ':')
54 static void ColouriseCsoundDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
57 WordList
&opcode
= *keywordlists
[0];
58 WordList
&headerStmt
= *keywordlists
[1];
59 WordList
&otherKeyword
= *keywordlists
[2];
61 // Do not leak onto next line
62 if (initStyle
== SCE_CSOUND_STRINGEOL
)
63 initStyle
= SCE_CSOUND_DEFAULT
;
65 StyleContext
sc(startPos
, length
, initStyle
, styler
);
67 for (; sc
.More(); sc
.Forward())
69 // Handle line continuation generically.
71 if (sc
.chNext
== '\n' || sc
.chNext
== '\r') {
73 if (sc
.ch
== '\r' && sc
.chNext
== '\n') {
80 // Determine if the current state should terminate.
81 if (sc
.state
== SCE_CSOUND_OPERATOR
) {
82 if (!IsCsoundOperator(static_cast<char>(sc
.ch
))) {
83 sc
.SetState(SCE_CSOUND_DEFAULT
);
85 }else if (sc
.state
== SCE_CSOUND_NUMBER
) {
86 if (!IsAWordChar(sc
.ch
)) {
87 sc
.SetState(SCE_CSOUND_DEFAULT
);
89 } else if (sc
.state
== SCE_CSOUND_IDENTIFIER
) {
90 if (!IsAWordChar(sc
.ch
) ) {
92 sc
.GetCurrent(s
, sizeof(s
));
94 if (opcode
.InList(s
)) {
95 sc
.ChangeState(SCE_CSOUND_OPCODE
);
96 } else if (headerStmt
.InList(s
)) {
97 sc
.ChangeState(SCE_CSOUND_HEADERSTMT
);
98 } else if (otherKeyword
.InList(s
)) {
99 sc
.ChangeState(SCE_CSOUND_USERKEYWORD
);
100 } else if (s
[0] == 'p') {
101 sc
.ChangeState(SCE_CSOUND_PARAM
);
102 } else if (s
[0] == 'a') {
103 sc
.ChangeState(SCE_CSOUND_ARATE_VAR
);
104 } else if (s
[0] == 'k') {
105 sc
.ChangeState(SCE_CSOUND_KRATE_VAR
);
106 } else if (s
[0] == 'i') { // covers both i-rate variables and i-statements
107 sc
.ChangeState(SCE_CSOUND_IRATE_VAR
);
108 } else if (s
[0] == 'g') {
109 sc
.ChangeState(SCE_CSOUND_GLOBAL_VAR
);
111 sc
.SetState(SCE_CSOUND_DEFAULT
);
114 else if (sc
.state
== SCE_CSOUND_COMMENT
) {
116 sc
.SetState(SCE_CSOUND_DEFAULT
);
119 else if ((sc
.state
== SCE_CSOUND_ARATE_VAR
) ||
120 (sc
.state
== SCE_CSOUND_KRATE_VAR
) ||
121 (sc
.state
== SCE_CSOUND_IRATE_VAR
)) {
122 if (!IsAWordChar(sc
.ch
)) {
123 sc
.SetState(SCE_CSOUND_DEFAULT
);
127 // Determine if a new state should be entered.
128 if (sc
.state
== SCE_CSOUND_DEFAULT
) {
130 sc
.SetState(SCE_CSOUND_COMMENT
);
131 } else if (isdigit(sc
.ch
) || (sc
.ch
== '.' && isdigit(sc
.chNext
))) {
132 sc
.SetState(SCE_CSOUND_NUMBER
);
133 } else if (IsAWordStart(sc
.ch
)) {
134 sc
.SetState(SCE_CSOUND_IDENTIFIER
);
135 } else if (IsCsoundOperator(static_cast<char>(sc
.ch
))) {
136 sc
.SetState(SCE_CSOUND_OPERATOR
);
137 } else if (sc
.ch
== 'p') {
138 sc
.SetState(SCE_CSOUND_PARAM
);
139 } else if (sc
.ch
== 'a') {
140 sc
.SetState(SCE_CSOUND_ARATE_VAR
);
141 } else if (sc
.ch
== 'k') {
142 sc
.SetState(SCE_CSOUND_KRATE_VAR
);
143 } else if (sc
.ch
== 'i') { // covers both i-rate variables and i-statements
144 sc
.SetState(SCE_CSOUND_IRATE_VAR
);
145 } else if (sc
.ch
== 'g') {
146 sc
.SetState(SCE_CSOUND_GLOBAL_VAR
);
153 static void FoldCsoundInstruments(unsigned int startPos
, int length
, int /* initStyle */, WordList
*[],
155 unsigned int lengthDoc
= startPos
+ length
;
156 int visibleChars
= 0;
157 int lineCurrent
= styler
.GetLine(startPos
);
158 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
159 int levelCurrent
= levelPrev
;
160 char chNext
= styler
[startPos
];
162 int styleNext
= styler
.StyleAt(startPos
);
163 for (unsigned int i
= startPos
; i
< lengthDoc
; i
++) {
165 chNext
= styler
.SafeGetCharAt(i
+ 1);
166 int style
= styleNext
;
167 styleNext
= styler
.StyleAt(i
+ 1);
168 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
169 if ((stylePrev
!= SCE_CSOUND_OPCODE
) && (style
== SCE_CSOUND_OPCODE
)) {
172 while ((j
< (sizeof(s
) - 1)) && (iswordchar(styler
[i
+ j
]))) {
173 s
[j
] = styler
[i
+ j
];
178 if (strcmp(s
, "instr") == 0)
180 if (strcmp(s
, "endin") == 0)
186 if (visibleChars
== 0)
187 lev
|= SC_FOLDLEVELWHITEFLAG
;
188 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
189 lev
|= SC_FOLDLEVELHEADERFLAG
;
190 if (lev
!= styler
.LevelAt(lineCurrent
)) {
191 styler
.SetLevel(lineCurrent
, lev
);
194 levelPrev
= levelCurrent
;
197 if (!isspacechar(ch
))
201 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
202 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
203 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
207 static const char * const csoundWordListDesc
[] = {
214 LexerModule
lmCsound(SCLEX_CSOUND
, ColouriseCsoundDoc
, "csound", FoldCsoundInstruments
, csoundWordListDesc
);