/[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 2888 - (hide annotations) (download)
Sun Apr 24 18:16:10 2016 UTC (8 years ago) by schoenebeck
File size: 7732 byte(s)
* Instrument Scripts: Fixed line numbers on parser error/warning messages.
* Instrument Scripts: Added output of precise column on parser
  error/warning messages.
* Shut up some irrelevant errors of parser generating shell scripts.
* Bumped version (2.0.0.svn6).

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 2888 context->addErr(locp->first_line, locp->first_column, err);
42 schoenebeck 2581 }
43    
44     static void scanner_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
45 schoenebeck 2888 context->addWrn(locp->first_line, locp->first_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     using namespace LinuxSampler;
52    
53 schoenebeck 2888 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 schoenebeck 2581 %}
75    
76 schoenebeck 2888 /* 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 schoenebeck 2581 /* 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     {DIGIT}+"."{DIGIT}* {
115     printf("A float: %s (%g)\n", yytext, atof(yytext));
116     }
117    
118    
119     /* Preprocessor statement: SET_CONDITION(name) */
120    
121     <*>"SET_CONDITION"[ \t]*"(" {
122 schoenebeck 2588 //printf("SET_CONDITION\n");
123 schoenebeck 2581 yy_push_state(PREPROC_SET_COND, yyscanner);
124     }
125     <PREPROC_SET_COND>{ID} {
126 schoenebeck 2588 //printf("preproc set condition '%s'\n", yytext);
127 schoenebeck 2581 bool success = yyextra->setPreprocessorCondition(yytext);
128     if (!success) {
129     SCANNER_WRN((String("Preprocessor: Condition '") +
130     yytext + "' is already set.").c_str());
131     }
132     }
133     <PREPROC_SET_COND>[ \t]*")" {
134 schoenebeck 2588 //printf("End of PREPROC_SET_COND\n");
135 schoenebeck 2581 yy_pop_state(yyscanner);
136     }
137    
138    
139     /* Preprocessor statement: RESET_CONDITION(name) */
140    
141     <*>"RESET_CONDITION"[ \t]*"(" {
142 schoenebeck 2588 //printf("RESET_CONDITION\n");
143 schoenebeck 2581 yy_push_state(PREPROC_RESET_COND, yyscanner);
144     }
145     <PREPROC_RESET_COND>{ID} {
146 schoenebeck 2588 //printf("preproc reset condition '%s'\n", yytext);
147 schoenebeck 2581 bool success = yyextra->resetPreprocessorCondition(yytext);
148     if (!success) {
149     SCANNER_ERR((String("Preprocessor: could not reset condition '") +
150     yytext + "' (either not set or a built-in condition).").c_str());
151     }
152     }
153     <PREPROC_RESET_COND>[ \t]*")" {
154 schoenebeck 2588 //printf("End of RESET_CONDITION\n");
155 schoenebeck 2581 yy_pop_state(yyscanner);
156     }
157    
158    
159     /* Preprocessor conditional statements:
160    
161     USE_CODE_IF(name)
162     ...
163     END_USE_CODE
164    
165     and:
166    
167     USE_CODE_IF_NOT(name)
168     ...
169     END_USE_CODE
170     */
171    
172     <*>"USE_CODE_IF"[ \t]*"(" {
173 schoenebeck 2588 //printf("USE_CODE_IF\n");
174 schoenebeck 2581 yy_push_state(PREPROC_IF, yyscanner);
175     }
176     <*>"USE_CODE_IF_NOT"[ \t]*"(" {
177 schoenebeck 2588 //printf("USE_CODE_IF_NOT\n");
178 schoenebeck 2581 yy_push_state(PREPROC_IF_NOT, yyscanner);
179     }
180     <PREPROC_IF>{ID} {
181 schoenebeck 2588 //printf("preproc use code if '%s'\n", yytext);
182 schoenebeck 2581 yy_pop_state(yyscanner);
183     if (yyextra->isPreprocessorConditionSet(yytext))
184     yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
185     else
186     yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
187     }
188     <PREPROC_IF_NOT>{ID} {
189 schoenebeck 2588 //printf("preproc use code if not '%s'\n", yytext);
190 schoenebeck 2581 yy_pop_state(yyscanner);
191     if (!yyextra->isPreprocessorConditionSet(yytext))
192     yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
193     else
194     yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
195     }
196     <PREPROC_PRE_BODY_USE>[ \t]*")" {
197     yy_pop_state(yyscanner);
198     yy_push_state(PREPROC_BODY_USE, yyscanner);
199     }
200     <PREPROC_PRE_BODY_EAT>[ \t]*")" {
201 schoenebeck 2588 //printf("PREPROCESSOR EAT : \n");
202 schoenebeck 2581 yy_pop_state(yyscanner);
203     yy_push_state(PREPROC_BODY_EAT, yyscanner);
204     }
205     <*>.*"END_USE_CODE" {
206 schoenebeck 2588 //printf("-->END_USE_CODE\n");
207 schoenebeck 2581 yy_pop_state(yyscanner);
208     }
209 schoenebeck 2888 <PREPROC_BODY_EAT>[ \t\r\n]* { /* eat up code block filtered out by preprocessor */
210     processLocation();
211     }
212     <PREPROC_BODY_EAT>.* { /* eat up code block filtered out by preprocessor */
213     processLocation();
214     }
215 schoenebeck 2581
216    
217     /* Language keywords */
218    
219     "on" return ON;
220     "end" return END;
221     "note" return NOTE;
222     "init" return INIT;
223     "declare" return DECLARE;
224     "while" return WHILE;
225     "if" return IF;
226     "or" return OR;
227     "release" return RELEASE;
228     "and" return AND;
229     "not" return NOT;
230     "else" return ELSE;
231     "controller" return CONTROLLER;
232     "case" return CASE;
233     "select" return SELECT;
234     "to" return TO;
235     "<=" return LE;
236     ">=" return GE;
237 schoenebeck 2585 "const" return CONST_; // note: "CONST" is already defined for C/C++ compilers on Windows by default
238 schoenebeck 2581 "polyphonic" return POLYPHONIC;
239     "mod" return MOD;
240    
241     on|end|note|init|declare|if|then|begin|end|procedure|function {
242     printf("A keyword: %s\n", yytext);
243     }
244    
245     [&,()[\]<>=*+#/-] { return *yytext; }
246    
247     ("$"|"@"){ID} {
248     yylval->sValue = strdup(yytext);
249     return VARIABLE;
250     }
251    
252     "%"{ID} {
253     yylval->sValue = strdup(yytext);
254     return VARIABLE;
255     }
256    
257     {ID} {
258     yylval->sValue = strdup(yytext);
259     return IDENTIFIER;
260     }
261    
262     ":=" return ASSIGNMENT;
263    
264     \n+ {
265 schoenebeck 2888 yylineno += countNewLineChars(yytext);
266     yycolumn = 0;
267 schoenebeck 2581 //printf("lex: new line %d\n", yylineno, yytext);
268     //return LF;
269     }
270    
271 schoenebeck 2888 "{"[^}]*"}" { /* eat up comments */
272     processLocation();
273     }
274 schoenebeck 2581
275     [ \t\r]+ /* eat up whitespace */
276    
277     "..." /* eat up */
278    
279     . printf( "Unrecognized character: %s\n", yytext );
280    
281     %%
282    
283     namespace LinuxSampler {
284    
285     void ParserContext::createScanner(std::istream* is) {
286     if (scanner) destroyScanner();
287     this->is = is;
288     yylex_init(&scanner);
289     yyset_extra(this, scanner);
290     }
291    
292     void ParserContext::destroyScanner() {
293     if (!scanner) return;
294     yylex_destroy(scanner);
295     scanner = NULL;
296     }
297    
298     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC