/[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 2947 by schoenebeck, Thu Jul 14 10:37:28 2016 UTC revision 3564 by schoenebeck, Sat Aug 24 09:18:57 2019 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014-2016 Christian Schoenebeck and Andreas Persson   * Copyright (c) 2014-2017 Christian Schoenebeck and Andreas Persson
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 18  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(loc,txt)  yyerror(&loc, context, txt)      #define PARSE_ERR(loc,txt)  yyerror(&loc, context, txt)
25      #define PARSE_WRN(loc,txt)  InstrScript_warning(&loc, context, txt)      #define PARSE_WRN(loc,txt)  InstrScript_warning(&loc, context, txt)
26        #define PARSE_DROP(loc)     context->addPreprocessorComment(loc.first_line, loc.last_line, loc.first_column+1, loc.last_column+1);
27        #define yytnamerr(res,str)  InstrScript_tnamerr(res, str)
28  %}  %}
29    
30  // generate reentrant safe parser  // generate reentrant safe parser
# Line 29  Line 32 
32  %parse-param { LinuxSampler::ParserContext* context }  %parse-param { LinuxSampler::ParserContext* context }
33  %lex-param { void* scanner }  %lex-param { void* scanner }
34  // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners  // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners
35  %name-prefix "InstrScript_"  // (NOTE: "=" is deprecated here with Bison 3.x, however removing it would cause an error with Bison 2.x)
36    %name-prefix="InstrScript_"
37  %locations  %locations
38  %defines  %defines
39  %error-verbose  %error-verbose
40    
41  %token <iValue> INTEGER  %token <iValue> INTEGER "integer literal"
42  %token <sValue> STRING  %token <iUnitValue> INTEGER_UNIT "integer literal with unit"
43  %token <sValue> IDENTIFIER  %token <sValue> STRING "string literal"
44  %token <sValue> VARIABLE  %token <sValue> IDENTIFIER "function name"
45  %token ON END INIT NOTE DECLARE ASSIGNMENT WHILE IF OR RELEASE AND ELSE  %token <sValue> VARIABLE "variable name"
46  %token BITWISE_OR BITWISE_AND BITWISE_NOT  %token ON "keyword 'on'"
47  %token CONTROLLER SELECT CASE TO NOT CONST_ POLYPHONIC MOD  %token END "keyword 'end'"
48  %token LE GE  %token INIT "keyword 'init'"
49    %token NOTE "keyword 'note'"
50  %type <nEventHandlers> script eventhandlers  %token RELEASE "keyword 'release'"
51  %type <nEventHandler> eventhandler  %token CONTROLLER "keyword 'controller'"
52  %type <nStatements> statements opt_statements  %token DECLARE "keyword 'declare'"
53    %token ASSIGNMENT "operator ':='"
54    %token CONST_ "keyword 'const'"
55    %token POLYPHONIC "keyword 'polyphonic'"
56    %token WHILE "keyword 'while'"
57    %token SYNCHRONIZED "keyword 'synchronized'"
58    %token IF "keyword 'if'"
59    %token ELSE "keyword 'else'"
60    %token SELECT "keyword 'select'"
61    %token CASE "keyword 'case'"
62    %token TO "keyword 'to'"
63    %token OR "operator 'or'"
64    %token AND "operator 'and'"
65    %token NOT "operator 'not'"
66    %token BITWISE_OR "bitwise operator '.or.'"
67    %token BITWISE_AND "bitwise operator '.and.'"
68    %token BITWISE_NOT "bitwise operator '.not.'"
69    %token FUNCTION "keyword 'function'"
70    %token CALL "keyword 'call'"
71    %token MOD "operator 'mod'"
72    %token LE "operator '<='"
73    %token GE "operator '>='"
74    %token END_OF_FILE 0 "end of file"
75    %token UNKNOWN_CHAR "unknown character"
76    
77    %type <nEventHandlers> script sections
78    %type <nEventHandler> section eventhandler
79    %type <nStatements> statements opt_statements userfunctioncall
80  %type <nStatement> statement assignment  %type <nStatement> statement assignment
81  %type <nFunctionCall> functioncall  %type <nFunctionCall> functioncall
82  %type <nArgs> args  %type <nArgs> args
# Line 58  Line 89 
89  %%  %%
90    
91  script:  script:
92      eventhandlers  {      sections  {
93          $$ = context->handlers = $1;          $$ = context->handlers = $1;
94      }      }
95    
96  eventhandlers:  sections:
97      eventhandler  {      section  {
98          $$ = new EventHandlers();          $$ = new EventHandlers();
99          $$->add($1);          if ($1) $$->add($1);
100        }
101        | sections section  {
102            $$ = $1;
103            if ($2) $$->add($2);
104        }
105    
106    section:
107        function_declaration  {
108            $$ = EventHandlerRef();
109      }      }
110      | eventhandlers eventhandler  {      | eventhandler  {
111          $$ = $1;          $$ = $1;
         $$->add($2);  
112      }      }
113    
114  eventhandler:  eventhandler:
# Line 98  eventhandler: Line 137  eventhandler:
137          $$ = context->onController;          $$ = context->onController;
138      }      }
139    
140    function_declaration:
141        FUNCTION IDENTIFIER opt_statements END FUNCTION  {
142            const char* name = $2;
143            if (context->functionProvider->functionByName(name)) {
144                PARSE_ERR(@2, (String("There is already a built-in function with name '") + name + "'.").c_str());
145            } else if (context->userFunctionByName(name)) {
146                PARSE_ERR(@2, (String("There is already a user defined function with name '") + name + "'.").c_str());
147            } else {
148                context->userFnTable[name] = $3;
149            }
150        }
151    
152  opt_statements:  opt_statements:
153      /* epsilon (empty argument) */  {      /* epsilon (empty argument) */  {
154          $$ = new Statements();          $$ = new Statements();
# Line 126  statement: Line 177  statement:
177      functioncall  {      functioncall  {
178          $$ = $1;          $$ = $1;
179      }      }
180        | userfunctioncall  {
181            $$ = $1;
182        }
183      | DECLARE VARIABLE  {      | DECLARE VARIABLE  {
184          const char* name = $2;          const char* name = $2;
185          //printf("declared var '%s'\n", name);          //printf("declared var '%s'\n", name);
# Line 175  statement: Line 229  statement:
229              if (name[0] == '@')              if (name[0] == '@')
230                  PARSE_WRN(@2, (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());
231              IntExprRef expr = $4;              IntExprRef expr = $4;
232                IntVariableRef var = new IntVariable(context);
233              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
234                  const int i = expr->evalInt();                  const vmint i = expr->evalInt();
                 IntVariableRef var = new IntVariable(context);  
                 context->vartable[name] = var;  
235                  $$ = new Assignment(var, new IntLiteral(i));                  $$ = new Assignment(var, new IntLiteral(i));
236              } else {              } else {
                 IntVariableRef var = new IntVariable(context);  
                 context->vartable[name] = var;  
237                  $$ = new Assignment(var, expr);                  $$ = new Assignment(var, expr);
238              }              }
239                var->copyUnitFrom(expr);
240                var->setFinal(expr->isFinal());
241                context->vartable[name] = var;
242          }          }
243      }      }
244      | DECLARE VARIABLE '[' expr ']'  {      | DECLARE VARIABLE '[' expr ']'  {
# Line 201  statement: Line 255  statement:
255              $$ = new FunctionCall("nothing", new Args, NULL); // whatever              $$ = new FunctionCall("nothing", new Args, NULL); // whatever
256          } else {          } else {
257              IntExprRef expr = $4;              IntExprRef expr = $4;
258              int size = expr->evalInt();              if (expr->unitType() || expr->unitPrefix(0)) {
259              if (size <= 0) {                  PARSE_ERR(@4, "Units are not allowed as array size.");
                 PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());  
260                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever
261              } else {              } else {
262                  context->vartable[name] = new IntArrayVariable(context, size);                  if (expr->isFinal())
263                  $$ = new NoOperation;                      PARSE_WRN(@4, "Final operator '!' is meaningless here.");
264                    vmint size = expr->evalInt();
265                    if (size <= 0) {
266                        PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
267                        $$ = new FunctionCall("nothing", new Args, NULL); // whatever
268                    } else {
269                        context->vartable[name] = new IntArrayVariable(context, size);
270                        $$ = new NoOperation;
271                    }
272              }              }
273          }          }
274      }      }
# Line 225  statement: Line 286  statement:
286          } else {          } else {
287              IntExprRef sizeExpr = $4;              IntExprRef sizeExpr = $4;
288              ArgsRef args = $8;              ArgsRef args = $8;
289              int size = sizeExpr->evalInt();              vmint size = sizeExpr->evalInt();
290              if (size <= 0) {              if (size <= 0) {
291                  PARSE_ERR(@4, (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());
292                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever
293              } else if (args->argsCount() > size) {              } else if (args->argsCount() > size) {
294                  PARSE_ERR(@8, (String("Variable '") + name +                  PARSE_ERR(@8, (String("Array variable '") + name +
295                            "' was declared with size " + ToString(size) +                            "' was declared with size " + ToString(size) +
296                            " but " + ToString(args->argsCount()) +                            " but " + ToString(args->argsCount()) +
297                            " values were assigned." ).c_str());                            " values were assigned." ).c_str());
298                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                            $$ = new FunctionCall("nothing", new Args, NULL); // whatever
299                } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {
300                    PARSE_ERR(@4, "Units are not allowed as array size.");
301                    $$ = new FunctionCall("nothing", new Args, NULL); // whatever
302              } else {              } else {
303                    if (sizeExpr->isFinal())
304                        PARSE_WRN(@4, "Final operator '!' is meaningless here.");
305                  bool argsOK = true;                  bool argsOK = true;
306                  for (int i = 0; i < args->argsCount(); ++i) {                  for (vmint i = 0; i < args->argsCount(); ++i) {
307                      if (args->arg(i)->exprType() != INT_EXPR) {                      if (args->arg(i)->exprType() != INT_EXPR) {
308                          PARSE_ERR(                          PARSE_ERR(
309                              @8,                              @8,
# Line 247  statement: Line 313  statement:
313                          );                          );
314                          argsOK = false;                          argsOK = false;
315                          break;                          break;
316                        } else if (args->arg(i)->asInt()->unitType() ||
317                                   args->arg(i)->asInt()->unitPrefix(0))
318                        {
319                            PARSE_ERR(
320                                @8,
321                                (String("Array variable '") + name +
322                                "' declared with invalid assignment values. Assigned element " +
323                                ToString(i+1) + " contains a unit.").c_str()
324                            );
325                            argsOK = false;
326                            break;
327                        }
328                    }
329                    if (argsOK) {
330                        context->vartable[name] = new IntArrayVariable(context, size, args);
331                        $$ = new NoOperation;
332                    } else
333                        $$ = new FunctionCall("nothing", new Args, NULL); // whatever
334                }
335            }
336        }
337        | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
338            const char* name = $3;
339            if (!$5->isConstExpr()) {
340                PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
341                $$ = new FunctionCall("nothing", new Args, NULL); // whatever
342            } else if ($5->exprType() != INT_EXPR) {
343                PARSE_ERR(@5, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
344                $$ = new FunctionCall("nothing", new Args, NULL); // whatever
345            } else if (context->variableByName(name)) {
346                PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
347                $$ = new FunctionCall("nothing", new Args, NULL); // whatever
348            } else {
349                IntExprRef sizeExpr = $5;
350                ArgsRef args = $9;
351                vmint size = sizeExpr->evalInt();
352                if (size <= 0) {
353                    PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
354                    $$ = new FunctionCall("nothing", new Args, NULL); // whatever
355                } else if (args->argsCount() > size) {
356                    PARSE_ERR(@9, (String("Array variable '") + name +
357                              "' was declared with size " + ToString(size) +
358                              " but " + ToString(args->argsCount()) +
359                              " values were assigned." ).c_str());
360                    $$ = new FunctionCall("nothing", new Args, NULL); // whatever
361                } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {
362                    PARSE_ERR(@5, "Units are not allowed as array size.");
363                    $$ = new FunctionCall("nothing", new Args, NULL); // whatever
364                } else {
365                    if (sizeExpr->isFinal())
366                        PARSE_WRN(@5, "Final operator '!' is meaningless here.");
367                    bool argsOK = true;
368                    for (vmint i = 0; i < args->argsCount(); ++i) {
369                        if (args->arg(i)->exprType() != INT_EXPR) {
370                            PARSE_ERR(
371                                @9,
372                                (String("Array variable '") + name +
373                                "' declared with invalid assignment values. Assigned element " +
374                                ToString(i+1) + " is not an integer expression.").c_str()
375                            );
376                            argsOK = false;
377                            break;
378                        }
379                        if (!args->arg(i)->isConstExpr()) {
380                            PARSE_ERR(
381                                @9,
382                                (String("const array variable '") + name +
383                                "' must be defined with const values. Assigned element " +
384                                ToString(i+1) + " is not a const expression though.").c_str()
385                            );
386                            argsOK = false;
387                            break;
388                        } else if (args->arg(i)->asInt()->unitType() ||
389                                   args->arg(i)->asInt()->unitPrefix(0))
390                        {
391                            PARSE_ERR(
392                                @9,
393                                (String("const array variable '") + name +
394                                "' declared with invalid assignment values. Assigned element " +
395                                ToString(i+1) + " contains a unit.").c_str()
396                            );
397                            argsOK = false;
398                            break;
399                      }                      }
400                  }                  }
401                  if (argsOK)                  if (argsOK) {
402                      $$ = context->vartable[name] = new IntArrayVariable(context, size, args);                      context->vartable[name] = new IntArrayVariable(context, size, args, true);
403                  else                      $$ = new NoOperation;
404                    } else
405                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever
406              }              }
407          }          }
# Line 274  statement: Line 424  statement:
424          } else {          } else {
425              if (name[0] == '@')              if (name[0] == '@')
426                  PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");                  PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");
427              int i = 0;              vmint i = 0;
428              IntExprRef expr = $5;              IntExprRef expr = $5;
429              if (expr->isConstExpr())              if (expr->isConstExpr())
430                  i = expr->evalInt();                  i = expr->evalInt();
431              else              else
432                  PARSE_ERR(@5, (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());
433              ConstIntVariableRef var = new ConstIntVariable(i);              ConstIntVariableRef var = new ConstIntVariable(i);
434                var->copyUnitFrom(expr);
435                var->setFinal(expr->isFinal());
436              context->vartable[name] = var;              context->vartable[name] = var;
437              //$$ = new Assignment(var, new IntLiteral(i));              //$$ = new Assignment(var, new IntLiteral(i));
438              $$ = new NoOperation();              $$ = new NoOperation();
# Line 291  statement: Line 443  statement:
443      }      }
444      | WHILE '(' expr ')' opt_statements END WHILE  {      | WHILE '(' expr ')' opt_statements END WHILE  {
445          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
446              $$ = new While($3, $5);              IntExprRef expr = $3;
447                if (expr->isFinal() && expr->isConstExpr())
448                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
449                $$ = new While(expr, $5);
450          } else {          } else {
451              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
452              $$ = new While(new IntLiteral(0), $5);              $$ = new While(new IntLiteral(0), $5);
453          }          }
454      }      }
455        | SYNCHRONIZED opt_statements END SYNCHRONIZED  {
456            $$ = new SyncBlock($2);
457        }
458      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {
459          $$ = new If($3, $5, $7);          if ($3->exprType() == INT_EXPR) {
460                IntExprRef expr = $3;
461                if (expr->isFinal() && expr->isConstExpr())
462                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
463                $$ = new If($3, $5, $7);
464            } else {
465                PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
466                $$ = new If(new IntLiteral(0), $5, $7);
467            }
468      }      }
469      | IF '(' expr ')' opt_statements END IF  {      | IF '(' expr ')' opt_statements END IF  {
470          $$ = new If($3, $5);          if ($3->exprType() == INT_EXPR) {
471                IntExprRef expr = $3;
472                if (expr->isFinal() && expr->isConstExpr())
473                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
474                $$ = new If($3, $5);
475            } else {
476                PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
477                $$ = new If(new IntLiteral(0), $5);
478            }
479      }      }
480      | SELECT expr caseclauses END SELECT  {      | SELECT expr caseclauses END SELECT  {
481          if ($2->exprType() == INT_EXPR) {          if ($2->exprType() == INT_EXPR) {
482              $$ = new SelectCase($2, $3);              IntExprRef expr = $2;
483                if (expr->unitType() || expr->unitPrefix(0)) {
484                    PARSE_ERR(@2, "Units are not allowed here.");
485                } else {
486                    if (expr->isFinal() && expr->isConstExpr())
487                        PARSE_WRN(@2, "Final operator '!' is meaningless here.");
488                    $$ = new SelectCase(expr, $3);
489                }
490          } else {          } else {
491              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
492              $$ = new SelectCase(new IntLiteral(0), $3);              $$ = new SelectCase(new IntLiteral(0), $3);
# Line 335  caseclause: Line 516  caseclause:
516          $$.statements = $5;          $$.statements = $5;
517      }      }
518    
519    userfunctioncall:
520        CALL IDENTIFIER  {
521            const char* name = $2;
522            StatementsRef fn = context->userFunctionByName(name);
523            if (context->functionProvider->functionByName(name)) {
524                PARSE_ERR(@1, (String("Keyword 'call' must only be used for user defined functions, not for any built-in function like '") + name + "'.").c_str());
525                $$ = StatementsRef();
526            } else if (!fn) {
527                PARSE_ERR(@2, (String("No user defined function with name '") + name + "'.").c_str());
528                $$ = StatementsRef();
529            } else {
530                $$ = fn;
531            }
532        }
533    
534  functioncall:  functioncall:
535      IDENTIFIER '(' args ')'  {      IDENTIFIER '(' args ')'  {
536          const char* name = $1;          const char* name = $1;
537          //printf("function call of '%s' with args\n", name);          //printf("function call of '%s' with args\n", name);
538          ArgsRef args = $3;          ArgsRef args = $3;
539          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
540          if (!fn) {          if (context->userFunctionByName(name)) {
541                PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
542                $$ = new FunctionCall(name, args, NULL);
543            } else if (!fn) {
544              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
545              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
546            } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
547                PARSE_DROP(@$);
548                $$ = new NoFunctionCall;
549          } else if (args->argsCount() < fn->minRequiredArgs()) {          } else if (args->argsCount() < fn->minRequiredArgs()) {
550              PARSE_ERR(@3, (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());
551              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
# Line 352  functioncall: Line 554  functioncall:
554              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
555          } else {          } else {
556              bool argsOK = true;              bool argsOK = true;
557              for (int i = 0; i < args->argsCount(); ++i) {              for (vmint i = 0; i < args->argsCount(); ++i) {
558                  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())) {
559                      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());                      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());
560                      argsOK = false;                      argsOK = false;
# Line 361  functioncall: Line 563  functioncall:
563                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
564                      argsOK = false;                      argsOK = false;
565                      break;                      break;
566                    } else if (args->arg(i)->exprType() == INT_EXPR && !fn->acceptsArgUnitType(i, args->arg(i)->asInt()->unitType())) {
567                        if (args->arg(i)->asInt()->unitType())
568                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect unit " + unitTypeStr(args->arg(i)->asInt()->unitType()) +  ".").c_str());
569                        else
570                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects a unit.").c_str());
571                        argsOK = false;
572                        break;
573                    } else if (args->arg(i)->exprType() == INT_EXPR && args->arg(i)->asInt()->unitPrefix(0) && !fn->acceptsArgUnitPrefix(i, args->arg(i)->asInt()->unitType())) {
574                        if (args->arg(i)->asInt()->unitType())
575                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix for unit" + unitTypeStr(args->arg(i)->asInt()->unitType()) + ".").c_str());
576                        else
577                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix.").c_str());
578                        argsOK = false;
579                        break;
580                    } else if (!fn->acceptsArgFinal(i) && args->arg(i)->exprType() == INT_EXPR && args->arg(i)->asInt()->isFinal()) {
581                        PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a \"final\" value.").c_str());
582                        argsOK = false;
583                        break;
584                  }                  }
585              }              }
586              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
# Line 371  functioncall: Line 591  functioncall:
591          //printf("function call of '%s' (with empty args)\n", name);          //printf("function call of '%s' (with empty args)\n", name);
592          ArgsRef args = new Args;          ArgsRef args = new Args;
593          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
594          if (!fn) {          if (context->userFunctionByName(name)) {
595                PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
596                $$ = new FunctionCall(name, args, NULL);
597            } else if (!fn) {
598              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
599              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
600            } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
601                PARSE_DROP(@$);
602                $$ = new NoFunctionCall;
603          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
604              PARSE_ERR(@3, (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());
605              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
# Line 386  functioncall: Line 612  functioncall:
612          //printf("function call of '%s' (without args)\n", name);          //printf("function call of '%s' (without args)\n", name);
613          ArgsRef args = new Args;          ArgsRef args = new Args;
614          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
615          if (!fn) {          if (context->userFunctionByName(name)) {
616                PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
617                $$ = new FunctionCall(name, args, NULL);
618            } else if (!fn) {
619              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
620              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
621            } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
622                PARSE_DROP(@$);
623                $$ = new NoFunctionCall;
624          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
625              PARSE_ERR(@1, (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());
626              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
# Line 423  assignment: Line 655  assignment:
655              PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());              PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
656          else if (var->exprType() != $3->exprType())          else if (var->exprType() != $3->exprType())
657              PARSE_ERR(@3, (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());
658            else if (var->exprType() == INT_EXPR) {
659                IntVariableRef intVar = var;
660                IntExprRef expr = $3;
661                if (intVar->unitType() != expr->unitType())
662                    PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has unit type " + unitTypeStr(intVar->unitType()) + ", assignment has unit type " + unitTypeStr(expr->unitType()) + " though.").c_str());
663                else if (intVar->unitFactor() != expr->unitFactor())
664                    PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has a different unit prefix.").c_str());
665                else if (intVar->isFinal() != expr->isFinal())
666                    PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' was declared as " + String(intVar->isFinal() ? "final" : "not final") + ", assignment is " + String(expr->isFinal() ? "final" : "not final") + " though.").c_str());
667            }
668          $$ = new Assignment(var, $3);          $$ = new Assignment(var, $3);
669      }      }
670      | VARIABLE '[' expr ']' ASSIGNMENT expr  {      | VARIABLE '[' expr ']' ASSIGNMENT expr  {
# Line 432  assignment: Line 674  assignment:
674              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
675          else if (var->exprType() != INT_ARR_EXPR)          else if (var->exprType() != INT_ARR_EXPR)
676              PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());              PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
677            else if (var->isConstExpr())
678                PARSE_ERR(@5, (String("Variable assignment: Cannot modify const array variable '") + name + "'.").c_str());
679            else if (!var->isAssignable())
680                PARSE_ERR(@5, (String("Variable assignment: Array variable '") + name + "' is not assignable.").c_str());
681          else if ($3->exprType() != INT_EXPR)          else if ($3->exprType() != INT_EXPR)
682              PARSE_ERR(@3, (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());
683            else if ($3->asInt()->unitType())
684                PARSE_ERR(@3, "Unit types are not allowed as array index.");
685          else if ($6->exprType() != INT_EXPR)          else if ($6->exprType() != INT_EXPR)
686              PARSE_ERR(@5, (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());
687            else if ($6->asInt()->unitType())
688                PARSE_ERR(@6, "Unit types are not allowed for array variables.");
689            else if ($6->asInt()->isFinal())
690                PARSE_ERR(@6, "Final operator '!' not allowed for array variables.");
691            else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())
692                PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
693                              " exceeds size of array variable '" + name +
694                              "' which was declared with size " +
695                              ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());
696            else if ($3->asInt()->isFinal())
697                PARSE_WRN(@3, "Final operator '!' is meaningless here.");
698          IntArrayElementRef element = new IntArrayElement(var, $3);          IntArrayElementRef element = new IntArrayElement(var, $3);
699          $$ = new Assignment(element, $6);          $$ = new Assignment(element, $6);
700      }      }
# Line 444  unary_expr: Line 703  unary_expr:
703      INTEGER  {      INTEGER  {
704          $$ = new IntLiteral($1);          $$ = new IntLiteral($1);
705      }      }
706        | INTEGER_UNIT  {
707            IntLiteralRef literal = new IntLiteral($1.iValue);
708            literal->setUnit($1.prefix, $1.unit);
709            $$ = literal;
710        }
711      | STRING    {      | STRING    {
712          $$ = new StringLiteral($1);          $$ = new StringLiteral($1);
713      }      }
# Line 469  unary_expr: Line 733  unary_expr:
733          } else if ($3->exprType() != INT_EXPR) {          } else if ($3->exprType() != INT_EXPR) {
734              PARSE_ERR(@3, (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());
735              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
736            } else if ($3->asInt()->unitType() || $3->asInt()->unitPrefix(0)) {
737                PARSE_ERR(@3, "Units are not allowed as array index.");
738                $$ = new IntLiteral(0);
739          } else {          } else {
740                if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())
741                    PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
742                                   " exceeds size of array variable '" + name +
743                                   "' which was declared with size " +
744                                   ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());
745                else if ($3->asInt()->isFinal())
746                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
747              $$ = new IntArrayElement(var, $3);              $$ = new IntArrayElement(var, $3);
748          }          }
749      }      }
# Line 486  unary_expr: Line 760  unary_expr:
760          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
761              PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());              PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
762              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
763            } else if ($2->asInt()->unitType() || $2->asInt()->unitPrefix(0)) {
764                PARSE_ERR(@2, "Units are not allowed for operands of bitwise operations.");
765                $$ = new IntLiteral(0);
766          } else {          } else {
767              $$ = new BitwiseNot($2);              $$ = new BitwiseNot($2);
768          }          }
# Line 494  unary_expr: Line 771  unary_expr:
771          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
772              PARSE_ERR(@2, (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());
773              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
774            } else if ($2->asInt()->unitType() || $2->asInt()->unitPrefix(0)) {
775                PARSE_ERR(@2, "Units are not allowed for operands of logical operations.");
776                $$ = new IntLiteral(0);
777          } else {          } else {
778              $$ = new Not($2);              $$ = new Not($2);
779          }          }
780      }      }
781        | '!' unary_expr  {
782            if ($2->exprType() != INT_EXPR) {
783                PARSE_ERR(@2, (String("Right operand of \"final\" operator '!' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
784                $$ = new IntLiteral(0);
785            } else {
786                $$ = new Final($2);
787            }
788        }
789    
790  expr:  expr:
791      concat_expr      concat_expr
# Line 527  logical_or_expr: Line 815  logical_or_expr:
815          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
816              PARSE_ERR(@3, (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());
817              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
818            } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
819                PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
820                $$ = new IntLiteral(0);
821            } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
822                PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
823                $$ = new IntLiteral(0);
824          } else {          } else {
825              $$ = new Or(lhs, rhs);              $$ = new Or(lhs, rhs);
826          }          }
# Line 545  logical_and_expr: Line 839  logical_and_expr:
839          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
840              PARSE_ERR(@3, (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());
841              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
842            } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
843                PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
844                $$ = new IntLiteral(0);
845            } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
846                PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
847                $$ = new IntLiteral(0);
848          } else {          } else {
849              $$ = new And(lhs, rhs);              $$ = new And(lhs, rhs);
850          }          }
# Line 561  bitwise_or_expr: Line 861  bitwise_or_expr:
861          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
862              PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
863              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
864            } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
865                PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
866                $$ = new IntLiteral(0);
867            } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
868                PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
869                $$ = new IntLiteral(0);
870          } else {          } else {
871              $$ = new BitwiseOr(lhs, rhs);              $$ = new BitwiseOr(lhs, rhs);
872          }          }
# Line 579  bitwise_and_expr: Line 885  bitwise_and_expr:
885          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
886              PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
887              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
888            } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
889                PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
890                $$ = new IntLiteral(0);
891            } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
892                PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
893                $$ = new IntLiteral(0);
894          } else {          } else {
895              $$ = new BitwiseAnd(lhs, rhs);              $$ = new BitwiseAnd(lhs, rhs);
896          }          }
# Line 595  rel_expr: Line 907  rel_expr:
907          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
908              PARSE_ERR(@3, (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());
909              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
910            } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||
911                       lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
912            {
913                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
914                $$ = new IntLiteral(0);
915          } else {          } else {
916              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
917          }          }
# Line 608  rel_expr: Line 925  rel_expr:
925          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
926              PARSE_ERR(@3, (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());
927              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
928            } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||
929                       lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
930            {
931                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
932                $$ = new IntLiteral(0);
933          } else {          } else {
934              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
935          }          }
# Line 621  rel_expr: Line 943  rel_expr:
943          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
944              PARSE_ERR(@3, (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());
945              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
946            } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||
947                       lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
948            {
949                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
950                $$ = new IntLiteral(0);
951          } else {          } else {
952              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
953          }          }
# Line 634  rel_expr: Line 961  rel_expr:
961          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
962              PARSE_ERR(@3, (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());
963              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
964            } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||
965                       lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
966            {
967                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
968                $$ = new IntLiteral(0);
969          } else {          } else {
970              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
971          }          }
972      }      }
973      | rel_expr '=' add_expr  {      | rel_expr '=' add_expr  {
974          $$ = new Relation($1, Relation::EQUAL, $3);          ExpressionRef lhs = $1;
975            ExpressionRef rhs = $3;
976            if (lhs->exprType() != INT_EXPR) {
977                PARSE_ERR(@1, (String("Left operand of operator '=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
978                $$ = new IntLiteral(0);
979            } else if (rhs->exprType() != INT_EXPR) {
980                PARSE_ERR(@3, (String("Right operand of operator '=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
981                $$ = new IntLiteral(0);
982            } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||
983                       lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
984            {
985                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
986                $$ = new IntLiteral(0);
987            } else {
988                $$ = new Relation(lhs, Relation::EQUAL, rhs);
989            }
990      }      }
991      | rel_expr '#' add_expr  {      | rel_expr '#' add_expr  {
992          $$ = new Relation($1, Relation::NOT_EQUAL, $3);          ExpressionRef lhs = $1;
993            ExpressionRef rhs = $3;
994            if (lhs->exprType() != INT_EXPR) {
995                PARSE_ERR(@1, (String("Left operand of operator '#' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
996                $$ = new IntLiteral(0);
997            } else if (rhs->exprType() != INT_EXPR) {
998                PARSE_ERR(@3, (String("Right operand of operator '#' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
999                $$ = new IntLiteral(0);
1000            } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||
1001                       lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
1002            {
1003                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
1004                $$ = new IntLiteral(0);
1005            } else {
1006                $$ = new Relation(lhs, Relation::NOT_EQUAL, rhs);
1007            }
1008      }      }
1009    
1010  add_expr:  add_expr:
# Line 656  add_expr: Line 1018  add_expr:
1018          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1019              PARSE_ERR(@3, (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());
1020              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1021            } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||
1022                       lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
1023            {
1024                PARSE_ERR(@2, "Operands of '+' operations must have same unit.");
1025                $$ = new IntLiteral(0);
1026          } else {          } else {
1027              $$ = new Add(lhs,rhs);              $$ = new Add(lhs,rhs);
1028          }          }
# Line 669  add_expr: Line 1036  add_expr:
1036          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1037              PARSE_ERR(@3, (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());
1038              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1039            } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||
1040                       lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
1041            {
1042                PARSE_ERR(@2, "Operands of '-' operations must have same unit.");
1043                $$ = new IntLiteral(0);
1044          } else {          } else {
1045              $$ = new Sub(lhs,rhs);              $$ = new Sub(lhs,rhs);
1046          }          }
# Line 685  mul_expr: Line 1057  mul_expr:
1057          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1058              PARSE_ERR(@3, (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());
1059              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1060            } else if (lhs->asInt()->unitType() && rhs->asInt()->unitType()) {
1061                PARSE_ERR(@2, "Only one operand of operator '*' may have a unit type");
1062                $$ = new IntLiteral(0);
1063            } else if (lhs->asInt()->unitPrefix(0) && rhs->asInt()->unitPrefix(0)) {
1064                PARSE_ERR(@2, "Only one operand of operator '*' may have a unit prefix");
1065                $$ = new IntLiteral(0);
1066          } else {          } else {
1067              $$ = new Mul(lhs,rhs);              $$ = new Mul(lhs,rhs);
1068          }          }
# Line 698  mul_expr: Line 1076  mul_expr:
1076          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1077              PARSE_ERR(@3, (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());
1078              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1079            } else if (lhs->asInt()->unitType() && rhs->asInt()->unitType() &&
1080                       lhs->asInt()->unitType() != rhs->asInt()->unitType())
1081            {
1082                PARSE_ERR(@2, "Operands of operator '/' with two different unit types.");
1083                $$ = new IntLiteral(0);
1084            } else if (!lhs->asInt()->unitType() && rhs->asInt()->unitType()) {
1085                PARSE_ERR(@3, ("Dividing left operand without any unit type by right operand with unit type " + typeStr(rhs->exprType()) + " is not possible.").c_str());
1086                $$ = new IntLiteral(0);
1087            } else if (lhs->asInt()->unitFactor()  != rhs->asInt()->unitFactor() &&
1088                       lhs->asInt()->unitPrefix(0) && rhs->asInt()->unitPrefix(0))
1089            {
1090                PARSE_ERR(@2, "Dividing two operands with two different unit prefixes is not possible.");
1091                $$ = new IntLiteral(0);
1092            } else if (lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor() &&
1093                       rhs->asInt()->unitPrefix(0))
1094            {
1095                PARSE_ERR(@3, "Dividing left operand without any unit prefix by right operand with unit prefix is not possible.");
1096                $$ = new IntLiteral(0);
1097          } else {          } else {
1098              $$ = new Div(lhs,rhs);              $$ = new Div(lhs,rhs);
1099          }          }
# Line 712  mul_expr: Line 1108  mul_expr:
1108              PARSE_ERR(@3, (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());
1109              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1110          } else {          } else {
1111                if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0))
1112                    PARSE_ERR(@1, "Operands of modulo operator must not use any unit.");
1113                if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0))
1114                    PARSE_ERR(@3, "Operands of modulo operator must not use any unit.");
1115              $$ = new Mod(lhs,rhs);              $$ = new Mod(lhs,rhs);
1116          }          }
1117      }      }
# Line 727  void InstrScript_warning(YYLTYPE* locp, Line 1127  void InstrScript_warning(YYLTYPE* locp,
1127      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
1128      context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);      context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
1129  }  }
1130    
1131    /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.
1132    int InstrScript_tnamerr(char* yyres, const char* yystr) {
1133      if (*yystr == '"') {
1134          int yyn = 0;
1135          char const *yyp = yystr;
1136          for (;;)
1137            switch (*++yyp)
1138              {
1139    /*
1140              case '\'':
1141              case ',':
1142                goto do_not_strip_quotes;
1143    
1144              case '\\':
1145                if (*++yyp != '\\')
1146                  goto do_not_strip_quotes;
1147    */
1148                /* Fall through.  */
1149              default:
1150                if (yyres)
1151                  yyres[yyn] = *yyp;
1152                yyn++;
1153                break;
1154    
1155              case '"':
1156                if (yyres)
1157                  yyres[yyn] = '\0';
1158                return yyn;
1159              }
1160    /*
1161        do_not_strip_quotes: ;
1162    */
1163        }
1164    
1165      if (! yyres)
1166        return (int) yystrlen (yystr);
1167    
1168      return int( yystpcpy (yyres, yystr) - yyres );
1169    }

Legend:
Removed from v.2947  
changed lines
  Added in v.3564

  ViewVC Help
Powered by ViewVC