/[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 3573 by schoenebeck, Tue Aug 27 21:36:53 2019 UTC revision 3595 by schoenebeck, Tue Sep 3 11:06:33 2019 UTC
# Line 190  statement: Line 190  statement:
190          } else if (name[0] == '@') {          } else if (name[0] == '@') {
191              context->vartable[name] = new StringVariable(context);              context->vartable[name] = new StringVariable(context);
192          } else if (name[0] == '~') {          } else if (name[0] == '~') {
193              context->vartable[name] = new RealVariable(context);              context->vartable[name] = new RealVariable({
194                    .ctx = context
195                });
196          } else if (name[0] == '$') {          } else if (name[0] == '$') {
197              context->vartable[name] = new IntVariable(context);              context->vartable[name] = new IntVariable({
198                    .ctx = context
199                });
200          } else if (name[0] == '?') {          } else if (name[0] == '?') {
201              PARSE_ERR(@2, (String("Real number array variable '") + name + "' declaration requires array size.").c_str());              PARSE_ERR(@2, (String("Real number array variable '") + name + "' declaration requires array size.").c_str());
202          } else if (name[0] == '%') {          } else if (name[0] == '%') {
# Line 210  statement: Line 214  statement:
214          } else if (name[0] != '$' && name[0] != '~') {          } else if (name[0] != '$' && name[0] != '~') {
215              PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");              PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");
216          } else if (name[0] == '~') {          } else if (name[0] == '~') {
217              context->vartable[name] = new PolyphonicRealVariable(context);              context->vartable[name] = new PolyphonicRealVariable({
218          } else {                  .ctx = context
219              context->vartable[name] = new PolyphonicIntVariable(context);              });
220            } else {
221                context->vartable[name] = new PolyphonicIntVariable({
222                    .ctx = context
223                });
224          }          }
225          $$ = new NoOperation;          $$ = new NoOperation;
226      }      }
# Line 241  statement: Line 249  statement:
249              if (name[0] != '~')              if (name[0] != '~')
250                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
251              RealExprRef expr = $4;              RealExprRef expr = $4;
252              RealVariableRef var = new RealVariable(context);              RealVariableRef var = new RealVariable({
253                    .ctx = context,
254                    .unitType = expr->unitType(),
255                    .isFinal = expr->isFinal()
256                });
257              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
258                  const vmfloat f = expr->evalReal();                  $$ = new Assignment(var, new RealLiteral({
259                  $$ = new Assignment(var, new RealLiteral(f));                      .value = expr->evalReal(),
260                        .unitFactor = expr->unitFactor(),
261                        .unitType = expr->unitType(),
262                        .isFinal = expr->isFinal()
263                    }));
264              } else {              } else {
265                  $$ = new Assignment(var, expr);                  $$ = new Assignment(var, expr);
266              }              }
             var->copyUnitFrom(expr);  
             var->setFinal(expr->isFinal());  
267              context->vartable[name] = var;              context->vartable[name] = var;
268          } else if ($4->exprType() == INT_EXPR) {          } else if ($4->exprType() == INT_EXPR) {
269              if (name[0] != '$')              if (name[0] != '$')
270                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
271              IntExprRef expr = $4;              IntExprRef expr = $4;
272              IntVariableRef var = new IntVariable(context);              IntVariableRef var = new IntVariable({
273                    .ctx = context,
274                    .unitType = expr->unitType(),
275                    .isFinal = expr->isFinal()
276                });
277              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
278                  const vmint i = expr->evalInt();                  $$ = new Assignment(var, new IntLiteral({
279                  $$ = new Assignment(var, new IntLiteral(i));                      .value = expr->evalInt(),
280                        .unitFactor = expr->unitFactor(),
281                        .unitType = expr->unitType(),
282                        .isFinal = expr->isFinal()
283                    }));
284              } else {              } else {
285                  $$ = new Assignment(var, expr);                  $$ = new Assignment(var, expr);
286              }              }
             var->copyUnitFrom(expr);  
             var->setFinal(expr->isFinal());  
287              context->vartable[name] = var;              context->vartable[name] = var;
288          } else if ($4->exprType() == EMPTY_EXPR) {          } else if ($4->exprType() == EMPTY_EXPR) {
289              PARSE_ERR(@4, "Expression does not result in a value.");              PARSE_ERR(@4, "Expression does not result in a value.");
# Line 283  statement: Line 303  statement:
303          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
304              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
305          } else {          } else {
306              IntExprRef expr = $4;              IntExprRef sizeExpr = $4;
307              if (expr->unitType() || expr->unitPrefix(0)) {              if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
308                  PARSE_ERR(@4, "Units are not allowed as array size.");                  PARSE_ERR(@4, "Units are not allowed as array size.");
309              } else {              } else {
310                  if (expr->isFinal())                  if (sizeExpr->isFinal())
311                      PARSE_WRN(@4, "Final operator '!' is meaningless here.");                      PARSE_WRN(@4, "Final operator '!' is meaningless here.");
312                  vmint size = expr->evalInt();                  vmint size = sizeExpr->evalInt();
313                  if (size <= 0) {                  if (size <= 0) {
314                      PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());                      PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
315                  } else {                  } else {
# Line 324  statement: Line 344  statement:
344                            "' was declared with size " + ToString(size) +                            "' was declared with size " + ToString(size) +
345                            " but " + ToString(args->argsCount()) +                            " but " + ToString(args->argsCount()) +
346                            " values were assigned." ).c_str());                            " values were assigned." ).c_str());
347              } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {              } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
348                  PARSE_ERR(@4, "Units are not allowed as array size.");                  PARSE_ERR(@4, "Units are not allowed as array size.");
349              } else {              } else {
350                  if (sizeExpr->isFinal())                  if (sizeExpr->isFinal())
# Line 355  statement: Line 375  statement:
375                              );                              );
376                              argsOK = false;                              argsOK = false;
377                              break;                              break;
378                          } else if (args->arg(i)->asInt()->unitType() ||                          } else if (args->arg(i)->asNumber()->unitType()) {
                                    args->arg(i)->asInt()->unitPrefix(0))  
                         {  
379                              PARSE_ERR(                              PARSE_ERR(
380                                  @8,                                  @8,
381                                  (String("Array variable '") + name +                                  (String("Array variable '") + name +
382                                  "' declared with invalid assignment values. Assigned element " +                                  "' declared with invalid assignment values. Assigned element " +
383                                  ToString(i+1) + " contains a unit.").c_str()                                  ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
384                                );
385                                argsOK = false;
386                                break;
387                            } else if (args->arg(i)->asNumber()->isFinal()) {
388                                PARSE_ERR(
389                                    @8,
390                                    (String("Array variable '") + name +
391                                    "' declared with invalid assignment values. Assigned element " +
392                                    ToString(i+1) + " declared as 'final' value.").c_str()
393                              );                              );
394                              argsOK = false;                              argsOK = false;
395                              break;                              break;
# Line 398  statement: Line 425  statement:
425                            "' was declared with size " + ToString(size) +                            "' was declared with size " + ToString(size) +
426                            " but " + ToString(args->argsCount()) +                            " but " + ToString(args->argsCount()) +
427                            " values were assigned." ).c_str());                            " values were assigned." ).c_str());
428              } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {              } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
429                  PARSE_ERR(@5, "Units are not allowed as array size.");                  PARSE_ERR(@5, "Units are not allowed as array size.");
430              } else {              } else {
431                  if (sizeExpr->isFinal())                  if (sizeExpr->isFinal())
# Line 423  statement: Line 450  statement:
450                          if (args->arg(i)->exprType() != declType) {                          if (args->arg(i)->exprType() != declType) {
451                              PARSE_ERR(                              PARSE_ERR(
452                                  @9,                                  @9,
453                                  (String("Array variable '") + name +                                  (String("const array variable '") + name +
454                                  "' declared with invalid assignment values. Assigned element " +                                  "' declared with invalid assignment values. Assigned element " +
455                                  ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()                                  ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
456                              );                              );
# Line 439  statement: Line 466  statement:
466                              );                              );
467                              argsOK = false;                              argsOK = false;
468                              break;                              break;
469                          } else if (args->arg(i)->asInt()->unitType() ||                          } else if (args->arg(i)->asNumber()->unitType()) {
                                    args->arg(i)->asInt()->unitPrefix(0))  
                         {  
470                              PARSE_ERR(                              PARSE_ERR(
471                                  @9,                                  @9,
472                                  (String("const array variable '") + name +                                  (String("const array variable '") + name +
473                                  "' declared with invalid assignment values. Assigned element " +                                  "' declared with invalid assignment values. Assigned element " +
474                                  ToString(i+1) + " contains a unit.").c_str()                                  ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
475                                );
476                                argsOK = false;
477                                break;
478                            } else if (args->arg(i)->asNumber()->isFinal()) {
479                                PARSE_ERR(
480                                    @9,
481                                    (String("const array variable '") + name +
482                                    "' declared with invalid assignment values. Assigned element " +
483                                    ToString(i+1) + " declared as 'final' value.").c_str()
484                              );                              );
485                              argsOK = false;                              argsOK = false;
486                              break;                              break;
# Line 481  statement: Line 515  statement:
515          } else if ($5->exprType() == REAL_EXPR) {          } else if ($5->exprType() == REAL_EXPR) {
516              if (name[0] != '~')              if (name[0] != '~')
517                  PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());                  PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
             vmfloat f = 0;  
518              RealExprRef expr = $5;              RealExprRef expr = $5;
519              if (expr->isConstExpr())              if (!expr->isConstExpr()) {
                 f = expr->evalReal();  
             else  
520                  PARSE_ERR(@5, (String("Assignment to const real number variable '") + name + "' requires const expression.").c_str());                  PARSE_ERR(@5, (String("Assignment to const real number variable '") + name + "' requires const expression.").c_str());
521              ConstRealVariableRef var = new ConstRealVariable(f);              }
522              var->copyUnitFrom(expr);              ConstRealVariableRef var = new ConstRealVariable(
523              var->setFinal(expr->isFinal());                  #if defined(__GNUC__) && !defined(__clang__)
524                    (const RealVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
525                    #endif
526                {
527                    .value = (expr->isConstExpr()) ? expr->evalReal() : vmfloat(0),
528                    .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,
529                    .unitType = expr->unitType(),
530                    .isFinal = expr->isFinal()
531                });
532              context->vartable[name] = var;              context->vartable[name] = var;
533              //$$ = new Assignment(var, new IntLiteral(i));              //$$ = new Assignment(var, new IntLiteral(i));
534          } else if ($5->exprType() == INT_EXPR) {          } else if ($5->exprType() == INT_EXPR) {
535              if (name[0] != '$')              if (name[0] != '$')
536                  PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());                  PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
             vmint i = 0;  
537              IntExprRef expr = $5;              IntExprRef expr = $5;
538              if (expr->isConstExpr())              if (!expr->isConstExpr()) {
                 i = expr->evalInt();  
             else  
539                  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());
540              ConstIntVariableRef var = new ConstIntVariable(i);              }
541              var->copyUnitFrom(expr);              ConstIntVariableRef var = new ConstIntVariable(
542              var->setFinal(expr->isFinal());                  #if defined(__GNUC__) && !defined(__clang__)
543                    (const IntVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
544                    #endif
545                {
546                    .value = (expr->isConstExpr()) ? expr->evalInt() : 0,
547                    .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,
548                    .unitType = expr->unitType(),
549                    .isFinal = expr->isFinal()
550                });
551              context->vartable[name] = var;              context->vartable[name] = var;
552              //$$ = new Assignment(var, new IntLiteral(i));              //$$ = new Assignment(var, new IntLiteral(i));
553          } else if ($5->exprType() == EMPTY_EXPR) {          } else if ($5->exprType() == EMPTY_EXPR) {
# Line 519  statement: Line 563  statement:
563      | WHILE '(' expr ')' opt_statements END WHILE  {      | WHILE '(' expr ')' opt_statements END WHILE  {
564          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
565              IntExprRef expr = $3;              IntExprRef expr = $3;
566              if (expr->isFinal() && expr->isConstExpr())              if (expr->asNumber()->unitType() ||
567                    expr->asNumber()->hasUnitFactorEver())
568                    PARSE_WRN(@3, "Condition for 'while' loops contains a unit.");
569                else if (expr->isFinal() && expr->isConstExpr())
570                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");
571              $$ = new While(expr, $5);              $$ = new While(expr, $5);
572          } else {          } else {
573              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
574              $$ = new While(new IntLiteral(0), $5);              $$ = new While(new IntLiteral({ .value = 0 }), $5);
575          }          }
576      }      }
577      | SYNCHRONIZED opt_statements END SYNCHRONIZED  {      | SYNCHRONIZED opt_statements END SYNCHRONIZED  {
# Line 533  statement: Line 580  statement:
580      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {
581          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
582              IntExprRef expr = $3;              IntExprRef expr = $3;
583              if (expr->isFinal() && expr->isConstExpr())              if (expr->asNumber()->unitType() ||
584                    expr->asNumber()->hasUnitFactorEver())
585                    PARSE_WRN(@3, "Condition for 'if' contains a unit.");
586                else if (expr->isFinal() && expr->isConstExpr())
587                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");
588              $$ = new If($3, $5, $7);              $$ = new If($3, $5, $7);
589          } else {          } else {
590              PARSE_ERR(@3, "Condition for 'if' must be integer expression.");              PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
591              $$ = new If(new IntLiteral(0), $5, $7);              $$ = new If(new IntLiteral({ .value = 0 }), $5, $7);
592          }          }
593      }      }
594      | IF '(' expr ')' opt_statements END IF  {      | IF '(' expr ')' opt_statements END IF  {
595          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
596              IntExprRef expr = $3;              IntExprRef expr = $3;
597              if (expr->isFinal() && expr->isConstExpr())              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.");                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");
602              $$ = new If($3, $5);              $$ = new If($3, $5);
603          } else {          } else {
604              PARSE_ERR(@3, "Condition for 'if' must be integer expression.");              PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
605              $$ = new If(new IntLiteral(0), $5);              $$ = new If(new IntLiteral({ .value = 0 }), $5);
606          }          }
607      }      }
608      | SELECT expr caseclauses END SELECT  {      | SELECT expr caseclauses END SELECT  {
609          if ($2->exprType() == INT_EXPR) {          if ($2->exprType() == INT_EXPR) {
610              IntExprRef expr = $2;              IntExprRef expr = $2;
611              if (expr->unitType() || expr->unitPrefix(0)) {              if (expr->unitType() || expr->hasUnitFactorEver()) {
612                  PARSE_ERR(@2, "Units are not allowed here.");                  PARSE_ERR(@2, "Units are not allowed here.");
613                    $$ = new SelectCase(new IntLiteral({ .value = 0 }), $3);
614              } else {              } else {
615                  if (expr->isFinal() && expr->isConstExpr())                  if (expr->isFinal() && expr->isConstExpr())
616                      PARSE_WRN(@2, "Final operator '!' is meaningless here.");                      PARSE_WRN(@2, "Final operator '!' is meaningless here.");
# Line 564  statement: Line 618  statement:
618              }              }
619          } else {          } else {
620              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
621              $$ = new SelectCase(new IntLiteral(0), $3);              $$ = new SelectCase(new IntLiteral({ .value = 0 }), $3);
622          }          }
623      }      }
624    
# Line 581  caseclauses: Line 635  caseclauses:
635  caseclause:  caseclause:
636      CASE INTEGER opt_statements  {      CASE INTEGER opt_statements  {
637          $$ = CaseBranch();          $$ = CaseBranch();
638          $$.from = new IntLiteral($2);          $$.from = new IntLiteral({ .value = $2 });
639          $$.statements = $3;          $$.statements = $3;
640      }      }
641      | CASE INTEGER TO INTEGER opt_statements  {      | CASE INTEGER TO INTEGER opt_statements  {
642          $$ = CaseBranch();          $$ = CaseBranch();
643          $$.from = new IntLiteral($2);          $$.from = new IntLiteral({ .value = $2 });
644          $$.to   = new IntLiteral($4);          $$.to   = new IntLiteral({ .value = $4 });
645          $$.statements = $5;          $$.statements = $5;
646      }      }
647    
# Line 630  functioncall: Line 684  functioncall:
684          } else {          } else {
685              bool argsOK = true;              bool argsOK = true;
686              for (vmint i = 0; i < args->argsCount(); ++i) {              for (vmint i = 0; i < args->argsCount(); ++i) {
687                  if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {                  if (!fn->acceptsArgType(i, args->arg(i)->exprType())) {
688                      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());
689                      argsOK = false;                      argsOK = false;
690                      break;                      break;
691                  } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {                  } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
692                      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());
693                      argsOK = false;                      argsOK = false;
694                      break;                      break;
695                  } else if (isScalarNumber(args->arg(i)->exprType()) && !fn->acceptsArgUnitType(i, args->arg(i)->asScalarNumberExpr()->unitType())) {                  } else if (isNumber(args->arg(i)->exprType()) && !fn->acceptsArgUnitType(i, args->arg(i)->asNumber()->unitType())) {
696                      if (args->arg(i)->asScalarNumberExpr()->unitType())                      if (args->arg(i)->asNumber()->unitType())
697                          PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect unit " + unitTypeStr(args->arg(i)->asScalarNumberExpr()->unitType()) +  ".").c_str());                          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());
698                      else                      else
699                          PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects a unit.").c_str());                          PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects a unit.").c_str());
700                      argsOK = false;                      argsOK = false;
701                      break;                      break;
702                  } else if (isScalarNumber(args->arg(i)->exprType()) && args->arg(i)->asScalarNumberExpr()->unitPrefix(0) && !fn->acceptsArgUnitPrefix(i, args->arg(i)->asScalarNumberExpr()->unitType())) {                  } else if (isNumber(args->arg(i)->exprType()) && args->arg(i)->asNumber()->hasUnitFactorEver() && !fn->acceptsArgUnitPrefix(i, args->arg(i)->asNumber()->unitType())) {
703                      if (args->arg(i)->asScalarNumberExpr()->unitType())                      if (args->arg(i)->asNumber()->unitType())
704                          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)->asScalarNumberExpr()->unitType()) + ".").c_str());                          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());
705                      else                      else
706                          PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix.").c_str());                          PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix.").c_str());
707                      argsOK = false;                      argsOK = false;
708                      break;                      break;
709                  } else if (!fn->acceptsArgFinal(i) && isScalarNumber(args->arg(i)->exprType()) && args->arg(i)->asScalarNumberExpr()->isFinal()) {                  } else if (!fn->acceptsArgFinal(i) && isNumber(args->arg(i)->exprType()) && args->arg(i)->asNumber()->isFinal()) {
710                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a \"final\" value.").c_str());                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a \"final\" value.").c_str());
711                      argsOK = false;                      argsOK = false;
712                      break;                      break;
713                  }                  }
714              }              }
715                if (argsOK) {
716                    // perform built-in function's own, custom arguments checks (if any)
717                    fn->checkArgs(&*args, [&](String err) {
718                        PARSE_ERR(@3, (String("Built-in function '") + name + "()': " + err).c_str());
719                        argsOK = false;
720                    }, [&](String wrn) {
721                        PARSE_WRN(@3, (String("Built-in function '") + name + "()': " + wrn).c_str());
722                    });
723                }
724              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
725          }          }
726      }      }
# Line 730  assignment: Line 793  assignment:
793              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());
794          else if (var->exprType() != $3->exprType())          else if (var->exprType() != $3->exprType())
795              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());
796          else if (isScalarNumber(var->exprType())) {          else if (isNumber(var->exprType())) {
797              ScalarNumberVariableRef numberVar = var;              NumberVariableRef numberVar = var;
798              ScalarNumberExprRef expr = $3;              NumberExprRef expr = $3;
799              if (numberVar->unitType() != expr->unitType())              if (numberVar->unitType() != expr->unitType())
800                  PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has unit type " + unitTypeStr(numberVar->unitType()) + ", assignment has unit type " + unitTypeStr(expr->unitType()) + " though.").c_str());                  PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has unit type " + unitTypeStr(numberVar->unitType()) + ", assignment has unit type " + unitTypeStr(expr->unitType()) + " though.").c_str());
             else if (numberVar->unitFactor() != expr->unitFactor())  
                 PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has a different unit prefix.").c_str());  
