/[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 3562 - (hide annotations) (download)
Fri Aug 23 12:51:58 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 9200 byte(s)
* NKSP script editor API: Added support for detecting standard unit tokens
  and their potential metric prefix token.

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

  ViewVC Help
Powered by ViewVC