/[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 3591 - (show annotations) (download)
Mon Sep 2 09:21:43 2019 UTC (4 months, 2 weeks ago) by schoenebeck
File size: 9260 byte(s)
NKSP editor API: Fixed parsing of metric prefix "da" and unit type "Hz".

1 /*
2 * Copyright (c) 2015-2019 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 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 // 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 // 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 // lexer errors (so the debugger may pause with the appropriate back trace)
53 #include <stdexcept>
54 #define YY_FATAL_ERROR(msg) throw std::runtime_error(msg)
55
56 %}
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 %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
72 DIGIT [0-9]
73 ID [a-zA-Z][a-zA-Z0-9_]*
74 METRIC (k|h|(da)|d|c|m|u)
75 UNIT (s|(Hz)|B)
76 END_ID on|while|if|select|function|synchronized
77
78 %%
79
80 \"[^"]*\" {
81 yyextra->token = StringLiteralToken(yytext);
82 return yyextra->token.baseType;
83 }
84
85 {DIGIT}+("."{DIGIT}+)? {
86 yyextra->token = NumberLiteralToken(yytext);
87 return yyextra->token.baseType;
88 }
89
90 {DIGIT}+("."{DIGIT}+)?/{METRIC}{1,2} {
91 yy_push_state(METRIC, yyscanner);
92 yyextra->token = NumberLiteralToken(yytext);
93 return yyextra->token.baseType;
94 }
95
96 {DIGIT}+("."{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 = MetricPrefixToken(yytext);
104 yy_pop_state(yyscanner);
105 return yyextra->token.baseType;
106 }
107
108 <METRIC>{METRIC}{1,2}/{UNIT} {
109 yyextra->token = MetricPrefixToken(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
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 <PREPROC_END_NAME>[ \t]*{END_ID}? {
257 yy_pop_state(yyscanner);
258 yyextra->token = KeywordToken(yytext);
259 return yyextra->token.baseType;
260 }
261
262 ".or."|".and."|".not." {
263 yyextra->token = KeywordToken(yytext);
264 return yyextra->token.baseType;
265 }
266
267 declare|while|if|or|and|not|else|case|select|to|mod|const|polyphonic|function|call|synchronized {
268 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 "~"{ID} {
281 yyextra->token = RealVariableToken(yytext);
282 return yyextra->token.baseType;
283 }
284
285 "@"{ID} {
286 yyextra->token = StringVariableToken(yytext);
287 return yyextra->token.baseType;
288 }
289
290 "%"{ID} {
291 yyextra->token = IntegerArrayVariableToken(yytext);
292 return yyextra->token.baseType;
293 }
294
295 "?"{ID} {
296 yyextra->token = RealArrayVariableToken(yytext);
297 return yyextra->token.baseType;
298 }
299
300 {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