/[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 3308 - (hide 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 schoenebeck 2885 /*
2 schoenebeck 3260 * Copyright (c) 2015-2017 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 3308 // 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 schoenebeck 2885 %}
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 schoenebeck 2935 ID [a-zA-Z0-9_]+
75 schoenebeck 3308 END_ID on|while|if|select|function|synchronized
76 schoenebeck 2885
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 schoenebeck 2935 /* there is currently no support for floating point numbers in NKSP yet */
90     /*{DIGIT}+"."{DIGIT}* {
91 schoenebeck 2885 yyextra->token = NumberLiteralToken(yytext);
92     return yyextra->token.baseType;
93 schoenebeck 2935 }*/
94 schoenebeck 2885
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 schoenebeck 3308 <PREPROC_END_NAME>[ \t]*{END_ID}? {
231 schoenebeck 2885 yy_pop_state(yyscanner);
232     yyextra->token = KeywordToken(yytext);
233     return yyextra->token.baseType;
234     }
235    
236 schoenebeck 2935 ".or."|".and."|".not." {
237     yyextra->token = KeywordToken(yytext);
238     return yyextra->token.baseType;
239     }
240    
241 schoenebeck 3260 declare|while|if|or|and|not|else|case|select|to|mod|const|polyphonic|function|call|synchronized {
242 schoenebeck 2885 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