/[svn]/linuxsampler/trunk/src/scriptvm/editor/nksp.l
ViewVC logotype

Contents of /linuxsampler/trunk/src/scriptvm/editor/nksp.l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3308 - (show annotations) (download)
Sat Jul 15 01:14:20 2017 UTC (6 years, 9 months ago) by schoenebeck
File size: 8335 byte(s)
* NKSP script editor API: Fixed app termination due to a lexer start
  condition stack underrun.
* NKSP preprocessor: Fixed wrong behavior on nested USE_CODE_IF() and
  USE_CODE_IF_NOT() preprocessor statements.
* Bumped version (2.0.0.svn70).

1 /*
2 * Copyright (c) 2015-2017 Christian Schoenebeck
3 *
4 * http://www.linuxsampler.org
5 *
6 * This file is part of LinuxSampler and released under the same terms.
7 * See README file for details.
8 */
9
10 /* Token scanner used for generating syntax highlighting for NKSP instrument
11 script language code (this is not used by the sampler itself, but rather
12 provided for external script editor applications). */
13
14 %{
15
16 #include "NkspScanner.h"
17 // reentrant scanner data context
18 #define YY_EXTRA_TYPE NkspScanner*
19 // custom (f)lex input for reading from std::istream object
20 #define YY_INPUT(buf,result,max_size) \
21 { \
22 char c = yyextra->is->get(); \
23 if (yyextra->is->eof()) \
24 result = YY_NULL; \
25 else { \
26 buf[0] = c; \
27 result = 1; \
28 } \
29 }
30 // handle position (line, column) for each recognized token
31 #define YY_USER_ACTION \
32 yyextra->line = yylineno - 1; \
33 yyextra->column = yycolumn; \
34 yycolumn += yyleng;
35
36 using namespace LinuxSampler;
37
38 static int countNewLineChars(const char* txt) {
39 int n = 0;
40 for (int i = 0; txt[i]; ++i)
41 if (txt[i] == '\n') ++n;
42 return n;
43 }
44
45 // shut up warning that 'register' keyword is deprecated as of C++11
46 #if defined(__cplusplus) && __cplusplus >= 201103L
47 # define register
48 #endif
49
50 // if compiled for debugging, throw an exception instead of exiting on fatal
51 // lexer errors (so the debugger may pause with the appropriate back trace)
52 #if DEBUG
53 # include <stdexcept>
54 # define YY_FATAL_ERROR(msg) throw std::runtime_error(msg)
55 #endif
56
57 %}
58
59 /* generate a reentrant safe scanner */
60 %option reentrant
61 /* avoid symbol collision with ones of other scanners */
62 %option prefix="Nksp_"
63 /* yywrap() would be called at EOF, we don't need it */
64 %option noyywrap
65 /* enable functions yy_push_state(), yy_pop_state(), yy_top_state() */
66 %option stack
67
68 /* inclusive scanner conditions */
69 %s PREPROC_BODY_USE
70 /* exclusive scanner conditions */
71 %x PREPROC_SET_COND PREPROC_RESET_COND PREPROC_IF PREPROC_IF_NOT PREPROC_BODY_EAT PREPROC_PRE_BODY_USE PREPROC_PRE_BODY_EAT PREPROC_EVENT_NAME PREPROC_END_NAME
72
73 DIGIT [0-9]
74 ID [a-zA-Z0-9_]+
75 END_ID on|while|if|select|function|synchronized
76
77 %%
78
79 \"[^"]*\" {
80 yyextra->token = StringLiteralToken(yytext);
81 return yyextra->token.baseType;
82 }
83
84 {DIGIT}+ {
85 yyextra->token = NumberLiteralToken(yytext);
86 return yyextra->token.baseType;
87 }
88
89 /* there is currently no support for floating point numbers in NKSP yet */
90 /*{DIGIT}+"."{DIGIT}* {
91 yyextra->token = NumberLiteralToken(yytext);
92 return yyextra->token.baseType;
93 }*/
94
95
96 /* Preprocessor statement: SET_CONDITION(name) */
97
98 <*>"SET_CONDITION"[ \t]*"(" {
99 //printf("SET_CONDITION\n");
100 yy_push_state(PREPROC_SET_COND, yyscanner);
101 yyextra->token = PreprocessorToken(yytext);
102 return yyextra->token.baseType;
103 }
104 <PREPROC_SET_COND>{ID} {
105 //printf("preproc set condition '%s'\n", yytext);
106 yyextra->token = PreprocessorToken(yytext);
107 return yyextra->token.baseType;
108 }
109 <PREPROC_SET_COND>[ \t]*")" {
110 //printf("End of PREPROC_SET_COND\n");
111 yy_pop_state(yyscanner);
112 yyextra->token = PreprocessorToken(yytext);
113 return yyextra->token.baseType;
114 }
115
116
117 /* Preprocessor statement: RESET_CONDITION(name) */
118
119 <*>"RESET_CONDITION"[ \t]*"(" {
120 //printf("RESET_CONDITION\n");
121 yy_push_state(PREPROC_RESET_COND, yyscanner);
122 yyextra->token = PreprocessorToken(yytext);
123 return yyextra->token.baseType;
124 }
125 <PREPROC_RESET_COND>{ID} {
126 //printf("preproc reset condition '%s'\n", yytext);
127 yyextra->token = PreprocessorToken(yytext);
128 return yyextra->token.baseType;
129 }
130 <PREPROC_RESET_COND>[ \t]*")" {
131 //printf("End of RESET_CONDITION\n");
132 yy_pop_state(yyscanner);
133 yyextra->token = PreprocessorToken(yytext);
134 return yyextra->token.baseType;
135 }
136
137
138 /* Preprocessor conditional statements:
139
140 USE_CODE_IF(name)
141 ...
142 END_USE_CODE
143
144 and:
145
146 USE_CODE_IF_NOT(name)
147 ...
148 END_USE_CODE
149 */
150
151 <*>"USE_CODE_IF"[ \t]*"(" {
152 //printf("USE_CODE_IF\n");
153 yy_push_state(PREPROC_IF, yyscanner);
154 yyextra->token = PreprocessorToken(yytext);
155 return yyextra->token.baseType;
156 }
157 <*>"USE_CODE_IF_NOT"[ \t]*"(" {
158 //printf("USE_CODE_IF_NOT\n");
159 yy_push_state(PREPROC_IF_NOT, yyscanner);
160 yyextra->token = PreprocessorToken(yytext);
161 return yyextra->token.baseType;
162 }
163 <PREPROC_IF>{ID} {
164 //printf("preproc use code if '%s'\n", yytext);
165 yy_pop_state(yyscanner);
166 yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
167 //yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
168 yyextra->token = PreprocessorToken(yytext);
169 return yyextra->token.baseType;
170 }
171 <PREPROC_IF_NOT>{ID} {
172 //printf("preproc use code if not '%s'\n", yytext);
173 yy_pop_state(yyscanner);
174 yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
175 //yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
176 yyextra->token = PreprocessorToken(yytext);
177 return yyextra->token.baseType;
178 }
179 <PREPROC_PRE_BODY_USE>[ \t]*")" {
180 yy_pop_state(yyscanner);
181 yy_push_state(PREPROC_BODY_USE, yyscanner);
182 yyextra->token = PreprocessorToken(yytext);
183 return yyextra->token.baseType;
184 }
185 <PREPROC_PRE_BODY_EAT>[ \t]*")" {
186 //printf("PREPROCESSOR EAT : \n");
187 yy_pop_state(yyscanner);
188 yy_push_state(PREPROC_BODY_EAT, yyscanner);
189 yyextra->token = PreprocessorToken(yytext);
190 return yyextra->token.baseType;
191 }
192 <*>.*"END_USE_CODE" {
193 //printf("-->END_USE_CODE\n");
194 yy_pop_state(yyscanner);
195 yyextra->token = PreprocessorToken(yytext);
196 return yyextra->token.baseType;
197 }
198 <PREPROC_BODY_EAT>[ \t\r\n]* /* eat up code block filtered out by preprocessor */
199 <PREPROC_BODY_EAT>.* /* eat up code block filtered out by preprocessor */
200
201
202 /* Event Handler Names (only if they occur alone in a document!) */
203
204 ^\s*(init|note|release|controller) {
205 yyextra->token = EventHandlerNameToken(yytext);
206 return yyextra->token.baseType;
207 }
208
209
210 /* Language keywords */
211
212 on {
213 yy_push_state(PREPROC_EVENT_NAME, yyscanner);
214 yyextra->token = KeywordToken(yytext);
215 return yyextra->token.baseType;
216 }
217
218 <PREPROC_EVENT_NAME>[ \t]*{ID} {
219 yy_pop_state(yyscanner);
220 yyextra->token = EventHandlerNameToken(yytext);
221 return yyextra->token.baseType;
222 }
223
224 end {
225 yy_push_state(PREPROC_END_NAME, yyscanner);
226 yyextra->token = KeywordToken(yytext);
227 return yyextra->token.baseType;
228 }
229
230 <PREPROC_END_NAME>[ \t]*{END_ID}? {
231 yy_pop_state(yyscanner);
232 yyextra->token = KeywordToken(yytext);
233 return yyextra->token.baseType;
234 }
235
236 ".or."|".and."|".not." {
237 yyextra->token = KeywordToken(yytext);
238 return yyextra->token.baseType;
239 }
240
241 declare|while|if|or|and|not|else|case|select|to|mod|const|polyphonic|function|call|synchronized {
242 yyextra->token = KeywordToken(yytext);
243 return yyextra->token.baseType;
244 }
245
246
247 /* Variables */
248
249 "$"{ID} {
250 yyextra->token = IntegerVariableToken(yytext);
251 return yyextra->token.baseType;
252 }
253
254 "@"{ID} {
255 yyextra->token = StringVariableToken(yytext);
256 return yyextra->token.baseType;
257 }
258
259 "%"{ID} {
260 yyextra->token = ArrayVariableToken(yytext);
261 return yyextra->token.baseType;
262 }
263
264 {ID} {
265 yyextra->token = IdentifierToken(yytext);
266 return yyextra->token.baseType;
267 }
268
269
270 /* other */
271
272 <*>\n {
273 yyextra->token = NewLineToken();
274 ++yylineno;
275 yycolumn = 0;
276 return yyextra->token.baseType;
277 }
278
279 "{"[^}]*"}" {
280 yyextra->token = CommentToken(yytext);
281 yylineno += countNewLineChars(yytext);
282 return yyextra->token.baseType;
283 }
284
285 <*>\t {
286 yyextra->token = OtherToken(" ");
287 return yyextra->token.baseType;
288 }
289
290 \r+ /* eat up \r */
291
292 <<EOF>> {
293 yyextra->token = EofToken();
294 yyterminate();
295 }
296
297 <*>. {
298 yyextra->token = OtherToken(yytext);
299 return yyextra->token.baseType;
300 }
301
302
303 %%
304
305 namespace LinuxSampler {
306
307 int NkspScanner::processScanner() {
308 return Nksp_lex(scanner);
309 }
310
311 void NkspScanner::createScanner(std::istream* is) {
312 if (scanner) destroyScanner();
313 this->is = is;
314 Nksp_lex_init(&scanner);
315 Nksp_set_extra(this, scanner);
316 }
317
318 void NkspScanner::destroyScanner() {
319 if (!scanner) return;
320 Nksp_lex_destroy(scanner);
321 scanner = NULL;
322 }
323
324 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC