/[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 3561 by schoenebeck, Fri Aug 23 11:44:00 2019 UTC revision 3581 by schoenebeck, Fri Aug 30 11:40:25 2019 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"  %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 183  statement: Line 185  statement:
185      | DECLARE VARIABLE  {      | DECLARE VARIABLE  {
186          const char* name = $2;          const char* name = $2;
187          //printf("declared var '%s'\n", name);          //printf("declared var '%s'\n", name);
188          if (context->variableByName(name))          if (context->variableByName(name)) {
189              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
190          if (name[0] == '@') {          } else if (name[0] == '@') {
191              context->vartable[name] = new StringVariable(context);              context->vartable[name] = new StringVariable(context);
192              $$ = new NoOperation;          } else if (name[0] == '~') {
193                context->vartable[name] = new RealVariable({
194                    .ctx = context
195                });
196            } else if (name[0] == '$') {
197                context->vartable[name] = new IntVariable({
198                    .ctx = context
199                });
200            } else if (name[0] == '?') {
201                PARSE_ERR(@2, (String("Real number array variable '") + name + "' declaration requires array size.").c_str());
202            } else if (name[0] == '%') {
203                PARSE_ERR(@2, (String("Integer array variable '") + name + "' declaration requires array size.").c_str());
204          } else {          } else {
205              context->vartable[name] = new IntVariable(context);              PARSE_ERR(@2, (String("Variable '") + name + "' declared with unknown type.").c_str());
             $$ = new NoOperation;  
206          }          }
207            $$ = new NoOperation;
208      }      }
209      | DECLARE POLYPHONIC VARIABLE  {      | DECLARE POLYPHONIC VARIABLE  {
210          const char* name = $3;          const char* name = $3;
211          //printf("declared polyphonic var '%s'\n", name);          //printf("declared polyphonic var '%s'\n", name);
212          if (context->variableByName(name))          if (context->variableByName(name)) {
213              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
214          if (name[0] != '$') {          } else if (name[0] != '$' && name[0] != '~') {
215              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.");
216              $$ = new FunctionCall("nothing", new Args, NULL); // whatever          } else if (name[0] == '~') {
217          } else {              context->vartable[name] = new PolyphonicRealVariable({
218              context->vartable[name] = new PolyphonicIntVariable(context);                  .ctx = context
219              $$ = new NoOperation;              });
220            } else {
221                context->vartable[name] = new PolyphonicIntVariable({
222                    .ctx = context
223                });
224          }          }
225            $$ = new NoOperation;
226      }      }
227      | DECLARE VARIABLE ASSIGNMENT expr  {      | DECLARE VARIABLE ASSIGNMENT expr  {
228          const char* name = $2;          const char* name = $2;
229          //printf("declared assign var '%s'\n", name);          //printf("declared assign var '%s'\n", name);
230          if (context->variableByName(name))          const ExprType_t declType = exprTypeOfVarName(name);
231            if (context->variableByName(name)) {
232              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
233          if ($4->exprType() == STRING_EXPR) {              $$ = new NoOperation;
234              if (name[0] == '$')          } else if ($4->exprType() == STRING_EXPR) {
235                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as integer, string expression assigned though.").c_str());              if (name[0] != '@')
236                    PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());
237              StringExprRef expr = $4;              StringExprRef expr = $4;
238              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
239                  const String s = expr->evalStr();                  const String s = expr->evalStr();
# Line 225  statement: Line 245  statement:
245                  context->vartable[name] = var;                  context->vartable[name] = var;
246                  $$ = new Assignment(var, expr);                  $$ = new Assignment(var, expr);
247              }              }
248          } else {          } else if ($4->exprType() == REAL_EXPR) {
249              if (name[0] == '@')              if (name[0] != '~')
250                  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());
251                RealExprRef expr = $4;
252                RealVariableRef var = new RealVariable({
253                    .ctx = context,
254                    .unitType = expr->unitType(),
255                    .isFinal = expr->isFinal()
256                });
257                if (expr->isConstExpr()) {
258                    $$ = new Assignment(var, new RealLiteral({
259                        .value = expr->evalReal(),
260                        .unitFactor = expr->unitFactor(),
261                        .unitType = expr->unitType(),
262                        .isFinal = expr->isFinal()
263                    }));
264                } else {
265                    $$ = new Assignment(var, expr);
266                }
267                context->vartable[name] = var;
268            } else if ($4->exprType() == INT_EXPR) {
269                if (name[0] != '$')
270                    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) {
289                PARSE_ERR(@4, "Expression does not result in a value.");
290                $$ = new NoOperation;
291            } else if (isArray($4->exprType())) {
292                PARSE_ERR(@2, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
293                $$ = new NoOperation;
294          }          }
295      }      }
296      | DECLARE VARIABLE '[' expr ']'  {      | DECLARE VARIABLE '[' expr ']'  {
# Line 246  statement: Line 298  statement:
298          const char* name = $2;          const char* name = $2;
299          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
300              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  
301          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
302              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  
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());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
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.");
                 $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
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());
                     $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
