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

Contents of /linuxsampler/trunk/src/scriptvm/scanner.l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3260 - (show annotations) (download)
Wed May 31 21:07:44 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 8089 byte(s)
* NKSP language: Added support for "synchronized .. end synchronized"
  code blocks.
* Bumped version (2.0.0.svn60).

1 /*
2 * Copyright (c) 2014-2017 Christian Schoenebeck and Andreas Persson
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 for NKSP real-time instrument script language. */
11
12 %{
13
14 #include "parser_shared.h"
15 #include <math.h>
16 // reentrant scanner data context
17 #define YY_EXTRA_TYPE ParserContext*
18 // set line number each time a token is recognized
19 #define YY_USER_ACTION \
20 { \
21 yylloc->first_line = yylineno; \
22 yylloc->last_line = yylineno; \
23 yylloc->first_column = yycolumn; \
24 yycolumn += yyleng; \
25 yylloc->last_column = yycolumn - 1; \
26 /*printf("lex: line '%s'\n", yytext);*/ \
27 }
28 // custom (f)lex input for reading from std::istream object
29 #define YY_INPUT(buf,result,max_size) \
30 { \
31 char c = yyextra->is->get(); \
32 if (yyextra->is->eof()) \
33 result = YY_NULL; \
34 else { \
35 buf[0] = c; \
36 result = 1; \
37 } \
38 }
39
40 static void scanner_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
41 context->addErr(locp->first_line, locp->last_line, locp->first_column, locp->last_column, err);
42 }
43
44 static void scanner_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
45 context->addWrn(locp->first_line, locp->last_line, locp->first_column, locp->last_column, txt);
46 }
47
48 #define SCANNER_ERR(txt) scanner_error(yylloc, yyextra, txt)
49 #define SCANNER_WRN(txt) scanner_warning(yylloc, yyextra, txt)
50
51 // shut up warning that 'register' keyword is deprecated as of C++11
52 #if defined(__cplusplus) && __cplusplus >= 201103L
53 # define register
54 #endif
55
56 using namespace LinuxSampler;
57
58 static int countNewLineChars(const char* txt) {
59 int n = 0;
60 for (int i = 0; txt[i]; ++i)
61 if (txt[i] == '\n') ++n;
62 return n;
63 }
64
65 static int countCharsPastLastNewLine(const char* txt) {
66 const int n = (int)strlen(txt);
67 for (int i = n - 1; i >= 0; --i)
68 if (txt[i] == '\n')
69 return n - i - 1;
70 return n;
71 }
72
73 #define processLocation() { \
74 const int nl = countNewLineChars(yytext); \
75 yylineno += nl; \
76 if (nl) yycolumn = countCharsPastLastNewLine(yytext); \
77 }
78
79 %}
80
81 /* use Flex's built-in support for line numbers
82 (disabled, because it seems to be unreliable, so we are using our own
83 tracking code in the respective scanner rules below) */
84 /*%option yylineno*/
85 /* generate a reentrant safe scanner */
86 %option reentrant
87 /* avoid symbol collision with other (i.e. future) scanner symbols */
88 %option prefix="InstrScript_"
89 /* bison-bridge adds an argument yylval to yylex, and bison-locations adds an
90 argument code yylloc for location tracking. */
91 %option bison-bridge
92 %option bison-locations
93 /* yywrap() would be called at EOF, we don't need it */
94 %option noyywrap
95 /* enable functions yy_push_state(), yy_pop_state(), yy_top_state() */
96 %option stack
97
98 /* inclusive scanner conditions */
99 %s PREPROC_BODY_USE
100 /* exclusive scanner conditions */
101 %x PREPROC_SET_COND PREPROC_RESET_COND PREPROC_IF PREPROC_IF_NOT PREPROC_BODY_EAT PREPROC_PRE_BODY_USE PREPROC_PRE_BODY_EAT
102
103 DIGIT [0-9]
104 ID [a-zA-Z0-9_]+
105
106 %%
107
108 \"[^"]*\" {
109 yylval->sValue = strdup(yytext + 1);
110 yylval->sValue[strlen(yylval->sValue) - 1] = '\0';
111 return STRING;
112 }
113
114 {DIGIT}+ {
115 yylval->iValue = atoi(yytext);
116 return INTEGER;
117 }
118
119 /* there is currently no support for floating point numbers in NKSP yet */
120 /*{DIGIT}+"."{DIGIT}* {
121 printf("A float: %s (%g)\n", yytext, atof(yytext));
122 }*/
123
124
125 /* Preprocessor statement: SET_CONDITION(name) */
126
127 <*>"SET_CONDITION"[ \t]*"(" {
128 //printf("SET_CONDITION\n");
129 yy_push_state(PREPROC_SET_COND, yyscanner);
130 }
131 <PREPROC_SET_COND>{ID} {
132 //printf("preproc set condition '%s'\n", yytext);
133 bool success = yyextra->setPreprocessorCondition(yytext);
134 if (!success) {
135 SCANNER_WRN((String("Preprocessor: Condition '") +
136 yytext + "' is already set.").c_str());
137 }
138 }
139 <PREPROC_SET_COND>[ \t]*")" {
140 //printf("End of PREPROC_SET_COND\n");
141 yy_pop_state(yyscanner);
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 }
151 <PREPROC_RESET_COND>{ID} {
152 //printf("preproc reset condition '%s'\n", yytext);
153 bool success = yyextra->resetPreprocessorCondition(yytext);
154 if (!success) {
155 SCANNER_ERR((String("Preprocessor: could not reset condition '") +
156 yytext + "' (either not set or a built-in condition).").c_str());
157 }
158 }
159 <PREPROC_RESET_COND>[ \t]*")" {
160 //printf("End of RESET_CONDITION\n");
161 yy_pop_state(yyscanner);
162 }
163
164
165 /* Preprocessor conditional statements:
166
167 USE_CODE_IF(name)
168 ...
169 END_USE_CODE
170
171 and:
172
173 USE_CODE_IF_NOT(name)
174 ...
175 END_USE_CODE
176 */
177
178 <*>"USE_CODE_IF"[ \t]*"(" {
179 //printf("USE_CODE_IF\n");
180 yy_push_state(PREPROC_IF, yyscanner);
181 }
182 <*>"USE_CODE_IF_NOT"[ \t]*"(" {
183 //printf("USE_CODE_IF_NOT\n");
184 yy_push_state(PREPROC_IF_NOT, yyscanner);
185 }
186 <PREPROC_IF>{ID} {
187 //printf("preproc use code if '%s'\n", yytext);
188 yy_pop_state(yyscanner);
189 if (yyextra->isPreprocessorConditionSet(yytext))
190 yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
191 else
192 yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
193 }
194 <PREPROC_IF_NOT>{ID} {
195 //printf("preproc use code if not '%s'\n", yytext);
196 yy_pop_state(yyscanner);
197 if (!yyextra->isPreprocessorConditionSet(yytext))
198 yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
199 else
200 yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
201 }
202 <PREPROC_PRE_BODY_USE>[ \t]*")" {
203 yy_pop_state(yyscanner);
204 yy_push_state(PREPROC_BODY_USE, yyscanner);
205 }
206 <PREPROC_PRE_BODY_EAT>[ \t]*")" {
207 //printf("PREPROCESSOR EAT : \n");
208 yy_pop_state(yyscanner);
209 yy_push_state(PREPROC_BODY_EAT, yyscanner);
210 }
211 <*>.*"END_USE_CODE" {
212 //printf("-->END_USE_CODE\n");
213 yy_pop_state(yyscanner);
214 }
215 <PREPROC_BODY_EAT>[ \t\r\n]* { /* eat up code block filtered out by preprocessor */
216 processLocation();
217 }
218 <PREPROC_BODY_EAT>.* { /* eat up code block filtered out by preprocessor */
219 processLocation();
220 }
221
222
223 /* Language keywords */
224
225 "on" return ON;
226 "end" return END;
227 "note" return NOTE;
228 "init" return INIT;
229 "declare" return DECLARE;
230 "while" return WHILE;
231 "if" return IF;
232 ".or." return BITWISE_OR;
233 "or" return OR;
234 "release" return RELEASE;
235 ".and." return BITWISE_AND;
236 "and" return AND;
237 ".not." return BITWISE_NOT;
238 "not" return NOT;
239 "else" return ELSE;
240 "controller" return CONTROLLER;
241 "case" return CASE;
242 "select" return SELECT;
243 "to" return TO;
244 "<=" return LE;
245 ">=" return GE;
246 "const" return CONST_; // note: "CONST" is already defined for C/C++ compilers on Windows by default
247 "polyphonic" return POLYPHONIC;
248 "mod" return MOD;
249 "function" return FUNCTION;
250 "call" return CALL;
251 "synchronized" return SYNCHRONIZED;
252
253 [&,()[\]<>=*+#/-] {
254 return *yytext;
255 }
256
257 ("$"|"@"|"%"){ID} {
258 yylval->sValue = strdup(yytext);
259 return VARIABLE;
260 }
261
262 {ID} {
263 yylval->sValue = strdup(yytext);
264 return IDENTIFIER;
265 }
266
267 ":=" return ASSIGNMENT;
268
269 \n+ {
270 yylineno += countNewLineChars(yytext);
271 yycolumn = 0;
272 //printf("lex: new line %d\n", yylineno, yytext);
273 //return LF;
274 }
275
276 "{"[^}]*"}" { /* eat up comments */
277 processLocation();
278 }
279
280 [ \t\r]+ /* eat up whitespace */
281
282 . {
283 printf( "Unrecognized character: '%s' (line %d, column %d)\n", yytext, yylineno, yycolumn);
284 return UNKNOWN_CHAR;
285 }
286
287 %%
288
289 namespace LinuxSampler {
290
291 void ParserContext::createScanner(std::istream* is) {
292 if (scanner) destroyScanner();
293 this->is = is;
294 yylex_init(&scanner);
295 yyset_extra(this, scanner);
296 }
297
298 void ParserContext::destroyScanner() {
299 if (!scanner) return;
300 yylex_destroy(scanner);
301 scanner = NULL;
302 }
303
304 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC