--- linuxsampler/trunk/src/scriptvm/parser.y 2016/10/15 23:54:27 3013 +++ linuxsampler/trunk/src/scriptvm/parser.y 2017/05/31 14:41:04 3259 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Christian Schoenebeck and Andreas Persson + * Copyright (c) 2014-2017 Christian Schoenebeck and Andreas Persson * * http://www.linuxsampler.org * @@ -31,7 +31,8 @@ %parse-param { LinuxSampler::ParserContext* context } %lex-param { void* scanner } // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners -%name-prefix "InstrScript_" +// (NOTE: "=" is deprecated here with Bison 3.x, however removing it would cause an error with Bison 2.x) +%name-prefix="InstrScript_" %locations %defines %error-verbose @@ -68,6 +69,7 @@ %token LE "operator '<='" %token GE "operator '>='" %token END_OF_FILE 0 "end of file" +%token UNKNOWN_CHAR "unknown character" %type script sections %type section eventhandler @@ -279,7 +281,7 @@ PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str()); $$ = new FunctionCall("nothing", new Args, NULL); // whatever } else if (args->argsCount() > size) { - PARSE_ERR(@8, (String("Variable '") + name + + PARSE_ERR(@8, (String("Array variable '") + name + "' was declared with size " + ToString(size) + " but " + ToString(args->argsCount()) + " values were assigned." ).c_str()); @@ -306,6 +308,62 @@ } } } + | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')' { + const char* name = $3; + if (!$5->isConstExpr()) { + PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with constant array size.").c_str()); + $$ = new FunctionCall("nothing", new Args, NULL); // whatever + } else if ($5->exprType() != INT_EXPR) { + PARSE_ERR(@5, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str()); + $$ = new FunctionCall("nothing", new Args, NULL); // whatever + } else if (context->variableByName(name)) { + PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str()); + $$ = new FunctionCall("nothing", new Args, NULL); // whatever + } else { + IntExprRef sizeExpr = $5; + ArgsRef args = $9; + int size = sizeExpr->evalInt(); + if (size <= 0) { + PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str()); + $$ = new FunctionCall("nothing", new Args, NULL); // whatever + } 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()); + $$ = new FunctionCall("nothing", new Args, NULL); // whatever + } else { + bool argsOK = true; + for (int i = 0; i < args->argsCount(); ++i) { + if (args->arg(i)->exprType() != INT_EXPR) { + PARSE_ERR( + @9, + (String("Array variable '") + name + + "' declared with invalid assignment values. Assigned element " + + ToString(i+1) + " is not an integer expression.").c_str() + ); + argsOK = false; + break; + } + if (!args->arg(i)->isConstExpr()) { + PARSE_ERR( + @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; + } + } + if (argsOK) { + context->vartable[name] = new IntArrayVariable(context, size, args, true); + $$ = new NoOperation; + } else + $$ = new FunctionCall("nothing", new Args, NULL); // whatever + } + } + } | DECLARE CONST_ VARIABLE ASSIGNMENT expr { const char* name = $3; if ($5->exprType() == STRING_EXPR) { @@ -506,10 +564,19 @@ PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str()); else if (var->exprType() != INT_ARR_EXPR) PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str()); + else if (var->isConstExpr()) + PARSE_ERR(@5, (String("Variable assignment: Cannot modify const array variable '") + name + "'.").c_str()); + else if (!var->isAssignable()) + PARSE_ERR(@5, (String("Variable assignment: Array variable '") + name + "' is not assignable.").c_str()); else if ($3->exprType() != INT_EXPR) PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str()); else if ($6->exprType() != INT_EXPR) PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str()); + else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize()) + PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) + + " exceeds size of array variable '" + name + + "' which was declared with size " + + ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str()); IntArrayElementRef element = new IntArrayElement(var, $3); $$ = new Assignment(element, $6); } @@ -544,6 +611,11 @@ PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str()); $$ = new IntLiteral(0); } else { + if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize()) + PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) + + " exceeds size of array variable '" + name + + "' which was declared with size " + + ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str()); $$ = new IntArrayElement(var, $3); } } @@ -831,11 +903,13 @@ yyres[yyn] = '\0'; return yyn; } +/* do_not_strip_quotes: ; +*/ } if (! yyres) - return yystrlen (yystr); + return (int) yystrlen (yystr); - return yystpcpy (yyres, yystr) - yyres; + return int( yystpcpy (yyres, yystr) - yyres ); }