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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3054 - (hide annotations) (download)
Thu Dec 15 12:47:45 2016 UTC (7 years, 3 months ago) by schoenebeck
File size: 8020 byte(s)
* Fixed numerous compiler warnings.
* Bumped version (2.0.0.svn32).

1 schoenebeck 2581 /*
2 schoenebeck 2888 * Copyright (c) 2014-2016 Christian Schoenebeck and Andreas Persson
3 schoenebeck 2581 *
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 schoenebeck 2888 /* Token scanner for NKSP real-time instrument script language. */
11 schoenebeck 2581
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 schoenebeck 2888 yylloc->first_column = yycolumn; \
24     yycolumn += yyleng; \
25     yylloc->last_column = yycolumn - 1; \
26 schoenebeck 2581 /*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 schoenebeck 2889 context->addErr(locp->first_line, locp->last_line, locp->first_column, locp->last_column, err);
42 schoenebeck 2581 }
43    
44     static void scanner_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
45 schoenebeck 2889 context->addWrn(locp->first_line, locp->last_line, locp->first_column, locp->last_column, txt);
46 schoenebeck 2581 }
47    
48     #define SCANNER_ERR(txt) scanner_error(yylloc, yyextra, txt)
49     #define SCANNER_WRN(txt) scanner_warning(yylloc, yyextra, txt)
50    
51 schoenebeck 3054 // 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 schoenebeck 2581 using namespace LinuxSampler;
57    
58 schoenebeck 2888 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 schoenebeck 3054 const int n = (int)strlen(txt);
67 schoenebeck 2888 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 schoenebeck 2581 %}
80    
81 schoenebeck 2888 /* 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 schoenebeck 2581 /* 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 schoenebeck 2935 ID [a-zA-Z0-9_]+
105 schoenebeck 2581
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 schoenebeck 2935 /* there is currently no support for floating point numbers in NKSP yet */
120     /*{DIGIT}+"."{DIGIT}* {
121 schoenebeck 2581 printf("A float: %s (%g)\n", yytext, atof(yytext));
122 schoenebeck 2935 }*/
123 schoenebeck 2581
124    
125     /* Preprocessor statement: SET_CONDITION(name) */
126    
127     <*>"SET_CONDITION"[ \t]*"(" {
128 schoenebeck 2588 //printf("SET_CONDITION\n");
129 schoenebeck 2581 yy_push_state(PREPROC_SET_COND, yyscanner);
130     }
131     <PREPROC_SET_COND>{ID} {
132 schoenebeck 2588 //printf("preproc set condition '%s'\n", yytext);
133 schoenebeck 2581 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 schoenebeck 2588 //printf("End of PREPROC_SET_COND\n");
141 schoenebeck 2581 yy_pop_state(yyscanner);
142     }
143    
144    
145     /* Preprocessor statement: RESET_CONDITION(name) */
146    
147     <*>"RESET_CONDITION"[ \t]*"(" {
148 schoenebeck 2588 //printf("RESET_CONDITION\n");
149 schoenebeck 2581 yy_push_state(PREPROC_RESET_COND, yyscanner);
150     }
151     <PREPROC_RESET_COND>{ID} {
152 schoenebeck 2588 //printf("preproc reset condition '%s'\n", yytext);
153 schoenebeck 2581 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 schoenebeck 2588 //printf("End of RESET_CONDITION\n");
161 schoenebeck 2581 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 schoenebeck 2588 //printf("USE_CODE_IF\n");
180 schoenebeck 2581 yy_push_state(PREPROC_IF, yyscanner);
181     }
182     <*>"USE_CODE_IF_NOT"[ \t]*"(" {
183 schoenebeck 2588 //printf("USE_CODE_IF_NOT\n");
184 schoenebeck 2581 yy_push_state(PREPROC_IF_NOT, yyscanner);
185     }
186     <PREPROC_IF>{ID} {
187 schoenebeck 2588 //printf("preproc use code if '%s'\n", yytext);
188 schoenebeck 2581 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 schoenebeck 2588 //printf("preproc use code if not '%s'\n", yytext);
196 schoenebeck 2581 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 schoenebeck 2588 //printf("PREPROCESSOR EAT : \n");
208 schoenebeck 2581 yy_pop_state(yyscanner);
209     yy_push_state(PREPROC_BODY_EAT, yyscanner);
210     }
211     <*>.*"END_USE_CODE" {
212 schoenebeck 2588 //printf("-->END_USE_CODE\n");
213 schoenebeck 2581 yy_pop_state(yyscanner);
214     }
215 schoenebeck 2888 <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 schoenebeck 2581
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 schoenebeck 2935 ".or." return BITWISE_OR;
233 schoenebeck 2581 "or" return OR;
234     "release" return RELEASE;
235 schoenebeck 2935 ".and." return BITWISE_AND;
236 schoenebeck 2581 "and" return AND;
237 schoenebeck 2935 ".not." return BITWISE_NOT;
238 schoenebeck 2581 "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 schoenebeck 2585 "const" return CONST_; // note: "CONST" is already defined for C/C++ compilers on Windows by default
247 schoenebeck 2581 "polyphonic" return POLYPHONIC;
248     "mod" return MOD;
249 schoenebeck 2951 "function" return FUNCTION;
250     "call" return CALL;
251 schoenebeck 2581
252 schoenebeck 2935 [&,()[\]<>=*+#/-] {
253     return *yytext;
254 schoenebeck 2581 }
255    
256 schoenebeck 2935 ("$"|"@"|"%"){ID} {
257 schoenebeck 2581 yylval->sValue = strdup(yytext);
258     return VARIABLE;
259     }
260    
261     {ID} {
262     yylval->sValue = strdup(yytext);
263     return IDENTIFIER;
264     }
265    
266     ":=" return ASSIGNMENT;
267    
268     \n+ {
269 schoenebeck 2888 yylineno += countNewLineChars(yytext);
270     yycolumn = 0;
271 schoenebeck 2581 //printf("lex: new line %d\n", yylineno, yytext);
272     //return LF;
273     }
274    
275 schoenebeck 2888 "{"[^}]*"}" { /* eat up comments */
276     processLocation();
277     }
278 schoenebeck 2581
279     [ \t\r]+ /* eat up whitespace */
280    
281 schoenebeck 2942 . printf( "Unrecognized character: '%s' (line %d, column %d)\n", yytext, yylineno, yycolumn);
282 schoenebeck 2581
283     %%
284    
285     namespace LinuxSampler {
286    
287     void ParserContext::createScanner(std::istream* is) {
288     if (scanner) destroyScanner();
289     this->is = is;
290     yylex_init(&scanner);
291     yyset_extra(this, scanner);
292     }
293    
294     void ParserContext::destroyScanner() {
295     if (!scanner) return;
296     yylex_destroy(scanner);
297     scanner = NULL;
298     }
299    
300     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC