/[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 3733 - (show annotations) (download)
Sat Feb 1 18:11:20 2020 UTC (4 years, 1 month ago) by schoenebeck
File size: 9353 byte(s)
NKSP: Added support for 'patch' variables.

* NKSP language: Added support for 'patch' variable qualifier
  (as new dedicated keyword 'patch').

* NKSP parser: capture locations of 'patch' variable declarations
  in script's source code.

* ScriptVM: Allow patching 'patch' script variables by replacing
  their default assignment expression with a supplied replacement
  variable initialization expression by optional 2nd argument when
  calling loadScript().

* ScriptVM: Allow retrieval of default initialization expressions
  of all 'patch' variables by optional 3rd argument when calling
  loadScript() (i.e. for instrument editors).

* gig engine: Implemented support for loading real-time instrument
  scripts with 'patch' variables bundled with gig instruments.

* Bumped version (2.1.1.svn46).


1 /*
2 * Copyright (c) 2015-2020 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 yyextra->offset += (int) yyleng; \
35 yyextra->length = (int) yyleng; \
36 yycolumn += yyleng;
37
38 using namespace LinuxSampler;
39
40 static int countNewLineChars(const char* txt) {
41 int n = 0;
42 for (int i = 0; txt[i]; ++i)
43 if (txt[i] == '\n') ++n;
44 return n;
45 }
46
47 // shut up warning that 'register' keyword is deprecated as of C++11
48 #if defined(__cplusplus) && __cplusplus >= 201103L
49 # define register
50 #endif
51
52 // Since this parser is solely used by script code editors, thus not used in a
53 // real-time context, always throw an exception instead of exiting on fatal
54 // lexer errors (so the debugger may pause with the appropriate back trace)
55 #include <stdexcept>
56 #define YY_FATAL_ERROR(msg) throw std::runtime_error(msg)
57
58 %}
59
60 /* generate a reentrant safe scanner */
61 %option reentrant
62 /* avoid symbol collision with ones of other scanners */
63 %option prefix="Nksp_"
64 /* yywrap() would be called at EOF, we don't need it */
65 %option noyywrap
66 /* enable functions yy_push_state(), yy_pop_state(), yy_top_state() */
67 %option stack
68
69 /* inclusive scanner conditions */
70 %s PREPROC_BODY_USE
71 /* exclusive scanner conditions */
72 %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 METRIC UNIT
73
74 DIGIT [0-9]
75 ID [a-zA-Z][a-zA-Z0-9_]*
76 METRIC (k|h|(da)|d|c|m|u)
77 UNIT (s|(Hz)|B)
78 END_ID on|while|if|select|function|synchronized
79
80 %%
81
82 \"[^"]*\" {
83 yyextra->token = StringLiteralToken(yytext);
84 return yyextra->token.baseType;
85 }
86
87 {DIGIT}+("."{DIGIT}+)? {
88 yyextra->token = NumberLiteralToken(yytext);
89 return yyextra->token.baseType;
90 }
91
92 {DIGIT}+("."{DIGIT}+)?/{METRIC}{1,2} {
93 yy_push_state(METRIC, yyscanner);
94 yyextra->token = NumberLiteralToken(yytext);
95 return yyextra->token.baseType;
96 }
97
98 {DIGIT}+("."{DIGIT}+)?/{UNIT} {
99 yy_push_state(UNIT, yyscanner);
100 yyextra->token = NumberLiteralToken(yytext);
101 return yyextra->token.baseType;
102 }
103
104 <METRIC>{METRIC}{1,2} {
105 yyextra->token = MetricPrefixToken(yytext);
106 yy_pop_state(yyscanner);
107 return yyextra->token.baseType;
108 }
109
110 <METRIC>{METRIC}{1,2}/{UNIT} {
111 yyextra->token = MetricPrefixToken(yytext);
112 yy_pop_state(yyscanner);
113 yy_push_state(UNIT, yyscanner);
114 return yyextra->token.baseType;
115 }
116
117 <UNIT>{UNIT} {
118 yyextra->token = StdUnitToken(yytext);
119 yy_pop_state(yyscanner);
120 return yyextra->token.baseType;
121 }
122
123
124 /* Preprocessor statement: SET_CONDITION(name) */
125
126 <*>"SET_CONDITION"[ \t]*"(" {
127 //printf("SET_CONDITION\n");
128 yy_push_state(PREPROC_SET_COND, yyscanner);
129 yyextra->token = PreprocessorToken(yytext);
130 return yyextra->token.baseType;
131 }
132 <PREPROC_SET_COND>{ID} {
133 //printf("preproc set condition '%s'\n", yytext);
134 yyextra->token = PreprocessorToken(yytext);
135 return yyextra->token.baseType;
136 }
137 <PREPROC_SET_COND>[ \t]*")" {
138 //printf("End of PREPROC_SET_COND\n");
139 yy_pop_state(yyscanner);
140 yyextra->token = PreprocessorToken(yytext);
141 return yyextra->token.baseType;
142 }
143
144
145 /* Preprocessor statement: RESET_CONDITION(name) */
146
147 <*>"RESET_CONDITION"[ \t]*"(" {
148 //printf("RESET_CONDITION\n");
149 yy_push_state(PREPROC_RESET_COND, yyscanner);
150 yyextra->token = PreprocessorToken(yytext);
151 return yyextra->token.baseType;
152 }
153 <PREPROC_RESET_COND>{ID} {
154 //printf("preproc reset condition '%s'\n", yytext);
155 yyextra->token = PreprocessorToken(yytext);
156 return yyextra->token.baseType;
157 }
158 <PREPROC_RESET_COND>[ \t]*")" {
159 //printf("End of RESET_CONDITION\n");
160 yy_pop_state(yyscanner);
161 yyextra->token = PreprocessorToken(yytext);
162 return yyextra->token.baseType;
163 }
164
165
166 /* Preprocessor conditional statements:
167
168 USE_CODE_IF(name)
169 ...
170 END_USE_CODE
171
172 and:
173
174 USE_CODE_IF_NOT(name)
175 ...
176 END_USE_CODE
177 */
178
179 <*>"USE_CODE_IF"[ \t]*"(" {
180 //printf("USE_CODE_IF\n");
181 yy_push_state(PREPROC_IF, yyscanner);
182 yyextra->token = PreprocessorToken(yytext);
183 return yyextra->token.baseType;
184 }
185 <*>"USE_CODE_IF_NOT"[ \t]*"(" {
186 //printf("USE_CODE_IF_NOT\n");
187 yy_push_state(PREPROC_IF_NOT, yyscanner);
188 yyextra->token = PreprocessorToken(yytext);
189 return yyextra->token.baseType;
190 }
191 <PREPROC_IF>{ID} {
192 //printf("preproc use code if '%s'\n", yytext);
193 yy_pop_state(yyscanner);
194 yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
195 //yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
196 yyextra->token = PreprocessorToken(yytext);
197 return yyextra->token.baseType;
198 }
199 <PREPROC_IF_NOT>{ID} {
200 //printf("preproc use code if not '%s'\n", yytext);
201 yy_pop_state(yyscanner);
202 yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
203 //yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
204 yyextra->token = PreprocessorToken(yytext);
205 return yyextra->token.baseType;
206 }
207 <PREPROC_PRE_BODY_USE>[ \t]*")" {
208 yy_pop_state(yyscanner);
209 yy_push_state(PREPROC_BODY_USE, yyscanner);
210 yyextra->token = PreprocessorToken(yytext);
211 return yyextra->token.baseType;
212 }
213 <PREPROC_PRE_BODY_EAT>[ \t]*")" {
214 //printf("PREPROCESSOR EAT : \n");
215 yy_pop_state(yyscanner);
216 yy_push_state(PREPROC_BODY_EAT, yyscanner);
217 yyextra->token = PreprocessorToken(yytext);
218 return yyextra->token.baseType;
219 }
220 <*>.*"END_USE_CODE" {
221 //printf("-->END_USE_CODE\n");
222 yy_pop_state(yyscanner);
223 yyextra->token = PreprocessorToken(yytext);
224 return yyextra->token.baseType;
225 }
226 <PREPROC_BODY_EAT>[ \t\r\n]* /* eat up code block filtered out by preprocessor */
227 <PREPROC_BODY_EAT>.* /* eat up code block filtered out by preprocessor */
228
229
230 /* Event Handler Names (only if they occur alone in a document!) */
231
232 ^\s*(init|note|release|controller|rpn|nrpn) {
233 yyextra->token = EventHandlerNameToken(yytext);
234 return yyextra->token.baseType;
235 }
236
237
238 /* Language keywords */
239
240 on {
241 yy_push_state(PREPROC_EVENT_NAME, yyscanner);
242 yyextra->token = KeywordToken(yytext);
243 return yyextra->token.baseType;
244 }
245
246 <PREPROC_EVENT_NAME>[ \t]*{ID} {
247 yy_pop_state(yyscanner);
248 yyextra->token = EventHandlerNameToken(yytext);
249 return yyextra->token.baseType;
250 }
251
252 end {
253 yy_push_state(PREPROC_END_NAME, yyscanner);
254 yyextra->token = KeywordToken(yytext);
255 return yyextra->token.baseType;
256 }
257
258 <PREPROC_END_NAME>[ \t]*{END_ID}? {
259 yy_pop_state(yyscanner);
260 yyextra->token = KeywordToken(yytext);
261 return yyextra->token.baseType;
262 }
263
264 ".or."|".and."|".not." {
265 yyextra->token = KeywordToken(yytext);
266 return yyextra->token.baseType;
267 }
268
269 declare|while|if|or|and|not|else|case|select|to|mod|const|polyphonic|function|call|synchronized|patch {
270 yyextra->token = KeywordToken(yytext);
271 return yyextra->token.baseType;
272 }
273
274
275 /* Variables */
276
277 "$"{ID} {
278 yyextra->token = IntegerVariableToken(yytext);
279 return yyextra->token.baseType;
280 }
281
282 "~"{ID} {
283 yyextra->token = RealVariableToken(yytext);
284 return yyextra->token.baseType;
285 }
286
287 "@"{ID} {
288 yyextra->token = StringVariableToken(yytext);
289 return yyextra->token.baseType;
290 }
291
292 "%"{ID} {
293 yyextra->token = IntegerArrayVariableToken(yytext);
294 return yyextra->token.baseType;
295 }
296
297 "?"{ID} {
298 yyextra->token = RealArrayVariableToken(yytext);
299 return yyextra->token.baseType;
300 }
301
302 {ID} {
303 yyextra->token = IdentifierToken(yytext);
304 return yyextra->token.baseType;
305 }
306
307
308 /* other */
309
310 <*>\n {
311 yyextra->token = NewLineToken();
312 ++yylineno;
313 yycolumn = 0;
314 return yyextra->token.baseType;
315 }
316
317 "{"[^}]*"}" {
318 yyextra->token = CommentToken(yytext);
319 yylineno += countNewLineChars(yytext);
320 return yyextra->token.baseType;
321 }
322
323 <*>\t {
324 yyextra->token = OtherToken(" ");
325 return yyextra->token.baseType;
326 }
327
328 \r+ /* eat up \r */
329
330 <<EOF>> {
331 yyextra->token = EofToken();
332 yyterminate();
333 }
334
335 <*>. {
336 yyextra->token = OtherToken(yytext);
337 return yyextra->token.baseType;
338 }
339
340
341 %%
342
343 namespace LinuxSampler {
344
345 int NkspScanner::processScanner() {
346 return Nksp_lex(scanner);
347 }
348
349 void NkspScanner::createScanner(std::istream* is) {
350 if (scanner) destroyScanner();
351 this->is = is;
352 Nksp_lex_init(&scanner);
353 Nksp_set_extra(this, scanner);
354 }
355
356 void NkspScanner::destroyScanner() {
357 if (!scanner) return;
358 Nksp_lex_destroy(scanner);
359 scanner = NULL;
360 }
361
362 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC