/[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 3013 by schoenebeck, Sat Oct 15 23:54:27 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 237  statement: Line 298  statement:
298                          break;                          break;
299                      }                      }
300                  }                  }
301                  if (argsOK)                  if (argsOK) {
302                      $$ = context->vartable[name] = new IntArrayVariable(context, size, args);                      context->vartable[name] = new IntArrayVariable(context, size, args);
303                  else                      $$ = new NoOperation;
304                    } else
305                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever
306              }              }
307          }          }
308      }      }
309      | DECLARE CONST VARIABLE ASSIGNMENT expr  {      | DECLARE CONST_ VARIABLE ASSIGNMENT expr  {
310          const char* name = $3;          const char* name = $3;
311          if ($5->exprType() == STRING_EXPR) {          if ($5->exprType() == STRING_EXPR) {
312              if (name[0] == '$')              if (name[0] == '$')
313                  PARSE_WRN("Variable declared as integer, string expression assigned though.");                  PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");
314              String s;              String s;
315              StringExprRef expr = $5;              StringExprRef expr = $5;
316              if (expr->isConstExpr())              if (expr->isConstExpr())
317                  s = expr->evalStr();                  s = expr->evalStr();
318              else              else
319                  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());
320              ConstStringVariableRef var = new ConstStringVariable(context, s);              ConstStringVariableRef var = new ConstStringVariable(context, s);
321              context->vartable[name] = var;              context->vartable[name] = var;
322              //$$ = new Assignment(var, new StringLiteral(s));              //$$ = new Assignment(var, new StringLiteral(s));
323              $$ = new NoOperation();              $$ = new NoOperation();
324          } else {          } else {
325              if (name[0] == '@')              if (name[0] == '@')
326                  PARSE_WRN("Variable declared as string, integer expression assigned though.");                  PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");
327              int i = 0;              int i = 0;
328              IntExprRef expr = $5;              IntExprRef expr = $5;
329              if (expr->isConstExpr())              if (expr->isConstExpr())
330                  i = expr->evalInt();                  i = expr->evalInt();
331              else              else
332                  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());
333              ConstIntVariableRef var = new ConstIntVariable(i);              ConstIntVariableRef var = new ConstIntVariable(i);
334              context->vartable[name] = var;              context->vartable[name] = var;
335              //$$ = new Assignment(var, new IntLiteral(i));              //$$ = new Assignment(var, new IntLiteral(i));
# Line 277  statement: Line 339  statement:
339      | assignment  {      | assignment  {
340          $$ = $1;          $$ = $1;
341      }      }
342      | WHILE '(' expr ')' statements END WHILE  {      | WHILE '(' expr ')' opt_statements END WHILE  {
343          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
344              $$ = new While($3, $5);              $$ = new While($3, $5);
345          } else {          } else {
346              PARSE_ERR("Condition for 'while' loops must be integer expression.");              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
347              $$ = new While(new IntLiteral(0), $5);              $$ = new While(new IntLiteral(0), $5);
348          }          }
349      }      }
350      | IF '(' expr ')' statements ELSE statements END IF  {      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {
351          $$ = new If($3, $5, $7);          $$ = new If($3, $5, $7);
352      }      }
353      | IF '(' expr ')' statements END IF  {      | IF '(' expr ')' opt_statements END IF  {
354          $$ = new If($3, $5);          $$ = new If($3, $5);
355      }      }
356      | SELECT expr caseclauses END SELECT  {      | SELECT expr caseclauses END SELECT  {
357          if ($2->exprType() == INT_EXPR) {          if ($2->exprType() == INT_EXPR) {
358              $$ = new SelectCase($2, $3);              $$ = new SelectCase($2, $3);
359          } else {          } else {
360              PARSE_ERR("Statement 'select' can only by applied to integer expressions.");              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
361              $$ = new SelectCase(new IntLiteral(0), $3);              $$ = new SelectCase(new IntLiteral(0), $3);
362          }          }
363      }      }
# Line 311  caseclauses: Line 373  caseclauses:
373      }      }
374    
375  caseclause:  caseclause:
376      CASE INTEGER statements  {      CASE INTEGER opt_statements  {
377          $$ = CaseBranch();          $$ = CaseBranch();
378          $$.from = new IntLiteral($2);          $$.from = new IntLiteral($2);
379          $$.statements = $3;          $$.statements = $3;
380      }      }
381      | CASE INTEGER TO INTEGER statements  {      | CASE INTEGER TO INTEGER opt_statements  {
382          $$ = CaseBranch();          $$ = CaseBranch();
383          $$.from = new IntLiteral($2);          $$.from = new IntLiteral($2);
384          $$.to   = new IntLiteral($4);          $$.to   = new IntLiteral($4);
385          $$.statements = $5;          $$.statements = $5;
386      }      }
387    
388    userfunctioncall:
389        CALL IDENTIFIER  {
390            const char* name = $2;
391            StatementsRef fn = context->userFunctionByName(name);
392            if (context->functionProvider->functionByName(name)) {
393                PARSE_ERR(@1, (String("Keyword 'call' must only be used for user defined functions, not for any built-in function like '") + name + "'.").c_str());
394                $$ = StatementsRef();
395            } else if (!fn) {
396                PARSE_ERR(@2, (String("No user defined function with name '") + name + "'.").c_str());
397                $$ = StatementsRef();
398            } else {
399                $$ = fn;
400            }
401        }
402    
403  functioncall:  functioncall:
404      IDENTIFIER '(' args ')'  {      IDENTIFIER '(' args ')'  {
405          const char* name = $1;          const char* name = $1;
406          //printf("function call of '%s' with args\n", name);          //printf("function call of '%s' with args\n", name);
407          ArgsRef args = $3;          ArgsRef args = $3;
408          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
409          if (!fn) {          if (context->userFunctionByName(name)) {
410              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());
411                $$ = new FunctionCall(name, args, NULL);
412            } else if (!fn) {
413                PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
414              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
415          } else if (args->argsCount() < fn->minRequiredArgs()) {          } else if (args->argsCount() < fn->minRequiredArgs()) {
416              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());
417              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
418          } else if (args->argsCount() > fn->maxAllowedArgs()) {          } else if (args->argsCount() > fn->maxAllowedArgs()) {
419              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());
420              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
421          } else {          } else {
422              bool argsOK = true;              bool argsOK = true;
423              for (int i = 0; i < args->argsCount(); ++i) {              for (int i = 0; i < args->argsCount(); ++i) {
424                  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())) {
425                      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());
426                        argsOK = false;
427                        break;
428                    } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
429                        PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
430                      argsOK = false;                      argsOK = false;
431                      break;                      break;
432                  }                  }
# Line 355  functioncall: Line 439  functioncall:
439          //printf("function call of '%s' (with empty args)\n", name);          //printf("function call of '%s' (with empty args)\n", name);
440          ArgsRef args = new Args;          ArgsRef args = new Args;
441          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
442          if (!fn) {          if (context->userFunctionByName(name)) {
443              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());
444                $$ = new FunctionCall(name, args, NULL);
445            } else if (!fn) {
446                PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
447              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
448          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
449              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());
450              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
451          } else {          } else {
452              $$ = new FunctionCall(name, args, fn);              $$ = new FunctionCall(name, args, fn);
# Line 370  functioncall: Line 457  functioncall:
457          //printf("function call of '%s' (without args)\n", name);          //printf("function call of '%s' (without args)\n", name);
458          ArgsRef args = new Args;          ArgsRef args = new Args;
459          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
460          if (!fn) {          if (context->userFunctionByName(name)) {
461              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());
462                $$ = new FunctionCall(name, args, NULL);
463            } else if (!fn) {
464                PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
465              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
466          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
467              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());
468              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
469          } else {          } else {
470              $$ = new FunctionCall(name, args, fn);              $$ = new FunctionCall(name, args, fn);
# Line 400  assignment: Line 490  assignment:
490          const char* name = $1;          const char* name = $1;
491          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
492          if (!var)          if (!var)
493              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());
494          else if (var->isConstExpr())          else if (var->isConstExpr())
495              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());
496            else if (!var->isAssignable())
497                PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
498          else if (var->exprType() != $3->exprType())          else if (var->exprType() != $3->exprType())
499              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());
500          $$ = new Assignment(var, $3);          $$ = new Assignment(var, $3);
501      }      }
502      | VARIABLE '[' expr ']' ASSIGNMENT expr  {      | VARIABLE '[' expr ']' ASSIGNMENT expr  {
503          const char* name = $1;          const char* name = $1;
504          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
505          if (!var)          if (!var)
506              PARSE_ERR((String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
507          else if (var->exprType() != INT_ARR_EXPR)          else if (var->exprType() != INT_ARR_EXPR)
508              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());
509          else if ($3->exprType() != INT_EXPR)          else if ($3->exprType() != INT_EXPR)
510              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());
511          else if ($6->exprType() != INT_EXPR)          else if ($6->exprType() != INT_EXPR)
512              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());
513          IntArrayElementRef element = new IntArrayElement(var, $3);          IntArrayElementRef element = new IntArrayElement(var, $3);
514          $$ = new Assignment(element, $6);          $$ = new Assignment(element, $6);
515      }      }
# Line 435  unary_expr: Line 527  unary_expr:
527          if (var)          if (var)
528              $$ = var;              $$ = var;
529          else {          else {
530              PARSE_ERR((String("No variable declared with name '") + $1 + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
531              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
532          }          }
533      }      }
# Line 443  unary_expr: Line 535  unary_expr:
535          const char* name = $1;          const char* name = $1;
536          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
537          if (!var) {          if (!var) {
538              PARSE_ERR((String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
539              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
540          } else if (var->exprType() != INT_ARR_EXPR) {          } else if (var->exprType() != INT_ARR_EXPR) {
541              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());
542              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
543          } else if ($3->exprType() != INT_EXPR) {          } else if ($3->exprType() != INT_EXPR) {
544              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());
545              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
546          } else {          } else {
547              $$ = new IntArrayElement(var, $3);              $$ = new IntArrayElement(var, $3);
# Line 464  unary_expr: Line 556  unary_expr:
556      | '-' unary_expr  {      | '-' unary_expr  {
557          $$ = new Neg($2);          $$ = new Neg($2);
558      }      }
559        | BITWISE_NOT unary_expr  {
560            if ($2->exprType() != INT_EXPR) {
561                PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
562                $$ = new IntLiteral(0);
563            } else {
564                $$ = new BitwiseNot($2);
565            }
566        }
567      | NOT unary_expr  {      | NOT unary_expr  {
568          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
569              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());
570              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
571          } else {          } else {
572              $$ = new Not($2);              $$ = new Not($2);
# Line 477  expr: Line 577  expr:
577      concat_expr      concat_expr
578    
579  concat_expr:  concat_expr:
580      or_expr      logical_or_expr
581      | concat_expr '&' or_expr  {      | concat_expr '&' logical_or_expr  {
582          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
583          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
584          if (lhs->isConstExpr() && rhs->isConstExpr()) {          if (lhs->isConstExpr() && rhs->isConstExpr()) {
# Line 490  concat_expr: Line 590  concat_expr:
590          }          }
591      }      }
592    
593  or_expr:  logical_or_expr:
594      and_expr      logical_and_expr
595      | or_expr OR and_expr  {      | logical_or_expr OR logical_and_expr  {
596          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
597          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
598          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
599              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());
600              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
601          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
602              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());
603              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
604          } else {          } else {
605              $$ = new Or(lhs, rhs);              $$ = new Or(lhs, rhs);
606          }          }
607      }      }
608    
609  and_expr:  logical_and_expr:
610      rel_expr  {      bitwise_or_expr  {
611          $$ = $1;          $$ = $1;
612      }      }
613      | and_expr AND rel_expr  {      | logical_and_expr AND bitwise_or_expr  {
614          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
615          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
616          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
617              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());
618              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
619          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
620              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());
621              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
622          } else {          } else {
623              $$ = new And(lhs, rhs);              $$ = new And(lhs, rhs);
624          }          }
625      }      }
626    
627    bitwise_or_expr:
628        bitwise_and_expr
629        | bitwise_or_expr BITWISE_OR bitwise_and_expr  {
630            ExpressionRef lhs = $1;
631            ExpressionRef rhs = $3;
632            if (lhs->exprType() != INT_EXPR) {
633                PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
634                $$ = new IntLiteral(0);
635            } else if (rhs->exprType() != INT_EXPR) {
636                PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
637                $$ = new IntLiteral(0);
638            } else {
639                $$ = new BitwiseOr(lhs, rhs);
640            }
641        }
642    
643    bitwise_and_expr:
644        rel_expr  {
645            $$ = $1;
646        }
647        | bitwise_and_expr BITWISE_AND rel_expr  {
648            ExpressionRef lhs = $1;
649            ExpressionRef rhs = $3;
650            if (lhs->exprType() != INT_EXPR) {
651                PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
652                $$ = new IntLiteral(0);
653            } else if (rhs->exprType() != INT_EXPR) {
654                PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
655                $$ = new IntLiteral(0);
656            } else {
657                $$ = new BitwiseAnd(lhs, rhs);
658            }
659        }
660    
661  rel_expr:  rel_expr:
662        add_expr        add_expr
663      | rel_expr '<' add_expr  {      | rel_expr '<' add_expr  {
664          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
665          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
666          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
667              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());
668              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
669          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
670              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());
671              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
672          } else {          } else {
673              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
# Line 543  rel_expr: Line 677  rel_expr:
677          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
678          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
679          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
680              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());
681              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
682          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
683              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());
684              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
685          } else {          } else {
686              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
# Line 556  rel_expr: Line 690  rel_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 '<=' 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());
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 '<=' 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());
697              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
698          } else {          } else {
699              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
# Line 569  rel_expr: Line 703  rel_expr:
703          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
704          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
705          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
706              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());
707              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
708          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
709              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());
710              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
711          } else {          } else {
712              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
# Line 591  add_expr: Line 725  add_expr:
725          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
726          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
727          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
728              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());
729              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
730          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
731              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());
732              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
733          } else {          } else {
734              $$ = new Add(lhs,rhs);              $$ = new Add(lhs,rhs);
# Line 604  add_expr: Line 738  add_expr:
738          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
739          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
740          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
741              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());
742              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
743          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
744              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());
745              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
746          } else {          } else {
747              $$ = new Sub(lhs,rhs);              $$ = new Sub(lhs,rhs);
# Line 620  mul_expr: Line 754  mul_expr:
754          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
755          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
756          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
757              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());
758              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
759          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
760              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());
761              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
762          } else {          } else {
763              $$ = new Mul(lhs,rhs);              $$ = new Mul(lhs,rhs);
# Line 633  mul_expr: Line 767  mul_expr:
767          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
768          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
769          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
770              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());
771              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
772          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
773              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());
774              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
775          } else {          } else {
776              $$ = new Div(lhs,rhs);              $$ = new Div(lhs,rhs);
# Line 646  mul_expr: Line 780  mul_expr:
780          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
781          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
782          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
783              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());
784              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
785          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
786              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());
787              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
788          } else {          } else {
789              $$ = new Mod(lhs,rhs);              $$ = new Mod(lhs,rhs);
# Line 660  mul_expr: Line 794  mul_expr:
794    
795  void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {  void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
796      //fprintf(stderr, "%d: %s\n", locp->first_line, err);      //fprintf(stderr, "%d: %s\n", locp->first_line, err);
797      context->addErr(locp->first_line, err);      context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);
798  }  }
799    
800  void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {  void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
801      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
802      context->addWrn(locp->first_line, txt);      context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
803    }
804    
805    /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.
806    int InstrScript_tnamerr(char* yyres, const char* yystr) {
807      if (*yystr == '"') {
808          int yyn = 0;
809          char const *yyp = yystr;
810          for (;;)
811            switch (*++yyp)
812              {
813    /*
814              case '\'':
815              case ',':
816                goto do_not_strip_quotes;
817    
818              case '\\':
819                if (*++yyp != '\\')
820                  goto do_not_strip_quotes;
821    */
822                /* Fall through.  */
823              default:
824                if (yyres)
825                  yyres[yyn] = *yyp;
826                yyn++;
827                break;
828    
829              case '"':
830                if (yyres)
831                  yyres[yyn] = '\0';
832                return yyn;
833              }
834        do_not_strip_quotes: ;
835        }
836    
837      if (! yyres)
838        return yystrlen (yystr);
839    
840      return yystpcpy (yyres, yystr) - yyres;
841  }  }

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

  ViewVC Help
Powered by ViewVC