/[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 3573 - (hide annotations) (download)
Tue Aug 27 21:36:53 2019 UTC (4 years, 7 months ago) by schoenebeck
File size: 9256 byte(s)
NKSP: Introducing floating point support.

* NKSP language: Added support for NKSP real number literals and
  arithmetic operations on them (e.g. "(3.9 + 2.9) / 12.3 - 42.0").

* NKSP language: Added support for NKSP real number (floating point)
  script variables (declare ~foo := 3.4).

* NKSP language: Added support for NKSP real number (floating point)
  array script variables (declare ?foo[3] := ( 1.1, 2.7, 49.0 )).

* NKSP built-in script function "message()" accepts now real number
  argument as well.

* Added built-in NKSP script function "real_to_int()" and its short
  hand form "int()" for casting from real number to integer in NKSP
  scripts.

* Added built-in NKSP script function "int_to_real()" and its short
  hand form "real()" for casting from integer to real number in NKSP
  scripts.

* Bumped version (2.1.1.svn6).

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 schoenebeck 3573 {DIGIT}+("."{DIGIT}+)? {
86 schoenebeck 2885 yyextra->token = NumberLiteralToken(yytext);
87     return yyextra->token.baseType;
88     }
89    
90 schoenebeck 3573 {DIGIT}+("."{DIGIT}+)?/{METRIC}{1,2} {
91 schoenebeck 3562 yy_push_state(METRIC, yyscanner);
92 schoenebeck 3561 yyextra->token = NumberLiteralToken(yytext);
93     return yyextra->token.baseType;
94     }
95    
96 schoenebeck 3573 {DIGIT}+("."{DIGIT}+)?/{UNIT} {
97 schoenebeck 3562 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 2885
122     /* Preprocessor statement: SET_CONDITION(name) */
123    
124     <*>"SET_CONDITION"[ \t]*"(" {
125     //printf("SET_CONDITION\n");
126     yy_push_state(PREPROC_SET_COND, yyscanner);
127     yyextra->token = PreprocessorToken(yytext);
128     return yyextra->token.baseType;
129     }
130     <PREPROC_SET_COND>{ID} {
131     //printf("preproc set condition '%s'\n", yytext);
132     yyextra->token = PreprocessorToken(yytext);
133     return yyextra->token.baseType;
134     }
135     <PREPROC_SET_COND>[ \t]*")" {
136     //printf("End of PREPROC_SET_COND\n");
137     yy_pop_state(yyscanner);
138     yyextra->token = PreprocessorToken(yytext);
139     return yyextra->token.baseType;
140     }
141    
142    
143     /* Preprocessor statement: RESET_CONDITION(name) */
144    
145     <*>"RESET_CONDITION"[ \t]*"(" {
146     //printf("RESET_CONDITION\n");
147     yy_push_state(PREPROC_RESET_COND, yyscanner);
148     yyextra->token = PreprocessorToken(yytext);
149     return yyextra->token.baseType;
150     }
151     <PREPROC_RESET_COND>{ID} {
152     //printf("preproc reset condition '%s'\n", yytext);
153     yyextra->token = PreprocessorToken(yytext);
154     return yyextra->token.baseType;
155     }
156     <PREPROC_RESET_COND>[ \t]*")" {
157     //printf("End of RESET_CONDITION\n");
158     yy_pop_state(yyscanner);
159     yyextra->token = PreprocessorToken(yytext);
160     return yyextra->token.baseType;
161     }
162    
163    
164     /* Preprocessor conditional statements:
165    
166     USE_CODE_IF(name)
167     ...
168     END_USE_CODE
169    
170     and:
171    
172     USE_CODE_IF_NOT(name)
173     ...
174     END_USE_CODE
175     */
176    
177     <*>"USE_CODE_IF"[ \t]*"(" {
178     //printf("USE_CODE_IF\n");
179     yy_push_state(PREPROC_IF, yyscanner);
180     yyextra->token = PreprocessorToken(yytext);
181     return yyextra->token.baseType;
182     }
183     <*>"USE_CODE_IF_NOT"[ \t]*"(" {
184     //printf("USE_CODE_IF_NOT\n");
185     yy_push_state(PREPROC_IF_NOT, yyscanner);
186     yyextra->token = PreprocessorToken(yytext);
187     return yyextra->token.baseType;
188     }
189     <PREPROC_IF>{ID} {
190     //printf("preproc use code if '%s'\n", yytext);
191     yy_pop_state(yyscanner);
192     yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
193     //yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
194     yyextra->token = PreprocessorToken(yytext);
195     return yyextra->token.baseType;
196     }
197     <PREPROC_IF_NOT>{ID} {
198     //printf("preproc use code if not '%s'\n", yytext);
199     yy_pop_state(yyscanner);
200     yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
201     //yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
202     yyextra->token = PreprocessorToken(yytext);
203     return yyextra->token.baseType;
204     }
205     <PREPROC_PRE_BODY_USE>[ \t]*")" {
206     yy_pop_state(yyscanner);
207     yy_push_state(PREPROC_BODY_USE, yyscanner);
208     yyextra->token = PreprocessorToken(yytext);
209     return yyextra->token.baseType;
210     }
211     <PREPROC_PRE_BODY_EAT>[ \t]*")" {
212     //printf("PREPROCESSOR EAT : \n");
213     yy_pop_state(yyscanner);
214     yy_push_state(PREPROC_BODY_EAT, yyscanner);
215     yyextra->token = PreprocessorToken(yytext);
216     return yyextra->token.baseType;
217     }
218     <*>.*"END_USE_CODE" {
219     //printf("-->END_USE_CODE\n");
220     yy_pop_state(yyscanner);
221     yyextra->token = PreprocessorToken(yytext);
222     return yyextra->token.baseType;
223     }
224     <PREPROC_BODY_EAT>[ \t\r\n]* /* eat up code block filtered out by preprocessor */
225     <PREPROC_BODY_EAT>.* /* eat up code block filtered out by preprocessor */
226    
227    
228     /* Event Handler Names (only if they occur alone in a document!) */
229    
230     ^\s*(init|note|release|controller) {
231     yyextra->token = EventHandlerNameToken(yytext);
232     return yyextra->token.baseType;
233     }
234    
235    
236     /* Language keywords */
237    
238     on {
239     yy_push_state(PREPROC_EVENT_NAME, yyscanner);
240     yyextra->token = KeywordToken(yytext);
241     return yyextra->token.baseType;
242     }
243    
244     <PREPROC_EVENT_NAME>[ \t]*{ID} {
245     yy_pop_state(yyscanner);
246     yyextra->token = EventHandlerNameToken(yytext);
247     return yyextra->token.baseType;
248     }
249    
250     end {
251     yy_push_state(PREPROC_END_NAME, yyscanner);
252     yyextra->token = KeywordToken(yytext);
253     return yyextra->token.baseType;
254     }
255    
256 schoenebeck 3308 <PREPROC_END_NAME>[ \t]*{END_ID}? {
257 schoenebeck 2885 yy_pop_state(yyscanner);
258     yyextra->token = KeywordToken(yytext);
259     return yyextra->token.baseType;
260     }
261    
262 schoenebeck 2935 ".or."|".and."|".not." {
263     yyextra->token = KeywordToken(yytext);
264     return yyextra->token.baseType;
265     }
266    
267 schoenebeck 3260 declare|while|if|or|and|not|else|case|select|to|mod|const|polyphonic|function|call|synchronized {
268 schoenebeck 2885 yyextra->token = KeywordToken(yytext);
269     return yyextra->token.baseType;
270     }
271    
272    
273     /* Variables */
274    
275     "$"{ID} {
276     yyextra->token = IntegerVariableToken(yytext);
277     return yyextra->token.baseType;
278     }
279    
280 schoenebeck 3573 "~"{ID} {
281     yyextra->token = RealVariableToken(yytext);
282     return yyextra->token.baseType;
283     }
284    
285 schoenebeck 2885 "@"{ID} {
286     yyextra->token = StringVariableToken(yytext);
287     return yyextra->token.baseType;
288     }
289    
290     "%"{ID} {
291 schoenebeck 3573 yyextra->token = IntegerArrayVariableToken(yytext);
292 schoenebeck 2885 return yyextra->token.baseType;
293     }
294    
295 schoenebeck 3573 "?"{ID} {
296     yyextra->token = RealArrayVariableToken(yytext);
297     return yyextra->token.baseType;
298     }
299    
300 schoenebeck 2885 {ID} {
301     yyextra->token = IdentifierToken(yytext);
302     return yyextra->token.baseType;
303     }
304    
305    
306     /* other */
307    
308     <*>\n {
309     yyextra->token = NewLineToken();
310     ++yylineno;
311     yycolumn = 0;
312     return yyextra->token.baseType;
313     }
314    
315     "{"[^}]*"}" {
316     yyextra->token = CommentToken(yytext);
317     yylineno += countNewLineChars(yytext);
318     return yyextra->token.baseType;
319     }
320    
321     <*>\t {
322     yyextra->token = OtherToken(" ");
323     return yyextra->token.baseType;
324     }
325    
326     \r+ /* eat up \r */
327    
328     <<EOF>> {
329     yyextra->token = EofToken();
330     yyterminate();
331     }
332    
333     <*>. {
334     yyextra->token = OtherToken(yytext);
335     return yyextra->token.baseType;
336     }
337    
338    
339     %%
340    
341     namespace LinuxSampler {
342    
343     int NkspScanner::processScanner() {
344     return Nksp_lex(scanner);
345     }
346    
347     void NkspScanner::createScanner(std::istream* is) {
348     if (scanner) destroyScanner();
349     this->is = is;
350     Nksp_lex_init(&scanner);
351     Nksp_set_extra(this, scanner);
352     }
353    
354     void NkspScanner::destroyScanner() {
355     if (!scanner) return;
356     Nksp_lex_destroy(scanner);
357     scanner = NULL;
358     }
359    
360     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC