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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3733 - (hide annotations) (download)
Sat Feb 1 18:11:20 2020 UTC (4 years, 2 months 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 schoenebeck 2885 /*
2 schoenebeck 3690 * Copyright (c) 2015-2020 Christian Schoenebeck
3 schoenebeck 2885 *
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 schoenebeck 3729 yyextra->offset += (int) yyleng; \
35     yyextra->length = (int) yyleng; \
36 schoenebeck 2885 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 schoenebeck 3054 // 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 schoenebeck 3332 // 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 schoenebeck 3308 // lexer errors (so the debugger may pause with the appropriate back trace)
55 schoenebeck 3332 #include <stdexcept>
56     #define YY_FATAL_ERROR(msg) throw std::runtime_error(msg)
57 schoenebeck 3308
58 schoenebeck 2885 %}
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 schoenebeck 3562 %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 schoenebeck 2885
74     DIGIT [0-9]
75 schoenebeck 3561 ID [a-zA-Z][a-zA-Z0-9_]*
76 schoenebeck 3591 METRIC (k|h|(da)|d|c|m|u)
77     UNIT (s|(Hz)|B)
78 schoenebeck 3308 END_ID on|while|if|select|function|synchronized
79 schoenebeck 2885
80     %%
81    
82     \"[^"]*\" {
83     yyextra->token = StringLiteralToken(yytext);
84     return yyextra->token.baseType;
85     }
86    
87 schoenebeck 3573 {DIGIT}+("."{DIGIT}+)? {
88 schoenebeck 2885 yyextra->token = NumberLiteralToken(yytext);
89     return yyextra->token.baseType;
90     }
91    
92 schoenebeck 3573 {DIGIT}+("."{DIGIT}+)?/{METRIC}{1,2} {
93 schoenebeck 3562 yy_push_state(METRIC, yyscanner);
94 schoenebeck 3561 yyextra->token = NumberLiteralToken(yytext);
95     return yyextra->token.baseType;
96     }
97    
98 schoenebeck 3573 {DIGIT}+("."{DIGIT}+)?/{UNIT} {
99 schoenebeck 3562 yy_push_state(UNIT, yyscanner);
100     yyextra->token = NumberLiteralToken(yytext);
101     return yyextra->token.baseType;
102     }
103    
104     <METRIC>{METRIC}{1,2} {
105 schoenebeck 3591 yyextra->token = MetricPrefixToken(yytext);
106 schoenebeck 3562 yy_pop_state(yyscanner);
107     return yyextra->token.baseType;
108     }
109    
110     <METRIC>{METRIC}{1,2}/{UNIT} {
111 schoenebeck 3591 yyextra->token = MetricPrefixToken(yytext);
112 schoenebeck 3562 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 schoenebeck 2885
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 schoenebeck 3690 ^\s*(init|note|release|controller|rpn|nrpn) {
233 schoenebeck 2885 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 schoenebeck 3308 <PREPROC_END_NAME>[ \t]*{END_ID}? {
259 schoenebeck 2885 yy_pop_state(yyscanner);
260     yyextra->token = KeywordToken(yytext);
261     return yyextra->token.baseType;
262     }
263    
264 schoenebeck 2935 ".or."|".and."|".not." {
265     yyextra->token = KeywordToken(yytext);
266     return yyextra->token.baseType;
267     }
268    
269 schoenebeck 3733 declare|while|if|or|and|not|else|case|select|to|mod|const|polyphonic|function|call|synchronized|patch {
270 schoenebeck 2885 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 schoenebeck 3573 "~"{ID} {
283     yyextra->token = RealVariableToken(yytext);
284     return yyextra->token.baseType;
285     }
286    
287 schoenebeck 2885 "@"{ID} {
288     yyextra->token = StringVariableToken(yytext);
289     return yyextra->token.baseType;
290     }
291    
292     "%"{ID} {
293 schoenebeck 3573 yyextra->token = IntegerArrayVariableToken(yytext);
294 schoenebeck 2885 return yyextra->token.baseType;
295     }
296    
297 schoenebeck 3573 "?"{ID} {
298     yyextra->token = RealArrayVariableToken(yytext);
299     return yyextra->token.baseType;
300     }
301    
302 schoenebeck 2885 {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