/[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 3557 by schoenebeck, Sun Aug 18 00:06:04 2019 UTC revision 3690 by schoenebeck, Fri Jan 3 10:18:21 2020 UTC
# Line 39  Line 39 
39  %error-verbose  %error-verbose
40    
41  %token <iValue> INTEGER "integer literal"  %token <iValue> INTEGER "integer literal"
42    %token <fValue> REAL "real number literal"
43    %token <iUnitValue> INTEGER_UNIT "integer literal with unit"
44    %token <fUnitValue> REAL_UNIT "real number literal with unit"
45  %token <sValue> STRING "string literal"  %token <sValue> STRING "string literal"
46  %token <sValue> IDENTIFIER "function name"  %token <sValue> IDENTIFIER "function name"
47  %token <sValue> VARIABLE "variable name"  %token <sValue> VARIABLE "variable name"
# Line 48  Line 51 
51  %token NOTE "keyword 'note'"  %token NOTE "keyword 'note'"
52  %token RELEASE "keyword 'release'"  %token RELEASE "keyword 'release'"
53  %token CONTROLLER "keyword 'controller'"  %token CONTROLLER "keyword 'controller'"
54    %token RPN "keyword 'rpn'"
55    %token NRPN "keyword 'nrpn'"
56  %token DECLARE "keyword 'declare'"  %token DECLARE "keyword 'declare'"
57  %token ASSIGNMENT "operator ':='"  %token ASSIGNMENT "operator ':='"
58  %token CONST_ "keyword 'const'"  %token CONST_ "keyword 'const'"
# Line 135  eventhandler: Line 140  eventhandler:
140          context->onController = new OnController($3);          context->onController = new OnController($3);
141          $$ = context->onController;          $$ = context->onController;
142      }      }
143        | ON RPN opt_statements END ON  {
144            if (context->onRpn)
145                PARSE_ERR(@2, "Redeclaration of 'rpn' event handler.");
146            context->onRpn = new OnRpn($3);
147            $$ = context->onRpn;
148        }
149        | ON NRPN opt_statements END ON  {
150            if (context->onNrpn)
151                PARSE_ERR(@2, "Redeclaration of 'nrpn' event handler.");
152            context->onNrpn = new OnNrpn($3);
153            $$ = context->onNrpn;
154        }
155    
156  function_declaration:  function_declaration:
157      FUNCTION IDENTIFIER opt_statements END FUNCTION  {      FUNCTION IDENTIFIER opt_statements END FUNCTION  {
# Line 182  statement: Line 199  statement:
199      | DECLARE VARIABLE  {      | DECLARE VARIABLE  {
200          const char* name = $2;          const char* name = $2;
201          //printf("declared var '%s'\n", name);          //printf("declared var '%s'\n", name);
202          if (context->variableByName(name))          if (context->variableByName(name)) {
203              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
204          if (name[0] == '@') {          } else if (name[0] == '@') {
205              context->vartable[name] = new StringVariable(context);              context->vartable[name] = new StringVariable(context);
206              $$ = new NoOperation;          } else if (name[0] == '~') {
207                context->vartable[name] = new RealVariable({
208                    .ctx = context
209                });
210            } else if (name[0] == '$') {
211                context->vartable[name] = new IntVariable({
212                    .ctx = context
213                });
214            } else if (name[0] == '?') {
215                PARSE_ERR(@2, (String("Real number array variable '") + name + "' declaration requires array size.").c_str());
216            } else if (name[0] == '%') {
217                PARSE_ERR(@2, (String("Integer array variable '") + name + "' declaration requires array size.").c_str());
218          } else {          } else {
219              context->vartable[name] = new IntVariable(context);              PARSE_ERR(@2, (String("Variable '") + name + "' declared with unknown type.").c_str());
             $$ = new NoOperation;  
220          }          }
221            $$ = new NoOperation;
222      }      }
223      | DECLARE POLYPHONIC VARIABLE  {      | DECLARE POLYPHONIC VARIABLE  {
224          const char* name = $3;          const char* name = $3;
225          //printf("declared polyphonic var '%s'\n", name);          //printf("declared polyphonic var '%s'\n", name);
226          if (context->variableByName(name))          if (context->variableByName(name)) {
227              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
228          if (name[0] != '$') {          } else if (name[0] != '$' && name[0] != '~') {
229              PARSE_ERR(@3, "Polyphonic variables may only be declared as integers.");              PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");
230              $$ = new FunctionCall("nothing", new Args, NULL); // whatever          } else if (name[0] == '~') {
231          } else {              context->vartable[name] = new PolyphonicRealVariable({
232              context->vartable[name] = new PolyphonicIntVariable(context);                  .ctx = context
233              $$ = new NoOperation;              });
234            } else {
235                context->vartable[name] = new PolyphonicIntVariable({
236                    .ctx = context
237                });
238          }          }
239            $$ = new NoOperation;
240      }      }
241      | DECLARE VARIABLE ASSIGNMENT expr  {      | DECLARE VARIABLE ASSIGNMENT expr  {
242          const char* name = $2;          const char* name = $2;
243          //printf("declared assign var '%s'\n", name);          //printf("declared assign var '%s'\n", name);
244          if (context->variableByName(name))          const ExprType_t declType = exprTypeOfVarName(name);
245            if (context->variableByName(name)) {
246              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
247          if ($4->exprType() == STRING_EXPR) {              $$ = new NoOperation;
248              if (name[0] == '$')          } else if ($4->exprType() == STRING_EXPR) {
249                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as integer, string expression assigned though.").c_str());              if (name[0] != '@')
250                    PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());
251              StringExprRef expr = $4;              StringExprRef expr = $4;
252              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
253                  const String s = expr->evalStr();                  const String s = expr->evalStr();
# Line 224  statement: Line 259  statement:
259                  context->vartable[name] = var;                  context->vartable[name] = var;
260                  $$ = new Assignment(var, expr);                  $$ = new Assignment(var, expr);
261              }              }
262          } else {          } else if ($4->exprType() == REAL_EXPR) {
263              if (name[0] == '@')              if (name[0] != '~')
264                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as string, integer expression assigned though.").c_str());                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
265                RealExprRef expr = $4;
266                RealVariableRef var = new RealVariable({
267                    .ctx = context,
268                    .unitType = expr->unitType(),
269                    .isFinal = expr->isFinal()
270                });
271                if (expr->isConstExpr()) {
272                    $$ = new Assignment(var, new RealLiteral({
273                        .value = expr->evalReal(),
274                        .unitFactor = expr->unitFactor(),
275                        .unitType = expr->unitType(),
276                        .isFinal = expr->isFinal()
277                    }));
278                } else {
279                    $$ = new Assignment(var, expr);
280                }
281                context->vartable[name] = var;
282            } else if ($4->exprType() == INT_EXPR) {
283                if (name[0] != '$')
284                    PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
285              IntExprRef expr = $4;              IntExprRef expr = $4;
286                IntVariableRef var = new IntVariable({
287                    .ctx = context,
288                    .unitType = expr->unitType(),
289                    .isFinal = expr->isFinal()
290                });
291              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
292                  const vmint i = expr->evalInt();                  $$ = new Assignment(var, new IntLiteral({
293                  IntVariableRef var = new IntVariable(context);                      .value = expr->evalInt(),
294                  context->vartable[name] = var;                      .unitFactor = expr->unitFactor(),
295                  $$ = new Assignment(var, new IntLiteral(i));                      .unitType = expr->unitType(),
296                        .isFinal = expr->isFinal()
297                    }));
298              } else {              } else {
                 IntVariableRef var = new IntVariable(context);  
                 context->vartable[name] = var;  
299                  $$ = new Assignment(var, expr);                  $$ = new Assignment(var, expr);
300              }              }
301                context->vartable[name] = var;
302            } else if ($4->exprType() == EMPTY_EXPR) {
303                PARSE_ERR(@4, "Expression does not result in a value.");
304                $$ = new NoOperation;
305            } else if (isArray($4->exprType())) {
306                PARSE_ERR(@2, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
307                $$ = new NoOperation;
308          }          }
309      }      }
310      | DECLARE VARIABLE '[' expr ']'  {      | DECLARE VARIABLE '[' expr ']'  {
# Line 245  statement: Line 312  statement:
312          const char* name = $2;          const char* name = $2;
313          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
314              PARSE_ERR(@4, (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());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
315          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
316              PARSE_ERR(@4, (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());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
317          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
318              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
319          } else {          } else {
320              IntExprRef expr = $4;              IntExprRef sizeExpr = $4;
321              vmint size = expr->evalInt();              if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
322              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());  
                 $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
323              } else {              } else {
324                  context->vartable[name] = new IntArrayVariable(context, size);                  if (sizeExpr->isFinal())
325                  $$ = new NoOperation;                      PARSE_WRN(@4, "Final operator '!' is meaningless here.");
326                    vmint size = sizeExpr->evalInt();
327                    if (size <= 0) {
328                        PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
329                    } else {
330                        if (name[0] == '?') {
331                            context->vartable[name] = new RealArrayVariable(context, size);
332                        } else if (name[0] == '%') {
333                            context->vartable[name] = new IntArrayVariable(context, size);
334                        } else {
335                            PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
336                        }
337                    }
338              }              }
339          }          }
340            $$ = new NoOperation;
341      }      }
342      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
343          const char* name = $2;          const char* name = $2;
344          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
345              PARSE_ERR(@4, (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());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
346          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
347              PARSE_ERR(@4, (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());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
348          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
349              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
350          } else {          } else {
351              IntExprRef sizeExpr = $4;              IntExprRef sizeExpr = $4;
352              ArgsRef args = $8;              ArgsRef args = $8;
353              vmint size = sizeExpr->evalInt();              vmint size = sizeExpr->evalInt();
354              if (size <= 0) {              if (size <= 0) {
355                  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());
                 $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
356              } else if (args->argsCount() > size) {              } else if (args->argsCount() > size) {
357                  PARSE_ERR(@8, (String("Array variable '") + name +                  PARSE_ERR(@8, (String("Array variable '") + name +
358                            "' was declared with size " + ToString(size) +                            "' was declared with size " + ToString(size) +
359                            " but " + ToString(args->argsCount()) +                            " but " + ToString(args->argsCount()) +
360                            " values were assigned." ).c_str());                            " values were assigned." ).c_str());
361                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                        } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
362                    PARSE_ERR(@4, "Units are not allowed as array size.");
363              } else {              } else {
364                    if (sizeExpr->isFinal())
365                        PARSE_WRN(@4, "Final operator '!' is meaningless here.");
366                    ExprType_t declType = EMPTY_EXPR;
367                    if (name[0] == '%') {
368                        declType = INT_EXPR;
369                    } else if (name[0] == '?') {
370                        declType = REAL_EXPR;
371                    } else if (name[0] == '$') {
372                        PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
373                    } else if (name[0] == '~') {
374                        PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
375                    } else {
376                        PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
377                    }
378                  bool argsOK = true;                  bool argsOK = true;
379                  for (vmint i = 0; i < args->argsCount(); ++i) {                  if (declType == EMPTY_EXPR) {
380                      if (args->arg(i)->exprType() != INT_EXPR) {                      argsOK = false;
381                          PARSE_ERR(                  } else {
382                              @8,                      for (vmint i = 0; i < args->argsCount(); ++i) {
383                              (String("Array variable '") + name +                          if (args->arg(i)->exprType() != declType) {
384                              "' declared with invalid assignment values. Assigned element " +                              PARSE_ERR(
385                              ToString(i+1) + " is not an integer expression.").c_str()                                  @8,
386                          );                                  (String("Array variable '") + name +
387                          argsOK = false;                                  "' declared with invalid assignment values. Assigned element " +
388                          break;                                  ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
389                                );
390                                argsOK = false;
391                                break;
392                            } else if (args->arg(i)->asNumber()->unitType()) {
393                                PARSE_ERR(
394                                    @8,
395                                    (String("Array variable '") + name +
396                                    "' declared with invalid assignment values. Assigned element " +
397                                    ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
398                                );
399                                argsOK = false;
400                                break;
401                            } else if (args->arg(i)->asNumber()->isFinal()) {
402                                PARSE_ERR(
403                                    @8,
404                                    (String("Array variable '") + name +
405                                    "' declared with invalid assignment values. Assigned element " +
406                                    ToString(i+1) + " declared as 'final' value.").c_str()
407                                );
408                                argsOK = false;
409                                break;
410                            }
411                      }                      }
412                  }                  }
413                  if (argsOK) {                  if (argsOK) {
414                      context->vartable[name] = new IntArrayVariable(context, size, args);                      if (declType == REAL_EXPR)
415                      $$ = new NoOperation;                          context->vartable[name] = new RealArrayVariable(context, size, args);
416                  } else                      else
417                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever                          context->vartable[name] = new IntArrayVariable(context, size, args);
418                    }
419              }              }
420          }          }
421            $$ = new NoOperation;
422      }      }
423      | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {      | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
424          const char* name = $3;          const char* name = $3;
425          if (!$5->isConstExpr()) {          if (!$5->isConstExpr()) {
426              PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());              PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
427          } else if ($5->exprType() != INT_EXPR) {          } else if ($5->exprType() != INT_EXPR) {
428              PARSE_ERR(@5, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());              PARSE_ERR(@5, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
429          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
430              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
431          } else {          } else {
432              IntExprRef sizeExpr = $5;              IntExprRef sizeExpr = $5;
433              ArgsRef args = $9;              ArgsRef args = $9;
434              vmint size = sizeExpr->evalInt();              vmint size = sizeExpr->evalInt();
435              if (size <= 0) {              if (size <= 0) {
436                  PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());                  PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
                 $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
437              } else if (args->argsCount() > size) {              } else if (args->argsCount() > size) {
438                  PARSE_ERR(@9, (String("Array variable '") + name +                  PARSE_ERR(@9, (String("Array variable '") + name +
439                            "' was declared with size " + ToString(size) +                            "' was declared with size " + ToString(size) +
440                            " but " + ToString(args->argsCount()) +                            " but " + ToString(args->argsCount()) +
441                            " values were assigned." ).c_str());                            " values were assigned." ).c_str());
442                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                        } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
443                    PARSE_ERR(@5, "Units are not allowed as array size.");
444              } else {              } else {
445                    if (sizeExpr->isFinal())
446                        PARSE_WRN(@5, "Final operator '!' is meaningless here.");
447                    ExprType_t declType = EMPTY_EXPR;
448                    if (name[0] == '%') {
449                        declType = INT_EXPR;
450                    } else if (name[0] == '?') {
451                        declType = REAL_EXPR;
452                    } else if (name[0] == '$') {
453                        PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
454                    } else if (name[0] == '~') {
455                        PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
456                    } else {
457                        PARSE_ERR(@3, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
458                    }
459                  bool argsOK = true;                  bool argsOK = true;
460                  for (vmint i = 0; i < args->argsCount(); ++i) {                  if (declType == EMPTY_EXPR) {
461                      if (args->arg(i)->exprType() != INT_EXPR) {                      argsOK = false;
462                          PARSE_ERR(                  } else {
463                              @9,                      for (vmint i = 0; i < args->argsCount(); ++i) {
464                              (String("Array variable '") + name +                          if (args->arg(i)->exprType() != declType) {
465                              "' declared with invalid assignment values. Assigned element " +                              PARSE_ERR(
466                              ToString(i+1) + " is not an integer expression.").c_str()                                  @9,
467                          );                                  (String("const array variable '") + name +
468                          argsOK = false;                                  "' declared with invalid assignment values. Assigned element " +
469                          break;                                  ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
470                      }                              );
471                      if (!args->arg(i)->isConstExpr()) {                              argsOK = false;
472                          PARSE_ERR(                              break;
473                              @9,                          }
474                              (String("const array variable '") + name +                          if (!args->arg(i)->isConstExpr()) {
475                              "' must be defined with const values. Assigned element " +                              PARSE_ERR(
476                              ToString(i+1) + " is not a const expression though.").c_str()                                  @9,
477                          );                                  (String("const array variable '") + name +
478                          argsOK = false;                                  "' must be defined with const values. Assigned element " +
479                          break;                                  ToString(i+1) + " is not a const expression though.").c_str()
480                                );
481                                argsOK = false;
482                                break;
483                            } else if (args->arg(i)->asNumber()->unitType()) {
484                                PARSE_ERR(
485                                    @9,
486                                    (String("const array variable '") + name +
487                                    "' declared with invalid assignment values. Assigned element " +
488                                    ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
489                                );
490                                argsOK = false;
491                                break;
492                            } else if (args->arg(i)->asNumber()->isFinal()) {
493                                PARSE_ERR(
494                                    @9,
495                                    (String("const array variable '") + name +
496                                    "' declared with invalid assignment values. Assigned element " +
497                                    ToString(i+1) + " declared as 'final' value.").c_str()
498                                );
499                                argsOK = false;
500                                break;
501                            }
502                      }                      }
503                  }                  }
504                  if (argsOK) {                  if (argsOK) {
505                      context->vartable[name] = new IntArrayVariable(context, size, args, true);                      if (declType == REAL_EXPR)
506                      $$ = new NoOperation;                          context->vartable[name] = new RealArrayVariable(context, size, args, true);
507                  } else                      else
508                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever                          context->vartable[name] = new IntArrayVariable(context, size, args, true);
509                    }
510              }              }
511          }          }
512            $$ = new NoOperation;
513      }      }
514      | DECLARE CONST_ VARIABLE ASSIGNMENT expr  {      | DECLARE CONST_ VARIABLE ASSIGNMENT expr  {
515          const char* name = $3;          const char* name = $3;
516            const ExprType_t declType = exprTypeOfVarName(name);
517          if ($5->exprType() == STRING_EXPR) {          if ($5->exprType() == STRING_EXPR) {
518              if (name[0] == '$')              if (name[0] != '@')
519                  PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");                  PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());
520              String s;              String s;
521              StringExprRef expr = $5;              StringExprRef expr = $5;
522              if (expr->isConstExpr())              if (expr->isConstExpr())
# Line 380  statement: Line 526  statement:
526              ConstStringVariableRef var = new ConstStringVariable(context, s);              ConstStringVariableRef var = new ConstStringVariable(context, s);
527              context->vartable[name] = var;              context->vartable[name] = var;
528              //$$ = new Assignment(var, new StringLiteral(s));              //$$ = new Assignment(var, new StringLiteral(s));
529              $$ = new NoOperation();          } else if ($5->exprType() == REAL_EXPR) {
530          } else {              if (name[0] != '~')
531              if (name[0] == '@')                  PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
532                  PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");              RealExprRef expr = $5;
533              vmint i = 0;              if (!expr->isConstExpr()) {
534                    PARSE_ERR(@5, (String("Assignment to const real number variable '") + name + "' requires const expression.").c_str());
535                }
536                ConstRealVariableRef var = new ConstRealVariable(
537                    #if defined(__GNUC__) && !defined(__clang__)
538                    (const RealVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
539                    #endif
540                {
541                    .value = (expr->isConstExpr()) ? expr->evalReal() : vmfloat(0),
542                    .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,
543                    .unitType = expr->unitType(),
544                    .isFinal = expr->isFinal()
545                });
546                context->vartable[name] = var;
547                //$$ = new Assignment(var, new IntLiteral(i));
548            } else if ($5->exprType() == INT_EXPR) {
549                if (name[0] != '$')
550                    PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
551              IntExprRef expr = $5;              IntExprRef expr = $5;
552              if (expr->isConstExpr())              if (!expr->isConstExpr()) {
                 i = expr->evalInt();  
             else  
553                  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());
554              ConstIntVariableRef var = new ConstIntVariable(i);              }
555                ConstIntVariableRef var = new ConstIntVariable(
556                    #if defined(__GNUC__) && !defined(__clang__)
557                    (const IntVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
558                    #endif
559                {
560                    .value = (expr->isConstExpr()) ? expr->evalInt() : 0,
561                    .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,
562                    .unitType = expr->unitType(),
563                    .isFinal = expr->isFinal()
564                });
565              context->vartable[name] = var;              context->vartable[name] = var;
566              //$$ = new Assignment(var, new IntLiteral(i));              //$$ = new Assignment(var, new IntLiteral(i));
567              $$ = new NoOperation();          } else if ($5->exprType() == EMPTY_EXPR) {
568                PARSE_ERR(@5, "Expression does not result in a value.");
569            } else if (isArray($5->exprType())) {
570                PARSE_ERR(@5, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
571          }          }
572            $$ = new NoOperation();
573      }      }
574      | assignment  {      | assignment  {
575          $$ = $1;          $$ = $1;
576      }      }
577      | WHILE '(' expr ')' opt_statements END WHILE  {      | WHILE '(' expr ')' opt_statements END WHILE  {
578          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
579              $$ = new While($3, $5);              IntExprRef expr = $3;
580                if (expr->asNumber()->unitType() ||
581                    expr->asNumber()->hasUnitFactorEver())
582                    PARSE_WRN(@3, "Condition for 'while' loops contains a unit.");
583                else if (expr->isFinal() && expr->isConstExpr())
584                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
585                $$ = new While(expr, $5);
586          } else {          } else {
587              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
588              $$ = new While(new IntLiteral(0), $5);              $$ = new While(new IntLiteral({ .value = 0 }), $5);
589          }          }
590      }      }
591      | SYNCHRONIZED opt_statements END SYNCHRONIZED  {      | SYNCHRONIZED opt_statements END SYNCHRONIZED  {
592          $$ = new SyncBlock($2);          $$ = new SyncBlock($2);
593      }      }
594      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {
595          $$ = new If($3, $5, $7);          if ($3->exprType() == INT_EXPR) {
596                IntExprRef expr = $3;
597                if (expr->asNumber()->unitType() ||
598                    expr->asNumber()->hasUnitFactorEver())
599                    PARSE_WRN(@3, "Condition for 'if' contains a unit.");
600                else if (expr->isFinal() && expr->isConstExpr())
601                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
602                $$ = new If($3, $5, $7);
603            } else {
604                PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
605                $$ = new If(new IntLiteral({ .value = 0 }), $5, $7);
606            }
607      }      }
608      | IF '(' expr ')' opt_statements END IF  {      | IF '(' expr ')' opt_statements END IF  {
609          $$ = new If($3, $5);          if ($3->exprType() == INT_EXPR) {
610                IntExprRef expr = $3;
611                if (expr->asNumber()->unitType() ||
612                    expr->asNumber()->hasUnitFactorEver())
613                    PARSE_WRN(@3, "Condition for 'if' contains a unit.");
614                else if (expr->isFinal() && expr->isConstExpr())
615                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
616                $$ = new If($3, $5);
617            } else {
618                PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
619                $$ = new If(new IntLiteral({ .value = 0 }), $5);
620            }
621      }      }
622      | SELECT expr caseclauses END SELECT  {      | SELECT expr caseclauses END SELECT  {
623          if ($2->exprType() == INT_EXPR) {          if ($2->exprType() == INT_EXPR) {
624              $$ = new SelectCase($2, $3);              IntExprRef expr = $2;
625                if (expr->unitType() || expr->hasUnitFactorEver()) {
626                    PARSE_ERR(@2, "Units are not allowed here.");
627                    $$ = new SelectCase(new IntLiteral({ .value = 0 }), $3);
628                } else {
629                    if (expr->isFinal() && expr->isConstExpr())
630                        PARSE_WRN(@2, "Final operator '!' is meaningless here.");
631                    $$ = new SelectCase(expr, $3);
632                }
633          } else {          } else {
634              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
635              $$ = new SelectCase(new IntLiteral(0), $3);              $$ = new SelectCase(new IntLiteral({ .value = 0 }), $3);
636          }          }
637      }      }
638    
# Line 438  caseclauses: Line 649  caseclauses:
649  caseclause:  caseclause:
650      CASE INTEGER opt_statements  {      CASE INTEGER opt_statements  {
651          $$ = CaseBranch();          $$ = CaseBranch();
652          $$.from = new IntLiteral($2);          $$.from = new IntLiteral({ .value = $2 });
653          $$.statements = $3;          $$.statements = $3;
654      }      }
655      | CASE INTEGER TO INTEGER opt_statements  {      | CASE INTEGER TO INTEGER opt_statements  {
656          $$ = CaseBranch();          $$ = CaseBranch();
657          $$.from = new IntLiteral($2);          $$.from = new IntLiteral({ .value = $2 });
658          $$.to   = new IntLiteral($4);          $$.to   = new IntLiteral({ .value = $4 });
659          $$.statements = $5;          $$.statements = $5;
660      }      }
661    
# Line 487  functioncall: Line 698  functioncall:
698          } else {          } else {
699              bool argsOK = true;              bool argsOK = true;
700              for (vmint i = 0; i < args->argsCount(); ++i) {              for (vmint i = 0; i < args->argsCount(); ++i) {
701                  if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {                  if (!fn->acceptsArgType(i, args->arg(i)->exprType())) {
702                      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 " + acceptedArgTypesStr(fn, i) + " type, but type " + typeStr(args->arg(i)->exprType()) + " was given instead.").c_str());
703                      argsOK = false;                      argsOK = false;
704                      break;                      break;
705                  } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {                  } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
706                      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());
707                      argsOK = false;                      argsOK = false;
708                      break;                      break;
709                    } else if (isNumber(args->arg(i)->exprType()) && !fn->acceptsArgUnitType(i, args->arg(i)->asNumber()->unitType())) {
710                        if (args->arg(i)->asNumber()->unitType())
711                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect unit " + unitTypeStr(args->arg(i)->asNumber()->unitType()) +  ".").c_str());
712                        else
713                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects a unit.").c_str());
714                        argsOK = false;
715                        break;
716                    } else if (isNumber(args->arg(i)->exprType()) && args->arg(i)->asNumber()->hasUnitFactorEver() && !fn->acceptsArgUnitPrefix(i, args->arg(i)->asNumber()->unitType())) {
717                        if (args->arg(i)->asNumber()->unitType())
718                            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)->asNumber()->unitType()) + ".").c_str());
719                        else
720                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix.").c_str());
721                        argsOK = false;
722                        break;
723                    } else if (!fn->acceptsArgFinal(i) && isNumber(args->arg(i)->exprType()) && args->arg(i)->asNumber()->isFinal()) {
724                        PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a \"final\" value.").c_str());
725                        argsOK = false;
726                        break;
727                  }                  }
728              }              }
729                if (argsOK) {
730                    // perform built-in function's own, custom arguments checks (if any)
731                    fn->checkArgs(&*args, [&](String err) {
732                        PARSE_ERR(@3, (String("Built-in function '") + name + "()': " + err).c_str());
733                        argsOK = false;
734                    }, [&](String wrn) {
735                        PARSE_WRN(@3, (String("Built-in function '") + name + "()': " + wrn).c_str());
736                    });
737                }
738              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
739          }          }
740      }      }
# Line 569  assignment: Line 807  assignment:
807              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());
808          else if (var->exprType() != $3->exprType())          else if (var->exprType() != $3->exprType())
809              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());
810            else if (isNumber(var->exprType())) {
811                NumberVariableRef numberVar = var;
812                NumberExprRef expr = $3;
813                if (numberVar->unitType() != expr->unitType())
814                    PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has unit type " + unitTypeStr(numberVar->unitType()) + ", assignment has unit type " + unitTypeStr(expr->unitType()) + " though.").c_str());
815                else if (numberVar->isFinal() != expr->isFinal())
816                    PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' was declared as " + String(numberVar->isFinal() ? "final" : "not final") + ", assignment is " + String(expr->isFinal() ? "final" : "not final") + " though.").c_str());
817            }
818          $$ = new Assignment(var, $3);          $$ = new Assignment(var, $3);
819      }      }
820      | VARIABLE '[' expr ']' ASSIGNMENT expr  {      | VARIABLE '[' expr ']' ASSIGNMENT expr  {
# Line 576  assignment: Line 822  assignment:
822          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
823          if (!var)          if (!var)
824              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
825          else if (var->exprType() != INT_ARR_EXPR)          else if (!isArray(var->exprType()))
826              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());
827          else if (var->isConstExpr())          else if (var->isConstExpr())
828              PARSE_ERR(@5, (String("Variable assignment: Cannot modify const array variable '") + name + "'.").c_str());              PARSE_ERR(@5, (String("Variable assignment: Cannot modify const array variable '") + name + "'.").c_str());
# Line 584  assignment: Line 830  assignment:
830              PARSE_ERR(@5, (String("Variable assignment: Array variable '") + name + "' is not assignable.").c_str());              PARSE_ERR(@5, (String("Variable assignment: Array variable '") + name + "' is not assignable.").c_str());
831          else if ($3->exprType() != INT_EXPR)          else if ($3->exprType() != INT_EXPR)
832              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());
833          else if ($6->exprType() != INT_EXPR)          else if ($3->asInt()->unitType())
834              PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());              PARSE_ERR(@3, "Unit types are not allowed as array index.");
835          else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())          else if ($6->exprType() != scalarTypeOfArray(var->exprType()))
836                PARSE_ERR(@5, (String("Variable '") + name + "' was declared as " + typeStr(var->exprType()) + ", assigned expression is " + typeStr($6->exprType()) + " though.").c_str());
837            else if ($6->asNumber()->unitType())
838                PARSE_ERR(@6, "Unit types are not allowed for array variables.");
839            else if ($6->asNumber()->isFinal())
840                PARSE_ERR(@6, "Final operator '!' not allowed for array variables.");
841            else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
842              PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +              PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
843                            " exceeds size of array variable '" + name +                            " exceeds size of array variable '" + name +
844                            "' which was declared with size " +                            "' which was declared with size " +
845                            ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());                            ToString(((ArrayExprRef)var)->arraySize()) + ".").c_str());
846          IntArrayElementRef element = new IntArrayElement(var, $3);          else if ($3->asInt()->isFinal())
847          $$ = new Assignment(element, $6);              PARSE_WRN(@3, "Final operator '!' is meaningless here.");
848            if (var->exprType() == INT_ARR_EXPR) {
849                IntArrayElementRef element = new IntArrayElement(var, $3);
850                $$ = new Assignment(element, $6);
851            } else if (var->exprType() == REAL_ARR_EXPR) {
852                RealArrayElementRef element = new RealArrayElement(var, $3);
853                $$ = new Assignment(element, $6);
854            } else {
855                $$ = new NoOperation; // actually not possible to ever get here
856            }
857      }      }
858    
859  unary_expr:  unary_expr:
860      INTEGER  {      INTEGER  {
861          $$ = new IntLiteral($1);          $$ = new IntLiteral({ .value = $1 });
862        }
863        | REAL  {
864            $$ = new RealLiteral({ .value = $1 });
865        }
866        | INTEGER_UNIT  {
867            IntLiteralRef literal = new IntLiteral({
868                .value = $1.iValue,
869                .unitFactor = VMUnit::unitFactor($1.prefix),
870                .unitType = $1.unit
871            });
872            $$ = literal;
873        }
874        | REAL_UNIT  {
875            RealLiteralRef literal = new RealLiteral({
876                .value = $1.fValue,
877                .unitFactor = VMUnit::unitFactor($1.prefix),
878                .unitType = $1.unit
879            });
880            $$ = literal;
881      }      }
882      | STRING    {      | STRING    {
883          $$ = new StringLiteral($1);          $$ = new StringLiteral($1);
# Line 609  unary_expr: Line 889  unary_expr:
889              $$ = var;              $$ = var;
890          else {          else {
891              PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
892              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
893          }          }
894      }      }
895      | VARIABLE '[' expr ']'  {      | VARIABLE '[' expr ']'  {
# Line 617  unary_expr: Line 897  unary_expr:
897          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
898          if (!var) {          if (!var) {
899              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
900              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
901          } else if (var->exprType() != INT_ARR_EXPR) {          } else if (!isArray(var->exprType())) {
902              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());
903              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
904          } else if ($3->exprType() != INT_EXPR) {          } else if ($3->exprType() != INT_EXPR) {
905              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());
906              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
907            } else if ($3->asInt()->unitType() || $3->asInt()->hasUnitFactorEver()) {
908                PARSE_ERR(@3, "Units are not allowed as array index.");
909                $$ = new IntLiteral({ .value = 0 });
910          } else {          } else {
911              if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())              if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
912                  PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +                  PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
913                                 " exceeds size of array variable '" + name +                                 " exceeds size of array variable '" + name +
914                                 "' which was declared with size " +                                 "' which was declared with size " +
915                                 ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());                                 ToString(((ArrayExprRef)var)->arraySize()) + ".").c_str());
916              $$ = new IntArrayElement(var, $3);              else if ($3->asInt()->isFinal())
917                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
918                if (var->exprType() == REAL_ARR_EXPR) {
919                    $$ = new RealArrayElement(var, $3);
920                } else {
921                    $$ = new IntArrayElement(var, $3);
922                }
923          }          }
924      }      }
925      | '(' expr ')'  {      | '(' expr ')'  {
# Line 639  unary_expr: Line 928  unary_expr:
928      | functioncall  {      | functioncall  {
929          $$ = $1;          $$ = $1;
930      }      }
931        | '+' unary_expr  {
932            $$ = $2;
933        }
934      | '-' unary_expr  {      | '-' unary_expr  {
935          $$ = new Neg($2);          $$ = new Neg($2);
936      }      }
937      | BITWISE_NOT unary_expr  {      | BITWISE_NOT unary_expr  {
938          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
939              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());
940              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
941            } else if ($2->asInt()->unitType() || $2->asInt()->hasUnitFactorEver()) {
942                PARSE_ERR(@2, "Units are not allowed for operands of bitwise operations.");
943                $$ = new IntLiteral({ .value = 0 });
944          } else {          } else {
945              $$ = new BitwiseNot($2);              $$ = new BitwiseNot($2);
946          }          }
# Line 653  unary_expr: Line 948  unary_expr:
948      | NOT unary_expr  {      | NOT unary_expr  {
949          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
950              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());
951              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
952            } else if ($2->asInt()->unitType() || $2->asInt()->hasUnitFactorEver()) {
953                PARSE_ERR(@2, "Units are not allowed for operands of logical operations.");
954                $$ = new IntLiteral({ .value = 0 });
955          } else {          } else {
956              $$ = new Not($2);              $$ = new Not($2);
957          }          }
958      }      }
959        | '!' unary_expr  {
960            if (!isNumber($2->exprType())) {
961                PARSE_ERR(@2, (String("Right operand of \"final\" operator '!' must be a scalar number expression, is ") + typeStr($2->exprType()) + " though.").c_str());
962                $$ = new IntLiteral({ .value = 0 });
963            } else {
964                $$ = new Final($2);
965            }
966        }
967    
968  expr:  expr:
969      concat_expr      concat_expr
# Line 683  logical_or_expr: Line 989  logical_or_expr:
989          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
990          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
991              PARSE_ERR(@1, (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());
992              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
993          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
994              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());
995              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
996          } else {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
997                PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
998                $$ = new IntLiteral({ .value = 0 });
999            } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1000                PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
1001                $$ = new IntLiteral({ .value = 0 });
1002            } else {
1003                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1004                    PARSE_WRN(@3, "Right operand of 'or' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1005                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1006                    PARSE_WRN(@1, "Left operand of 'or' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1007              $$ = new Or(lhs, rhs);              $$ = new Or(lhs, rhs);
1008          }          }
1009      }      }
# Line 701  logical_and_expr: Line 1017  logical_and_expr:
1017          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1018          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1019              PARSE_ERR(@1, (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());
1020              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1021          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1022              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());
1023              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1024          } else {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1025                PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
1026                $$ = new IntLiteral({ .value = 0 });
1027            } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1028                PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
1029                $$ = new IntLiteral({ .value = 0 });
1030            } else {
1031                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1032                    PARSE_WRN(@3, "Right operand of 'and' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1033                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1034                    PARSE_WRN(@1, "Left operand of 'and' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1035              $$ = new And(lhs, rhs);              $$ = new And(lhs, rhs);
1036          }          }
1037      }      }
# Line 717  bitwise_or_expr: Line 1043  bitwise_or_expr:
1043          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1044          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1045              PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1046              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1047          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1048              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());
1049              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1050          } else {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1051                PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
1052                $$ = new IntLiteral({ .value = 0 });
1053            } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1054                PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
1055                $$ = new IntLiteral({ .value = 0 });
1056            } else {
1057                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1058                    PARSE_WRN(@3, "Right operand of '.or.' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1059                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1060                    PARSE_WRN(@1, "Left operand of '.or.' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1061              $$ = new BitwiseOr(lhs, rhs);              $$ = new BitwiseOr(lhs, rhs);
1062          }          }
1063      }      }
# Line 735  bitwise_and_expr: Line 1071  bitwise_and_expr:
1071          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1072          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1073              PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1074              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1075          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1076              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());
1077              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1078          } else {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1079                PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
1080                $$ = new IntLiteral({ .value = 0 });
1081            } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1082                PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
1083                $$ = new IntLiteral({ .value = 0 });
1084            } else {
1085                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1086                    PARSE_WRN(@3, "Right operand of '.and.' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1087                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1088                    PARSE_WRN(@1, "Left operand of '.and.' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1089              $$ = new BitwiseAnd(lhs, rhs);              $$ = new BitwiseAnd(lhs, rhs);
1090          }          }
1091      }      }
# Line 749  rel_expr: Line 1095  rel_expr:
1095      | rel_expr '<' add_expr  {      | rel_expr '<' add_expr  {
1096          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1097          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1098          if (lhs->exprType() != INT_EXPR) {          if (!isNumber(lhs->exprType())) {
1099              PARSE_ERR(@1, (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 a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1100              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1101          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isNumber(rhs->exprType())) {
1102              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 a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1103              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1104          } else {          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1105                PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1106                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1107                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1108                $$ = new IntLiteral({ .value = 0 });
1109            } else {
1110                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1111                    PARSE_WRN(@3, "Right operand of '<' comparison is not 'final', left operand is 'final' though.");
1112                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1113                    PARSE_WRN(@1, "Left operand of '<' comparison is not 'final', right operand is 'final' though.");
1114              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
1115          }          }
1116      }      }
1117      | rel_expr '>' add_expr  {      | rel_expr '>' add_expr  {
1118          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1119          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1120          if (lhs->exprType() != INT_EXPR) {          if (!isNumber(lhs->exprType())) {
1121              PARSE_ERR(@1, (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 a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1122              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1123          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isNumber(rhs->exprType())) {
1124              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 a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1125              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1126          } else {          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1127                PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1128                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1129                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1130                $$ = new IntLiteral({ .value = 0 });
1131            } else {
1132                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1133                    PARSE_WRN(@3, "Right operand of '>' comparison is not 'final', left operand is 'final' though.");
1134                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1135                    PARSE_WRN(@1, "Left operand of '>' comparison is not 'final', right operand is 'final' though.");
1136              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
1137          }          }
1138      }      }
1139      | rel_expr LE add_expr  {      | rel_expr LE add_expr  {
1140          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1141          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1142          if (lhs->exprType() != INT_EXPR) {          if (!isNumber(lhs->exprType())) {
1143              PARSE_ERR(@1, (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 a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1144              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1145          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isNumber(rhs->exprType())) {
1146              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 a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1147              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1148          } else {          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1149                PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1150                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1151                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1152                $$ = new IntLiteral({ .value = 0 });
1153            } else {
1154                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1155                    PARSE_WRN(@3, "Right operand of '<=' comparison is not 'final', left operand is 'final' though.");
1156                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1157                    PARSE_WRN(@1, "Left operand of '<=' comparison is not 'final', right operand is 'final' though.");
1158              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
1159          }          }
1160      }      }
1161      | rel_expr GE add_expr  {      | rel_expr GE add_expr  {
1162          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1163          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1164          if (lhs->exprType() != INT_EXPR) {          if (!isNumber(lhs->exprType())) {
1165              PARSE_ERR(@1, (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 a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1166              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1167          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isNumber(rhs->exprType())) {
1168              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 a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1169              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1170          } else {          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1171                PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1172                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1173                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1174                $$ = new IntLiteral({ .value = 0 });
1175            } else {
1176                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1177                    PARSE_WRN(@3, "Right operand of '>=' comparison is not 'final', left operand is 'final' though.");
1178                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1179                    PARSE_WRN(@1, "Left operand of '>=' comparison is not 'final', right operand is 'final' though.");
1180              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
1181          }          }
1182      }      }
1183      | rel_expr '=' add_expr  {      | rel_expr '=' add_expr  {
1184          $$ = new Relation($1, Relation::EQUAL, $3);          ExpressionRef lhs = $1;
1185            ExpressionRef rhs = $3;
1186            if (!isNumber(lhs->exprType())) {
1187                PARSE_ERR(@1, (String("Left operand of operator '=' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1188                $$ = new IntLiteral({ .value = 0 });
1189            } else if (!isNumber(rhs->exprType())) {
1190                PARSE_ERR(@3, (String("Right operand of operator '=' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1191                $$ = new IntLiteral({ .value = 0 });
1192            } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1193                PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1194                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1195                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1196                $$ = new IntLiteral({ .value = 0 });
1197            } else {
1198                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1199                    PARSE_WRN(@3, "Right operand of '=' comparison is not 'final', left operand is 'final' though.");
1200                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1201                    PARSE_WRN(@1, "Left operand of '=' comparison is not 'final', right operand is 'final' though.");
1202                $$ = new Relation(lhs, Relation::EQUAL, rhs);
1203            }
1204      }      }
1205      | rel_expr '#' add_expr  {      | rel_expr '#' add_expr  {
1206          $$ = new Relation($1, Relation::NOT_EQUAL, $3);          ExpressionRef lhs = $1;
1207            ExpressionRef rhs = $3;
1208            if (!isNumber(lhs->exprType())) {
1209                PARSE_ERR(@1, (String("Left operand of operator '#' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1210                $$ = new IntLiteral({ .value = 0 });
1211            } else if (!isNumber(rhs->exprType())) {
1212                PARSE_ERR(@3, (String("Right operand of operator '#' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1213                $$ = new IntLiteral({ .value = 0 });
1214            } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1215                PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1216                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1217                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1218                $$ = new IntLiteral({ .value = 0 });
1219            } else {
1220                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1221                    PARSE_WRN(@3, "Right operand of '#' comparison is not 'final', left operand is 'final' though.");
1222                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1223                    PARSE_WRN(@1, "Left operand of '#' comparison is not 'final', right operand is 'final' though.");
1224                $$ = new Relation(lhs, Relation::NOT_EQUAL, rhs);
1225            }
1226      }      }
1227    
1228  add_expr:  add_expr:
# Line 810  add_expr: Line 1230  add_expr:
1230      | add_expr '+' mul_expr  {      | add_expr '+' mul_expr  {
1231          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1232          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1233          if (lhs->exprType() != INT_EXPR) {          if (!isNumber(lhs->exprType())) {
1234              PARSE_ERR(@1, (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 a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1235              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1236          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isNumber(rhs->exprType())) {
1237              PARSE_ERR(@3, (String("Right operand of operator '+' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Right operand of operator '+' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1238              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1239          } else {          } else if (lhs->exprType() != rhs->exprType()) {
1240                PARSE_ERR(@2, (String("Operands of operator '+' must have same type; left operand is ") +
1241                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1242                $$ = new IntLiteral({ .value = 0 });
1243            } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1244                PARSE_ERR(@2, (String("Operands of '+' operations must have same unit, left operand is ") +
1245                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1246                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1247                $$ = new IntLiteral({ .value = 0 });
1248            } else {
1249                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1250                    PARSE_WRN(@3, "Right operand of '+' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1251                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1252                    PARSE_WRN(@1, "Left operand of '+' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1253              $$ = new Add(lhs,rhs);              $$ = new Add(lhs,rhs);
1254          }          }
1255      }      }
1256      | add_expr '-' mul_expr  {      | add_expr '-' mul_expr  {
1257          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1258          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1259          if (lhs->exprType() != INT_EXPR) {          if (!isNumber(lhs->exprType())) {
1260              PARSE_ERR(@1, (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 a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1261              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1262          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isNumber(rhs->exprType())) {
1263              PARSE_ERR(@3, (String("Right operand of operator '-' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Right operand of operator '-' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1264              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1265          } else {          } else if (lhs->exprType() != rhs->exprType()) {
1266                PARSE_ERR(@2, (String("Operands of operator '-' must have same type; left operand is ") +
1267                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1268                $$ = new IntLiteral({ .value = 0 });
1269            } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1270                PARSE_ERR(@2, (String("Operands of '-' operations must have same unit, left operand is ") +
1271                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1272                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1273                $$ = new IntLiteral({ .value = 0 });
1274            } else {
1275                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1276                    PARSE_WRN(@3, "Right operand of '-' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1277                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1278                    PARSE_WRN(@1, "Left operand of '-' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1279              $$ = new Sub(lhs,rhs);              $$ = new Sub(lhs,rhs);
1280          }          }
1281      }      }
# Line 839  mul_expr: Line 1285  mul_expr:
1285      | mul_expr '*' unary_expr  {      | mul_expr '*' unary_expr  {
1286          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1287          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1288          if (lhs->exprType() != INT_EXPR) {          if (!isNumber(lhs->exprType())) {
1289              PARSE_ERR(@1, (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 a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1290              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1291          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isNumber(rhs->exprType())) {
1292              PARSE_ERR(@3, (String("Right operand of operator '*' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Right operand of operator '*' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1293              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1294          } else {          } else if (lhs->asNumber()->unitType() && rhs->asNumber()->unitType()) {
1295                PARSE_ERR(@2, (String("Only one operand of operator '*' may have a unit type, left operand is ") +
1296                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1297                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1298                $$ = new IntLiteral({ .value = 0 });
1299            } else if (lhs->exprType() != rhs->exprType()) {
1300                PARSE_ERR(@2, (String("Operands of operator '*' must have same type; left operand is ") +
1301                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1302                $$ = new IntLiteral({ .value = 0 });
1303            } else {
1304                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1305                    PARSE_WRN(@3, "Right operand of '*' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1306                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1307                    PARSE_WRN(@1, "Left operand of '*' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1308              $$ = new Mul(lhs,rhs);              $$ = new Mul(lhs,rhs);
1309          }          }
1310      }      }
1311      | mul_expr '/' unary_expr  {      | mul_expr '/' unary_expr  {
1312          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1313          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1314          if (lhs->exprType() != INT_EXPR) {          if (!isNumber(lhs->exprType())) {
1315              PARSE_ERR(@1, (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 a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1316              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1317          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isNumber(rhs->exprType())) {
1318              PARSE_ERR(@3, (String("Right operand of operator '/' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Right operand of operator '/' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1319              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1320          } else {          } else if (lhs->asNumber()->unitType() && rhs->asNumber()->unitType() &&
1321                       lhs->asNumber()->unitType() != rhs->asNumber()->unitType())
1322            {
1323                PARSE_ERR(@2, (String("Operands of operator '/' with two different unit types, left operand is ") +
1324                    unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1325                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1326                $$ = new IntLiteral({ .value = 0 });
1327            } else if (!lhs->asNumber()->unitType() && rhs->asNumber()->unitType()) {
1328                PARSE_ERR(@3, ("Dividing left operand without any unit type by right operand with unit type (" +
1329                    unitTypeStr(rhs->asNumber()->unitType()) + ") is not possible.").c_str());
1330                $$ = new IntLiteral({ .value = 0 });
1331            } else if (lhs->exprType() != rhs->exprType()) {
1332                PARSE_ERR(@2, (String("Operands of operator '/' must have same type; left operand is ") +
1333                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1334                $$ = new IntLiteral({ .value = 0 });
1335            } else {
1336                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1337                    PARSE_WRN(@3, "Right operand of '/' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1338                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1339                    PARSE_WRN(@1, "Left operand of '/' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1340              $$ = new Div(lhs,rhs);              $$ = new Div(lhs,rhs);
1341          }          }
1342      }      }
# Line 867  mul_expr: Line 1345  mul_expr:
1345          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1346          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1347              PARSE_ERR(@1, (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());
1348              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1349          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1350              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());
1351              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1352          } else {          } else {
1353                if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver())
1354                    PARSE_ERR(@1, "Operands of modulo operator must not use any unit.");
1355                if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver())
1356                    PARSE_ERR(@3, "Operands of modulo operator must not use any unit.");
1357                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1358                    PARSE_WRN(@3, "Right operand of 'mod' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1359                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1360                    PARSE_WRN(@1, "Left operand of 'mod' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1361              $$ = new Mod(lhs,rhs);              $$ = new Mod(lhs,rhs);
1362          }          }
1363      }      }

Legend:
Removed from v.3557  
changed lines
  Added in v.3690

  ViewVC Help
Powered by ViewVC