/[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 2942 - (show annotations) (download)
Wed Jul 13 15:51:06 2016 UTC (2 years, 11 months ago) by schoenebeck
File size: 7821 byte(s)
* NKSP: Implemented built-in script variable "$KSP_TIMER".
* NKSP: Implemented built-in script variable "$NKSP_REAL_TIMER".
* NKSP: Implemented built-in script variable "$NKSP_PERF_TIMER".
* NKSP: Implemented built-in script variable "$ENGINE_UPTIME".
* Bumped version (2.0.0.svn14).

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

  ViewVC Help
Powered by ViewVC