/[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 3582 by schoenebeck, Fri Aug 30 12:23:40 2019 UTC revision 3729 by schoenebeck, Fri Jan 31 10:57:53 2020 UTC
# Line 23  Line 23 
23      #define scanner context->scanner      #define scanner context->scanner
24      #define PARSE_ERR(loc,txt)  yyerror(&loc, context, txt)      #define PARSE_ERR(loc,txt)  yyerror(&loc, context, txt)
25      #define PARSE_WRN(loc,txt)  InstrScript_warning(&loc, context, txt)      #define PARSE_WRN(loc,txt)  InstrScript_warning(&loc, context, txt)
26      #define PARSE_DROP(loc)     context->addPreprocessorComment(loc.first_line, loc.last_line, loc.first_column+1, loc.last_column+1);      #define PARSE_DROP(loc) \
27            context->addPreprocessorComment( \
28                loc.first_line, loc.last_line, loc.first_column+1, \
29                loc.last_column+1, loc.first_byte, loc.length_bytes \
30            );
31      #define yytnamerr(res,str)  InstrScript_tnamerr(res, str)      #define yytnamerr(res,str)  InstrScript_tnamerr(res, str)
32  %}  %}
33    
# Line 51  Line 55 
55  %token NOTE "keyword 'note'"  %token NOTE "keyword 'note'"
56  %token RELEASE "keyword 'release'"  %token RELEASE "keyword 'release'"
57  %token CONTROLLER "keyword 'controller'"  %token CONTROLLER "keyword 'controller'"
58    %token RPN "keyword 'rpn'"
59    %token NRPN "keyword 'nrpn'"
60  %token DECLARE "keyword 'declare'"  %token DECLARE "keyword 'declare'"
61  %token ASSIGNMENT "operator ':='"  %token ASSIGNMENT "operator ':='"
62  %token CONST_ "keyword 'const'"  %token CONST_ "keyword 'const'"
# Line 81  Line 87 
87  %type <nStatements> statements opt_statements userfunctioncall  %type <nStatements> statements opt_statements userfunctioncall
88  %type <nStatement> statement assignment  %type <nStatement> statement assignment
89  %type <nFunctionCall> functioncall  %type <nFunctionCall> functioncall
90  %type <nArgs> args  %type <nArgs> args opt_arr_assignment
91  %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
92  %type <nCaseBranch> caseclause  %type <nCaseBranch> caseclause
93  %type <nCaseBranches> caseclauses  %type <nCaseBranches> caseclauses
94    %type <varQualifier> opt_qualifiers qualifiers qualifier
95    
96  %start script  %start script
97    
# Line 138  eventhandler: Line 145  eventhandler:
145          context->onController = new OnController($3);          context->onController = new OnController($3);
146          $$ = context->onController;          $$ = context->onController;
147      }      }
148        | ON RPN opt_statements END ON  {
149            if (context->onRpn)
150                PARSE_ERR(@2, "Redeclaration of 'rpn' event handler.");
151            context->onRpn = new OnRpn($3);
152            $$ = context->onRpn;
153        }
154        | ON NRPN opt_statements END ON  {
155            if (context->onNrpn)
156                PARSE_ERR(@2, "Redeclaration of 'nrpn' event handler.");
157            context->onNrpn = new OnNrpn($3);
158            $$ = context->onNrpn;
159        }
160    
161  function_declaration:  function_declaration:
162      FUNCTION IDENTIFIER opt_statements END FUNCTION  {      FUNCTION IDENTIFIER opt_statements END FUNCTION  {
# Line 182  statement: Line 201  statement:
201      | userfunctioncall  {      | userfunctioncall  {
202          $$ = $1;          $$ = $1;
203      }      }
204      | DECLARE VARIABLE  {      | DECLARE opt_qualifiers VARIABLE opt_assignment  {
205          const char* name = $2;          $$ = new NoOperation; // just as default result value
206          //printf("declared var '%s'\n", name);          const bool qConst      = $2 & QUALIFIER_CONST;
207          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  {  
208          const char* name = $3;          const char* name = $3;
209          //printf("declared polyphonic var '%s'\n", name);          ExpressionRef expr = $4;
210          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);  
211          const ExprType_t declType = exprTypeOfVarName(name);          const ExprType_t declType = exprTypeOfVarName(name);
212          if (context->variableByName(name)) {          if (context->variableByName(name)) {
213              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
214              $$ = new NoOperation;          } else if (qConst && !expr) {
215          } else if ($4->exprType() == STRING_EXPR) {              PARSE_ERR(@2, (String("Variable '") + name + "' declared const without value assignment.").c_str());
216              if (name[0] != '@')          } else if (qConst && qPolyphonic) {
217                  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());
218              StringExprRef expr = $4;          } else {
219              if (expr->isConstExpr()) {              if (!expr) {
220                  const String s = expr->evalStr();                  if (qPolyphonic) {
221                  StringVariableRef var = new StringVariable(context);                      if (name[0] != '$' && name[0] != '~') {
222                  context->vartable[name] = var;                          PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");
223                  $$ = new Assignment(var, new StringLiteral(s));                      } else if (name[0] == '~') {
224              } else {                          context->vartable[name] = new PolyphonicRealVariable({
225                  StringVariableRef var = new StringVariable(context);                              .ctx = context
226                  context->vartable[name] = var;                          });
227                  $$ = new Assignment(var, expr);                      } else {
228              }                          context->vartable[name] = new PolyphonicIntVariable({
229          } else if ($4->exprType() == REAL_EXPR) {                              .ctx = context
230              if (name[0] != '~')                          });
231                  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());  
232                  } else {                  } else {
233                      if (name[0] == '?') {                      if (name[0] == '@') {
234                          context->vartable[name] = new RealArrayVariable(context, size);                          context->vartable[name] = new StringVariable(context);
235                        } else if (name[0] == '~') {
236                            context->vartable[name] = new RealVariable({
237                                .ctx = context
238                            });
239                        } else if (name[0] == '$') {
240                            context->vartable[name] = new IntVariable({
241                                .ctx = context
242                            });
243                        } else if (name[0] == '?') {
244                            PARSE_ERR(@3, (String("Real number array variable '") + name + "' declaration requires array size.").c_str());
245                      } else if (name[0] == '%') {                      } else if (name[0] == '%') {
246                          context->vartable[name] = new IntArrayVariable(context, size);                          PARSE_ERR(@3, (String("Integer array variable '") + name + "' declaration requires array size.").c_str());
247                      } else {                      } else {
248                          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());
249                      }                      }
250                  }                  }
             }  
         }  
         $$ = 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.");  
251              } else {              } else {
252                  if (sizeExpr->isFinal())                  if (qPolyphonic && !isNumber(expr->exprType())) {
253                      PARSE_WRN(@4, "Final operator '!' is meaningless here.");                      PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");
254                  ExprType_t declType = EMPTY_EXPR;                  } else if (expr->exprType() == STRING_EXPR) {
255                  if (name[0] == '%') {                      if (name[0] != '@')
256                      declType = INT_EXPR;                          PARSE_WRN(@3, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());
257                  } else if (name[0] == '?') {                      StringExprRef strExpr = expr;
258                      declType = REAL_EXPR;                      String s;
259                  } else if (name[0] == '$') {                      if (qConst) {
260                      PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());                          if (strExpr->isConstExpr())
261                  } else if (name[0] == '~') {                              s = strExpr->evalStr();
262                      PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());                          else
263                  } else {                              PARSE_ERR(@4, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());
264                      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);
265                  }                          context->vartable[name] = var;
266                  bool argsOK = true;                      } else {
267                  if (declType == EMPTY_EXPR) {                          if (strExpr->isConstExpr()) {
268                      argsOK = false;                              s = strExpr->evalStr();
269                  } else {                              StringVariableRef var = new StringVariable(context);
270                      for (vmint i = 0; i < args->argsCount(); ++i) {                              context->vartable[name] = var;
271                          if (args->arg(i)->exprType() != declType) {                              $$ = new Assignment(var, new StringLiteral(s));
272                              PARSE_ERR(                          } else {
273                                  @8,                              StringVariableRef var = new StringVariable(context);
274                                  (String("Array variable '") + name +                              context->vartable[name] = var;
275                                  "' 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;  
276                          }                          }
277                      }                      }
278                  }                  } else if (expr->exprType() == REAL_EXPR) {
279                  if (argsOK) {                      if (name[0] != '~')
280                      if (declType == REAL_EXPR)                          PARSE_WRN(@3, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
281                          context->vartable[name] = new RealArrayVariable(context, size, args);                      RealExprRef realExpr = expr;
282                      else                      if (qConst) {
283                          context->vartable[name] = new IntArrayVariable(context, size, args);                          if (!realExpr->isConstExpr()) {
284                                PARSE_ERR(@4, (String("Assignment to const real number variable '") + name + "' requires const expression.").c_str());
285                            }
286                            ConstRealVariableRef var = new ConstRealVariable(
287                                #if defined(__GNUC__) && !defined(__clang__)
288                                (const RealVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
289                                #endif
290                            {
291                                .value = (realExpr->isConstExpr()) ? realExpr->evalReal() : vmfloat(0),
292                                .unitFactor = (realExpr->isConstExpr()) ? realExpr->unitFactor() : VM_NO_FACTOR,
293                                .unitType = realExpr->unitType(),
294                                .isFinal = realExpr->isFinal()
295                            });
296                            context->vartable[name] = var;
297                        } else {
298                            RealVariableRef var = new RealVariable({
299                                .ctx = context,
300                                .unitType = realExpr->unitType(),
301                                .isFinal = realExpr->isFinal()
302                            });
303                            if (realExpr->isConstExpr()) {
304                                $$ = new Assignment(var, new RealLiteral({
305                                    .value = realExpr->evalReal(),
306                                    .unitFactor = realExpr->unitFactor(),
307                                    .unitType = realExpr->unitType(),
308                                    .isFinal = realExpr->isFinal()
309                                }));
310                            } else {
311                                $$ = new Assignment(var, realExpr);
312                            }
313                            context->vartable[name] = var;
314                        }
315                    } else if (expr->exprType() == INT_EXPR) {
316                        if (name[0] != '$')
317                            PARSE_WRN(@3, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
318                        IntExprRef intExpr = expr;
319                        if (qConst) {
320                            if (!intExpr->isConstExpr()) {
321                                PARSE_ERR(@4, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
322                            }
323                            ConstIntVariableRef var = new ConstIntVariable(
324                                #if defined(__GNUC__) && !defined(__clang__)
325                                (const IntVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
326                                #endif
327                            {
328                                .value = (intExpr->isConstExpr()) ? intExpr->evalInt() : 0,
329                                .unitFactor = (intExpr->isConstExpr()) ? intExpr->unitFactor() : VM_NO_FACTOR,
330                                .unitType = intExpr->unitType(),
331                                .isFinal = intExpr->isFinal()
332                            });
333                            context->vartable[name] = var;
334                        } else {
335                            IntVariableRef var = new IntVariable({
336                                .ctx = context,
337                                .unitType = intExpr->unitType(),
338                                .isFinal = intExpr->isFinal()
339                            });
340                            if (intExpr->isConstExpr()) {
341                                $$ = new Assignment(var, new IntLiteral({
342                                    .value = intExpr->evalInt(),
343                                    .unitFactor = intExpr->unitFactor(),
344                                    .unitType = intExpr->unitType(),
345                                    .isFinal = intExpr->isFinal()
346                                }));
347                            } else {
348                                $$ = new Assignment(var, intExpr);
349                            }
350                            context->vartable[name] = var;
351                        }
352                    } else if (expr->exprType() == EMPTY_EXPR) {
353                        PARSE_ERR(@4, "Expression does not result in a value.");
354                        $$ = new NoOperation;
355                    } else if (isArray(expr->exprType())) {
356                        PARSE_ERR(@3, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
357                        $$ = new NoOperation;
358                  }                  }
359              }              }
360          }          }
         $$ = new NoOperation;  
361      }      }
362      | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {      | DECLARE opt_qualifiers VARIABLE '[' expr ']' opt_arr_assignment  {
363            $$ = new NoOperation; // just as default result value
364            const bool qConst      = $2 & QUALIFIER_CONST;
365            const bool qPolyphonic = $2 & QUALIFIER_POLYPHONIC;
366          const char* name = $3;          const char* name = $3;
367          if (!$5->isConstExpr()) {          if (!$5->isConstExpr()) {
368              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 414  statement: Line 370  statement:
370              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());
371          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
372              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
373            } else if (qConst && !$7) {
374                PARSE_ERR(@2, (String("Array variable '") + name + "' declared const without value assignment.").c_str());
375            } else if (qPolyphonic) {
376                PARSE_ERR(@2, (String("Array variable '") + name + "' must not be declared polyphonic.").c_str());
377          } else {          } else {
378              IntExprRef sizeExpr = $5;              IntExprRef sizeExpr = $5;
379              ArgsRef args = $9;              ArgsRef args = $7;
380              vmint size = sizeExpr->evalInt();              vmint size = sizeExpr->evalInt();
381              if (size <= 0) {              if (size <= 0) {
382                  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());  
383              } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {              } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
384                  PARSE_ERR(@5, "Units are not allowed as array size.");                  PARSE_ERR(@5, "Units are not allowed as array size.");
385              } else {              } else {
386                  if (sizeExpr->isFinal())                  if (sizeExpr->isFinal())
387                      PARSE_WRN(@5, "Final operator '!' is meaningless here.");                      PARSE_WRN(@5, "Final operator '!' is meaningless here.");
388                  ExprType_t declType = EMPTY_EXPR;                  if (!args) {
389                  if (name[0] == '%') {                      if (name[0] == '?') {
390                      declType = INT_EXPR;                          context->vartable[name] = new RealArrayVariable(context, size);
391                  } else if (name[0] == '?') {                      } else if (name[0] == '%') {
392                      declType = REAL_EXPR;                          context->vartable[name] = new IntArrayVariable(context, size);
393                  } else if (name[0] == '$') {                      } else {
394                      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());
395                  } 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;  
396                  } else {                  } else {
397                      for (vmint i = 0; i < args->argsCount(); ++i) {                      if (size <= 0) {
398                          if (args->arg(i)->exprType() != declType) {                          PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
399                              PARSE_ERR(                      } else if (args->argsCount() > size) {
400                                  @9,                          PARSE_ERR(@7, (String("Array variable '") + name +
401                                  (String("const array variable '") + name +                                    "' was declared with size " + ToString(size) +
402                                  "' declared with invalid assignment values. Assigned element " +                                    " but " + ToString(args->argsCount()) +
403                                  ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()                                    " values were assigned." ).c_str());
404                              );                      } else {
405                              argsOK = false;                          ExprType_t declType = EMPTY_EXPR;
406                              break;                          if (name[0] == '%') {
407                                declType = INT_EXPR;
408                            } else if (name[0] == '?') {
409                                declType = REAL_EXPR;
410                            } else if (name[0] == '$') {
411                                PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
412                            } else if (name[0] == '~') {
413                                PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
414                            } else {
415                                PARSE_ERR(@3, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
416                          }                          }
417                          if (!args->arg(i)->isConstExpr()) {                          bool argsOK = true;
418                              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()  
                             );  
                             argsOK = false;  
                             break;  
                         } else if (args->arg(i)->asNumber()->unitType()) {  
                             PARSE_ERR(  
                                 @9,  
                                 (String("const 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(  
                                 @9,  
                                 (String("const array variable '") + name +  
                                 "' declared with invalid assignment values. Assigned element " +  
                                 ToString(i+1) + " declared as 'final' value.").c_str()  
                             );  
419                              argsOK = false;                              argsOK = false;
420                              break;                          } else {
421                                for (vmint i = 0; i < args->argsCount(); ++i) {
422                                    if (args->arg(i)->exprType() != declType) {
423                                        PARSE_ERR(
424                                            @7,
425                                            (String("Array variable '") + name +
426                                            "' declared with invalid assignment values. Assigned element " +
427                                            ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
428                                        );
429                                        argsOK = false;
430                                        break;
431                                    } else if (qConst && !args->arg(i)->isConstExpr()) {
432                                        PARSE_ERR(
433                                            @7,
434                                            (String("const array variable '") + name +
435                                            "' must be defined with const values. Assigned element " +
436                                            ToString(i+1) + " is not a const expression though.").c_str()
437                                        );
438                                        argsOK = false;
439                                        break;
440                                    } else if (args->arg(i)->asNumber()->unitType()) {
441                                        PARSE_ERR(
442                                            @7,
443                                            (String("Array variable '") + name +
444                                            "' declared with invalid assignment values. Assigned element " +
445                                            ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
446                                        );
447                                        argsOK = false;
448                                        break;
449                                    } else if (args->arg(i)->asNumber()->isFinal()) {
450                                        PARSE_ERR(
451                                            @7,
452                                            (String("Array variable '") + name +
453                                            "' declared with invalid assignment values. Assigned element " +
454                                            ToString(i+1) + " declared as 'final' value.").c_str()
455                                        );
456                                        argsOK = false;
457                                        break;
458                                    }
459                                }
460                            }
461                            if (argsOK) {
462                                if (declType == REAL_EXPR)
463                                    context->vartable[name] = new RealArrayVariable(context, size, args, qConst);
464                                else
465                                    context->vartable[name] = new IntArrayVariable(context, size, args, qConst);
466                          }                          }
467                      }                      }
468                  }                  }
                 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());  
469              }              }
             ConstRealVariableRef var = new ConstRealVariable({  
                 .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({  
                 .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());  
470          }          }
         $$ = new NoOperation();  
471      }      }
472      | assignment  {      | assignment  {
473          $$ = $1;          $$ = $1;
# Line 676  functioncall: Line 596  functioncall:
596          } else {          } else {
597              bool argsOK = true;              bool argsOK = true;
598              for (vmint i = 0; i < args->argsCount(); ++i) {              for (vmint i = 0; i < args->argsCount(); ++i) {
599                  if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {                  if (!fn->acceptsArgType(i, args->arg(i)->exprType())) {
600                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects " + typeStr(fn->argType(i)) + " type, but type " + typeStr(args->arg(i)->exprType()) + " was given instead.").c_str());                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects " + acceptedArgTypesStr(fn, i) + " type, but type " + typeStr(args->arg(i)->exprType()) + " was given instead.").c_str());
601                      argsOK = false;                      argsOK = false;
602                      break;                      break;
603                  } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {                  } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
# Line 772  args: Line 692  args:
692  arg:  arg:
693      expr      expr
694    
695    opt_qualifiers:
696        /* epsilon (empty argument) */  {
697            $$ = QUALIFIER_NONE;
698        }
699        | qualifiers  {
700            $$ = $1;
701        }
702    
703    qualifiers:
704        qualifier  {
705            $$ = $1;
706        }
707        | qualifiers qualifier  {
708            if ($1 & $2)
709                PARSE_ERR(@2, ("Qualifier '" + qualifierStr($2) + "' must only be listed once.").c_str());
710            $$ = (Qualifier_t) ($1 | $2);
711        }
712    
713    qualifier:
714        CONST_  {
715            $$ = QUALIFIER_CONST;
716        }
717        | POLYPHONIC  {
718            $$ = QUALIFIER_POLYPHONIC;
719        }
720    
721    opt_assignment:
722        /* epsilon (empty argument) */  {
723            $$ = ExpressionRef();
724        }
725        | ASSIGNMENT expr  {
726            $$ = $2;
727        }
728    
729    opt_arr_assignment:
730        /* epsilon (empty argument) */  {
731            $$ = ArgsRef();
732        }
733        | ASSIGNMENT '(' args ')'  {
734            $$ = $3;
735        }
736    
737  assignment:  assignment:
738      VARIABLE ASSIGNMENT expr  {      VARIABLE ASSIGNMENT expr  {
739          //printf("variable lookup with name '%s' as assignment expr\n", $1);          //printf("variable lookup with name '%s' as assignment expr\n", $1);
# Line 810  assignment: Line 772  assignment:
772              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());
773          else if ($3->asInt()->unitType())          else if ($3->asInt()->unitType())
774              PARSE_ERR(@3, "Unit types are not allowed as array index.");              PARSE_ERR(@3, "Unit types are not allowed as array index.");
775          else if ($6->exprType() != var->exprType())          else if ($6->exprType() != scalarTypeOfArray(var->exprType()))
776              PARSE_ERR(@5, (String("Variable '") + name + "' was declared as " + typeStr(var->exprType()) + ", assigned expression is " + typeStr($6->exprType()) + " though.").c_str());              PARSE_ERR(@5, (String("Variable '") + name + "' was declared as " + typeStr(var->exprType()) + ", assigned expression is " + typeStr($6->exprType()) + " though.").c_str());
777          else if ($6->asNumber()->unitType())          else if ($6->asNumber()->unitType())
778              PARSE_ERR(@6, "Unit types are not allowed for array variables.");              PARSE_ERR(@6, "Unit types are not allowed for array variables.");
# Line 906  unary_expr: Line 868  unary_expr:
868      | functioncall  {      | functioncall  {
869          $$ = $1;          $$ = $1;
870      }      }
871        | '+' unary_expr  {
872            $$ = $2;
873        }
874      | '-' unary_expr  {      | '-' unary_expr  {
875          $$ = new Neg($2);          $$ = new Neg($2);
876      }      }
# Line 1341  mul_expr: Line 1306  mul_expr:
1306    
1307  void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {  void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
1308      //fprintf(stderr, "%d: %s\n", locp->first_line, err);      //fprintf(stderr, "%d: %s\n", locp->first_line, err);
1309      context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);      context->addErr(locp->first_line, locp->last_line, locp->first_column+1,
1310                        locp->last_column+1, locp->first_byte, locp->length_bytes,
1311                        err);
1312  }  }
1313    
1314  void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {  void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
1315      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
1316      context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);      context->addWrn(locp->first_line, locp->last_line, locp->first_column+1,
1317                        locp->last_column+1, locp->first_byte, locp->length_bytes,
1318                        txt);
1319  }  }
1320    
1321  /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.  /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.

Legend:
Removed from v.3582  
changed lines
  Added in v.3729

  ViewVC Help
Powered by ViewVC