/[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 2581 by schoenebeck, Fri May 30 12:48:05 2014 UTC revision 3008 by schoenebeck, Tue Oct 11 18:25:12 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   *   *
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 32  Line 36 
36  %defines  %defines
37  %error-verbose  %error-verbose
38    
39  %token <iValue> INTEGER  %token <iValue> INTEGER "integer literal"
40  %token <sValue> STRING  %token <sValue> STRING "string literal"
41  %token <sValue> IDENTIFIER  %token <sValue> IDENTIFIER "function name"
42  %token <sValue> VARIABLE  %token <sValue> VARIABLE "variable name"
43  %token ON END INIT NOTE DECLARE ASSIGNMENT WHILE IF OR RELEASE AND ELSE  %token ON "keyword 'on'"
44  %token CONTROLLER SELECT CASE TO NOT CONST POLYPHONIC MOD  %token END "keyword 'end'"
45  %token LE GE  %token INIT "keyword 'init'"
46    %token NOTE "keyword 'note'"
47  %type <nEventHandlers> script eventhandlers  %token RELEASE "keyword 'release'"
48  %type <nEventHandler> eventhandler  %token CONTROLLER "keyword 'controller'"
49  %type <nStatements> statements  %token DECLARE "keyword 'declare'"
50    %token ASSIGNMENT "operator ':='"
51    %token CONST_ "keyword 'const'"
52    %token POLYPHONIC "keyword 'polyphonic'"
53    %token WHILE "keyword 'while'"
54    %token IF "keyword 'if'"
55    %token ELSE "keyword 'else'"
56    %token SELECT "keyword 'select'"
57    %token CASE "keyword 'case'"
58    %token TO "keyword 'to'"
59    %token OR "operator 'or'"
60    %token AND "operator 'and'"
61    %token NOT "operator 'not'"
62    %token BITWISE_OR "bitwise operator '.or.'"
63    %token BITWISE_AND "bitwise operator '.and.'"
64    %token BITWISE_NOT "bitwise operator '.not.'"
65    %token FUNCTION "keyword 'function'"
66    %token CALL "keyword 'call'"
67    %token MOD "operator 'mod'"
68    %token LE "operator '<='"
69    %token GE "operator '>='"
70    %token END_OF_FILE 0 "end of file"
71    
72    %type <nEventHandlers> script sections
73    %type <nEventHandler> section eventhandler
74    %type <nStatements> statements opt_statements userfunctioncall
75  %type <nStatement> statement assignment  %type <nStatement> statement assignment
76  %type <nFunctionCall> functioncall  %type <nFunctionCall> functioncall
77  %type <nArgs> args  %type <nArgs> args
78  %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
79  %type <nCaseBranch> caseclause  %type <nCaseBranch> caseclause
80  %type <nCaseBranches> caseclauses  %type <nCaseBranches> caseclauses
81    
# Line 55  Line 84 
84  %%  %%
85    
86  script:  script:
87      eventhandlers  {      sections  {
88          $$ = context->handlers = $1;          $$ = context->handlers = $1;
89      }      }
90    
91  eventhandlers:  sections:
92      eventhandler  {      section  {
93          $$ = new EventHandlers();          $$ = new EventHandlers();
94          $$->add($1);          if ($1) $$->add($1);
95        }
96        | sections section  {
97            $$ = $1;
98            if ($2) $$->add($2);
99        }
100    
101    section:
102        function_declaration  {
103            $$ = EventHandlerRef();
104      }      }
105      | eventhandlers eventhandler  {      | eventhandler  {
106          $$ = $1;          $$ = $1;
         $$->add($2);  
107      }      }
108    
109  eventhandler:  eventhandler:
110      ON NOTE statements END ON  {      ON NOTE opt_statements END ON  {
111          if (context->onNote)          if (context->onNote)
112              PARSE_ERR("Redeclaration of 'note' event handler.");              PARSE_ERR(@2, "Redeclaration of 'note' event handler.");
113          context->onNote = new OnNote($3);          context->onNote = new OnNote($3);
114          $$ = context->onNote;          $$ = context->onNote;
115      }      }
116      | ON INIT statements END ON  {      | ON INIT opt_statements END ON  {
117          if (context->onInit)          if (context->onInit)
118              PARSE_ERR("Redeclaration of 'init' event handler.");              PARSE_ERR(@2, "Redeclaration of 'init' event handler.");
119          context->onInit = new OnInit($3);          context->onInit = new OnInit($3);
120          $$ = context->onInit;          $$ = context->onInit;
121      }      }
122      | ON RELEASE statements END ON  {      | ON RELEASE opt_statements END ON  {
123          if (context->onRelease)          if (context->onRelease)
124              PARSE_ERR("Redeclaration of 'release' event handler.");              PARSE_ERR(@2, "Redeclaration of 'release' event handler.");
125          context->onRelease = new OnRelease($3);          context->onRelease = new OnRelease($3);
126          $$ = context->onRelease;          $$ = context->onRelease;
127      }      }
128      | ON CONTROLLER statements END ON  {      | ON CONTROLLER opt_statements END ON  {
129          if (context->onController)          if (context->onController)
130              PARSE_ERR("Redeclaration of 'controller' event handler.");              PARSE_ERR(@2, "Redeclaration of 'controller' event handler.");
131          context->onController = new OnController($3);          context->onController = new OnController($3);
132          $$ = context->onController;          $$ = context->onController;
133      }      }
134    
135    function_declaration:
136        FUNCTION IDENTIFIER opt_statements END FUNCTION  {
137            const char* name = $2;
138            if (context->functionProvider->functionByName(name)) {
139                PARSE_ERR(@2, (String("There is already a built-in function with name '") + name + "'.").c_str());
140            } else if (context->userFunctionByName(name)) {
141                PARSE_ERR(@2, (String("There is already a user defined function with name '") + name + "'.").c_str());
142            } else {
143                context->userFnTable[name] = $3;
144            }
145        }
146    
147    opt_statements:
148        /* epsilon (empty argument) */  {
149            $$ = new Statements();
150        }
151        | statements  {
152            $$ = $1;
153        }
154    
155  statements:  statements:
156      statement  {      statement  {
157          $$ = new Statements();          $$ = new Statements();
158          if ($1) {          if ($1) {
159              if (!isNoOperation($1)) $$->add($1); // filter out NoOperation statements              if (!isNoOperation($1)) $$->add($1); // filter out NoOperation statements
160          } else          } else
161              PARSE_WRN("Not a statement.");              PARSE_WRN(@1, "Not a statement.");
162      }      }
163      | statements statement  {      | statements statement  {
164          $$ = $1;          $$ = $1;
165          if ($2) {          if ($2) {
166              if (!isNoOperation($2)) $$->add($2); // filter out NoOperation statements              if (!isNoOperation($2)) $$->add($2); // filter out NoOperation statements
167          } else          } else
168              PARSE_WRN("Not a statement.");              PARSE_WRN(@2, "Not a statement.");
169      }      }
170    
171  statement:  statement:
172      functioncall  {      functioncall  {
173          $$ = $1;          $$ = $1;
174      }      }
175        | userfunctioncall  {
176            $$ = $1;
177        }
178      | DECLARE VARIABLE  {      | DECLARE VARIABLE  {
179          const char* name = $2;          const char* name = $2;
180          //printf("declared var '%s'\n", name);          //printf("declared var '%s'\n", name);
181          if (context->variableByName(name))          if (context->variableByName(name))
182              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
183          if (name[0] == '@') {          if (name[0] == '@') {
184              context->vartable[name] = new StringVariable(context);              context->vartable[name] = new StringVariable(context);
185              $$ = new NoOperation;              $$ = new NoOperation;
# Line 132  statement: Line 192  statement:
192          const char* name = $3;          const char* name = $3;
193          //printf("declared polyphonic var '%s'\n", name);          //printf("declared polyphonic var '%s'\n", name);
194          if (context->variableByName(name))          if (context->variableByName(name))
195              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
196          if (name[0] != '$') {          if (name[0] != '$') {
197              PARSE_ERR("Polyphonic variables may only be declared as integers.");              PARSE_ERR(@3, "Polyphonic variables may only be declared as integers.");
198              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
199          } else {          } else {
200              context->vartable[name] = new PolyphonicIntVariable(context);              context->vartable[name] = new PolyphonicIntVariable(context);
# Line 145  statement: Line 205  statement:
205          const char* name = $2;          const char* name = $2;
206          //printf("declared assign var '%s'\n", name);          //printf("declared assign var '%s'\n", name);
207          if (context->variableByName(name))          if (context->variableByName(name))
208              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
209          if ($4->exprType() == STRING_EXPR) {          if ($4->exprType() == STRING_EXPR) {
210              if (name[0] == '$')              if (name[0] == '$')
211                  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());
212              StringExprRef expr = $4;              StringExprRef expr = $4;
213              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
214                  const String s = expr->evalStr();                  const String s = expr->evalStr();
# Line 162  statement: Line 222  statement:
222              }              }
223          } else {          } else {
224              if (name[0] == '@')              if (name[0] == '@')
225                  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());
226              IntExprRef expr = $4;              IntExprRef expr = $4;
227              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
228                  const int i = expr->evalInt();                  const int i = expr->evalInt();
# Line 180  statement: Line 240  statement:
240          //printf("declare array without args\n");          //printf("declare array without args\n");
241          const char* name = $2;          const char* name = $2;
242          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
243              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());
244              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
245          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
246              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());
247              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
248          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
249              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
250              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
251          } else {          } else {
252              IntExprRef expr = $4;              IntExprRef expr = $4;
253              int size = expr->evalInt();              int size = expr->evalInt();
254              if (size <= 0) {              if (size <= 0) {
255                  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());
256                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever
257              } else {              } else {
258                  context->vartable[name] = new IntArrayVariable(context, size);                  context->vartable[name] = new IntArrayVariable(context, size);
# Line 203  statement: Line 263  statement:
263      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
264          const char* name = $2;          const char* name = $2;
265          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
266              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());
267              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
268          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
269              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());
270              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
271          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
272              PARSE_ERR((String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
273              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
274          } else {          } else {
275              IntExprRef sizeExpr = $4;              IntExprRef sizeExpr = $4;
276              ArgsRef args = $8;              ArgsRef args = $8;
277              int size = sizeExpr->evalInt();              int size = sizeExpr->evalInt();
278              if (size <= 0) {              if (size <= 0) {
279                  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());
280                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever
281              } else if (args->argsCount() > size) {              } else if (args->argsCount() > size) {
282                  PARSE_ERR((String("Variable '") + name +                  PARSE_ERR(@8, (String("Variable '") + name +
283                            "' was declared with size " + ToString(size) +                            "' was declared with size " + ToString(size) +
284                            " but " + ToString(args->argsCount()) +                            " but " + ToString(args->argsCount()) +
285                            " values were assigned." ).c_str());                            " values were assigned." ).c_str());
# Line 229  statement: Line 289  statement:
289                  for (int i = 0; i < args->argsCount(); ++i) {                  for (int i = 0; i < args->argsCount(); ++i) {
290                      if (args->arg(i)->exprType() != INT_EXPR) {                      if (args->arg(i)->exprType() != INT_EXPR) {
291                          PARSE_ERR(                          PARSE_ERR(
292                                @8,
293                              (String("Array variable '") + name +                              (String("Array variable '") + name +
294                              "' declared with invalid assignment values. Assigned element " +                              "' declared with invalid assignment values. Assigned element " +
295                              ToString(i+1) + " is not an integer expression.").c_str()                              ToString(i+1) + " is not an integer expression.").c_str()
# Line 244  statement: Line 305  statement:
305              }              }
306          }          }
307      }      }
308      | DECLARE CONST VARIABLE ASSIGNMENT expr  {      | DECLARE CONST_ VARIABLE ASSIGNMENT expr  {
309          const char* name = $3;          const char* name = $3;
310          if ($5->exprType() == STRING_EXPR) {          if ($5->exprType() == STRING_EXPR) {
311              if (name[0] == '$')              if (name[0] == '$')
312                  PARSE_WRN("Variable declared as integer, string expression assigned though.");                  PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");
313              String s;              String s;
314              StringExprRef expr = $5;              StringExprRef expr = $5;
315              if (expr->isConstExpr())              if (expr->isConstExpr())
316                  s = expr->evalStr();                  s = expr->evalStr();
317              else              else
318                  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());
319              ConstStringVariableRef var = new ConstStringVariable(context, s);              ConstStringVariableRef var = new ConstStringVariable(context, s);
320              context->vartable[name] = var;              context->vartable[name] = var;
321              //$$ = new Assignment(var, new StringLiteral(s));              //$$ = new Assignment(var, new StringLiteral(s));
322              $$ = new NoOperation();              $$ = new NoOperation();
323          } else {          } else {
324              if (name[0] == '@')              if (name[0] == '@')
325                  PARSE_WRN("Variable declared as string, integer expression assigned though.");                  PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");
326              int i = 0;              int i = 0;
327              IntExprRef expr = $5;              IntExprRef expr = $5;
328              if (expr->isConstExpr())              if (expr->isConstExpr())
329                  i = expr->evalInt();                  i = expr->evalInt();
330              else              else
331                  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());
332              ConstIntVariableRef var = new ConstIntVariable(i);              ConstIntVariableRef var = new ConstIntVariable(i);
333              context->vartable[name] = var;              context->vartable[name] = var;
334              //$$ = new Assignment(var, new IntLiteral(i));              //$$ = new Assignment(var, new IntLiteral(i));
# Line 277  statement: Line 338  statement:
338      | assignment  {      | assignment  {
339          $$ = $1;          $$ = $1;
340      }      }
341      | WHILE '(' expr ')' statements END WHILE  {      | WHILE '(' expr ')' opt_statements END WHILE  {
342          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
343              $$ = new While($3, $5);              $$ = new While($3, $5);
344          } else {          } else {
345              PARSE_ERR("Condition for 'while' loops must be integer expression.");              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
346              $$ = new While(new IntLiteral(0), $5);              $$ = new While(new IntLiteral(0), $5);
347          }          }
348      }      }
349      | IF '(' expr ')' statements ELSE statements END IF  {      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {
350          $$ = new If($3, $5, $7);          $$ = new If($3, $5, $7);
351      }      }
352      | IF '(' expr ')' statements END IF  {      | IF '(' expr ')' opt_statements END IF  {
353          $$ = new If($3, $5);          $$ = new If($3, $5);
354      }      }
355      | SELECT expr caseclauses END SELECT  {      | SELECT expr caseclauses END SELECT  {
356          if ($2->exprType() == INT_EXPR) {          if ($2->exprType() == INT_EXPR) {
357              $$ = new SelectCase($2, $3);              $$ = new SelectCase($2, $3);
358          } else {          } else {
359              PARSE_ERR("Statement 'select' can only by applied to integer expressions.");              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
360              $$ = new SelectCase(new IntLiteral(0), $3);              $$ = new SelectCase(new IntLiteral(0), $3);
361          }          }
362      }      }
# Line 311  caseclauses: Line 372  caseclauses:
372      }      }
373    
374  caseclause:  caseclause:
375      CASE INTEGER statements  {      CASE INTEGER opt_statements  {
376          $$ = CaseBranch();          $$ = CaseBranch();
377          $$.from = new IntLiteral($2);          $$.from = new IntLiteral($2);
378          $$.statements = $3;          $$.statements = $3;
379      }      }
380      | CASE INTEGER TO INTEGER statements  {      | CASE INTEGER TO INTEGER opt_statements  {
381          $$ = CaseBranch();          $$ = CaseBranch();
382          $$.from = new IntLiteral($2);          $$.from = new IntLiteral($2);
383          $$.to   = new IntLiteral($4);          $$.to   = new IntLiteral($4);
384          $$.statements = $5;          $$.statements = $5;
385      }      }
386    
387    userfunctioncall:
388        CALL IDENTIFIER  {
389            const char* name = $2;
390            StatementsRef fn = context->userFunctionByName(name);
391            if (context->functionProvider->functionByName(name)) {
392                PARSE_ERR(@1, (String("Keyword 'call' must only be used for user defined functions, not for any built-in function like '") + name + "'.").c_str());
393                $$ = StatementsRef();
394            } else if (!fn) {
395                PARSE_ERR(@2, (String("No user defined function with name '") + name + "'.").c_str());
396                $$ = StatementsRef();
397            } else {
398                $$ = fn;
399            }
400        }
401    
402  functioncall:  functioncall:
403      IDENTIFIER '(' args ')'  {      IDENTIFIER '(' args ')'  {
404          const char* name = $1;          const char* name = $1;
405          //printf("function call of '%s' with args\n", name);          //printf("function call of '%s' with args\n", name);
406          ArgsRef args = $3;          ArgsRef args = $3;
407          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
408          if (!fn) {          if (context->userFunctionByName(name)) {
409              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());
410                $$ = new FunctionCall(name, args, NULL);
411            } else if (!fn) {
412                PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
413              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
414          } else if (args->argsCount() < fn->minRequiredArgs()) {          } else if (args->argsCount() < fn->minRequiredArgs()) {
415              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());
416              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
417          } else if (args->argsCount() > fn->maxAllowedArgs()) {          } else if (args->argsCount() > fn->maxAllowedArgs()) {
418              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());
419              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
420          } else {          } else {
421              bool argsOK = true;              bool argsOK = true;
422              for (int i = 0; i < args->argsCount(); ++i) {              for (int i = 0; i < args->argsCount(); ++i) {
423                  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())) {
424                      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());
425                        argsOK = false;
426                        break;
427                    } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
428                        PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
429                      argsOK = false;                      argsOK = false;
430                      break;                      break;
431                  }                  }
# Line 355  functioncall: Line 438  functioncall:
438          //printf("function call of '%s' (with empty args)\n", name);          //printf("function call of '%s' (with empty args)\n", name);
439          ArgsRef args = new Args;          ArgsRef args = new Args;
440          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
441          if (!fn) {          if (context->userFunctionByName(name)) {
442              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());
443                $$ = new FunctionCall(name, args, NULL);
444            } else if (!fn) {
445                PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
446              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
447          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
448              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());
449              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
450          } else {          } else {
451              $$ = new FunctionCall(name, args, fn);              $$ = new FunctionCall(name, args, fn);
# Line 370  functioncall: Line 456  functioncall:
456          //printf("function call of '%s' (without args)\n", name);          //printf("function call of '%s' (without args)\n", name);
457          ArgsRef args = new Args;          ArgsRef args = new Args;
458          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
459          if (!fn) {          if (context->userFunctionByName(name)) {
460              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());
461                $$ = new FunctionCall(name, args, NULL);
462            } else if (!fn) {
463                PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
464              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
465          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
466              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());
467              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
468          } else {          } else {
469              $$ = new FunctionCall(name, args, fn);              $$ = new FunctionCall(name, args, fn);
# Line 400  assignment: Line 489  assignment:
489          const char* name = $1;          const char* name = $1;
490          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
491          if (!var)          if (!var)
492              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());
493          else if (var->isConstExpr())          else if (var->isConstExpr())
494              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());
495            else if (!var->isAssignable())
496                PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
497          else if (var->exprType() != $3->exprType())          else if (var->exprType() != $3->exprType())
498              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());
499          $$ = new Assignment(var, $3);          $$ = new Assignment(var, $3);
500      }      }
501      | VARIABLE '[' expr ']' ASSIGNMENT expr  {      | VARIABLE '[' expr ']' ASSIGNMENT expr  {
502          const char* name = $1;          const char* name = $1;
503          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
504          if (!var)          if (!var)
505              PARSE_ERR((String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
506          else if (var->exprType() != INT_ARR_EXPR)          else if (var->exprType() != INT_ARR_EXPR)
507              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());
508          else if ($3->exprType() != INT_EXPR)          else if ($3->exprType() != INT_EXPR)
509              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());
510          else if ($6->exprType() != INT_EXPR)          else if ($6->exprType() != INT_EXPR)
511              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());
512          IntArrayElementRef element = new IntArrayElement(var, $3);          IntArrayElementRef element = new IntArrayElement(var, $3);
513          $$ = new Assignment(element, $6);          $$ = new Assignment(element, $6);
514      }      }
# Line 435  unary_expr: Line 526  unary_expr:
526          if (var)          if (var)
527              $$ = var;              $$ = var;
528          else {          else {
529              PARSE_ERR((String("No variable declared with name '") + $1 + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
530              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
531          }          }
532      }      }
# Line 443  unary_expr: Line 534  unary_expr:
534          const char* name = $1;          const char* name = $1;
535          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
536          if (!var) {          if (!var) {
537              PARSE_ERR((String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
538              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
539          } else if (var->exprType() != INT_ARR_EXPR) {          } else if (var->exprType() != INT_ARR_EXPR) {
540              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());
541              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
542          } else if ($3->exprType() != INT_EXPR) {          } else if ($3->exprType() != INT_EXPR) {
543              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());
544              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
545          } else {          } else {
546              $$ = new IntArrayElement(var, $3);              $$ = new IntArrayElement(var, $3);
# Line 464  unary_expr: Line 555  unary_expr:
555      | '-' unary_expr  {      | '-' unary_expr  {
556          $$ = new Neg($2);          $$ = new Neg($2);
557      }      }
558        | BITWISE_NOT unary_expr  {
559            if ($2->exprType() != INT_EXPR) {
560                PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
561                $$ = new IntLiteral(0);
562            } else {
563                $$ = new BitwiseNot($2);
564            }
565        }
566      | NOT unary_expr  {      | NOT unary_expr  {
567          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
568              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());
569              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
570          } else {          } else {
571              $$ = new Not($2);              $$ = new Not($2);
# Line 477  expr: Line 576  expr:
576      concat_expr      concat_expr
577    
578  concat_expr:  concat_expr:
579      or_expr      logical_or_expr
580      | concat_expr '&' or_expr  {      | concat_expr '&' logical_or_expr  {
581          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
582          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
583          if (lhs->isConstExpr() && rhs->isConstExpr()) {          if (lhs->isConstExpr() && rhs->isConstExpr()) {
# Line 490  concat_expr: Line 589  concat_expr:
589          }          }
590      }      }
591    
592  or_expr:  logical_or_expr:
593      and_expr      logical_and_expr
594      | or_expr OR and_expr  {      | logical_or_expr OR logical_and_expr  {
595          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
596          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
597          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
598              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());
599              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
600          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
601              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());
602              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
603          } else {          } else {
604              $$ = new Or(lhs, rhs);              $$ = new Or(lhs, rhs);
605          }          }
606      }      }
607    
608  and_expr:  logical_and_expr:
609      rel_expr  {      bitwise_or_expr  {
610          $$ = $1;          $$ = $1;
611      }      }
612      | and_expr AND rel_expr  {      | logical_and_expr AND bitwise_or_expr  {
613          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
614          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
615          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
616              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());
617              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
618          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
619              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());
620              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
621          } else {          } else {
622              $$ = new And(lhs, rhs);              $$ = new And(lhs, rhs);
623          }          }
624      }      }
625    
626    bitwise_or_expr:
627        bitwise_and_expr
628        | bitwise_or_expr BITWISE_OR bitwise_and_expr  {
629            ExpressionRef lhs = $1;
630            ExpressionRef rhs = $3;
631            if (lhs->exprType() != INT_EXPR) {
632                PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
633                $$ = new IntLiteral(0);
634            } else if (rhs->exprType() != INT_EXPR) {
635                PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
636                $$ = new IntLiteral(0);
637            } else {
638                $$ = new BitwiseOr(lhs, rhs);
639            }
640        }
641    
642    bitwise_and_expr:
643        rel_expr  {
644            $$ = $1;
645        }
646        | bitwise_and_expr BITWISE_AND rel_expr  {
647            ExpressionRef lhs = $1;
648            ExpressionRef rhs = $3;
649            if (lhs->exprType() != INT_EXPR) {
650                PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
651                $$ = new IntLiteral(0);
652            } else if (rhs->exprType() != INT_EXPR) {
653                PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
654                $$ = new IntLiteral(0);
655            } else {
656                $$ = new BitwiseAnd(lhs, rhs);
657            }
658        }
659    
660  rel_expr:  rel_expr:
661        add_expr        add_expr
662      | rel_expr '<' add_expr  {      | rel_expr '<' add_expr  {
663          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
664          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
665          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
666              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());
667              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
668          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
669              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());
670              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
671          } else {          } else {
672              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
# Line 543  rel_expr: Line 676  rel_expr:
676          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
677          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
678          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
679              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());
680              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
681          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
682              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());
683              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
684          } else {          } else {
685              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
# Line 556  rel_expr: Line 689  rel_expr:
689          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
690          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
691          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
692              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());
693              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
694          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
695              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());
696              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
697          } else {          } else {
698              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
# Line 569  rel_expr: Line 702  rel_expr:
702          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
703          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
704          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
705              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());
706              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
707          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
708              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());
709              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
710          } else {          } else {
711              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
# Line 591  add_expr: Line 724  add_expr:
724          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
725          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
726          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
727              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());
728              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
729          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
730              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());
731              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
732          } else {          } else {
733              $$ = new Add(lhs,rhs);              $$ = new Add(lhs,rhs);
# Line 604  add_expr: Line 737  add_expr:
737          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
738          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
739          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
740              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());
741              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
742          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
743              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());
744              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
745          } else {          } else {
746              $$ = new Sub(lhs,rhs);              $$ = new Sub(lhs,rhs);
# Line 620  mul_expr: Line 753  mul_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 Mul(lhs,rhs);              $$ = new Mul(lhs,rhs);
# Line 633  mul_expr: Line 766  mul_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 Div(lhs,rhs);              $$ = new Div(lhs,rhs);
# Line 646  mul_expr: Line 779  mul_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 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());
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 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());
786              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
787          } else {          } else {
788              $$ = new Mod(lhs,rhs);              $$ = new Mod(lhs,rhs);
# Line 660  mul_expr: Line 793  mul_expr:
793    
794  void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {  void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
795      //fprintf(stderr, "%d: %s\n", locp->first_line, err);      //fprintf(stderr, "%d: %s\n", locp->first_line, err);
796      context->addErr(locp->first_line, err);      context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);
797  }  }
798    
799  void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {  void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
800      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
801      context->addWrn(locp->first_line, txt);      context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
802    }
803    
804    /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.
805    int InstrScript_tnamerr(char* yyres, const char* yystr) {
806      if (*yystr == '"') {
807          int yyn = 0;
808          char const *yyp = yystr;
809          for (;;)
810            switch (*++yyp)
811              {
812    /*
813              case '\'':
814              case ',':
815                goto do_not_strip_quotes;
816    
817              case '\\':
818                if (*++yyp != '\\')
819                  goto do_not_strip_quotes;
820    */
821                /* Fall through.  */
822              default:
823                if (yyres)
824                  yyres[yyn] = *yyp;
825                yyn++;
826                break;
827    
828              case '"':
829                if (yyres)
830                  yyres[yyn] = '\0';
831                return yyn;
832              }
833        do_not_strip_quotes: ;
834        }
835    
836      if (! yyres)
837        return yystrlen (yystr);
838    
839      return yystpcpy (yyres, yystr) - yyres;
840  }  }

Legend:
Removed from v.2581  
changed lines
  Added in v.3008

  ViewVC Help
Powered by ViewVC