/[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 2889 by schoenebeck, Mon Apr 25 17:28:23 2016 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014 Christian Schoenebeck and Andreas Persson   * Copyright (c) 2014-2016 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)
# Line 55  static void scanner_warning(YYLTYPE* loc Line 50  static void scanner_warning(YYLTYPE* loc
50    
51  using namespace LinuxSampler;  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 */  /* use Flex's built-in support for line numbers
77  %option yylineno     (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 */  /* generate a reentrant safe scanner */
81  %option reentrant  %option reentrant
82  /* avoid symbol collision with other (i.e. future) scanner symbols */  /* avoid symbol collision with other (i.e. future) scanner symbols */
# Line 101  ID       [a-zA-Z0-9_]* Line 119  ID       [a-zA-Z0-9_]*
119   /* Preprocessor statement:  SET_CONDITION(name) */   /* Preprocessor statement:  SET_CONDITION(name) */
120    
121  <*>"SET_CONDITION"[ \t]*"(" {  <*>"SET_CONDITION"[ \t]*"(" {
122      printf("SET_CONDITION\n");      //printf("SET_CONDITION\n");
123      yy_push_state(PREPROC_SET_COND, yyscanner);      yy_push_state(PREPROC_SET_COND, yyscanner);
124  }  }
125  <PREPROC_SET_COND>{ID} {  <PREPROC_SET_COND>{ID} {
126      printf("preproc set condition '%s'\n", yytext);      //printf("preproc set condition '%s'\n", yytext);
127      bool success = yyextra->setPreprocessorCondition(yytext);      bool success = yyextra->setPreprocessorCondition(yytext);
128      if (!success) {      if (!success) {
129          SCANNER_WRN((String("Preprocessor: Condition '") +          SCANNER_WRN((String("Preprocessor: Condition '") +
# Line 113  ID       [a-zA-Z0-9_]* Line 131  ID       [a-zA-Z0-9_]*
131      }      }
132  }  }
133  <PREPROC_SET_COND>[ \t]*")" {  <PREPROC_SET_COND>[ \t]*")" {
134      printf("End of PREPROC_SET_COND\n");      //printf("End of PREPROC_SET_COND\n");
135      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
136  }  }
137    
# Line 121  ID       [a-zA-Z0-9_]* Line 139  ID       [a-zA-Z0-9_]*
139   /* Preprocessor statement:  RESET_CONDITION(name) */   /* Preprocessor statement:  RESET_CONDITION(name) */
140    
141  <*>"RESET_CONDITION"[ \t]*"(" {  <*>"RESET_CONDITION"[ \t]*"(" {
142      printf("RESET_CONDITION\n");      //printf("RESET_CONDITION\n");
143      yy_push_state(PREPROC_RESET_COND, yyscanner);      yy_push_state(PREPROC_RESET_COND, yyscanner);
144  }  }
145  <PREPROC_RESET_COND>{ID} {  <PREPROC_RESET_COND>{ID} {
146      printf("preproc reset condition '%s'\n", yytext);      //printf("preproc reset condition '%s'\n", yytext);
147      bool success = yyextra->resetPreprocessorCondition(yytext);      bool success = yyextra->resetPreprocessorCondition(yytext);
148      if (!success) {      if (!success) {
149          SCANNER_ERR((String("Preprocessor: could not reset condition '") +          SCANNER_ERR((String("Preprocessor: could not reset condition '") +
# Line 133  ID       [a-zA-Z0-9_]* Line 151  ID       [a-zA-Z0-9_]*
151      }      }
152  }  }
153  <PREPROC_RESET_COND>[ \t]*")" {  <PREPROC_RESET_COND>[ \t]*")" {
154      printf("End of RESET_CONDITION\n");      //printf("End of RESET_CONDITION\n");
155      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
156  }  }
157    
# Line 152  ID       [a-zA-Z0-9_]* Line 170  ID       [a-zA-Z0-9_]*
170   */   */
171    
172  <*>"USE_CODE_IF"[ \t]*"(" {  <*>"USE_CODE_IF"[ \t]*"(" {
173      printf("USE_CODE_IF\n");      //printf("USE_CODE_IF\n");
174      yy_push_state(PREPROC_IF, yyscanner);      yy_push_state(PREPROC_IF, yyscanner);
175  }  }
176  <*>"USE_CODE_IF_NOT"[ \t]*"(" {  <*>"USE_CODE_IF_NOT"[ \t]*"(" {
177      printf("USE_CODE_IF_NOT\n");      //printf("USE_CODE_IF_NOT\n");
178      yy_push_state(PREPROC_IF_NOT, yyscanner);      yy_push_state(PREPROC_IF_NOT, yyscanner);
179  }  }
180  <PREPROC_IF>{ID} {  <PREPROC_IF>{ID} {
181      printf("preproc use code if '%s'\n", yytext);      //printf("preproc use code if '%s'\n", yytext);
182      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
183      if (yyextra->isPreprocessorConditionSet(yytext))      if (yyextra->isPreprocessorConditionSet(yytext))
184          yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);          yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
# Line 168  ID       [a-zA-Z0-9_]* Line 186  ID       [a-zA-Z0-9_]*
186          yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);          yy_push_state(PREPROC_PRE_BODY_EAT, yyscanner);
187  }  }
188  <PREPROC_IF_NOT>{ID} {  <PREPROC_IF_NOT>{ID} {
189      printf("preproc use code if not '%s'\n", yytext);      //printf("preproc use code if not '%s'\n", yytext);
190      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
191      if (!yyextra->isPreprocessorConditionSet(yytext))      if (!yyextra->isPreprocessorConditionSet(yytext))
192          yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);          yy_push_state(PREPROC_PRE_BODY_USE, yyscanner);
# Line 180  ID       [a-zA-Z0-9_]* Line 198  ID       [a-zA-Z0-9_]*
198      yy_push_state(PREPROC_BODY_USE, yyscanner);      yy_push_state(PREPROC_BODY_USE, yyscanner);
199  }  }
200  <PREPROC_PRE_BODY_EAT>[ \t]*")" {  <PREPROC_PRE_BODY_EAT>[ \t]*")" {
201        //printf("PREPROCESSOR EAT : \n");
202      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
203      yy_push_state(PREPROC_BODY_EAT, yyscanner);      yy_push_state(PREPROC_BODY_EAT, yyscanner);
204  }  }
205  <*>.*"END_USE_CODE" {  <*>.*"END_USE_CODE" {
206      printf("END_USE_CODE\n");      //printf("-->END_USE_CODE\n");
207      yy_pop_state(yyscanner);      yy_pop_state(yyscanner);
208  }  }
209    <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    
216    
217   /* Language keywords */   /* Language keywords */
# Line 237  on|end|note|init|declare|if|then|begin|e Line 262  on|end|note|init|declare|if|then|begin|e
262  ":=" return ASSIGNMENT;  ":=" return ASSIGNMENT;
263    
264  \n+ {  \n+ {
265         yylineno += countNewLineChars(yytext);
266         yycolumn = 0;
267      //printf("lex: new line %d\n", yylineno, yytext);      //printf("lex: new line %d\n", yylineno, yytext);
268      //return LF;      //return LF;
269  }  }
270    
271  "{"[^}]*"}" /* eat up comments */  "{"[^}]*"}" { /* eat up comments */
272        processLocation();
273    }
274    
275  [ \t\r]+ /* eat up whitespace */  [ \t\r]+ /* eat up whitespace */
276    

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

  ViewVC Help
Powered by ViewVC