801              else if (numberVar->isFinal() != expr->isFinal())              else if (numberVar->isFinal() != expr->isFinal())
802                  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());                  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());
803          }          }
# Line 757  assignment: Line 818  assignment:
818              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());
819          else if ($3->asInt()->unitType())          else if ($3->asInt()->unitType())
820              PARSE_ERR(@3, "Unit types are not allowed as array index.");              PARSE_ERR(@3, "Unit types are not allowed as array index.");
821          else if ($6->exprType() != var->exprType())          else if ($6->exprType() != scalarTypeOfArray(var->exprType()))
822              PARSE_ERR(@5, (String("Variable '") + name + "' was declared as " + typeStr(var->exprType()) + ", assigned expression is " + typeStr($6->exprType()) + " though.").c_str());              PARSE_ERR(@5, (String("Variable '") + name + "' was declared as " + typeStr(var->exprType()) + ", assigned expression is " + typeStr($6->exprType()) + " though.").c_str());
823          else if ($6->asScalarNumberExpr()->unitType())          else if ($6->asNumber()->unitType())
824              PARSE_ERR(@6, "Unit types are not allowed for array variables.");              PARSE_ERR(@6, "Unit types are not allowed for array variables.");
825          else if ($6->asScalarNumberExpr()->isFinal())          else if ($6->asNumber()->isFinal())
826              PARSE_ERR(@6, "Final operator '!' not allowed for array variables.");              PARSE_ERR(@6, "Final operator '!' not allowed for array variables.");
827          else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())          else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
828              PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +              PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
# Line 777  assignment: Line 838  assignment:
838              RealArrayElementRef element = new RealArrayElement(var, $3);              RealArrayElementRef element = new RealArrayElement(var, $3);
839              $$ = new Assignment(element, $6);              $$ = new Assignment(element, $6);
840          } else {          } else {
841              $$ = new NoOperation;              $$ = new NoOperation; // actually not possible to ever get here
842          }          }
843      }      }
844    
845  unary_expr:  unary_expr:
846      INTEGER  {      INTEGER  {
847          $$ = new IntLiteral($1);          $$ = new IntLiteral({ .value = $1 });
848      }      }
849      | REAL  {      | REAL  {
850          $$ = new RealLiteral($1);          $$ = new RealLiteral({ .value = $1 });
851      }      }
852      | INTEGER_UNIT  {      | INTEGER_UNIT  {
853          IntLiteralRef literal = new IntLiteral($1.iValue);          IntLiteralRef literal = new IntLiteral({
854          literal->setUnit($1.prefix, $1.unit);              .value = $1.iValue,
855                .unitFactor = VMUnit::unitFactor($1.prefix),
856                .unitType = $1.unit
857            });
858          $$ = literal;          $$ = literal;
859      }      }
860      | REAL_UNIT  {      | REAL_UNIT  {
861          RealLiteralRef literal = new RealLiteral($1.fValue);          RealLiteralRef literal = new RealLiteral({
862          literal->setUnit($1.prefix, $1.unit);              .value = $1.fValue,
863                .unitFactor = VMUnit::unitFactor($1.prefix),
864                .unitType = $1.unit
865            });
866          $$ = literal;          $$ = literal;
867      }      }
868      | STRING    {      | STRING    {
# Line 808  unary_expr: Line 875  unary_expr:
875              $$ = var;              $$ = var;
876          else {          else {
877              PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
878              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
879          }          }
880      }      }
881      | VARIABLE '[' expr ']'  {      | VARIABLE '[' expr ']'  {
# Line 816  unary_expr: Line 883  unary_expr:
883          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
884          if (!var) {          if (!var) {
885              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
886              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
887          } else if (!isArray(var->exprType())) {          } else if (!isArray(var->exprType())) {
888              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());
889              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
890          } else if ($3->exprType() != INT_EXPR) {          } else if ($3->exprType() != INT_EXPR) {
891              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());
892              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
893          } else if ($3->asInt()->unitType() || $3->asInt()->unitPrefix(0)) {          } else if ($3->asInt()->unitType() || $3->asInt()->hasUnitFactorEver()) {
894              PARSE_ERR(@3, "Units are not allowed as array index.");              PARSE_ERR(@3, "Units are not allowed as array index.");
895              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
896          } else {          } else {
897              if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())              if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
898                  PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +                  PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
# Line 847  unary_expr: Line 914  unary_expr:
914      | functioncall  {      | functioncall  {
915          $$ = $1;          $$ = $1;
916      }      }
917        | '+' unary_expr  {
918            $$ = $2;
919        }
920      | '-' unary_expr  {      | '-' unary_expr  {
921          $$ = new Neg($2);          $$ = new Neg($2);
922      }      }
923      | BITWISE_NOT unary_expr  {      | BITWISE_NOT unary_expr  {
924          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
925              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());
926              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
927          } else if ($2->asInt()->unitType() || $2->asInt()->unitPrefix(0)) {          } else if ($2->asInt()->unitType() || $2->asInt()->hasUnitFactorEver()) {
928              PARSE_ERR(@2, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@2, "Units are not allowed for operands of bitwise operations.");
929              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
930          } else {          } else {
931              $$ = new BitwiseNot($2);              $$ = new BitwiseNot($2);
932          }          }
# Line 864  unary_expr: Line 934  unary_expr:
934      | NOT unary_expr  {      | NOT unary_expr  {
935          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
936              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());
937              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
938          } else if ($2->asInt()->unitType() || $2->asInt()->unitPrefix(0)) {          } else if ($2->asInt()->unitType() || $2->asInt()->hasUnitFactorEver()) {
939              PARSE_ERR(@2, "Units are not allowed for operands of logical operations.");              PARSE_ERR(@2, "Units are not allowed for operands of logical operations.");
940              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
941          } else {          } else {
942              $$ = new Not($2);              $$ = new Not($2);
943          }          }
944      }      }
945      | '!' unary_expr  {      | '!' unary_expr  {
946          if (!isScalarNumber($2->exprType())) {          if (!isNumber($2->exprType())) {
947              PARSE_ERR(@2, (String("Right operand of \"final\" operator '!' must be a scalar number expression, is ") + typeStr($2->exprType()) + " though.").c_str());              PARSE_ERR(@2, (String("Right operand of \"final\" operator '!' must be a scalar number expression, is ") + typeStr($2->exprType()) + " though.").c_str());
948              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
949          } else {          } else {
950              $$ = new Final($2);              $$ = new Final($2);
951          }          }
# Line 905  logical_or_expr: Line 975  logical_or_expr:
975          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
976          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
977              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());
978              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
979          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
980              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());
981              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
982          } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
983              PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");              PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
984              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
985          } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {          } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
986              PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");              PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
987              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
988          } else {          } else {
989                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
990                    PARSE_WRN(@3, "Right operand of 'or' operation is not 'final', result will be 'final' though since left operand is 'final'.");
991                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
992                    PARSE_WRN(@1, "Left operand of 'or' operation is not 'final', result will be 'final' though since right operand is 'final'.");
993              $$ = new Or(lhs, rhs);              $$ = new Or(lhs, rhs);
994          }          }
995      }      }
# Line 929  logical_and_expr: Line 1003  logical_and_expr:
1003          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1004          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1005              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());
1006              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1007          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1008              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());
1009              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1010          } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1011              PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");              PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
1012              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1013          } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {          } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1014              PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");              PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
1015              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1016          } else {          } else {
1017                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1018                    PARSE_WRN(@3, "Right operand of 'and' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1019                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1020                    PARSE_WRN(@1, "Left operand of 'and' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1021              $$ = new And(lhs, rhs);              $$ = new And(lhs, rhs);
1022          }          }
1023      }      }
# Line 951  bitwise_or_expr: Line 1029  bitwise_or_expr:
1029          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1030          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1031              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());
1032              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1033          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1034              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());
1035              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1036          } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1037              PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
1038              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1039          } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {          } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1040              PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
1041              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1042          } else {          } else {
1043                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1044                    PARSE_WRN(@3, "Right operand of '.or.' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1045                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1046                    PARSE_WRN(@1, "Left operand of '.or.' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1047              $$ = new BitwiseOr(lhs, rhs);              $$ = new BitwiseOr(lhs, rhs);
1048          }          }
1049      }      }
# Line 975  bitwise_and_expr: Line 1057  bitwise_and_expr:
1057          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1058          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1059              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());
1060              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1061          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1062              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());
1063              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1064          } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1065              PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
1066              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1067          } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {          } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1068              PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
1069              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1070          } else {          } else {
1071                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1072                    PARSE_WRN(@3, "Right operand of '.and.' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1073                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1074                    PARSE_WRN(@1, "Left operand of '.and.' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1075              $$ = new BitwiseAnd(lhs, rhs);              $$ = new BitwiseAnd(lhs, rhs);
1076          }          }
1077      }      }
# Line 995  rel_expr: Line 1081  rel_expr:
1081      | rel_expr '<' add_expr  {      | rel_expr '<' add_expr  {
1082          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1083          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1084          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1085              PARSE_ERR(@1, (String("Left operand of operator '<' must be a scalar number 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());
1086              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1087          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1088              PARSE_ERR(@3, (String("Right operand of operator '<' must be a scalar number 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());
1089              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1090          } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1091                     lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1092          {                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1093              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1094              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1095          } else {          } else {
1096                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1097                    PARSE_WRN(@3, "Right operand of '<' comparison is not 'final', left operand is 'final' though.");
1098                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1099                    PARSE_WRN(@1, "Left operand of '<' comparison is not 'final', right operand is 'final' though.");
1100              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
1101          }          }
1102      }      }
1103      | rel_expr '>' add_expr  {      | rel_expr '>' add_expr  {
1104          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1105          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1106          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1107              PARSE_ERR(@1, (String("Left operand of operator '>' must be a scalar number 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());
1108              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1109          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1110              PARSE_ERR(@3, (String("Right operand of operator '>' must be a scalar number 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());
1111              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1112          } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1113                     lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1114          {                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1115              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1116              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1117          } else {          } else {
1118                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1119                    PARSE_WRN(@3, "Right operand of '>' comparison is not 'final', left operand is 'final' though.");
1120                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1121                    PARSE_WRN(@1, "Left operand of '>' comparison is not 'final', right operand is 'final' though.");
1122              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
1123          }          }
1124      }      }
1125      | rel_expr LE add_expr  {      | rel_expr LE add_expr  {
1126          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1127          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1128          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1129              PARSE_ERR(@1, (String("Left operand of operator '<=' must be a scalar number 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());
1130              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1131          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1132              PARSE_ERR(@3, (String("Right operand of operator '<=' must be a scalar number 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());
1133              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1134          } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1135                     lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1136          {                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1137              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1138              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1139          } else {          } else {
1140                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1141                    PARSE_WRN(@3, "Right operand of '<=' comparison is not 'final', left operand is 'final' though.");
1142                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1143                    PARSE_WRN(@1, "Left operand of '<=' comparison is not 'final', right operand is 'final' though.");
1144              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
1145          }          }
1146      }      }
1147      | rel_expr GE add_expr  {      | rel_expr GE add_expr  {
1148          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1149          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1150          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1151              PARSE_ERR(@1, (String("Left operand of operator '>=' must be a scalar number 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());
1152              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1153          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1154              PARSE_ERR(@3, (String("Right operand of operator '>=' must be a scalar number 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());
1155              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1156          } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1157                     lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1158          {                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1159              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1160              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1161          } else {          } else {
1162                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1163                    PARSE_WRN(@3, "Right operand of '>=' comparison is not 'final', left operand is 'final' though.");
1164                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1165                    PARSE_WRN(@1, "Left operand of '>=' comparison is not 'final', right operand is 'final' though.");
1166              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
1167          }          }
1168      }      }
1169      | rel_expr '=' add_expr  {      | rel_expr '=' add_expr  {
1170          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1171          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1172          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1173              PARSE_ERR(@1, (String("Left operand of operator '=' must be a scalar number 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());
1174              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1175          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1176              PARSE_ERR(@3, (String("Right operand of operator '=' must be a scalar number 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());
1177              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1178          } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1179                     lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1180          {                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1181              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1182              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1183          } else {          } else {
1184                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1185                    PARSE_WRN(@3, "Right operand of '=' comparison is not 'final', left operand is 'final' though.");
1186                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1187                    PARSE_WRN(@1, "Left operand of '=' comparison is not 'final', right operand is 'final' though.");
1188              $$ = new Relation(lhs, Relation::EQUAL, rhs);              $$ = new Relation(lhs, Relation::EQUAL, rhs);
1189          }          }
1190      }      }
1191      | rel_expr '#' add_expr  {      | rel_expr '#' add_expr  {
1192          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1193          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1194          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1195              PARSE_ERR(@1, (String("Left operand of operator '#' must be a scalar number 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());
1196              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1197          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1198              PARSE_ERR(@3, (String("Right operand of operator '#' must be a scalar number 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());
1199              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1200          } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1201                     lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1202          {                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1203              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1204              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1205          } else {          } else {
1206                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1207                    PARSE_WRN(@3, "Right operand of '#' comparison is not 'final', left operand is 'final' though.");
1208                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1209                    PARSE_WRN(@1, "Left operand of '#' comparison is not 'final', right operand is 'final' though.");
1210              $$ = new Relation(lhs, Relation::NOT_EQUAL, rhs);              $$ = new Relation(lhs, Relation::NOT_EQUAL, rhs);
1211          }          }
1212      }      }
# Line 1106  add_expr: Line 1216  add_expr:
1216      | add_expr '+' mul_expr  {      | add_expr '+' mul_expr  {
1217          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1218          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1219          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1220              PARSE_ERR(@1, (String("Left operand of operator '+' must be a scalar number 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());
1221              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1222          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1223              PARSE_ERR(@1, (String("Right operand of operator '+' must be a scalar number 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());
1224              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1225          } else if (lhs->exprType() != rhs->exprType()) {          } else if (lhs->exprType() != rhs->exprType()) {
1226              PARSE_ERR(@2, (String("Operands of operator '+' must have same type; left operand is ") +              PARSE_ERR(@2, (String("Operands of operator '+' must have same type; left operand is ") +
1227                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1228              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1229          } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1230                     lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())              PARSE_ERR(@2, (String("Operands of '+' operations must have same unit, left operand is ") +
1231          {                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1232              PARSE_ERR(@2, "Operands of '+' operations must have same unit.");                  unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1233              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1234          } else {          } else {
1235                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1236                    PARSE_WRN(@3, "Right operand of '+' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1237                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1238                    PARSE_WRN(@1, "Left operand of '+' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1239              $$ = new Add(lhs,rhs);              $$ = new Add(lhs,rhs);
1240          }          }
1241      }      }
1242      | add_expr '-' mul_expr  {      | add_expr '-' mul_expr  {
1243          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1244          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1245          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1246              PARSE_ERR(@1, (String("Left operand of operator '-' must be a scalar number 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());
1247              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1248          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1249              PARSE_ERR(@1, (String("Right operand of operator '-' must be a scalar number 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());
1250              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1251          } else if (lhs->exprType() != rhs->exprType()) {          } else if (lhs->exprType() != rhs->exprType()) {
1252              PARSE_ERR(@2, (String("Operands of operator '-' must have same type; left operand is ") +              PARSE_ERR(@2, (String("Operands of operator '-' must have same type; left operand is ") +
1253                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1254              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1255          } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||          } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1256                     lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())              PARSE_ERR(@2, (String("Operands of '-' operations must have same unit, left operand is ") +
1257          {                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1258              PARSE_ERR(@2, "Operands of '-' operations must have same unit.");                  unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1259              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1260          } else {          } else {
1261                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1262                    PARSE_WRN(@3, "Right operand of '-' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1263                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1264                    PARSE_WRN(@1, "Left operand of '-' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1265              $$ = new Sub(lhs,rhs);              $$ = new Sub(lhs,rhs);
1266          }          }
1267      }      }
# Line 1153  mul_expr: Line 1271  mul_expr:
1271      | mul_expr '*' unary_expr  {      | mul_expr '*' unary_expr  {
1272          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1273          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1274          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1275              PARSE_ERR(@1, (String("Left operand of operator '*' must be a scalar number 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());
1276              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1277          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1278              PARSE_ERR(@1, (String("Right operand of operator '*' must be a scalar number 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());
1279              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1280          } else if (lhs->asScalarNumberExpr()->unitType() && rhs->asScalarNumberExpr()->unitType()) {          } else if (lhs->asNumber()->unitType() && rhs->asNumber()->unitType()) {
1281              PARSE_ERR(@2, "Only one operand of operator '*' may have a unit type");              PARSE_ERR(@2, (String("Only one operand of operator '*' may have a unit type, left operand is ") +
1282              $$ = new IntLiteral(0);                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1283                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1284                $$ = new IntLiteral({ .value = 0 });
1285          } else if (lhs->exprType() != rhs->exprType()) {          } else if (lhs->exprType() != rhs->exprType()) {
1286              PARSE_ERR(@2, (String("Operands of operator '*' must have same type; left operand is ") +              PARSE_ERR(@2, (String("Operands of operator '*' must have same type; left operand is ") +
1287                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1288              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
         } else if (lhs->asScalarNumberExpr()->unitPrefix(0) && rhs->asScalarNumberExpr()->unitPrefix(0)) {  
             PARSE_ERR(@2, "Only one operand of operator '*' may have a unit prefix");  
             $$ = new IntLiteral(0);  
1289          } else {          } else {
1290                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1291                    PARSE_WRN(@3, "Right operand of '*' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1292                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1293                    PARSE_WRN(@1, "Left operand of '*' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1294              $$ = new Mul(lhs,rhs);              $$ = new Mul(lhs,rhs);
1295          }          }
1296      }      }
1297      | mul_expr '/' unary_expr  {      | mul_expr '/' unary_expr  {
1298          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1299          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1300          if (!isScalarNumber(lhs->exprType())) {          if (!isNumber(lhs->exprType())) {
1301              PARSE_ERR(@1, (String("Left operand of operator '/' must be a scalar number 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());
1302              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1303          } else if (!isScalarNumber(rhs->exprType())) {          } else if (!isNumber(rhs->exprType())) {
1304              PARSE_ERR(@1, (String("Right operand of operator '/' must be a scalar number 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());
1305              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1306          } else if (lhs->asScalarNumberExpr()->unitType() && rhs->asScalarNumberExpr()->unitType() &&          } else if (lhs->asNumber()->unitType() && rhs->asNumber()->unitType() &&
1307                     lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType())                     lhs->asNumber()->unitType() != rhs->asNumber()->unitType())
         {  
             PARSE_ERR(@2, "Operands of operator '/' with two different unit types.");  
             $$ = new IntLiteral(0);  
         } else if (!lhs->asScalarNumberExpr()->unitType() && rhs->asScalarNumberExpr()->unitType()) {  
             PARSE_ERR(@3, ("Dividing left operand without any unit type by right operand with unit type " + typeStr(rhs->exprType()) + " is not possible.").c_str());  
             $$ = new IntLiteral(0);  
         } else if (lhs->asScalarNumberExpr()->unitFactor()  != rhs->asScalarNumberExpr()->unitFactor() &&  
                    lhs->asScalarNumberExpr()->unitPrefix(0) && rhs->asScalarNumberExpr()->unitPrefix(0))  
         {  
             PARSE_ERR(@2, "Dividing two operands with two different unit prefixes is not possible.");  
             $$ = new IntLiteral(0);  
         } else if (lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor() &&  
                    rhs->asScalarNumberExpr()->unitPrefix(0))  
1308          {          {
1309              PARSE_ERR(@3, "Dividing left operand without any unit prefix by right operand with unit prefix is not possible.");              PARSE_ERR(@2, (String("Operands of operator '/' with two different unit types, left operand is ") +
1310              $$ = new IntLiteral(0);                  unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1311                    unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1312                $$ = new IntLiteral({ .value = 0 });
1313            } else if (!lhs->asNumber()->unitType() && rhs->asNumber()->unitType()) {
1314                PARSE_ERR(@3, ("Dividing left operand without any unit type by right operand with unit type (" +
1315                    unitTypeStr(rhs->asNumber()->unitType()) + ") is not possible.").c_str());
1316                $$ = new IntLiteral({ .value = 0 });
1317          } else if (lhs->exprType() != rhs->exprType()) {          } else if (lhs->exprType() != rhs->exprType()) {
1318              PARSE_ERR(@2, (String("Operands of operator '/' must have same type; left operand is ") +              PARSE_ERR(@2, (String("Operands of operator '/' must have same type; left operand is ") +
1319                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1320              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1321          } else {          } else {
1322                if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1323                    PARSE_WRN(@3, "Right operand of '/' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1324                else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1325                    PARSE_WRN(@1, "Left operand of '/' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1326              $$ = new Div(lhs,rhs);              $$ = new Div(lhs,rhs);
1327          }          }
1328      }      }
# Line 1213  mul_expr: Line 1331  mul_expr:
1331          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1332          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1333              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());
1334              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1335          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1336              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());
1337              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1338          } else {          } else {
1339              if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0))              if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver())
1340                  PARSE_ERR(@1, "Operands of modulo operator must not use any unit.");                  PARSE_ERR(@1, "Operands of modulo operator must not use any unit.");
1341              if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0))              if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver())
1342                  PARSE_ERR(@3, "Operands of modulo operator must not use any unit.");                  PARSE_ERR(@3, "Operands of modulo operator must not use any unit.");
1343                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1344                    PARSE_WRN(@3, "Right operand of 'mod' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1345                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1346                    PARSE_WRN(@1, "Left operand of 'mod' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1347              $$ = new Mod(lhs,rhs);              $$ = new Mod(lhs,rhs);
1348          }          }
1349      }      }

Legend:
Removed from v.3573  
changed lines
  Added in v.3595

  ViewVC Help
Powered by ViewVC