/[svn]/linuxsampler/trunk/src/scriptvm/parser.y
ViewVC logotype

Diff of /linuxsampler/trunk/src/scriptvm/parser.y

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   *   *
6   * This file is part of LinuxSampler and released under the same terms.   * This file is part of LinuxSampler and released under the same terms.
7   * See README file for details.   * See README file for details.
8   */   */
9    
10    /* Parser for NKSP real-time instrument script language. */
11    
12  %{  %{
13      #define YYERROR_VERBOSE 1      #define YYERROR_VERBOSE 1
# Line 16  Line 18 
18    
19      void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err);      void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err);
20      void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt);      void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt);
21        int InstrScript_tnamerr(char* yyres, const char* yystr);
22      int InstrScript_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);      int InstrScript_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);
23      #define scanner context->scanner      #define scanner context->scanner
24      #define PARSE_ERR(txt)  yyerror(&yylloc, context, txt)      #define PARSE_ERR(loc,txt)  yyerror(&loc, context, txt)
25      #define PARSE_WRN(txt)  InstrScript_warning(&yylloc, context, txt)      #define PARSE_WRN(loc,txt)  InstrScript_warning(&loc, context, txt)
26        #define yytnamerr(res,str)  InstrScript_tnamerr(res, str)
27  %}  %}
28    
29  // generate reentrant safe parser  // generate reentrant safe parser
# Line 27  Line 31 
31  %parse-param { LinuxSampler::ParserContext* context }  %parse-param { LinuxSampler::ParserContext* context }
32  %lex-param { void* scanner }  %lex-param { void* scanner }
33  // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners  // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners
34  %name-prefix "InstrScript_"  // (NOTE: "=" is deprecated here with Bison 3.x, however removing it would cause an error with Bison 2.x)
35    %name-prefix="InstrScript_"
36  %locations  %locations
37  %defines  %defines
38  %error-verbose  %error-verbose
39    
40  %token <iValue> INTEGER  %token <iValue> INTEGER "integer literal"
41  %token <sValue> STRING  %token <sValue> STRING "string literal"
42  %token <sValue> IDENTIFIER  %token <sValue> IDENTIFIER "function name"
43  %token <sValue> VARIABLE  %token <sValue> VARIABLE "variable name"
44  %token ON END INIT NOTE DECLARE ASSIGNMENT WHILE IF OR RELEASE AND ELSE  %token ON "keyword 'on'"
45  %token CONTROLLER SELECT CASE TO NOT CONST_ POLYPHONIC MOD  %token END "keyword 'end'"
46  %token LE GE  %token INIT "keyword 'init'"
47    %token NOTE "keyword 'note'"
48  %type <nEventHandlers> script eventhandlers  %token RELEASE "keyword 'release'"
49  %type <nEventHandler> eventhandler  %token CONTROLLER "keyword 'controller'"
50  %type <nStatements> statements  %token DECLARE "keyword 'declare'"
51    %token ASSIGNMENT "operator ':='"
52    %token CONST_ "keyword 'const'"
53    %token POLYPHONIC "keyword 'polyphonic'"
54    %token WHILE "keyword 'while'"
55    %token SYNCHRONIZED "keyword 'synchronized'"
56    %token IF "keyword 'if'"
57    %token ELSE "keyword 'else'"
58    %token SELECT "keyword 'select'"
59    %token CASE "keyword 'case'"
60    %token TO "keyword 'to'"
61    %token OR "operator 'or'"
62    %token AND "operator 'and'"
63    %token NOT "operator 'not'"
64    %token BITWISE_OR "bitwise operator '.or.'"
65    %token BITWISE_AND "bitwise operator '.and.'"
66    %token BITWISE_NOT "bitwise operator '.not.'"
67    %token FUNCTION "keyword 'function'"
68    %token CALL "keyword 'call'"
69    %token MOD "operator 'mod'"
70    %token LE "operator '<='"
71    %token GE "operator '>='"
72    %token END_OF_FILE 0 "end of file"
73    %token UNKNOWN_CHAR "unknown character"
74    
75    %type <nEventHandlers> script sections
76    %type <nEventHandler> section eventhandler
77    %type <nStatements> statements opt_statements userfunctioncall
78  %type <nStatement> statement assignment  %type <nStatement> statement assignment
79  %type <nFunctionCall> functioncall  %type <nFunctionCall> functioncall
80  %type <nArgs> args  %type <nArgs> args
81  %type <nExpression> arg expr or_expr and_expr rel_expr add_expr mul_expr unary_expr concat_expr  %type <nExpression> arg expr logical_or_expr logical_and_expr bitwise_or_expr bitwise_and_expr rel_expr add_expr mul_expr unary_expr concat_expr
82  %type <nCaseBranch> caseclause  %type <nCaseBranch> caseclause
83  %type <nCaseBranches> caseclauses  %type <nCaseBranches> caseclauses
84    
# Line 55  Line 87 
87  %%  %%
88    
89  script:  script:
90      eventhandlers  {      sections  {
91          $$ = context->handlers = $1;          $$ = context->handlers = $1;
92      }      }
93    
94  eventhandlers:  sections:
95      eventhandler  {      section  {
96          $$ = new EventHandlers();          $$ = new EventHandlers();
97          $$->add($1);          if ($1) $$->add($1);
98      }      }
99      | eventhandlers eventhandler  {      | sections section  {
100            $$ = $1;
101            if ($2) $$->add($2);
102        }
103    
104    section:
105        function_declaration  {
106            $$ = EventHandlerRef();
107        }
108        | eventhandler  {
109          $$ = $1;          $$ = $1;
         $$->add($2);  
110      }      }
111    
112  eventhandler:  eventhandler:
113      ON NOTE statements END ON  {      ON NOTE opt_statements END ON  {
114          if (context->onNote)          if (context->onNote)
115              PARSE_ERR("Redeclaration of 'note' event handler.");              PARSE_ERR(@2, "Redeclaration of 'note' event handler.");
116          context->onNote = new OnNote($3);          context->onNote = new OnNote($3);
117          $$ = context->onNote;          $$ = context->onNote;
118      }      }
119      | ON INIT statements END ON  {      | ON INIT opt_statements END ON  {
120          if (context->onInit)          if (context->onInit)
121              PARSE_ERR("Redeclaration of 'init' event handler.");              PARSE_ERR(@2, "Redeclaration of 'init' event handler.");
122          context->onInit = new OnInit($3);          context->onInit = new OnInit($3);
123          $$ = context->onInit;          $$ = context->onInit;
124      }      }
125      | ON RELEASE statements END ON  {      | ON RELEASE opt_statements END ON  {
126          if (context->onRelease)          if (context->onRelease)
127              PARSE_ERR("Redeclaration of 'release' event handler.");              PARSE_ERR(@2, "Redeclaration of 'release' event handler.");
128          context->onRelease = new OnRelease($3);          context->onRelease = new OnRelease($3);
129          $$ = context->onRelease;          $$ = context->onRelease;
130      }      }
131      | ON CONTROLLER statements END ON  {      | ON CONTROLLER opt_statements END ON  {
132          if (context->onController)          if (context->onController)
133              PARSE_ERR("Redeclaration of 'controller' event handler.");              PARSE_ERR(@2, "Redeclaration of 'controller' event handler.");
134          context->onController = new OnController($3);          context->onController = new OnController($3);
135          $$ = context->onController;          $$ = context->onController;
136      }      }
137    
138    function_declaration:
139        FUNCTION IDENTIFIER opt_statements END FUNCTION  {
140            const char* name = $2;
141            if (context->functionProvider->functionByName(name)) {
142                PARSE_ERR(@2, (String("There is already a built-in function with name '") + name + "'.").c_str());
143            } else if (context->userFunctionByName(name)) {
144                PARSE_ERR(@2, (String("There is already a user defined function with name '") + name + "'.").c_str());
145            } else {
146                context->userFnTable[name] = $3;
147            }
148        }
149    
150    opt_statements:
151        /* epsilon (empty argument) */  {
152            $$ = new Statements();
153        }
154        | statements  {
155            $$ = $1;
156        }
157    
158  statements:  statements:
159      statement  {      statement  {
160          $$ = new Statements();          $$ = new Statements();
161          if ($1) {          if ($1) {
162              if (!isNoOperation($1)) $$->add($1); // filter out NoOperation statements              if (!isNoOperation($1)) $$->add($1); // filter out NoOperation statements
163          } else          } else
164              PARSE_WRN("Not a statement.");              PARSE_WRN(@1, "Not a statement.");
165      }      }
166      | statements statement  {      | statements statement  {
167          $$ = $1;          $$ = $1;
168          if ($2) {          if ($2) {
169              if (!isNoOperation($2)) $$->add($2); // filter out NoOperation statements              if (!isNoOperation($2)) $$->add($2); // filter out NoOperation statements
170          } else          } else
171              PARSE_WRN("Not a statement.");              PARSE_WRN(@2, "Not a statement.");
172      }      }
173    
174  statement:  statement:
175      functioncall  {      functioncall  {
176          $$ = $1;          $$ = $1;
177      }      }
178        | userfunctioncall  {
179            $$ = $1;
180        }
181      | DECLARE VARIABLE  {      | DECLARE VARIABLE  {
182          const char* name = $2;          const char* name = $2;
183          //printf("declared var '%s'\n", name);          //printf("declared var '%s'\n", name);
184          if (context->variableByName(name))          if (context->variableByName(name))
185              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
186          if (name[0] == '@') {          if (name[0] == '@') {
187              context->vartable[name] = new StringVariable(context);              context->vartable[name] = new StringVariable(context);
188              $$ = new NoOperation;              $$ = new NoOperation;
# Line 132  statement: Line 195  statement:
195          const char* name = $3;          const char* name = $3;
196          //printf("declared polyphonic var '%s'\n", name);          //printf("declared polyphonic var '%s'\n", name);
197          if (context->variableByName(name))          if (context->variableByName(name))
198              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
199          if (name[0] != '$') {          if (name[0] != '$') {
200              PARSE_ERR("Polyphonic variables may only be declared as integers.");              PARSE_ERR(@3, "Polyphonic variables may only be declared as integers.");
201              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
202          } else {          } else {
203              context->vartable[name] = new PolyphonicIntVariable(context);              context->vartable[name] = new PolyphonicIntVariable(context);
# Line 145  statement: Line 208  statement:
208          const char* name = $2;          const char* name = $2;
209          //printf("declared assign var '%s'\n", name);          //printf("declared assign var '%s'\n", name);
210          if (context->variableByName(name))          if (context->variableByName(name))
211              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
212          if ($4->exprType() == STRING_EXPR) {          if ($4->exprType() == STRING_EXPR) {
213              if (name[0] == '$')              if (name[0] == '$')
214                  PARSE_WRN((String("Variable '") + name + "' declared as integer, string expression assigned though.").c_str());                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as integer, string expression assigned though.").c_str());
215              StringExprRef expr = $4;              StringExprRef expr = $4;
216              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
217                  const String s = expr->evalStr();                  const String s = expr->evalStr();
# Line 162  statement: Line 225  statement:
225              }              }
226          } else {          } else {
227              if (name[0] == '@')              if (name[0] == '@')
228                  PARSE_WRN((String("Variable '") + name + "' declared as string, integer expression assigned though.").c_str());                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as string, integer expression assigned though.").c_str());
229              IntExprRef expr = $4;              IntExprRef expr = $4;
230              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
231                  const int i = expr->evalInt();                  const int i = expr->evalInt();
# Line 180  statement: Line 243  statement:
243          //printf("declare array without args\n");          //printf("declare array without args\n");
244          const char* name = $2;          const char* name = $2;
245          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
246              PARSE_ERR((String("Array variable '") + name + "' must be declared with constant array size.").c_str());              PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
247              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
248          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
249              PARSE_ERR((String("Size of array variable '") + name + "' declared with non integer expression.").c_str());              PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
250              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
251          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
252              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
253              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
254          } else {          } else {
255              IntExprRef expr = $4;              IntExprRef expr = $4;
256              int size = expr->evalInt();              int size = expr->evalInt();
257              if (size <= 0) {              if (size <= 0) {
258                  PARSE_ERR((String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());                  PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
259                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever
260              } else {              } else {
261                  context->vartable[name] = new IntArrayVariable(context, size);                  context->vartable[name] = new IntArrayVariable(context, size);
# Line 203  statement: Line 266  statement:
266      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
267          const char* name = $2;          const char* name = $2;
268          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
269              PARSE_ERR((String("Array variable '") + name + "' must be declared with constant array size.").c_str());              PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
270              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
271          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
272              PARSE_ERR((String("Size of array variable '") + name + "' declared with non integer expression.").c_str());              PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
273              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
274          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
275              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
276              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
277          } else {          } else {
278              IntExprRef sizeExpr = $4;              IntExprRef sizeExpr = $4;
279              ArgsRef args = $8;              ArgsRef args = $8;
280              int size = sizeExpr->evalInt();              int size = sizeExpr->evalInt();
281              if (size <= 0) {              if (size <= 0) {
282                  PARSE_ERR((String("Array variable '") + name + "' must be declared with positive array size.").c_str());                  PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
283                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever
284              } else if (args->argsCount() > size) {              } else if (args->argsCount() > size) {
285                  PARSE_ERR((String("Variable '") + name +                  PARSE_ERR(@8, (String("Array variable '") + name +
286                            "' was declared with size " + ToString(size) +                            "' was declared with size " + ToString(size) +
287                            " but " + ToString(args->argsCount()) +                            " but " + ToString(args->argsCount()) +
288                            " values were assigned." ).c_str());                            " values were assigned." ).c_str());
# Line 229  statement: Line 292  statement:
292                  for (int i = 0; i < args->argsCount(); ++i) {                  for (int i = 0; i < args->argsCount(); ++i) {
293                      if (args->arg(i)->exprType() != INT_EXPR) {                      if (args->arg(i)->exprType() != INT_EXPR) {
294                          PARSE_ERR(                          PARSE_ERR(
295                                @8,
296                              (String("Array variable '") + name +                              (String("Array variable '") + name +
297                              "' declared with invalid assignment values. Assigned element " +                              "' declared with invalid assignment values. Assigned element " +
298                              ToString(i+1) + " is not an integer expression.").c_str()                              ToString(i+1) + " is not an integer expression.").c_str()
# Line 237  statement: Line 301  statement:
301                          break;                          break;
302                      }                      }
303                  }                  }
304                  if (argsOK)                  if (argsOK) {
305                      $$ = context->vartable[name] = new IntArrayVariable(context, size, args);                      context->vartable[name] = new IntArrayVariable(context, size, args);
306                  else                      $$ = new NoOperation;
307                    } else
308                        $$ = new FunctionCall("nothing", new Args, NULL); // whatever
309                }
310            }
311        }
312        | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
313            const char* name = $3;
314            if (!$5->isConstExpr()) {
315                PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
316                $$ = new FunctionCall("nothing", new Args, NULL); // whatever
317            } else if ($5->exprType() != INT_EXPR) {
318                PARSE_ERR(@5, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
319                $$ = new FunctionCall("nothing", new Args, NULL); // whatever
320            } else if (context->variableByName(name)) {
321                PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
322                $$ = new FunctionCall("nothing", new Args, NULL); // whatever
323            } else {
324                IntExprRef sizeExpr = $5;
325                ArgsRef args = $9;
326                int size = sizeExpr->evalInt();
327                if (size <= 0) {
328                    PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
329                    $$ = new FunctionCall("nothing", new Args, NULL); // whatever
330                } else if (args->argsCount() > size) {
331                    PARSE_ERR(@9, (String("Array variable '") + name +
332                              "' was declared with size " + ToString(size) +
333                              " but " + ToString(args->argsCount()) +
334                              " values were assigned." ).c_str());
335                    $$ = new FunctionCall("nothing", new Args, NULL); // whatever          
336                } else {
337                    bool argsOK = true;
338                    for (int i = 0; i < args->argsCount(); ++i) {
339                        if (args->arg(i)->exprType() != INT_EXPR) {
340                            PARSE_ERR(
341                                @9,
342                                (String("Array variable '") + name +
343                                "' declared with invalid assignment values. Assigned element " +
344                                ToString(i+1) + " is not an integer expression.").c_str()
345                            );
346                            argsOK = false;
347                            break;
348                        }
349                        if (!args->arg(i)->isConstExpr()) {
350                            PARSE_ERR(
351                                @9,
352                                (String("const array variable '") + name +
353                                "' must be defined with const values. Assigned element " +
354                                ToString(i+1) + " is not a const expression though.").c_str()
355                            );
356                            argsOK = false;
357                            break;
358                        }
359                    }
360                    if (argsOK) {
361                        context->vartable[name] = new IntArrayVariable(context, size, args, true);
362                        $$ = new NoOperation;
363                    } else
364                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever
365              }              }
366          }          }
# Line 248  statement: Line 369  statement:
369          const char* name = $3;          const char* name = $3;
370          if ($5->exprType() == STRING_EXPR) {          if ($5->exprType() == STRING_EXPR) {
371              if (name[0] == '$')              if (name[0] == '$')
372                  PARSE_WRN("Variable declared as integer, string expression assigned though.");                  PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");
373              String s;              String s;
374              StringExprRef expr = $5;              StringExprRef expr = $5;
375              if (expr->isConstExpr())              if (expr->isConstExpr())
376                  s = expr->evalStr();                  s = expr->evalStr();
377              else              else
378                  PARSE_ERR((String("Assignment to const string variable '") + name + "' requires const expression.").c_str());                  PARSE_ERR(@5, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());
379              ConstStringVariableRef var = new ConstStringVariable(context, s);              ConstStringVariableRef var = new ConstStringVariable(context, s);
380              context->vartable[name] = var;              context->vartable[name] = var;
381              //$$ = new Assignment(var, new StringLiteral(s));              //$$ = new Assignment(var, new StringLiteral(s));
382              $$ = new NoOperation();              $$ = new NoOperation();
383          } else {          } else {
384              if (name[0] == '@')              if (name[0] == '@')
385                  PARSE_WRN("Variable declared as string, integer expression assigned though.");                  PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");
386              int i = 0;              int i = 0;
387              IntExprRef expr = $5;              IntExprRef expr = $5;
388              if (expr->isConstExpr())              if (expr->isConstExpr())
389                  i = expr->evalInt();                  i = expr->evalInt();
390              else              else
391                  PARSE_ERR((String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());                  PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
392              ConstIntVariableRef var = new ConstIntVariable(i);              ConstIntVariableRef var = new ConstIntVariable(i);
393              context->vartable[name] = var;              context->vartable[name] = var;
394              //$$ = new Assignment(var, new IntLiteral(i));              //$$ = new Assignment(var, new IntLiteral(i));
# Line 277  statement: Line 398  statement:
398      | assignment  {      | assignment  {
399          $$ = $1;          $$ = $1;
400      }      }
401      | WHILE '(' expr ')' statements END WHILE  {      | WHILE '(' expr ')' opt_statements END WHILE  {
402          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
403              $$ = new While($3, $5);              $$ = new While($3, $5);
404          } else {          } else {
405              PARSE_ERR("Condition for 'while' loops must be integer expression.");              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
406              $$ = new While(new IntLiteral(0), $5);              $$ = new While(new IntLiteral(0), $5);
407          }          }
408      }      }
409      | IF '(' expr ')' statements ELSE statements END IF  {      | SYNCHRONIZED opt_statements END SYNCHRONIZED  {
410            $$ = new SyncBlock($2);
411        }
412        | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {
413          $$ = new If($3, $5, $7);          $$ = new If($3, $5, $7);
414      }      }
415      | IF '(' expr ')' statements END IF  {      | IF '(' expr ')' opt_statements END IF  {
416          $$ = new If($3, $5);          $$ = new If($3, $5);
417      }      }
418      | SELECT expr caseclauses END SELECT  {      | SELECT expr caseclauses END SELECT  {
419          if ($2->exprType() == INT_EXPR) {          if ($2->exprType() == INT_EXPR) {
420              $$ = new SelectCase($2, $3);              $$ = new SelectCase($2, $3);
421          } else {          } else {
422              PARSE_ERR("Statement 'select' can only by applied to integer expressions.");              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
423              $$ = new SelectCase(new IntLiteral(0), $3);              $$ = new SelectCase(new IntLiteral(0), $3);
424          }          }
425      }      }
# Line 311  caseclauses: Line 435  caseclauses:
435      }      }
436    
437  caseclause:  caseclause:
438      CASE INTEGER statements  {      CASE INTEGER opt_statements  {
439          $$ = CaseBranch();          $$ = CaseBranch();
440          $$.from = new IntLiteral($2);          $$.from = new IntLiteral($2);
441          $$.statements = $3;          $$.statements = $3;
442      }      }
443      | CASE INTEGER TO INTEGER statements  {      | CASE INTEGER TO INTEGER opt_statements  {
444          $$ = CaseBranch();          $$ = CaseBranch();
445          $$.from = new IntLiteral($2);          $$.from = new IntLiteral($2);
446          $$.to   = new IntLiteral($4);          $$.to   = new IntLiteral($4);
447          $$.statements = $5;          $$.statements = $5;
448      }      }
449    
450    userfunctioncall:
451        CALL IDENTIFIER  {
452            const char* name = $2;
453            StatementsRef fn = context->userFunctionByName(name);
454            if (context->functionProvider->functionByName(name)) {
455                PARSE_ERR(@1, (String("Keyword 'call' must only be used for user defined functions, not for any built-in function like '") + name + "'.").c_str());
456                $$ = StatementsRef();
457            } else if (!fn) {
458                PARSE_ERR(@2, (String("No user defined function with name '") + name + "'.").c_str());
459                $$ = StatementsRef();
460            } else {
461                $$ = fn;
462            }
463        }
464    
465  functioncall:  functioncall:
466      IDENTIFIER '(' args ')'  {      IDENTIFIER '(' args ')'  {
467          const char* name = $1;          const char* name = $1;
468          //printf("function call of '%s' with args\n", name);          //printf("function call of '%s' with args\n", name);
469          ArgsRef args = $3;          ArgsRef args = $3;
470          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
471          if (!fn) {          if (context->userFunctionByName(name)) {
472              PARSE_ERR((String("No built-in function with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
473                $$ = new FunctionCall(name, args, NULL);
474            } else if (!fn) {
475                PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
476              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
477          } else if (args->argsCount() < fn->minRequiredArgs()) {          } else if (args->argsCount() < fn->minRequiredArgs()) {
478              PARSE_ERR((String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());              PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
479              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
480          } else if (args->argsCount() > fn->maxAllowedArgs()) {          } else if (args->argsCount() > fn->maxAllowedArgs()) {
481              PARSE_ERR((String("Built-in function '") + name + "' accepts max. " + ToString(fn->maxAllowedArgs()) + " arguments.").c_str());              PARSE_ERR(@3, (String("Built-in function '") + name + "' accepts max. " + ToString(fn->maxAllowedArgs()) + " arguments.").c_str());
482              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
483          } else {          } else {
484              bool argsOK = true;              bool argsOK = true;
485              for (int i = 0; i < args->argsCount(); ++i) {              for (int i = 0; i < args->argsCount(); ++i) {
486                  if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {                  if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {
487                      PARSE_ERR((String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects " + typeStr(fn->argType(i)) + " type, but type " + typeStr(args->arg(i)->exprType()) + " was given instead.").c_str());                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects " + typeStr(fn->argType(i)) + " type, but type " + typeStr(args->arg(i)->exprType()) + " was given instead.").c_str());
488                        argsOK = false;
489                        break;
490                    } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
491                        PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
492                      argsOK = false;                      argsOK = false;
493                      break;                      break;
494                  }                  }
# Line 355  functioncall: Line 501  functioncall:
501          //printf("function call of '%s' (with empty args)\n", name);          //printf("function call of '%s' (with empty args)\n", name);
502          ArgsRef args = new Args;          ArgsRef args = new Args;
503          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
504          if (!fn) {          if (context->userFunctionByName(name)) {
505              PARSE_ERR((String("No built-in function with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
506                $$ = new FunctionCall(name, args, NULL);
507            } else if (!fn) {
508                PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
509              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
510          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
511              PARSE_ERR((String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());              PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
512              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
513          } else {          } else {
514              $$ = new FunctionCall(name, args, fn);              $$ = new FunctionCall(name, args, fn);
# Line 370  functioncall: Line 519  functioncall:
519          //printf("function call of '%s' (without args)\n", name);          //printf("function call of '%s' (without args)\n", name);
520          ArgsRef args = new Args;          ArgsRef args = new Args;
521          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
522          if (!fn) {          if (context->userFunctionByName(name)) {
523              PARSE_ERR((String("No built-in function with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
524                $$ = new FunctionCall(name, args, NULL);
525            } else if (!fn) {
526                PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
527              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
528          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
529              PARSE_ERR((String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());              PARSE_ERR(@1, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
530              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
531          } else {          } else {
532              $$ = new FunctionCall(name, args, fn);              $$ = new FunctionCall(name, args, fn);
# Line 400  assignment: Line 552  assignment:
552          const char* name = $1;          const char* name = $1;
553          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
554          if (!var)          if (!var)
555              PARSE_ERR((String("Variable assignment: No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("Variable assignment: No variable declared with name '") + name + "'.").c_str());
556          else if (var->isConstExpr())          else if (var->isConstExpr())
557              PARSE_ERR((String("Variable assignment: Cannot modify const variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Variable assignment: Cannot modify const variable '") + name + "'.").c_str());
558            else if (!var->isAssignable())
559                PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
560          else if (var->exprType() != $3->exprType())          else if (var->exprType() != $3->exprType())
561              PARSE_ERR((String("Variable assignment: Variable '") + name + "' is of type " + typeStr(var->exprType()) + ", assignment is of type " + typeStr($3->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' is of type " + typeStr(var->exprType()) + ", assignment is of type " + typeStr($3->exprType()) + " though.").c_str());
562          $$ = new Assignment(var, $3);          $$ = new Assignment(var, $3);
563      }      }
564      | VARIABLE '[' expr ']' ASSIGNMENT expr  {      | VARIABLE '[' expr ']' ASSIGNMENT expr  {
565          const char* name = $1;          const char* name = $1;
566          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
567          if (!var)          if (!var)
568              PARSE_ERR((String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
569          else if (var->exprType() != INT_ARR_EXPR)          else if (var->exprType() != INT_ARR_EXPR)
570              PARSE_ERR((String("Variable '") + name + "' is not an array variable.").c_str());              PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
571            else if (var->isConstExpr())
572                PARSE_ERR(@5, (String("Variable assignment: Cannot modify const array variable '") + name + "'.").c_str());
573            else if (!var->isAssignable())
574                PARSE_ERR(@5, (String("Variable assignment: Array variable '") + name + "' is not assignable.").c_str());
575          else if ($3->exprType() != INT_EXPR)          else if ($3->exprType() != INT_EXPR)
576              PARSE_ERR((String("Array variable '") + name + "' accessed with non integer expression.").c_str());              PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
577          else if ($6->exprType() != INT_EXPR)          else if ($6->exprType() != INT_EXPR)
578              PARSE_ERR((String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());              PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());
579            else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())
580                PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
581                              " exceeds size of array variable '" + name +
582                              "' which was declared with size " +
583                              ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());
584          IntArrayElementRef element = new IntArrayElement(var, $3);          IntArrayElementRef element = new IntArrayElement(var, $3);
585          $$ = new Assignment(element, $6);          $$ = new Assignment(element, $6);
586      }      }
# Line 435  unary_expr: Line 598  unary_expr:
598          if (var)          if (var)
599              $$ = var;              $$ = var;
600          else {          else {
601              PARSE_ERR((String("No variable declared with name '") + $1 + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
602              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
603          }          }
604      }      }
# Line 443  unary_expr: Line 606  unary_expr:
606          const char* name = $1;          const char* name = $1;
607          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
608          if (!var) {          if (!var) {
609              PARSE_ERR((String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
610              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
611          } else if (var->exprType() != INT_ARR_EXPR) {          } else if (var->exprType() != INT_ARR_EXPR) {
612              PARSE_ERR((String("Variable '") + name + "' is not an array variable.").c_str());              PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
613              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
614          } else if ($3->exprType() != INT_EXPR) {          } else if ($3->exprType() != INT_EXPR) {
615              PARSE_ERR((String("Array variable '") + name + "' accessed with non integer expression.").c_str());              PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
616              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
617          } else {          } else {
618                if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())
619                    PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
620                                   " exceeds size of array variable '" + name +
621                                   "' which was declared with size " +
622                                   ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());
623              $$ = new IntArrayElement(var, $3);              $$ = new IntArrayElement(var, $3);
624          }          }
625      }      }
# Line 464  unary_expr: Line 632  unary_expr:
632      | '-' unary_expr  {      | '-' unary_expr  {
633          $$ = new Neg($2);          $$ = new Neg($2);
634      }      }
635        | BITWISE_NOT unary_expr  {
636            if ($2->exprType() != INT_EXPR) {
637                PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
638                $$ = new IntLiteral(0);
639            } else {
640                $$ = new BitwiseNot($2);
641            }
642        }
643      | NOT unary_expr  {      | NOT unary_expr  {
644          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
645              PARSE_ERR((String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());              PARSE_ERR(@2, (String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
646              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
647          } else {          } else {
648              $$ = new Not($2);              $$ = new Not($2);
# Line 477  expr: Line 653  expr:
653      concat_expr      concat_expr
654    
655  concat_expr:  concat_expr:
656      or_expr      logical_or_expr
657      | concat_expr '&' or_expr  {      | concat_expr '&' logical_or_expr  {
658          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
659          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
660          if (lhs->isConstExpr() && rhs->isConstExpr()) {          if (lhs->isConstExpr() && rhs->isConstExpr()) {
# Line 490  concat_expr: Line 666  concat_expr:
666          }          }
667      }      }
668    
669  or_expr:  logical_or_expr:
670      and_expr      logical_and_expr
671      | or_expr OR and_expr  {      | logical_or_expr OR logical_and_expr  {
672          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
673          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
674          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
675              PARSE_ERR((String("Left operand of operator 'or' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator 'or' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
676              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
677          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
678              PARSE_ERR((String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
679              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
680          } else {          } else {
681              $$ = new Or(lhs, rhs);              $$ = new Or(lhs, rhs);
682          }          }
683      }      }
684    
685  and_expr:  logical_and_expr:
686      rel_expr  {      bitwise_or_expr  {
687          $$ = $1;          $$ = $1;
688      }      }
689      | and_expr AND rel_expr  {      | logical_and_expr AND bitwise_or_expr  {
690          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
691          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
692          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
693              PARSE_ERR((String("Left operand of operator 'and' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator 'and' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
694              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
695          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
696              PARSE_ERR((String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
697              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
698          } else {          } else {
699              $$ = new And(lhs, rhs);              $$ = new And(lhs, rhs);
700          }          }
701      }      }
702    
703    bitwise_or_expr:
704        bitwise_and_expr
705        | bitwise_or_expr BITWISE_OR bitwise_and_expr  {
706            ExpressionRef lhs = $1;
707            ExpressionRef rhs = $3;
708            if (lhs->exprType() != INT_EXPR) {
709                PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
710                $$ = new IntLiteral(0);
711            } else if (rhs->exprType() != INT_EXPR) {
712                PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
713                $$ = new IntLiteral(0);
714            } else {
715                $$ = new BitwiseOr(lhs, rhs);
716            }
717        }
718    
719    bitwise_and_expr:
720        rel_expr  {
721            $$ = $1;
722        }
723        | bitwise_and_expr BITWISE_AND rel_expr  {
724            ExpressionRef lhs = $1;
725            ExpressionRef rhs = $3;
726            if (lhs->exprType() != INT_EXPR) {
727                PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
728                $$ = new IntLiteral(0);
729            } else if (rhs->exprType() != INT_EXPR) {
730                PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
731                $$ = new IntLiteral(0);
732            } else {
733                $$ = new BitwiseAnd(lhs, rhs);
734            }
735        }
736    
737  rel_expr:  rel_expr:
738        add_expr        add_expr
739      | rel_expr '<' add_expr  {      | rel_expr '<' add_expr  {
740          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
741          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
742          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
743              PARSE_ERR((String("Left operand of operator '<' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '<' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
744              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
745          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
746              PARSE_ERR((String("Right operand of operator '<' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '<' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
747              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
748          } else {          } else {
749              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
# Line 543  rel_expr: Line 753  rel_expr:
753          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
754          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
755          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
756              PARSE_ERR((String("Left operand of operator '>' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '>' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
757              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
758          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
759              PARSE_ERR((String("Right operand of operator '>' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '>' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
760              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
761          } else {          } else {
762              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
# Line 556  rel_expr: Line 766  rel_expr:
766          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
767          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
768          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
769              PARSE_ERR((String("Left operand of operator '<=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '<=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
770              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
771          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
772              PARSE_ERR((String("Right operand of operator '<=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '<=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
773              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
774          } else {          } else {
775              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
# Line 569  rel_expr: Line 779  rel_expr:
779          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
780          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
781          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
782              PARSE_ERR((String("Left operand of operator '>=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '>=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
783              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
784          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
785              PARSE_ERR((String("Right operand of operator '>=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '>=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
786              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
787          } else {          } else {
788              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
# Line 591  add_expr: Line 801  add_expr:
801          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
802          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
803          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
804              PARSE_ERR((String("Left operand of operator '+' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '+' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
805              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
806          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
807              PARSE_ERR((String("Right operand of operator '+' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '+' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
808              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
809          } else {          } else {
810              $$ = new Add(lhs,rhs);              $$ = new Add(lhs,rhs);
# Line 604  add_expr: Line 814  add_expr:
814          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
815          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
816          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
817              PARSE_ERR((String("Left operand of operator '-' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '-' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
818              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
819          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
820              PARSE_ERR((String("Right operand of operator '-' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '-' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
821              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
822          } else {          } else {
823              $$ = new Sub(lhs,rhs);              $$ = new Sub(lhs,rhs);
# Line 620  mul_expr: Line 830  mul_expr:
830          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
831          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
832          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
833              PARSE_ERR((String("Left operand of operator '*' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '*' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
834              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
835          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
836              PARSE_ERR((String("Right operand of operator '*' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '*' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
837              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
838          } else {          } else {
839              $$ = new Mul(lhs,rhs);              $$ = new Mul(lhs,rhs);
# Line 633  mul_expr: Line 843  mul_expr:
843          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
844          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
845          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
846              PARSE_ERR((String("Left operand of operator '/' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '/' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
847              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
848          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
849              PARSE_ERR((String("Right operand of operator '/' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '/' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
850              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
851          } else {          } else {
852              $$ = new Div(lhs,rhs);              $$ = new Div(lhs,rhs);
# Line 646  mul_expr: Line 856  mul_expr:
856          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
857          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
858          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
859              PARSE_ERR((String("Left operand of modulo operator must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of modulo operator must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
860              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
861          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
862              PARSE_ERR((String("Right operand of modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
863              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
864          } else {          } else {
865              $$ = new Mod(lhs,rhs);              $$ = new Mod(lhs,rhs);
# Line 660  mul_expr: Line 870  mul_expr:
870    
871  void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {  void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
872      //fprintf(stderr, "%d: %s\n", locp->first_line, err);      //fprintf(stderr, "%d: %s\n", locp->first_line, err);
873      context->addErr(locp->first_line, err);      context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);
874  }  }
875    
876  void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {  void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
877      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
878      context->addWrn(locp->first_line, txt);      context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
879    }
880    
881    /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.
882    int InstrScript_tnamerr(char* yyres, const char* yystr) {
883      if (*yystr == '"') {
884          int yyn = 0;
885          char const *yyp = yystr;
886          for (;;)
887            switch (*++yyp)
888              {
889    /*
890              case '\'':
891              case ',':
892                goto do_not_strip_quotes;
893    
894              case '\\':
895                if (*++yyp != '\\')
896                  goto do_not_strip_quotes;
897    */
898                /* Fall through.  */
899              default:
900                if (yyres)
901                  yyres[yyn] = *yyp;
902                yyn++;
903                break;
904    
905              case '"':
906                if (yyres)
907                  yyres[yyn] = '\0';
908                return yyn;
909              }
910    /*
911        do_not_strip_quotes: ;
912    */
913        }
914    
915      if (! yyres)
916        return (int) yystrlen (yystr);
917    
918      return int( yystpcpy (yyres, yystr) - yyres );
919  }  }

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

  ViewVC Help
Powered by ViewVC