315                  } else {                  } else {
316                      context->vartable[name] = new IntArrayVariable(context, size);                      if (name[0] == '?') {
317                      $$ = new NoOperation;                          context->vartable[name] = new RealArrayVariable(context, size);
318                        } else if (name[0] == '%') {
319                            context->vartable[name] = new IntArrayVariable(context, size);
320                        } else {
321                            PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
322                        }
323                  }                  }
324              }              }
325          }          }
326            $$ = new NoOperation;
327      }      }
328      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
329          const char* name = $2;          const char* name = $2;
330          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
331              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  
332          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
333              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  
334          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
335              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  
336          } else {          } else {
337              IntExprRef sizeExpr = $4;              IntExprRef sizeExpr = $4;
338              ArgsRef args = $8;              ArgsRef args = $8;
339              vmint size = sizeExpr->evalInt();              vmint size = sizeExpr->evalInt();
340              if (size <= 0) {              if (size <= 0) {
341                  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  
342              } else if (args->argsCount() > size) {              } else if (args->argsCount() > size) {
343                  PARSE_ERR(@8, (String("Array variable '") + name +                  PARSE_ERR(@8, (String("Array variable '") + name +
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                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever              } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
             } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {  
348                  PARSE_ERR(@4, "Units are not allowed as array size.");                  PARSE_ERR(@4, "Units are not allowed as array size.");
                 $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
349              } else {              } else {
350                  if (sizeExpr->isFinal())                  if (sizeExpr->isFinal())
351                      PARSE_WRN(@4, "Final operator '!' is meaningless here.");                      PARSE_WRN(@4, "Final operator '!' is meaningless here.");
352                    ExprType_t declType = EMPTY_EXPR;
353                    if (name[0] == '%') {
354                        declType = INT_EXPR;
355                    } else if (name[0] == '?') {
356                        declType = REAL_EXPR;
357                    } else if (name[0] == '$') {
358                        PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
359                    } else if (name[0] == '~') {
360                        PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
361                    } else {
362                        PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
363                    }
364                  bool argsOK = true;                  bool argsOK = true;
365                  for (vmint i = 0; i < args->argsCount(); ++i) {                  if (declType == EMPTY_EXPR) {
366                      if (args->arg(i)->exprType() != INT_EXPR) {                      argsOK = false;
367                          PARSE_ERR(                  } else {
368                              @8,                      for (vmint i = 0; i < args->argsCount(); ++i) {
369                              (String("Array variable '") + name +                          if (args->arg(i)->exprType() != declType) {
370                              "' declared with invalid assignment values. Assigned element " +                              PARSE_ERR(
371                              ToString(i+1) + " is not an integer expression.").c_str()                                  @8,
372                          );                                  (String("Array variable '") + name +
373                          argsOK = false;                                  "' declared with invalid assignment values. Assigned element " +
374                          break;                                  ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
375                      } else if (args->arg(i)->asInt()->unitType() ||                              );
376                                 args->arg(i)->asInt()->unitPrefix(0))                              argsOK = false;
377                      {                              break;
378                          PARSE_ERR(                          } else if (args->arg(i)->asScalarNumberExpr()->unitType()) {
379                              @8,                              PARSE_ERR(
380                              (String("Array variable '") + name +                                  @8,
381                              "' declared with invalid assignment values. Assigned element " +                                  (String("Array variable '") + name +
382                              ToString(i+1) + " contains a unit.").c_str()                                  "' declared with invalid assignment values. Assigned element " +
383                          );                                  ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
384                          argsOK = false;                              );
385                          break;                              argsOK = false;
386                                break;
387                            } else if (args->arg(i)->asScalarNumberExpr()->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;
395                                break;
396                            }
397                      }                      }
398                  }                  }
399                  if (argsOK) {                  if (argsOK) {
400                      context->vartable[name] = new IntArrayVariable(context, size, args);                      if (declType == REAL_EXPR)
401                      $$ = new NoOperation;                          context->vartable[name] = new RealArrayVariable(context, size, args);
402                  } else                      else
403                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever                          context->vartable[name] = new IntArrayVariable(context, size, args);
404                    }
405              }              }
406          }          }
407            $$ = new NoOperation;
408      }      }
409      | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {      | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
410          const char* name = $3;          const char* name = $3;
411          if (!$5->isConstExpr()) {          if (!$5->isConstExpr()) {
412              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  
413          } else if ($5->exprType() != INT_EXPR) {          } else if ($5->exprType() != INT_EXPR) {
414              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  
415          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
416              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  
417          } else {          } else {
418              IntExprRef sizeExpr = $5;              IntExprRef sizeExpr = $5;
419              ArgsRef args = $9;              ArgsRef args = $9;
420              vmint size = sizeExpr->evalInt();              vmint size = sizeExpr->evalInt();
421              if (size <= 0) {              if (size <= 0) {
422                  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  
423              } else if (args->argsCount() > size) {              } else if (args->argsCount() > size) {
424                  PARSE_ERR(@9, (String("Array variable '") + name +                  PARSE_ERR(@9, (String("Array variable '") + name +
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                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever              } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
             } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {  
429                  PARSE_ERR(@5, "Units are not allowed as array size.");                  PARSE_ERR(@5, "Units are not allowed as array size.");
                 $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
430              } else {              } else {
431                  if (sizeExpr->isFinal())                  if (sizeExpr->isFinal())
432                      PARSE_WRN(@5, "Final operator '!' is meaningless here.");                      PARSE_WRN(@5, "Final operator '!' is meaningless here.");
433                    ExprType_t declType = EMPTY_EXPR;
434                    if (name[0] == '%') {
435                        declType = INT_EXPR;
436                    } else if (name[0] == '?') {
437                        declType = REAL_EXPR;
438                    } else if (name[0] == '$') {
439                        PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
440                    } else if (name[0] == '~') {
441                        PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
442                    } else {
443                        PARSE_ERR(@3, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
444                    }
445                  bool argsOK = true;                  bool argsOK = true;
446                  for (vmint i = 0; i < args->argsCount(); ++i) {                  if (declType == EMPTY_EXPR) {
447                      if (args->arg(i)->exprType() != INT_EXPR) {                      argsOK = false;
448                          PARSE_ERR(                  } else {
449                              @9,                      for (vmint i = 0; i < args->argsCount(); ++i) {
450                              (String("Array variable '") + name +                          if (args->arg(i)->exprType() != declType) {
451                              "' declared with invalid assignment values. Assigned element " +                              PARSE_ERR(
452                              ToString(i+1) + " is not an integer expression.").c_str()                                  @9,
453                          );                                  (String("const array variable '") + name +
454                          argsOK = false;                                  "' declared with invalid assignment values. Assigned element " +
455                          break;                                  ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
456                      }                              );
457                      if (!args->arg(i)->isConstExpr()) {                              argsOK = false;
458                          PARSE_ERR(                              break;
459                              @9,                          }
460                              (String("const array variable '") + name +                          if (!args->arg(i)->isConstExpr()) {
461                              "' must be defined with const values. Assigned element " +                              PARSE_ERR(
462                              ToString(i+1) + " is not a const expression though.").c_str()                                  @9,
463                          );                                  (String("const array variable '") + name +
464                          argsOK = false;                                  "' must be defined with const values. Assigned element " +
465                          break;                                  ToString(i+1) + " is not a const expression though.").c_str()
466                      } else if (args->arg(i)->asInt()->unitType() ||                              );
467                                 args->arg(i)->asInt()->unitPrefix(0))                              argsOK = false;
468                      {                              break;
469                          PARSE_ERR(                          } else if (args->arg(i)->asScalarNumberExpr()->unitType()) {
470                              @9,                              PARSE_ERR(
471                              (String("const array variable '") + name +                                  @9,
472                              "' declared with invalid assignment values. Assigned element " +                                  (String("const array variable '") + name +
473                              ToString(i+1) + " contains a unit.").c_str()                                  "' declared with invalid assignment values. Assigned element " +
474                          );                                  ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
475                          argsOK = false;                              );
476                          break;                              argsOK = false;
477                                break;
478                            } else if (args->arg(i)->asScalarNumberExpr()->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;
486                                break;
487                            }
488                      }                      }
489                  }                  }
490                  if (argsOK) {                  if (argsOK) {
491                      context->vartable[name] = new IntArrayVariable(context, size, args, true);                      if (declType == REAL_EXPR)
492                      $$ = new NoOperation;                          context->vartable[name] = new RealArrayVariable(context, size, args, true);
493                  } else                      else
494                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever                          context->vartable[name] = new IntArrayVariable(context, size, args, true);
495                    }
496              }              }
497          }          }
498            $$ = new NoOperation;
499      }      }
500      | DECLARE CONST_ VARIABLE ASSIGNMENT expr  {      | DECLARE CONST_ VARIABLE ASSIGNMENT expr  {
501          const char* name = $3;          const char* name = $3;
502            const ExprType_t declType = exprTypeOfVarName(name);
503          if ($5->exprType() == STRING_EXPR) {          if ($5->exprType() == STRING_EXPR) {
504              if (name[0] == '$')              if (name[0] != '@')
505                  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());
506              String s;              String s;
507              StringExprRef expr = $5;              StringExprRef expr = $5;
508              if (expr->isConstExpr())              if (expr->isConstExpr())
# Line 420  statement: Line 512  statement:
512              ConstStringVariableRef var = new ConstStringVariable(context, s);              ConstStringVariableRef var = new ConstStringVariable(context, s);
513              context->vartable[name] = var;              context->vartable[name] = var;
514              //$$ = new Assignment(var, new StringLiteral(s));              //$$ = new Assignment(var, new StringLiteral(s));
515              $$ = new NoOperation();          } else if ($5->exprType() == REAL_EXPR) {
516          } else {              if (name[0] != '~')
517              if (name[0] == '@')                  PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
518                  PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");              RealExprRef expr = $5;
519              vmint i = 0;              if (!expr->isConstExpr()) {
520                    PARSE_ERR(@5, (String("Assignment to const real number variable '") + name + "' requires const expression.").c_str());
521                }
522                ConstRealVariableRef var = new ConstRealVariable({
523                    .value = (expr->isConstExpr()) ? expr->evalReal() : vmfloat(0),
524                    .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,
525                    .unitType = expr->unitType(),
526                    .isFinal = expr->isFinal()
527                });
528                context->vartable[name] = var;
529                //$$ = new Assignment(var, new IntLiteral(i));
530            } else if ($5->exprType() == INT_EXPR) {
531                if (name[0] != '$')
532                    PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
533              IntExprRef expr = $5;              IntExprRef expr = $5;
534              if (expr->isConstExpr())              if (!expr->isConstExpr()) {
                 i = expr->evalInt();  
             else  
535                  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());
536              ConstIntVariableRef var = new ConstIntVariable(i);              }
537              var->copyUnitFrom(expr);              ConstIntVariableRef var = new ConstIntVariable({
538              var->setFinal(expr->isFinal());                  .value = (expr->isConstExpr()) ? expr->evalInt() : 0,
539                    .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,
540                    .unitType = expr->unitType(),
541                    .isFinal = expr->isFinal()
542                });
543              context->vartable[name] = var;              context->vartable[name] = var;
544              //$$ = new Assignment(var, new IntLiteral(i));              //$$ = new Assignment(var, new IntLiteral(i));
545              $$ = new NoOperation();          } else if ($5->exprType() == EMPTY_EXPR) {
546                PARSE_ERR(@5, "Expression does not result in a value.");
547            } else if (isArray($5->exprType())) {
548                PARSE_ERR(@5, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
549          }          }
550            $$ = new NoOperation();
551      }      }
552      | assignment  {      | assignment  {
553          $$ = $1;          $$ = $1;
# Line 444  statement: Line 555  statement:
555      | WHILE '(' expr ')' opt_statements END WHILE  {      | WHILE '(' expr ')' opt_statements END WHILE  {
556          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
557              IntExprRef expr = $3;              IntExprRef expr = $3;
558              if (expr->isFinal() && expr->isConstExpr())              if (expr->asScalarNumberExpr()->unitType() ||
559                    expr->asScalarNumberExpr()->hasUnitFactorEver())
560                    PARSE_WRN(@3, "Condition for 'while' loops contains a unit.");
561                else if (expr->isFinal() && expr->isConstExpr())
562                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");
563              $$ = new While(expr, $5);              $$ = new While(expr, $5);
564          } else {          } else {
565              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
566              $$ = new While(new IntLiteral(0), $5);              $$ = new While(new IntLiteral({ .value = 0 }), $5);
567          }          }
568      }      }
569      | SYNCHRONIZED opt_statements END SYNCHRONIZED  {      | SYNCHRONIZED opt_statements END SYNCHRONIZED  {
# Line 458  statement: Line 572  statement:
572      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {      | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {
573          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
574              IntExprRef expr = $3;              IntExprRef expr = $3;
575              if (expr->isFinal() && expr->isConstExpr())              if (expr->asScalarNumberExpr()->unitType() ||
576                    expr->asScalarNumberExpr()->hasUnitFactorEver())
577                    PARSE_WRN(@3, "Condition for 'if' contains a unit.");
578                else if (expr->isFinal() && expr->isConstExpr())
579                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");
580              $$ = new If($3, $5, $7);              $$ = new If($3, $5, $7);
581          } else {          } else {
582              PARSE_ERR(@3, "Condition for 'if' must be integer expression.");              PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
583              $$ = new If(new IntLiteral(0), $5, $7);              $$ = new If(new IntLiteral({ .value = 0 }), $5, $7);
584          }          }
585      }      }
586      | IF '(' expr ')' opt_statements END IF  {      | IF '(' expr ')' opt_statements END IF  {
587          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
588              IntExprRef expr = $3;              IntExprRef expr = $3;
589              if (expr->isFinal() && expr->isConstExpr())              if (expr->asScalarNumberExpr()->unitType() ||
590                    expr->asScalarNumberExpr()->hasUnitFactorEver())
591                    PARSE_WRN(@3, "Condition for 'if' contains a unit.");
592                else if (expr->isFinal() && expr->isConstExpr())
593                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");
594              $$ = new If($3, $5);              $$ = new If($3, $5);
595          } else {          } else {
596              PARSE_ERR(@3, "Condition for 'if' must be integer expression.");              PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
597              $$ = new If(new IntLiteral(0), $5);              $$ = new If(new IntLiteral({ .value = 0 }), $5);
598          }          }
599      }      }
600      | SELECT expr caseclauses END SELECT  {      | SELECT expr caseclauses END SELECT  {
601          if ($2->exprType() == INT_EXPR) {          if ($2->exprType() == INT_EXPR) {
602              IntExprRef expr = $2;              IntExprRef expr = $2;
603              if (expr->unitType() || expr->unitPrefix(0)) {              if (expr->unitType() || expr->hasUnitFactorEver()) {
604                  PARSE_ERR(@2, "Units are not allowed here.");                  PARSE_ERR(@2, "Units are not allowed here.");
605                    $$ = new SelectCase(new IntLiteral({ .value = 0 }), $3);
606              } else {              } else {
607                  if (expr->isFinal() && expr->isConstExpr())                  if (expr->isFinal() && expr->isConstExpr())
608                      PARSE_WRN(@2, "Final operator '!' is meaningless here.");                      PARSE_WRN(@2, "Final operator '!' is meaningless here.");
# Line 489  statement: Line 610  statement:
610              }              }
611          } else {          } else {
612              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
613              $$ = new SelectCase(new IntLiteral(0), $3);              $$ = new SelectCase(new IntLiteral({ .value = 0 }), $3);
614          }          }
615      }      }
616    
# Line 506  caseclauses: Line 627  caseclauses:
627  caseclause:  caseclause:
628      CASE INTEGER opt_statements  {      CASE INTEGER opt_statements  {
629          $$ = CaseBranch();          $$ = CaseBranch();
630          $$.from = new IntLiteral($2);          $$.from = new IntLiteral({ .value = $2 });
631          $$.statements = $3;          $$.statements = $3;
632      }      }
633      | CASE INTEGER TO INTEGER opt_statements  {      | CASE INTEGER TO INTEGER opt_statements  {
634          $$ = CaseBranch();          $$ = CaseBranch();
635          $$.from = new IntLiteral($2);          $$.from = new IntLiteral({ .value = $2 });
636          $$.to   = new IntLiteral($4);          $$.to   = new IntLiteral({ .value = $4 });
637          $$.statements = $5;          $$.statements = $5;
638      }      }
639    
# Line 563  functioncall: Line 684  functioncall:
684                      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());
685                      argsOK = false;                      argsOK = false;
686                      break;                      break;
687                  } else if (args->arg(i)->exprType() == INT_EXPR && !fn->acceptsArgUnitType(i, args->arg(i)->asInt()->unitType())) {                  } else if (isScalarNumber(args->arg(i)->exprType()) && !fn->acceptsArgUnitType(i, args->arg(i)->asScalarNumberExpr()->unitType())) {
688                      if (args->arg(i)->asInt()->unitType())                      if (args->arg(i)->asScalarNumberExpr()->unitType())
689                          PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect unit " + unitTypeStr(args->arg(i)->asInt()->unitType()) +  ".").c_str());                          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());
690                      else                      else
691                          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());
692                      argsOK = false;                      argsOK = false;
693                      break;                      break;
694                  } else if (!fn->acceptsArgUnitPrefix(i) && args->arg(i)->exprType() == INT_EXPR && args->arg(i)->asInt()->unitPrefix(0)) {                  } else if (isScalarNumber(args->arg(i)->exprType()) && args->arg(i)->asScalarNumberExpr()->hasUnitFactorEver() && !fn->acceptsArgUnitPrefix(i, args->arg(i)->asScalarNumberExpr()->unitType())) {
695                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix.").c_str());                      if (args->arg(i)->asScalarNumberExpr()->unitType())
696                            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());
697                        else
698                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix.").c_str());
699                      argsOK = false;                      argsOK = false;
700                      break;                      break;
701                  } else if (!fn->acceptsArgFinal(i) && args->arg(i)->exprType() == INT_EXPR && args->arg(i)->asInt()->isFinal()) {                  } else if (!fn->acceptsArgFinal(i) && isScalarNumber(args->arg(i)->exprType()) && args->arg(i)->asScalarNumberExpr()->isFinal()) {
702                      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());
703                      argsOK = false;                      argsOK = false;
704                      break;                      break;
705                  }                  }
706              }              }
707                if (argsOK) {
708                    // perform built-in function's own, custom arguments checks (if any)
709                    fn->checkArgs(&*args, [&](String err) {
710                        PARSE_ERR(@3, (String("Built-in function '") + name + "()': " + err).c_str());
711                        argsOK = false;
712                    }, [&](String wrn) {
713                        PARSE_WRN(@3, (String("Built-in function '") + name + "()': " + wrn).c_str());
714                    });
715                }
716              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
717          }          }
718      }      }
# Line 652  assignment: Line 785  assignment:
785              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());
786          else if (var->exprType() != $3->exprType())          else if (var->exprType() != $3->exprType())
787              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());
788          else if (var->exprType() == INT_EXPR) {          else if (isScalarNumber(var->exprType())) {
789              IntVariableRef intVar = var;              ScalarNumberVariableRef numberVar = var;
790              IntExprRef expr = $3;              ScalarNumberExprRef expr = $3;
791              if (intVar->unitType() != expr->unitType())              if (numberVar->unitType() != expr->unitType())
792                  PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has unit type " + unitTypeStr(intVar->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());
793              else if (intVar->unitFactor() != expr->unitFactor())              else if (numberVar->isFinal() != expr->isFinal())
794                  PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has a different unit prefix.").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());
             else if (intVar->isFinal() != expr->isFinal())  
                 PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' was declared as " + String(intVar->isFinal() ? "final" : "not final") + ", assignment is " + String(expr->isFinal() ? "final" : "not final") + " though.").c_str());  
795          }          }
796          $$ = new Assignment(var, $3);          $$ = new Assignment(var, $3);
797      }      }
# Line 669  assignment: Line 800  assignment:
800          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
801          if (!var)          if (!var)
802              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
803          else if (var->exprType() != INT_ARR_EXPR)          else if (!isArray(var->exprType()))
804              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());
805          else if (var->isConstExpr())          else if (var->isConstExpr())
806              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 679  assignment: Line 810  assignment:
810              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());
811          else if ($3->asInt()->unitType())          else if ($3->asInt()->unitType())
812              PARSE_ERR(@3, "Unit types are not allowed as array index.");              PARSE_ERR(@3, "Unit types are not allowed as array index.");
813          else if ($6->exprType() != INT_EXPR)          else if ($6->exprType() != var->exprType())
814              PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());              PARSE_ERR(@5, (String("Variable '") + name + "' was declared as " + typeStr(var->exprType()) + ", assigned expression is " + typeStr($6->exprType()) + " though.").c_str());
815          else if ($6->asInt()->unitType())          else if ($6->asScalarNumberExpr()->unitType())
816              PARSE_ERR(@6, "Unit types are not allowed for array variables.");              PARSE_ERR(@6, "Unit types are not allowed for array variables.");
817          else if ($6->asInt()->isFinal())          else if ($6->asScalarNumberExpr()->isFinal())
818              PARSE_ERR(@6, "Final operator '!' not allowed for array variables.");              PARSE_ERR(@6, "Final operator '!' not allowed for array variables.");
819          else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())          else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
820              PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +              PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
821                            " exceeds size of array variable '" + name +                            " exceeds size of array variable '" + name +
822                            "' which was declared with size " +                            "' which was declared with size " +
823                            ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());                            ToString(((ArrayExprRef)var)->arraySize()) + ".").c_str());
824          else if ($3->asInt()->isFinal())          else if ($3->asInt()->isFinal())
825              PARSE_WRN(@3, "Final operator '!' is meaningless here.");              PARSE_WRN(@3, "Final operator '!' is meaningless here.");
826          IntArrayElementRef element = new IntArrayElement(var, $3);          if (var->exprType() == INT_ARR_EXPR) {
827          $$ = new Assignment(element, $6);              IntArrayElementRef element = new IntArrayElement(var, $3);
828                $$ = new Assignment(element, $6);
829            } else if (var->exprType() == REAL_ARR_EXPR) {
830                RealArrayElementRef element = new RealArrayElement(var, $3);
831                $$ = new Assignment(element, $6);
832            } else {
833                $$ = new NoOperation; // actually not possible to ever get here
834            }
835      }      }
836    
837  unary_expr:  unary_expr:
838      INTEGER  {      INTEGER  {
839          $$ = new IntLiteral($1);          $$ = new IntLiteral({ .value = $1 });
840        }
841        | REAL  {
842            $$ = new RealLiteral({ .value = $1 });
843      }      }
844      | INTEGER_UNIT  {      | INTEGER_UNIT  {
845          IntLiteralRef literal = new IntLiteral($1.iValue);          IntLiteralRef literal = new IntLiteral({
846          literal->setUnit($1.prefix, $1.unit);              .value = $1.iValue,
847                .unitFactor = VMUnit::unitFactor($1.prefix),
848                .unitType = $1.unit
849            });
850            $$ = literal;
851        }
852        | REAL_UNIT  {
853            RealLiteralRef literal = new RealLiteral({
854                .value = $1.fValue,
855                .unitFactor = VMUnit::unitFactor($1.prefix),
856                .unitType = $1.unit
857            });
858          $$ = literal;          $$ = literal;
859      }      }
860      | STRING    {      | STRING    {
# Line 715  unary_expr: Line 867  unary_expr:
867              $$ = var;              $$ = var;
868          else {          else {
869              PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
870              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
871          }          }
872      }      }
873      | VARIABLE '[' expr ']'  {      | VARIABLE '[' expr ']'  {
# Line 723  unary_expr: Line 875  unary_expr:
875          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
876          if (!var) {          if (!var) {
877              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
878              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
879          } else if (var->exprType() != INT_ARR_EXPR) {          } else if (!isArray(var->exprType())) {
880              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());
881              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
882          } else if ($3->exprType() != INT_EXPR) {          } else if ($3->exprType() != INT_EXPR) {
883              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());
884              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
885          } else if ($3->asInt()->unitType() || $3->asInt()->unitPrefix(0)) {          } else if ($3->asInt()->unitType() || $3->asInt()->hasUnitFactorEver()) {
886              PARSE_ERR(@3, "Units are not allowed as array index.");              PARSE_ERR(@3, "Units are not allowed as array index.");
887              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
888          } else {          } else {
889              if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())              if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
890                  PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +                  PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
891                                 " exceeds size of array variable '" + name +                                 " exceeds size of array variable '" + name +
892                                 "' which was declared with size " +                                 "' which was declared with size " +
893                                 ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());                                 ToString(((ArrayExprRef)var)->arraySize()) + ".").c_str());
894              else if ($3->asInt()->isFinal())              else if ($3->asInt()->isFinal())
895                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");                  PARSE_WRN(@3, "Final operator '!' is meaningless here.");
896              $$ = new IntArrayElement(var, $3);              if (var->exprType() == REAL_ARR_EXPR) {
897                    $$ = new RealArrayElement(var, $3);
898                } else {
899                    $$ = new IntArrayElement(var, $3);
900                }
901          }          }
902      }      }
903      | '(' expr ')'  {      | '(' expr ')'  {
# Line 756  unary_expr: Line 912  unary_expr:
912      | BITWISE_NOT unary_expr  {      | BITWISE_NOT unary_expr  {
913          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
914              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());
915              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
916          } else if ($2->asInt()->unitType() || $2->asInt()->unitPrefix(0)) {          } else if ($2->asInt()->unitType() || $2->asInt()->hasUnitFactorEver()) {
917              PARSE_ERR(@2, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@2, "Units are not allowed for operands of bitwise operations.");
918              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
919          } else {          } else {
920              $$ = new BitwiseNot($2);              $$ = new BitwiseNot($2);
921          }          }
# Line 767  unary_expr: Line 923  unary_expr:
923      | NOT unary_expr  {      | NOT unary_expr  {
924          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
925              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());
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 logical operations.");              PARSE_ERR(@2, "Units are not allowed for operands of logical operations.");
929              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
930          } else {          } else {
931              $$ = new Not($2);              $$ = new Not($2);
932          }          }
933      }      }
934      | '!' unary_expr  {      | '!' unary_expr  {
935          if ($2->exprType() != INT_EXPR) {          if (!isScalarNumber($2->exprType())) {
936              PARSE_ERR(@2, (String("Right operand of \"final\" operator '!' must be an integer 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());
937              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
938          } else {          } else {
939              $$ = new Final($2);              $$ = new Final($2);
940          }          }
# Line 808  logical_or_expr: Line 964  logical_or_expr:
964          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
965          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
966              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());
967              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
968          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
969              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());
970              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
971          } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
972              PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");              PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
973              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
974          } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {          } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
975              PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");              PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
976              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
977          } else {          } else {
978                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
979                    PARSE_WRN(@3, "Right operand of 'or' operation is not 'final', result will be 'final' though since left operand is 'final'.");
980                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
981                    PARSE_WRN(@1, "Left operand of 'or' operation is not 'final', result will be 'final' though since right operand is 'final'.");
982              $$ = new Or(lhs, rhs);              $$ = new Or(lhs, rhs);
983          }          }
984      }      }
# Line 832  logical_and_expr: Line 992  logical_and_expr:
992          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
993          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
994              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());
995              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
996          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
997              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());
998              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
999          } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1000              PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");              PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
1001              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1002          } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {          } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1003              PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");              PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
1004              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1005          } else {          } else {
1006                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1007                    PARSE_WRN(@3, "Right operand of 'and' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1008                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1009                    PARSE_WRN(@1, "Left operand of 'and' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1010              $$ = new And(lhs, rhs);              $$ = new And(lhs, rhs);
1011          }          }
1012      }      }
# Line 854  bitwise_or_expr: Line 1018  bitwise_or_expr:
1018          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1019          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1020              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());
1021              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1022          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1023              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());
1024              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1025          } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1026              PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
1027              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1028          } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {          } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1029              PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
1030              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1031          } else {          } else {
1032                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1033                    PARSE_WRN(@3, "Right operand of '.or.' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1034                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1035                    PARSE_WRN(@1, "Left operand of '.or.' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1036              $$ = new BitwiseOr(lhs, rhs);              $$ = new BitwiseOr(lhs, rhs);
1037          }          }
1038      }      }
# Line 878  bitwise_and_expr: Line 1046  bitwise_and_expr:
1046          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1047          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1048              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());
1049              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1050          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1051              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());
1052              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1053          } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {          } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1054              PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
1055              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1056          } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {          } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1057              PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");              PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
1058              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1059          } else {          } else {
1060                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1061                    PARSE_WRN(@3, "Right operand of '.and.' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1062                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1063                    PARSE_WRN(@1, "Left operand of '.and.' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1064              $$ = new BitwiseAnd(lhs, rhs);              $$ = new BitwiseAnd(lhs, rhs);
1065          }          }
1066      }      }
# Line 898  rel_expr: Line 1070  rel_expr:
1070      | rel_expr '<' add_expr  {      | rel_expr '<' add_expr  {
1071          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1072          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1073          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1074              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());
1075              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1076          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1077              PARSE_ERR(@3, (String("Right operand of operator '<' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '<' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1078              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1079          } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||          } else if (lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType()) {
1080                     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1081          {                  unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1082              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1083              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1084          } else {          } else {
1085                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1086                    PARSE_WRN(@3, "Right operand of '<' comparison is not 'final', left operand is 'final' though.");
1087                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1088                    PARSE_WRN(@1, "Left operand of '<' comparison is not 'final', right operand is 'final' though.");
1089              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
1090          }          }
1091      }      }
1092      | rel_expr '>' add_expr  {      | rel_expr '>' add_expr  {
1093          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1094          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1095          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1096              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());
1097              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1098          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1099              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());
1100              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1101          } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||          } else if (lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType()) {
1102                     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1103          {                  unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1104              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1105              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1106          } else {          } else {
1107                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1108                    PARSE_WRN(@3, "Right operand of '>' comparison is not 'final', left operand is 'final' though.");
1109                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1110                    PARSE_WRN(@1, "Left operand of '>' comparison is not 'final', right operand is 'final' though.");
1111              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
1112          }          }
1113      }      }
1114      | rel_expr LE add_expr  {      | rel_expr LE add_expr  {
1115          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1116          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1117          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1118              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());
1119              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1120          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1121              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());
1122              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1123          } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||          } else if (lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType()) {
1124                     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1125          {                  unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1126              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1127              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1128          } else {          } else {
1129                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1130                    PARSE_WRN(@3, "Right operand of '<=' comparison is not 'final', left operand is 'final' though.");
1131                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1132                    PARSE_WRN(@1, "Left operand of '<=' comparison is not 'final', right operand is 'final' though.");
1133              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
1134          }          }
1135      }      }
1136      | rel_expr GE add_expr  {      | rel_expr GE add_expr  {
1137          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1138          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1139          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1140              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());
1141              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1142          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1143              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());
1144              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1145          } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||          } else if (lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType()) {
1146                     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1147          {                  unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1148              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1149              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1150          } else {          } else {
1151                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1152                    PARSE_WRN(@3, "Right operand of '>=' comparison is not 'final', left operand is 'final' though.");
1153                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1154                    PARSE_WRN(@1, "Left operand of '>=' comparison is not 'final', right operand is 'final' though.");
1155              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
1156          }          }
1157      }      }
1158      | rel_expr '=' add_expr  {      | rel_expr '=' add_expr  {
1159          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1160          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1161          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1162              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());
1163              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1164          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1165              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());
1166              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1167          } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||          } else if (lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType()) {
1168                     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1169          {                  unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1170              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1171              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1172          } else {          } else {
1173                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1174                    PARSE_WRN(@3, "Right operand of '=' comparison is not 'final', left operand is 'final' though.");
1175                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1176                    PARSE_WRN(@1, "Left operand of '=' comparison is not 'final', right operand is 'final' though.");
1177              $$ = new Relation(lhs, Relation::EQUAL, rhs);              $$ = new Relation(lhs, Relation::EQUAL, rhs);
1178          }          }
1179      }      }
1180      | rel_expr '#' add_expr  {      | rel_expr '#' add_expr  {
1181          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1182          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1183          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1184              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());
1185              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1186          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1187              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());
1188              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1189          } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||          } else if (lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType()) {
1190                     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())              PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1191          {                  unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1192              PARSE_ERR(@2, "Operands of relative operations must have same unit.");                  unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1193              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1194          } else {          } else {
1195                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1196                    PARSE_WRN(@3, "Right operand of '#' comparison is not 'final', left operand is 'final' though.");
1197                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1198                    PARSE_WRN(@1, "Left operand of '#' comparison is not 'final', right operand is 'final' though.");
1199              $$ = new Relation(lhs, Relation::NOT_EQUAL, rhs);              $$ = new Relation(lhs, Relation::NOT_EQUAL, rhs);
1200          }          }
1201      }      }
# Line 1009  add_expr: Line 1205  add_expr:
1205      | add_expr '+' mul_expr  {      | add_expr '+' mul_expr  {
1206          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1207          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1208          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1209              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());
1210              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1211          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1212              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());
1213              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1214          } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||          } else if (lhs->exprType() != rhs->exprType()) {
1215                     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())              PARSE_ERR(@2, (String("Operands of operator '+' must have same type; left operand is ") +
1216          {                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1217              PARSE_ERR(@2, "Operands of '+' operations must have same unit.");              $$ = new IntLiteral({ .value = 0 });
1218              $$ = new IntLiteral(0);          } else if (lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType()) {
1219          } else {              PARSE_ERR(@2, (String("Operands of '+' operations must have same unit, left operand is ") +
1220                    unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1221                    unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1222                $$ = new IntLiteral({ .value = 0 });
1223            } else {
1224                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1225                    PARSE_WRN(@3, "Right operand of '+' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1226                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1227                    PARSE_WRN(@1, "Left operand of '+' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1228              $$ = new Add(lhs,rhs);              $$ = new Add(lhs,rhs);
1229          }          }
1230      }      }
1231      | add_expr '-' mul_expr  {      | add_expr '-' mul_expr  {
1232          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1233          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1234          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1235              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());
1236              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1237          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1238              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());
1239              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1240          } else if (lhs->asInt()->unitType()   != rhs->asInt()->unitType() ||          } else if (lhs->exprType() != rhs->exprType()) {
1241                     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())              PARSE_ERR(@2, (String("Operands of operator '-' must have same type; left operand is ") +
1242          {                        typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1243              PARSE_ERR(@2, "Operands of '-' operations must have same unit.");              $$ = new IntLiteral({ .value = 0 });
1244              $$ = new IntLiteral(0);          } else if (lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType()) {
1245          } else {              PARSE_ERR(@2, (String("Operands of '-' operations must have same unit, left operand is ") +
1246                    unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1247                    unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1248                $$ = new IntLiteral({ .value = 0 });
1249            } else {
1250                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1251                    PARSE_WRN(@3, "Right operand of '-' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1252                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1253                    PARSE_WRN(@1, "Left operand of '-' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1254              $$ = new Sub(lhs,rhs);              $$ = new Sub(lhs,rhs);
1255          }          }
1256      }      }
# Line 1048  mul_expr: Line 1260  mul_expr:
1260      | mul_expr '*' unary_expr  {      | mul_expr '*' unary_expr  {
1261          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1262          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1263          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1264              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());
1265              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1266          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1267              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());
1268              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1269          } else if (lhs->asInt()->unitType() && rhs->asInt()->unitType()) {          } else if (lhs->asScalarNumberExpr()->unitType() && rhs->asScalarNumberExpr()->unitType()) {
1270              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 ") +
1271              $$ = new IntLiteral(0);                  unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1272          } else if (lhs->asInt()->unitPrefix(0) && rhs->asInt()->unitPrefix(0)) {                  unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1273              PARSE_ERR(@2, "Only one operand of operator '*' may have a unit prefix");              $$ = new IntLiteral({ .value = 0 });
1274              $$ = new IntLiteral(0);          } else if (lhs->exprType() != rhs->exprType()) {
1275          } else {              PARSE_ERR(@2, (String("Operands of operator '*' must have same type; left operand is ") +
1276                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1277                $$ = new IntLiteral({ .value = 0 });
1278            } else {
1279                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1280                    PARSE_WRN(@3, "Right operand of '*' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1281                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1282                    PARSE_WRN(@1, "Left operand of '*' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1283              $$ = new Mul(lhs,rhs);              $$ = new Mul(lhs,rhs);
1284          }          }
1285      }      }
1286      | mul_expr '/' unary_expr  {      | mul_expr '/' unary_expr  {
1287          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1288          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1289          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1290              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());
1291              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1292          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1293              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());
1294              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1295          } else if (lhs->asInt()->unitType() && rhs->asInt()->unitType() &&          } else if (lhs->asScalarNumberExpr()->unitType() && rhs->asScalarNumberExpr()->unitType() &&
1296                     lhs->asInt()->unitType() != rhs->asInt()->unitType())                     lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType())
         {  
             PARSE_ERR(@2, "Operands of operator '/' with two different unit types.");  
             $$ = new IntLiteral(0);  
         } else if (!lhs->asInt()->unitType() && rhs->asInt()->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->asInt()->unitFactor()  != rhs->asInt()->unitFactor() &&  
                    lhs->asInt()->unitPrefix(0) && rhs->asInt()->unitPrefix(0))  
