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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2585 by schoenebeck, Sat May 31 21:09:25 2014 UTC revision 3260 by schoenebeck, Wed May 31 21:07:44 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014 Christian Schoenebeck and Andreas Persson   * Copyright (c) 2014-2017 Christian Schoenebeck and Andreas Persson
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 7  Line 7 
7   * See README file for details.   * See README file for details.
8   */   */
9    
10  /* Token scanner for instrument script language. */  /* Token scanner for NKSP real-time instrument script language. */
   
 /* FIXME: line numbers (i.e. on error/warning messages) are incorrect, because  
    the current grammar does not process new line characters. \n is currently  
    filtered out in this lexer. Due to this, the parser will sometimes read  
    several lines before it matches the next complete grammar rule, causing the  
    incorrect lines in the error/warning messages. */  
11    
12  %{  %{
13    
# Line 26  Line 20 
20  {                                       \  {                                       \
21      yylloc->first_line = yylineno;      \      yylloc->first_line = yylineno;      \
22      yylloc->last_line  = yylineno;      \      yylloc->last_line  = yylineno;      \
23      /* first_column = TODO */           \      yylloc->first_column = yycolumn;    \
24      /* last_column  = TODO */           \      yycolumn += yyleng;                 \
25        yylloc->last_column = yycolumn - 1; \
26      /*printf("lex: line '%s'\n", yytext);*/  \      /*printf("lex: line '%s'\n", yytext);*/  \
27  }  }
28  // custom (f)lex input for reading from std::istream object  // custom (f)lex input for reading from std::istream object
# Line 43  Line 38 
38  }  }
39    
40  static void scanner_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {  static void scanner_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
41      context->addErr(locp->first_line, err);      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) {  static void scanner_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
45      context->addWrn(locp->first_line, txt);      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)  #define SCANNER_ERR(txt)  scanner_error(yylloc, yyextra, txt)
49  #define SCANNER_WRN(txt)  scanner_warning(yylloc, yyextra, txt)  #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;  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 */  /* use Flex's built-in support for line numbers
82  %option yylineno     (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 */  /* generate a reentrant safe scanner */
86  %option reentrant  %option reentrant
87  /* avoid symbol collision with other (i.e. future) scanner symbols */  /* avoid symbol collision with other (i.e. future) scanner symbols */
# Line 78  using namespace LinuxSampler; Line 101  using namespace LinuxSampler;
101  %x PREPROC_SET_COND PREPROC_RESET_COND PREPROC_IF PREPROC_IF_NOT PREPROC_BODY_EAT PREPROC_PRE_BODY_USE PREPROC_PRE_BODY_EAT  %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]  DIGIT    [0-9]
104  ID       [a-zA-Z0-9_]*  ID       [a-zA-Z0-9_]+
105    
106  %%  %%
107    
# Line 93  ID       [a-zA-Z0-9_]* Line 116  ID       [a-zA-Z0-9_]*
116      return INTEGER;      return INTEGER;
117  }  }
118    
119  {DIGIT}+"."{DIGIT}* {   /* 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));      printf("A float: %s (%g)\n", yytext, atof(yytext));
122  }   }*/
123    
124    
125   /* Preprocessor statement:  SET_CONDITION(name) */   /* Preprocessor statement:  SET_CONDITION(name) */
126    
127  <*>"SET_CONDITION"[ \t]*"(" {  <*>"SET_CONDITION"[ \t]*"(" {
128      printf("SET_CONDITION\n");      //printf("SET_CONDITION\n");
129      yy_push_state(PREPROC_SET_COND, yyscanner);      yy_push_state(PREPROC_SET_COND, yyscanner);
130  }  }
131  <PREPROC_SET_COND>{ID} {  <PREPROC_SET_COND>{ID} {
132      printf("preproc set condition '%s'\n", yytext);      //printf("preproc set condition '%s'\n", yytext);
133      bool success = yyextra->setPreprocessorCondition(yytext);      bool success = yyextra->setPreprocessorCondition(yytext);
134      if (!success) {      if (!success) {
135          SCANNER_WRN((String("Preprocessor: Condition '") +          SCANNER_WRN((String("Preprocessor: Condition '") +
# Line 113  ID       [a-zA-Z0-9_]* Line 137  ID       [a-zA-Z0-9_]*
137      }      }
138  }  }
139  <PREPROC_SET_COND>[ \t]*")" {  <PREPROC_SET_COND>[ \t]*")" {
140      printf("End of PREPROC_SET_COND\n");      //printf("End of PREPROC_SET_COND\n");
141      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
142  }  }
143    
# Line 121  ID       [a-zA-Z0-9_]* Line 145  ID       [a-zA-Z0-9_]*
145   /* Preprocessor statement:  RESET_CONDITION(name) */   /* Preprocessor statement:  RESET_CONDITION(name) */
146    
147  <*>"RESET_CONDITION"[ \t]*"(" {  <*>"RESET_CONDITION"[ \t]*"(" {
148      printf("RESET_CONDITION\n");      //printf("RESET_CONDITION\n");
149      yy_push_state(PREPROC_RESET_COND, yyscanner);      yy_push_state(PREPROC_RESET_COND, yyscanner);
150  }  }
151  <PREPROC_RESET_COND>{ID} {  <PREPROC_RESET_COND>{ID} {
152      printf("preproc reset condition '%s'\n", yytext);      //printf("preproc reset condition '%s'\n", yytext);
153      bool success = yyextra->resetPreprocessorCondition(yytext);      bool success = yyextra->resetPreprocessorCondition(yytext);
154      if (!success) {      if (!success) {
155          SCANNER_ERR((String("Preprocessor: could not reset condition '") +          SCANNER_ERR((String("Preprocessor: could not reset condition '") +
# Line 133  ID       [a-zA-Z0-9_]* Line 157  ID       [a-zA-Z0-9_]*
157      }      }
158  }  }
159  <PREPROC_RESET_COND>[ \t]*")" {  <PREPROC_RESET_COND>[ \t]*")" {
160      printf("End of RESET_CONDITION\n");      //printf("End of RESET_CONDITION\n");
161      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
162  }  }
163    
# Line 152  ID       [a-zA-Z0-9_]* Line 176  ID       [a-zA-Z0-9_]*
176   */   */
177    
178  <*>"USE_CODE_IF"[ \t]*"(" {  <*>"USE_CODE_IF"[ \t]*"(" {
179      printf("USE_CODE_IF\n");      //printf("USE_CODE_IF\n");
180      yy_push_state(PREPROC_IF, yyscanner);      yy_push_state(PREPROC_IF, yyscanner);
181  }  }
182  <*>"USE_CODE_IF_NOT"[ \t]*"(" {  <*>"USE_CODE_IF_NOT"[ \t]*"(" {
183      printf("USE_CODE_IF_NOT\n");      //printf("USE_CODE_IF_NOT\n");
184      yy_push_state(PREPROC_IF_NOT, yyscanner);      yy_push_state(PREPROC_IF_NOT, yyscanner);
185  }  }
186  <PREPROC_IF>{ID} {  <PREPROC_IF>{ID} {
187      printf("preproc use code if '%s'\n", yytext);      //printf("preproc use code if '%s'\n", yytext);
188      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
189      if (yyextra->isPreprocessorConditionSet(yytext))      if (yyextra->isPreprocessorConditionSet(yytext))
190          yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);          yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
# Line 168  ID       [a-zA-Z0-9_]* Line 192  ID       [a-zA-Z0-9_]*
192          yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);          yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
193  }  }
194  <PREPROC_IF_NOT>{ID} {  <PREPROC_IF_NOT>{ID} {
195      printf("preproc use code if not '%s'\n", yytext);      //printf("preproc use code if not '%s'\n", yytext);
196      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
197      if (!yyextra->isPreprocessorConditionSet(yytext))      if (!yyextra->isPreprocessorConditionSet(yytext))
198          yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);          yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
# Line 180  ID       [a-zA-Z0-9_]* Line 204  ID       [a-zA-Z0-9_]*
204      yy_push_state(PREPROC_BODY_USE, yyscanner);      yy_push_state(PREPROC_BODY_USE, yyscanner);
205  }  }
206  <PREPROC_PRE_BODY_EAT>[ \t]*")" {  <PREPROC_PRE_BODY_EAT>[ \t]*")" {
207        //printf("PREPROCESSOR EAT : \n");
208      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
209      yy_push_state(PREPROC_BODY_EAT, yyscanner);      yy_push_state(PREPROC_BODY_EAT, yyscanner);
210  }  }
211  <*>.*"END_USE_CODE" {  <*>.*"END_USE_CODE" {
212      printf("END_USE_CODE\n");      //printf("-->END_USE_CODE\n");
213      yy_pop_state(yyscanner);      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 */   /* Language keywords */
# Line 198  ID       [a-zA-Z0-9_]* Line 229  ID       [a-zA-Z0-9_]*
229  "declare" return DECLARE;  "declare" return DECLARE;
230  "while" return WHILE;  "while" return WHILE;
231  "if" return IF;  "if" return IF;
232    ".or." return BITWISE_OR;
233  "or" return OR;  "or" return OR;
234  "release" return RELEASE;  "release" return RELEASE;
235    ".and." return BITWISE_AND;
236  "and" return AND;  "and" return AND;
237    ".not." return BITWISE_NOT;
238  "not" return NOT;  "not" return NOT;
239  "else" return ELSE;  "else" return ELSE;
240  "controller" return CONTROLLER;  "controller" return CONTROLLER;
# Line 212  ID       [a-zA-Z0-9_]* Line 246  ID       [a-zA-Z0-9_]*
246  "const" return CONST_; // note: "CONST" is already defined for C/C++ compilers on Windows by default  "const" return CONST_; // note: "CONST" is already defined for C/C++ compilers on Windows by default
247  "polyphonic" return POLYPHONIC;  "polyphonic" return POLYPHONIC;
248  "mod" return MOD;  "mod" return MOD;
249    "function" return FUNCTION;
250    "call" return CALL;
251    "synchronized" return SYNCHRONIZED;
252    
253  on|end|note|init|declare|if|then|begin|end|procedure|function {  [&,()[\]<>=*+#/-] {
254      printf("A keyword: %s\n", yytext);      return *yytext;
255  }  }
256    
257  [&,()[\]<>=*+#/-] { return *yytext; }  ("$"|"@"|"%"){ID} {
   
 ("$"|"@"){ID} {  
     yylval->sValue = strdup(yytext);  
     return VARIABLE;  
 }  
   
 "%"{ID} {  
258      yylval->sValue = strdup(yytext);      yylval->sValue = strdup(yytext);
259      return VARIABLE;      return VARIABLE;
260  }  }
# Line 237  on|end|note|init|declare|if|then|begin|e Line 267  on|end|note|init|declare|if|then|begin|e
267  ":=" return ASSIGNMENT;  ":=" return ASSIGNMENT;
268    
269  \n+ {  \n+ {
270         yylineno += countNewLineChars(yytext);
271         yycolumn = 0;
272      //printf("lex: new line %d\n", yylineno, yytext);      //printf("lex: new line %d\n", yylineno, yytext);
273      //return LF;      //return LF;
274  }  }
275    
276  "{"[^}]*"}" /* eat up comments */  "{"[^}]*"}" { /* eat up comments */
277        processLocation();
278    }
279    
280  [ \t\r]+ /* eat up whitespace */  [ \t\r]+ /* eat up whitespace */
281    
282  "..." /* eat up */  . {
283        printf( "Unrecognized character: '%s' (line %d, column %d)\n", yytext, yylineno, yycolumn);
284  . printf( "Unrecognized character: %s\n", yytext );      return UNKNOWN_CHAR;
285    }
286    
287  %%  %%
288    

Legend:
Removed from v.2585  
changed lines
  Added in v.3260

  ViewVC Help
Powered by ViewVC