/[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 3727 by schoenebeck, Fri Jan 3 10:18:21 2020 UTC revision 3728 by schoenebeck, Wed Jan 29 13:58:33 2020 UTC
# Line 83  Line 83 
83  %type <nStatements> statements opt_statements userfunctioncall  %type <nStatements> statements opt_statements userfunctioncall
84  %type <nStatement> statement assignment  %type <nStatement> statement assignment
85  %type <nFunctionCall> functioncall  %type <nFunctionCall> functioncall
86  %type <nArgs> args  %type <nArgs> args opt_arr_assignment
87  %type <nExpression> arg expr logical_or_expr logical_and_expr bitwise_or_expr bitwise_and_expr rel_expr add_expr mul_expr unary_expr concat_expr  %type <nExpression> arg expr logical_or_expr logical_and_expr bitwise_or_expr bitwise_and_expr rel_expr add_expr mul_expr unary_expr concat_expr opt_assignment
88  %type <nCaseBranch> caseclause  %type <nCaseBranch> caseclause
89  %type <nCaseBranches> caseclauses  %type <nCaseBranches> caseclauses
90    %type <varQualifier> opt_qualifiers qualifiers qualifier
91    
92  %start script  %start script
93    
# Line 196  statement: Line 197  statement:
197      | userfunctioncall  {      | userfunctioncall  {
198          $$ = $1;          $$ = $1;
199      }      }
200      | DECLARE VARIABLE  {      | DECLARE opt_qualifiers VARIABLE opt_assignment  {
201          const char* name = $2;          $$ = new NoOperation; // just as default result value
202          //printf("declared var '%s'\n", name);          const bool qConst      = $2 & QUALIFIER_CONST;
203          if (context->variableByName(name)) {          const bool qPolyphonic = $2 & QUALIFIER_POLYPHONIC;
             PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());  
         } else if (name[0] == '@') {  
             context->vartable[name] = new StringVariable(context);  
         } else if (name[0] == '~') {  
             context->vartable[name] = new RealVariable({  
                 .ctx = context  
             });  
         } else if (name[0] == '$') {  
             context->vartable[name] = new IntVariable({  
                 .ctx = context  
             });  
         } else if (name[0] == '?') {  
             PARSE_ERR(@2, (String("Real number array variable '") + name + "' declaration requires array size.").c_str());  
         } else if (name[0] == '%') {  
             PARSE_ERR(@2, (String("Integer array variable '") + name + "' declaration requires array size.").c_str());  
         } else {  
             PARSE_ERR(@2, (String("Variable '") + name + "' declared with unknown type.").c_str());  
         }  
         $$ = new NoOperation;  
     }  
     | DECLARE POLYPHONIC VARIABLE  {  
204          const char* name = $3;          const char* name = $3;
205          //printf("declared polyphonic var '%s'\n", name);          ExpressionRef expr = $4;
206          if (context->variableByName(name)) {          //printf("declared var '%s'\n", name);
             PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());  
         } else if (name[0] != '$' && name[0] != '~') {  
             PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");  
         } else if (name[0] == '~') {  
             context->vartable[name] = new PolyphonicRealVariable({  
                 .ctx = context  
             });  
         } else {  
             context->vartable[name] = new PolyphonicIntVariable({  
                 .ctx = context  
             });  
         }  
         $$ = new NoOperation;  
     }  
     | DECLARE VARIABLE ASSIGNMENT expr  {  
         const char* name = $2;  
         //printf("declared assign var '%s'\n", name);  
207          const ExprType_t declType = exprTypeOfVarName(name);          const ExprType_t declType = exprTypeOfVarName(name);
208          if (context->variableByName(name)) {          if (context->variableByName(name)) {
209              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
210              $$ = new NoOperation;          } else if (qConst && !expr) {
211          } else if ($4->exprType() == STRING_EXPR) {              PARSE_ERR(@2, (String("Variable '") + name + "' declared const without value assignment.").c_str());
212              if (name[0] != '@')          } else if (qConst && qPolyphonic) {
213                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());              PARSE_ERR(@2, (String("Variable '") + name + "' must not be declared both const and polyphonic.").c_str());
214              StringExprRef expr = $4;          } else {
215              if (expr->isConstExpr()) {              if (!expr) {
216                  const String s = expr->evalStr();                  if (qPolyphonic) {
217                  StringVariableRef var = new StringVariable(context);                      if (name[0] != '$' && name[0] != '~') {
218                  context->vartable[name] = var;                          PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");
219                  $$ = new Assignment(var, new StringLiteral(s));                      } else if (name[0] == '~') {
220              } else {                          context->vartable[name] = new PolyphonicRealVariable({
221                  StringVariableRef var = new StringVariable(context);                              .ctx = context
222                  context->vartable[name] = var;                          });
223                  $$ = new Assignment(var, expr);                      } else {
224              }                          context->vartable[name] = new PolyphonicIntVariable({
225          } else if ($4->exprType() == REAL_EXPR) {                              .ctx = context
226              if (name[0] != '~')                          });
227                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());                      }
             RealExprRef expr = $4;  
             RealVariableRef var = new RealVariable({  
                 .ctx = context,  
                 .unitType = expr->unitType(),  
                 .isFinal = expr->isFinal()  
             });  
             if (expr->isConstExpr()) {  
                 $$ = new Assignment(var, new RealLiteral({  
                     .value = expr->evalReal(),  
                     .unitFactor = expr->unitFactor(),  
                     .unitType = expr->unitType(),  
                     .isFinal = expr->isFinal()  
                 }));  
             } else {  
                 $$ = new Assignment(var, expr);  
             }  
             context->vartable[name] = var;  
         } else if ($4->exprType() == INT_EXPR) {  
             if (name[0] != '$')  
                 PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());  
             IntExprRef expr = $4;  
             IntVariableRef var = new IntVariable({  
                 .ctx = context,  
                 .unitType = expr->unitType(),  
                 .isFinal = expr->isFinal()  
             });  
             if (expr->isConstExpr()) {  
                 $$ = new Assignment(var, new IntLiteral({  
                     .value = expr->evalInt(),  
                     .unitFactor = expr->unitFactor(),  
                     .unitType = expr->unitType(),  
                     .isFinal = expr->isFinal()  
                 }));  
             } else {  
                 $$ = new Assignment(var, expr);  
             }  
             context->vartable[name] = var;  
         } else if ($4->exprType() == EMPTY_EXPR) {  
             PARSE_ERR(@4, "Expression does not result in a value.");  
             $$ = new NoOperation;  
         } else if (isArray($4->exprType())) {  
             PARSE_ERR(@2, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());  
             $$ = new NoOperation;  
         }  
     }  
     | DECLARE VARIABLE '[' expr ']'  {  
         //printf("declare array without args\n");  
         const char* name = $2;  
         if (!$4->isConstExpr()) {  
             PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());  
         } else if ($4->exprType() != INT_EXPR) {  
             PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());  
         } else if (context->variableByName(name)) {  
             PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());  
         } else {  
             IntExprRef sizeExpr = $4;  
             if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {  
                 PARSE_ERR(@4, "Units are not allowed as array size.");  
             } else {  
                 if (sizeExpr->isFinal())  
                     PARSE_WRN(@4, "Final operator '!' is meaningless here.");  
                 vmint size = sizeExpr->evalInt();  
                 if (size <= 0) {  
                     PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());  
228                  } else {                  } else {
229                      if (name[0] == '?') {                      if (name[0] == '@') {
230                          context->vartable[name] = new RealArrayVariable(context, size);                          context->vartable[name] = new StringVariable(context);
231                        } else if (name[0] == '~') {
232                            context->vartable[name] = new RealVariable({
233                                .ctx = context
234                            });
235                        } else if (name[0] == '$') {
236                            context->vartable[name] = new IntVariable({
237                                .ctx = context
238                            });
239                        } else if (name[0] == '?') {
240                            PARSE_ERR(@3, (String("Real number array variable '") + name + "' declaration requires array size.").c_str());
241                      } else if (name[0] == '%') {                      } else if (name[0] == '%') {
242                          context->vartable[name] = new IntArrayVariable(context, size);                          PARSE_ERR(@3, (String("Integer array variable '") + name + "' declaration requires array size.").c_str());
243                      } else {                      } else {
244                          PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());                          PARSE_ERR(@3, (String("Variable '") + name + "' declared with unknown type.").c_str());
245                      }                      }
246                  }                  }
             }  
         }  
         $$ = new NoOperation;  
     }  
     | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {  
         const char* name = $2;  
         if (!$4->isConstExpr()) {  
             PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());  
         } else if ($4->exprType() != INT_EXPR) {  
             PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());  
         } else if (context->variableByName(name)) {  
             PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());  
         } else {  
             IntExprRef sizeExpr = $4;  
             ArgsRef args = $8;  
             vmint size = sizeExpr->evalInt();  
             if (size <= 0) {  
                 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());  
             } else if (args->argsCount() > size) {  
                 PARSE_ERR(@8, (String("Array variable '") + name +  
                           "' was declared with size " + ToString(size) +  
                           " but " + ToString(args->argsCount()) +  
                           " values were assigned." ).c_str());  
             } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {  
                 PARSE_ERR(@4, "Units are not allowed as array size.");  
247              } else {              } else {
248                  if (sizeExpr->isFinal())                  if (qPolyphonic && !isNumber(expr->exprType())) {
249                      PARSE_WRN(@4, "Final operator '!' is meaningless here.");                      PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");
250                  ExprType_t declType = EMPTY_EXPR;                  } else if (expr->exprType() == STRING_EXPR) {
251                  if (name[0] == '%') {                      if (name[0] != '@')
252                      declType = INT_EXPR;                          PARSE_WRN(@3, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());
253                  } else if (name[0] == '?') {                      StringExprRef strExpr = expr;
254                      declType = REAL_EXPR;                      String s;
255                  } else if (name[0] == '$') {                      if (qConst) {
256                      PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());                          if (strExpr->isConstExpr())
257                  } else if (name[0] == '~') {                              s = strExpr->evalStr();
258                      PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());                          else
259                  } else {                              PARSE_ERR(@4, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());
260                      PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());                          ConstStringVariableRef var = new ConstStringVariable(context, s);
261                  }                          context->vartable[name] = var;
262                  bool argsOK = true;                      } else {
263                  if (declType == EMPTY_EXPR) {                          if (strExpr->isConstExpr()) {
264                      argsOK = false;                              s = strExpr->evalStr();
265                  } else {                              StringVariableRef var = new StringVariable(context);
266                      for (vmint i = 0; i < args->argsCount(); ++i) {                              context->vartable[name] = var;
267                          if (args->arg(i)->exprType() != declType) {                              $$ = new Assignment(var, new StringLiteral(s));
268                              PARSE_ERR(                          } else {
269                                  @8,                              StringVariableRef var = new StringVariable(context);
270                                  (String("Array variable '") + name +                              context->vartable[name] = var;
271                                  "' declared with invalid assignment values. Assigned element " +                              $$ = new Assignment(var, strExpr);
                                 ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()  
                             );  
                             argsOK = false;  
                             break;  
                         } else if (args->arg(i)->asNumber()->unitType()) {  
                             PARSE_ERR(  
                                 @8,  
                                 (String("Array variable '") + name +  
                                 "' declared with invalid assignment values. Assigned element " +  
                                 ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()  
                             );  
                             argsOK = false;  
                             break;  
                         } else if (args->arg(i)->asNumber()->isFinal()) {  
                             PARSE_ERR(  
                                 @8,  
                                 (String("Array variable '") + name +  
                                 "' declared with invalid assignment values. Assigned element " +  
                                 ToString(i+1) + " declared as 'final' value.").c_str()  
                             );  
                             argsOK = false;  
                             break;  
272                          }                          }
273                      }                      }
274                  }                  } else if (expr->exprType() == REAL_EXPR) {
275                  if (argsOK) {                      if (name[0] != '~')
276                      if (declType == REAL_EXPR)                          PARSE_WRN(@3, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
277                          context->vartable[name] = new RealArrayVariable(context, size, args);                      RealExprRef realExpr = expr;
278                      else                      if (qConst) {
279                          context->vartable[name] = new IntArrayVariable(context, size, args);                          if (!realExpr->isConstExpr()) {
280                                PARSE_ERR(@4, (String("Assignment to const real number variable '") + name + "' requires const expression.").c_str());
281                            }
282                            ConstRealVariableRef var = new ConstRealVariable(
283                                #if defined(__GNUC__) && !defined(__clang__)
284                                (const RealVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
285                                #endif
286                            {
287                                .value = (realExpr->isConstExpr()) ? realExpr->evalReal() : vmfloat(0),
288                                .unitFactor = (realExpr->isConstExpr()) ? realExpr->unitFactor() : VM_NO_FACTOR,
289                                .unitType = realExpr->unitType(),
290                                .isFinal = realExpr->isFinal()
291                            });
292                            context->vartable[name] = var;
293                        } else {
294                            RealVariableRef var = new RealVariable({
295                                .ctx = context,
296                                .unitType = realExpr->unitType(),
297                                .isFinal = realExpr->isFinal()
298                            });
299                            if (realExpr->isConstExpr()) {
300                                $$ = new Assignment(var, new RealLiteral({
301                                    .value = realExpr->evalReal(),
302                                    .unitFactor = realExpr->unitFactor(),
303                                    .unitType = realExpr->unitType(),
304                                    .isFinal = realExpr->isFinal()
305                                }));
306                            } else {
307                                $$ = new Assignment(var, realExpr);
308                            }
309                            context->vartable[name] = var;
310                        }
311                    } else if (expr->exprType() == INT_EXPR) {
312                        if (name[0] != '$')
313                            PARSE_WRN(@3, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
314                        IntExprRef intExpr = expr;
315                        if (qConst) {
316                            if (!intExpr->isConstExpr()) {
317                                PARSE_ERR(@4, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
318                            }
319                            ConstIntVariableRef var = new ConstIntVariable(
320                                #if defined(__GNUC__) && !defined(__clang__)
321                                (const IntVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
322                                #endif
323                            {
324                                .value = (intExpr->isConstExpr()) ? intExpr->evalInt() : 0,
325                                .unitFactor = (intExpr->isConstExpr()) ? intExpr->unitFactor() : VM_NO_FACTOR,
326                                .unitType = intExpr->unitType(),
327                                .isFinal = intExpr->isFinal()
328                            });
329                            context->vartable[name] = var;
330                        } else {
331                            IntVariableRef var = new IntVariable({
332                                .ctx = context,
333                                .unitType = intExpr->unitType(),
334                                .isFinal = intExpr->isFinal()
335                            });
336                            if (intExpr->isConstExpr()) {
337                                $$ = new Assignment(var, new IntLiteral({
338                                    .value = intExpr->evalInt(),
339                                    .unitFactor = intExpr->unitFactor(),
340                                    .unitType = intExpr->unitType(),
341                                    .isFinal = intExpr->isFinal()
342                                }));
343                            } else {
344                                $$ = new Assignment(var, intExpr);
345                            }
346                            context->vartable[name] = var;
347                        }
348                    } else if (expr->exprType() == EMPTY_EXPR) {
349                        PARSE_ERR(@4, "Expression does not result in a value.");
350                        $$ = new NoOperation;
351                    } else if (isArray(expr->exprType())) {
352                        PARSE_ERR(@3, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
353                        $$ = new NoOperation;
354                  }                  }
355              }              }
356          }          }
         $$ = new NoOperation;  
357      }      }
358      | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {      | DECLARE opt_qualifiers VARIABLE '[' expr ']' opt_arr_assignment  {
359            $$ = new NoOperation; // just as default result value
360            const bool qConst      = $2 & QUALIFIER_CONST;
361            const bool qPolyphonic = $2 & QUALIFIER_POLYPHONIC;
362          const char* name = $3;          const char* name = $3;
363          if (!$5->isConstExpr()) {          if (!$5->isConstExpr()) {
364              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());
# Line 428  statement: Line 366  statement:
366              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());
367          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
368              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
369            } else if (qConst && !$7) {
370                PARSE_ERR(@2, (String("Array variable '") + name + "' declared const without value assignment.").c_str());
371            } else if (qPolyphonic) {
372                PARSE_ERR(@2, (String("Array variable '") + name + "' must not be declared polyphonic.").c_str());
373          } else {          } else {
374              IntExprRef sizeExpr = $5;              IntExprRef sizeExpr = $5;
375              ArgsRef args = $9;              ArgsRef args = $7;
376              vmint size = sizeExpr->evalInt();              vmint size = sizeExpr->evalInt();
377              if (size <= 0) {              if (size <= 0) {
378                  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());
             } else if (args->argsCount() > size) {  
                 PARSE_ERR(@9, (String("Array variable '") + name +  
                           "' was declared with size " + ToString(size) +  
                           " but " + ToString(args->argsCount()) +  
                           " values were assigned." ).c_str());  
379              } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {              } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
380                  PARSE_ERR(@5, "Units are not allowed as array size.");                  PARSE_ERR(@5, "Units are not allowed as array size.");
381              } else {              } else {
382                  if (sizeExpr->isFinal())                  if (sizeExpr->isFinal())
383                      PARSE_WRN(@5, "Final operator '!' is meaningless here.");                      PARSE_WRN(@5, "Final operator '!' is meaningless here.");
384                  ExprType_t declType = EMPTY_EXPR;                  if (!args) {
385                  if (name[0] == '%') {                      if (name[0] == '?') {
386                      declType = INT_EXPR;                          context->vartable[name] = new RealArrayVariable(context, size);
387                  } else if (name[0] == '?') {                      } else if (name[0] == '%') {
388                      declType = REAL_EXPR;                          context->vartable[name] = new IntArrayVariable(context, size);
389                  } else if (name[0] == '$') {                      } else {
390                      PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());                          PARSE_ERR(@3, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
391                  } else if (name[0] == '~') {                      }
                     PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());  
                 } else {  
                     PARSE_ERR(@3, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());  
                 }  
                 bool argsOK = true;  
                 if (declType == EMPTY_EXPR) {  
                     argsOK = false;  
392                  } else {                  } else {
393                      for (vmint i = 0; i < args->argsCount(); ++i) {                      if (size <= 0) {
394                          if (args->arg(i)->exprType() != declType) {                          PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
395                              PARSE_ERR(                      } else if (args->argsCount() > size) {
396                                  @9,                          PARSE_ERR(@7, (String("Array variable '") + name +
397                                  (String("const array variable '") + name +                                    "' was declared with size " + ToString(size) +
398                                  "' declared with invalid assignment values. Assigned element " +                                    " but " + ToString(args->argsCount()) +
399                                  ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()                                    " values were assigned." ).c_str());
400                              );                      } else {
401                              argsOK = false;                          ExprType_t declType = EMPTY_EXPR;
402                              break;                          if (name[0] == '%') {
403                                declType = INT_EXPR;
404                            } else if (name[0] == '?') {
405                                declType = REAL_EXPR;
406                            } else if (name[0] == '$') {
407                                PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
408                            } else if (name[0] == '~') {
409                                PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
410                            } else {
411                                PARSE_ERR(@3, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
412                          }                          }
413                          if (!args->arg(i)->isConstExpr()) {                          bool argsOK = true;
414                              PARSE_ERR(                          if (declType == EMPTY_EXPR) {
                                 @9,  
                                 (String("const array variable '") + name +  
                                 "' must be defined with const values. Assigned element " +  
                                 ToString(i+1) + " is not a const expression though.").c_str()  
                             );  
415                              argsOK = false;                              argsOK = false;
416                              break;                          } else {
417                          } else if (args->arg(i)->asNumber()->unitType()) {                              for (vmint i = 0; i < args->argsCount(); ++i) {
418                              PARSE_ERR(                                  if (args->arg(i)->exprType() != declType) {
419                                  @9,                                      PARSE_ERR(
420                                  (String("const array variable '") + name +                                          @7,
421                                  "' declared with invalid assignment values. Assigned element " +                                          (String("Array variable '") + name +
422                                  ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()                                          "' declared with invalid assignment values. Assigned element " +
423                              );                                          ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
424                              argsOK = false;                                      );
425                              break;                                      argsOK = false;
426                          } else if (args->arg(i)->asNumber()->isFinal()) {                                      break;
427                              PARSE_ERR(                                  } else if (qConst && !args->arg(i)->isConstExpr()) {
428                                  @9,                                      PARSE_ERR(
429                                  (String("const array variable '") + name +                                          @7,
430                                  "' declared with invalid assignment values. Assigned element " +                                          (String("const array variable '") + name +
431                                  ToString(i+1) + " declared as 'final' value.").c_str()                                          "' must be defined with const values. Assigned element " +
432                              );                                          ToString(i+1) + " is not a const expression though.").c_str()
433                              argsOK = false;                                      );
434                              break;                                      argsOK = false;
435                                        break;
436                                    } else if (args->arg(i)->asNumber()->unitType()) {
437                                        PARSE_ERR(
438                                            @7,
439                                            (String("Array variable '") + name +
440                                            "' declared with invalid assignment values. Assigned element " +
441                                            ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
442                                        );
443                                        argsOK = false;
444                                        break;
445                                    } else if (args->arg(i)->asNumber()->isFinal()) {
446                                        PARSE_ERR(
447                                            @7,
448                                            (String("Array variable '") + name +
449                                            "' declared with invalid assignment values. Assigned element " +
450                                            ToString(i+1) + " declared as 'final' value.").c_str()
451                                        );
452                                        argsOK = false;
453                                        break;
454                                    }
455                                }
456                            }
457                            if (argsOK) {
458                                if (declType == REAL_EXPR)
459                                    context->vartable[name] = new RealArrayVariable(context, size, args, qConst);
460                                else
461                                    context->vartable[name] = new IntArrayVariable(context, size, args, qConst);
462                          }                          }
463                      }                      }
464                  }                  }
                 if (argsOK) {  
                     if (declType == REAL_EXPR)  
                         context->vartable[name] = new RealArrayVariable(context, size, args, true);  
                     else  
                         context->vartable[name] = new IntArrayVariable(context, size, args, true);  
                 }  
             }  
         }  
         $$ = new NoOperation;  
     }  
     | DECLARE CONST_ VARIABLE ASSIGNMENT expr  {  
         const char* name = $3;  
         const ExprType_t declType = exprTypeOfVarName(name);  
         if ($5->exprType() == STRING_EXPR) {  
             if (name[0] != '@')  
                 PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());  
             String s;  
             StringExprRef expr = $5;  
             if (expr->isConstExpr())  
                 s = expr->evalStr();  
             else  
                 PARSE_ERR(@5, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());  
             ConstStringVariableRef var = new ConstStringVariable(context, s);  
             context->vartable[name] = var;  
             //$$ = new Assignment(var, new StringLiteral(s));  
         } else if ($5->exprType() == REAL_EXPR) {  
             if (name[0] != '~')  
                 PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());  
             RealExprRef expr = $5;  
             if (!expr->isConstExpr()) {  
                 PARSE_ERR(@5, (String("Assignment to const real number variable '") + name + "' requires const expression.").c_str());  
465              }              }
             ConstRealVariableRef var = new ConstRealVariable(  
                 #if defined(__GNUC__) && !defined(__clang__)  
                 (const RealVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though  
                 #endif  
             {  
                 .value = (expr->isConstExpr()) ? expr->evalReal() : vmfloat(0),  
                 .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,  
                 .unitType = expr->unitType(),  
                 .isFinal = expr->isFinal()  
             });  
             context->vartable[name] = var;  
             //$$ = new Assignment(var, new IntLiteral(i));  
         } else if ($5->exprType() == INT_EXPR) {  
             if (name[0] != '$')  
                 PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());  
             IntExprRef expr = $5;  
             if (!expr->isConstExpr()) {  
                 PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());  
             }  
             ConstIntVariableRef var = new ConstIntVariable(  
                 #if defined(__GNUC__) && !defined(__clang__)  
                 (const IntVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though  
                 #endif  
             {  
                 .value = (expr->isConstExpr()) ? expr->evalInt() : 0,  
                 .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,  
                 .unitType = expr->unitType(),  
                 .isFinal = expr->isFinal()  
             });  
             context->vartable[name] = var;  
             //$$ = new Assignment(var, new IntLiteral(i));  
         } else if ($5->exprType() == EMPTY_EXPR) {  
             PARSE_ERR(@5, "Expression does not result in a value.");  
         } else if (isArray($5->exprType())) {  
             PARSE_ERR(@5, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());  
466          }          }
         $$ = new NoOperation();  
467      }      }
468      | assignment  {      | assignment  {
469          $$ = $1;          $$ = $1;
# Line 794  args: Line 688  args:
688  arg:  arg:
689      expr      expr
690    
691    opt_qualifiers:
692        /* epsilon (empty argument) */  {
693            $$ = QUALIFIER_NONE;
694        }
695        | qualifiers  {
696            $$ = $1;
697        }
698    
699    qualifiers:
700        qualifier  {
701            $$ = $1;
702        }
703        | qualifiers qualifier  {
704            if ($1 & $2)
705                PARSE_ERR(@2, ("Qualifier '" + qualifierStr($2) + "' must only be listed once.").c_str());
706            $$ = (Qualifier_t) ($1 | $2);
707        }
708    
709    qualifier:
710        CONST_  {
711            $$ = QUALIFIER_CONST;
712        }
713        | POLYPHONIC  {
714            $$ = QUALIFIER_POLYPHONIC;
715        }
716    
717    opt_assignment:
718        /* epsilon (empty argument) */  {
719            $$ = ExpressionRef();
720        }
721        | ASSIGNMENT expr  {
722            $$ = $2;
723        }
724    
725    opt_arr_assignment:
726        /* epsilon (empty argument) */  {
727            $$ = ArgsRef();
728        }
729        | ASSIGNMENT '(' args ')'  {
730            $$ = $3;
731        }
732    
733  assignment:  assignment:
734      VARIABLE ASSIGNMENT expr  {      VARIABLE ASSIGNMENT expr  {
735          //printf("variable lookup with name '%s' as assignment expr\n", $1);          //printf("variable lookup with name '%s' as assignment expr\n", $1);

Legend:
Removed from v.3727  
changed lines
  Added in v.3728

  ViewVC Help
Powered by ViewVC