1297          {          {
1298              PARSE_ERR(@2, "Dividing two operands with two different unit prefixes is not possible.");              PARSE_ERR(@2, (String("Operands of operator '/' with two different unit types, left operand is ") +
1299              $$ = new IntLiteral(0);                  unitTypeStr(lhs->asScalarNumberExpr()->unitType()) + " and right operand is " +
1300          } else if (lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor() &&                  unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + " though.").c_str());
1301                     rhs->asInt()->unitPrefix(0))              $$ = new IntLiteral({ .value = 0 });
1302          {          } else if (!lhs->asScalarNumberExpr()->unitType() && rhs->asScalarNumberExpr()->unitType()) {
1303              PARSE_ERR(@3, "Dividing left operand without any unit prefix by right operand with unit prefix is not possible.");              PARSE_ERR(@3, ("Dividing left operand without any unit type by right operand with unit type (" +
1304              $$ = new IntLiteral(0);                  unitTypeStr(rhs->asScalarNumberExpr()->unitType()) + ") is not possible.").c_str());
1305          } else {              $$ = new IntLiteral({ .value = 0 });
1306            } else if (lhs->exprType() != rhs->exprType()) {
1307                PARSE_ERR(@2, (String("Operands of operator '/' must have same type; left operand is ") +
1308                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1309                $$ = new IntLiteral({ .value = 0 });
1310            } else {
1311                if (lhs->asScalarNumberExpr()->isFinal() && !rhs->asScalarNumberExpr()->isFinal())
1312                    PARSE_WRN(@3, "Right operand of '/' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1313                else if (!lhs->asScalarNumberExpr()->isFinal() && rhs->asScalarNumberExpr()->isFinal())
1314                    PARSE_WRN(@1, "Left operand of '/' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1315              $$ = new Div(lhs,rhs);              $$ = new Div(lhs,rhs);
1316          }          }
1317      }      }
# Line 1100  mul_expr: Line 1320  mul_expr:
1320          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1321          if (lhs->exprType() != INT_EXPR) {          if (lhs->exprType() != INT_EXPR) {
1322              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());
1323              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1324          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
1325              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());
1326              $$ = new IntLiteral(0);              $$ = new IntLiteral({ .value = 0 });
1327          } else {          } else {
1328              if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0))              if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver())
1329                  PARSE_ERR(@1, "Operands of modulo operator must not use any unit.");                  PARSE_ERR(@1, "Operands of modulo operator must not use any unit.");
1330              if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0))              if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver())
1331                  PARSE_ERR(@3, "Operands of modulo operator must not use any unit.");                  PARSE_ERR(@3, "Operands of modulo operator must not use any unit.");
1332                if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1333                    PARSE_WRN(@3, "Right operand of 'mod' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1334                else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1335                    PARSE_WRN(@1, "Left operand of 'mod' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1336              $$ = new Mod(lhs,rhs);              $$ = new Mod(lhs,rhs);
1337          }          }
1338      }      }

Legend:
Removed from v.3561  
changed lines
  Added in v.3581

  ViewVC Help
Powered by ViewVC