/[svn]/linuxsampler/trunk/src/scriptvm/parser.y
ViewVC logotype

Contents of /linuxsampler/trunk/src/scriptvm/parser.y

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3259 - (show annotations) (download)
Wed May 31 14:41:04 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 38270 byte(s)
* NKSP language fix: Unknown characters were not handled correctly.
* Bumped version (2.0.0.svn59).

1 /*
2 * Copyright (c) 2014-2017 Christian Schoenebeck and Andreas Persson
3 *
4 * http://www.linuxsampler.org
5 *
6 * This file is part of LinuxSampler and released under the same terms.
7 * See README file for details.
8 */
9
10 /* Parser for NKSP real-time instrument script language. */
11
12 %{
13 #define YYERROR_VERBOSE 1
14 #include "parser_shared.h"
15 #include <string>
16 #include <map>
17 using namespace LinuxSampler;
18
19 void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err);
20 void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt);
21 int InstrScript_tnamerr(char* yyres, const char* yystr);
22 int InstrScript_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);
23 #define scanner context->scanner
24 #define PARSE_ERR(loc,txt) yyerror(&loc, context, txt)
25 #define PARSE_WRN(loc,txt) InstrScript_warning(&loc, context, txt)
26 #define yytnamerr(res,str) InstrScript_tnamerr(res, str)
27 %}
28
29 // generate reentrant safe parser
30 %pure-parser
31 %parse-param { LinuxSampler::ParserContext* context }
32 %lex-param { void* scanner }
33 // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners
34 // (NOTE: "=" is deprecated here with Bison 3.x, however removing it would cause an error with Bison 2.x)
35 %name-prefix="InstrScript_"
36 %locations
37 %defines
38 %error-verbose
39
40 %token <iValue> INTEGER "integer literal"
41 %token <sValue> STRING "string literal"
42 %token <sValue> IDENTIFIER "function name"
43 %token <sValue> VARIABLE "variable name"
44 %token ON "keyword 'on'"
45 %token END "keyword 'end'"
46 %token INIT "keyword 'init'"
47 %token NOTE "keyword 'note'"
48 %token RELEASE "keyword 'release'"
49 %token CONTROLLER "keyword 'controller'"
50 %token DECLARE "keyword 'declare'"
51 %token ASSIGNMENT "operator ':='"
52 %token CONST_ "keyword 'const'"
53 %token POLYPHONIC "keyword 'polyphonic'"
54 %token WHILE "keyword 'while'"
55 %token IF "keyword 'if'"
56 %token ELSE "keyword 'else'"
57 %token SELECT "keyword 'select'"
58 %token CASE "keyword 'case'"
59 %token TO "keyword 'to'"
60 %token OR "operator 'or'"
61 %token AND "operator 'and'"
62 %token NOT "operator 'not'"
63 %token BITWISE_OR "bitwise operator '.or.'"
64 %token BITWISE_AND "bitwise operator '.and.'"
65 %token BITWISE_NOT "bitwise operator '.not.'"
66 %token FUNCTION "keyword 'function'"
67 %token CALL "keyword 'call'"
68 %token MOD "operator 'mod'"
69 %token LE "operator '<='"
70 %token GE "operator '>='"
71 %token END_OF_FILE 0 "end of file"
72 %token UNKNOWN_CHAR "unknown character"
73
74 %type <nEventHandlers> script sections
75 %type <nEventHandler> section eventhandler
76 %type <nStatements> statements opt_statements userfunctioncall
77 %type <nStatement> statement assignment
78 %type <nFunctionCall> functioncall
79 %type <nArgs> args
80 %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
81 %type <nCaseBranch> caseclause
82 %type <nCaseBranches> caseclauses
83
84 %start script
85
86 %%
87
88 script:
89 sections {
90 $$ = context->handlers = $1;
91 }
92
93 sections:
94 section {
95 $$ = new EventHandlers();
96 if ($1) $$->add($1);
97 }
98 | sections section {
99 $$ = $1;
100 if ($2) $$->add($2);
101 }
102
103 section:
104 function_declaration {
105 $$ = EventHandlerRef();
106 }
107 | eventhandler {
108 $$ = $1;
109 }
110
111 eventhandler:
112 ON NOTE opt_statements END ON {
113 if (context->onNote)
114 PARSE_ERR(@2, "Redeclaration of 'note' event handler.");
115 context->onNote = new OnNote($3);
116 $$ = context->onNote;
117 }
118 | ON INIT opt_statements END ON {
119 if (context->onInit)
120 PARSE_ERR(@2, "Redeclaration of 'init' event handler.");
121 context->onInit = new OnInit($3);
122 $$ = context->onInit;
123 }
124 | ON RELEASE opt_statements END ON {
125 if (context->onRelease)
126 PARSE_ERR(@2, "Redeclaration of 'release' event handler.");
127 context->onRelease = new OnRelease($3);
128 $$ = context->onRelease;
129 }
130 | ON CONTROLLER opt_statements END ON {
131 if (context->onController)
132 PARSE_ERR(@2, "Redeclaration of 'controller' event handler.");
133 context->onController = new OnController($3);
134 $$ = context->onController;
135 }
136
137 function_declaration:
138 FUNCTION IDENTIFIER opt_statements END FUNCTION {
139 const char* name = $2;
140 if (context->functionProvider->functionByName(name)) {
141 PARSE_ERR(@2, (String("There is already a built-in function with name '") + name + "'.").c_str());
142 } else if (context->userFunctionByName(name)) {
143 PARSE_ERR(@2, (String("There is already a user defined function with name '") + name + "'.").c_str());
144 } else {
145 context->userFnTable[name] = $3;
146 }
147 }
148
149 opt_statements:
150 /* epsilon (empty argument) */ {
151 $$ = new Statements();
152 }
153 | statements {
154 $$ = $1;
155 }
156
157 statements:
158 statement {
159 $$ = new Statements();
160 if ($1) {
161 if (!isNoOperation($1)) $$->add($1); // filter out NoOperation statements
162 } else
163 PARSE_WRN(@1, "Not a statement.");
164 }
165 | statements statement {
166 $$ = $1;
167 if ($2) {
168 if (!isNoOperation($2)) $$->add($2); // filter out NoOperation statements
169 } else
170 PARSE_WRN(@2, "Not a statement.");
171 }
172
173 statement:
174 functioncall {
175 $$ = $1;
176 }
177 | userfunctioncall {
178 $$ = $1;
179 }
180 | DECLARE VARIABLE {
181 const char* name = $2;
182 //printf("declared var '%s'\n", name);
183 if (context->variableByName(name))
184 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
185 if (name[0] == '@') {
186 context->vartable[name] = new StringVariable(context);
187 $$ = new NoOperation;
188 } else {
189 context->vartable[name] = new IntVariable(context);
190 $$ = new NoOperation;
191 }
192 }
193 | DECLARE POLYPHONIC VARIABLE {
194 const char* name = $3;
195 //printf("declared polyphonic var '%s'\n", name);
196 if (context->variableByName(name))
197 PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
198 if (name[0] != '$') {
199 PARSE_ERR(@3, "Polyphonic variables may only be declared as integers.");
200 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
201 } else {
202 context->vartable[name] = new PolyphonicIntVariable(context);
203 $$ = new NoOperation;
204 }
205 }
206 | DECLARE VARIABLE ASSIGNMENT expr {
207 const char* name = $2;
208 //printf("declared assign var '%s'\n", name);
209 if (context->variableByName(name))
210 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
211 if ($4->exprType() == STRING_EXPR) {
212 if (name[0] == '$')
213 PARSE_WRN(@2, (String("Variable '") + name + "' declared as integer, string expression assigned though.").c_str());
214 StringExprRef expr = $4;
215 if (expr->isConstExpr()) {
216 const String s = expr->evalStr();
217 StringVariableRef var = new StringVariable(context);
218 context->vartable[name] = var;
219 $$ = new Assignment(var, new StringLiteral(s));
220 } else {
221 StringVariableRef var = new StringVariable(context);
222 context->vartable[name] = var;
223 $$ = new Assignment(var, expr);
224 }
225 } else {
226 if (name[0] == '@')
227 PARSE_WRN(@2, (String("Variable '") + name + "' declared as string, integer expression assigned though.").c_str());
228 IntExprRef expr = $4;
229 if (expr->isConstExpr()) {
230 const int i = expr->evalInt();
231 IntVariableRef var = new IntVariable(context);
232 context->vartable[name] = var;
233 $$ = new Assignment(var, new IntLiteral(i));
234 } else {
235 IntVariableRef var = new IntVariable(context);
236 context->vartable[name] = var;
237 $$ = new Assignment(var, expr);
238 }
239 }
240 }
241 | DECLARE VARIABLE '[' expr ']' {
242 //printf("declare array without args\n");
243 const char* name = $2;
244 if (!$4->isConstExpr()) {
245 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
246 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
247 } else if ($4->exprType() != INT_EXPR) {
248 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
249 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
250 } else if (context->variableByName(name)) {
251 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
252 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
253 } else {
254 IntExprRef expr = $4;
255 int size = expr->evalInt();
256 if (size <= 0) {
257 PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
258 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
259 } else {
260 context->vartable[name] = new IntArrayVariable(context, size);
261 $$ = new NoOperation;
262 }
263 }
264 }
265 | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')' {
266 const char* name = $2;
267 if (!$4->isConstExpr()) {
268 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
269 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
270 } else if ($4->exprType() != INT_EXPR) {
271 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
272 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
273 } else if (context->variableByName(name)) {
274 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
275 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
276 } else {
277 IntExprRef sizeExpr = $4;
278 ArgsRef args = $8;
279 int size = sizeExpr->evalInt();
280 if (size <= 0) {
281 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
282 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
283 } else if (args->argsCount() > size) {
284 PARSE_ERR(@8, (String("Array variable '") + name +
285 "' was declared with size " + ToString(size) +
286 " but " + ToString(args->argsCount()) +
287 " values were assigned." ).c_str());
288 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
289 } else {
290 bool argsOK = true;
291 for (int i = 0; i < args->argsCount(); ++i) {
292 if (args->arg(i)->exprType() != INT_EXPR) {
293 PARSE_ERR(
294 @8,
295 (String("Array variable '") + name +
296 "' declared with invalid assignment values. Assigned element " +
297 ToString(i+1) + " is not an integer expression.").c_str()
298 );
299 argsOK = false;
300 break;
301 }
302 }
303 if (argsOK) {
304 context->vartable[name] = new IntArrayVariable(context, size, args);
305 $$ = new NoOperation;
306 } else
307 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
308 }
309 }
310 }
311 | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')' {
312 const char* name = $3;
313 if (!$5->isConstExpr()) {
314 PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
315 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
316 } else if ($5->exprType() != INT_EXPR) {
317 PARSE_ERR(@5, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
318 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
319 } else if (context->variableByName(name)) {
320 PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
321 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
322 } else {
323 IntExprRef sizeExpr = $5;
324 ArgsRef args = $9;
325 int size = sizeExpr->evalInt();
326 if (size <= 0) {
327 PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
328 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
329 } else if (args->argsCount() > size) {
330 PARSE_ERR(@9, (String("Array variable '") + name +
331 "' was declared with size " + ToString(size) +
332 " but " + ToString(args->argsCount()) +
333 " values were assigned." ).c_str());
334 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
335 } else {
336 bool argsOK = true;
337 for (int i = 0; i < args->argsCount(); ++i) {
338 if (args->arg(i)->exprType() != INT_EXPR) {
339 PARSE_ERR(
340 @9,
341 (String("Array variable '") + name +
342 "' declared with invalid assignment values. Assigned element " +
343 ToString(i+1) + " is not an integer expression.").c_str()
344 );
345 argsOK = false;
346 break;
347 }
348 if (!args->arg(i)->isConstExpr()) {
349 PARSE_ERR(
350 @9,
351 (String("const array variable '") + name +
352 "' must be defined with const values. Assigned element " +
353 ToString(i+1) + " is not a const expression though.").c_str()
354 );
355 argsOK = false;
356 break;
357 }
358 }
359 if (argsOK) {
360 context->vartable[name] = new IntArrayVariable(context, size, args, true);
361 $$ = new NoOperation;
362 } else
363 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
364 }
365 }
366 }
367 | DECLARE CONST_ VARIABLE ASSIGNMENT expr {
368 const char* name = $3;
369 if ($5->exprType() == STRING_EXPR) {
370 if (name[0] == '$')
371 PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");
372 String s;
373 StringExprRef expr = $5;
374 if (expr->isConstExpr())
375 s = expr->evalStr();
376 else
377 PARSE_ERR(@5, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());
378 ConstStringVariableRef var = new ConstStringVariable(context, s);
379 context->vartable[name] = var;
380 //$$ = new Assignment(var, new StringLiteral(s));
381 $$ = new NoOperation();
382 } else {
383 if (name[0] == '@')
384 PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");
385 int i = 0;
386 IntExprRef expr = $5;
387 if (expr->isConstExpr())
388 i = expr->evalInt();
389 else
390 PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
391 ConstIntVariableRef var = new ConstIntVariable(i);
392 context->vartable[name] = var;
393 //$$ = new Assignment(var, new IntLiteral(i));
394 $$ = new NoOperation();
395 }
396 }
397 | assignment {
398 $$ = $1;
399 }
400 | WHILE '(' expr ')' opt_statements END WHILE {
401 if ($3->exprType() == INT_EXPR) {
402 $$ = new While($3, $5);
403 } else {
404 PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
405 $$ = new While(new IntLiteral(0), $5);
406 }
407 }
408 | IF '(' expr ')' opt_statements ELSE opt_statements END IF {
409 $$ = new If($3, $5, $7);
410 }
411 | IF '(' expr ')' opt_statements END IF {
412 $$ = new If($3, $5);
413 }
414 | SELECT expr caseclauses END SELECT {
415 if ($2->exprType() == INT_EXPR) {
416 $$ = new SelectCase($2, $3);
417 } else {
418 PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
419 $$ = new SelectCase(new IntLiteral(0), $3);
420 }
421 }
422
423 caseclauses:
424 caseclause {
425 $$ = CaseBranches();
426 $$.push_back($1);
427 }
428 | caseclauses caseclause {
429 $$ = $1;
430 $$.push_back($2);
431 }
432
433 caseclause:
434 CASE INTEGER opt_statements {
435 $$ = CaseBranch();
436 $$.from = new IntLiteral($2);
437 $$.statements = $3;
438 }
439 | CASE INTEGER TO INTEGER opt_statements {
440 $$ = CaseBranch();
441 $$.from = new IntLiteral($2);
442 $$.to = new IntLiteral($4);
443 $$.statements = $5;
444 }
445
446 userfunctioncall:
447 CALL IDENTIFIER {
448 const char* name = $2;
449 StatementsRef fn = context->userFunctionByName(name);
450 if (context->functionProvider->functionByName(name)) {
451 PARSE_ERR(@1, (String("Keyword 'call' must only be used for user defined functions, not for any built-in function like '") + name + "'.").c_str());
452 $$ = StatementsRef();
453 } else if (!fn) {
454 PARSE_ERR(@2, (String("No user defined function with name '") + name + "'.").c_str());
455 $$ = StatementsRef();
456 } else {
457 $$ = fn;
458 }
459 }
460
461 functioncall:
462 IDENTIFIER '(' args ')' {
463 const char* name = $1;
464 //printf("function call of '%s' with args\n", name);
465 ArgsRef args = $3;
466 VMFunction* fn = context->functionProvider->functionByName(name);
467 if (context->userFunctionByName(name)) {
468 PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
469 $$ = new FunctionCall(name, args, NULL);
470 } else if (!fn) {
471 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
472 $$ = new FunctionCall(name, args, NULL);
473 } else if (args->argsCount() < fn->minRequiredArgs()) {
474 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
475 $$ = new FunctionCall(name, args, NULL);
476 } else if (args->argsCount() > fn->maxAllowedArgs()) {
477 PARSE_ERR(@3, (String("Built-in function '") + name + "' accepts max. " + ToString(fn->maxAllowedArgs()) + " arguments.").c_str());
478 $$ = new FunctionCall(name, args, NULL);
479 } else {
480 bool argsOK = true;
481 for (int i = 0; i < args->argsCount(); ++i) {
482 if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {
483 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());
484 argsOK = false;
485 break;
486 } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
487 PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
488 argsOK = false;
489 break;
490 }
491 }
492 $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
493 }
494 }
495 | IDENTIFIER '(' ')' {
496 const char* name = $1;
497 //printf("function call of '%s' (with empty args)\n", name);
498 ArgsRef args = new Args;
499 VMFunction* fn = context->functionProvider->functionByName(name);
500 if (context->userFunctionByName(name)) {
501 PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
502 $$ = new FunctionCall(name, args, NULL);
503 } else if (!fn) {
504 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
505 $$ = new FunctionCall(name, args, NULL);
506 } else if (fn->minRequiredArgs() > 0) {
507 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
508 $$ = new FunctionCall(name, args, NULL);
509 } else {
510 $$ = new FunctionCall(name, args, fn);
511 }
512 }
513 | IDENTIFIER {
514 const char* name = $1;
515 //printf("function call of '%s' (without args)\n", name);
516 ArgsRef args = new Args;
517 VMFunction* fn = context->functionProvider->functionByName(name);
518 if (context->userFunctionByName(name)) {
519 PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
520 $$ = new FunctionCall(name, args, NULL);
521 } else if (!fn) {
522 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
523 $$ = new FunctionCall(name, args, NULL);
524 } else if (fn->minRequiredArgs() > 0) {
525 PARSE_ERR(@1, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
526 $$ = new FunctionCall(name, args, NULL);
527 } else {
528 $$ = new FunctionCall(name, args, fn);
529 }
530 }
531
532 args:
533 arg {
534 $$ = new Args();
535 $$->add($1);
536 }
537 | args ',' arg {
538 $$ = $1;
539 $$->add($3);
540 }
541
542 arg:
543 expr
544
545 assignment:
546 VARIABLE ASSIGNMENT expr {
547 //printf("variable lookup with name '%s' as assignment expr\n", $1);
548 const char* name = $1;
549 VariableRef var = context->variableByName(name);
550 if (!var)
551 PARSE_ERR(@1, (String("Variable assignment: No variable declared with name '") + name + "'.").c_str());
552 else if (var->isConstExpr())
553 PARSE_ERR(@2, (String("Variable assignment: Cannot modify const variable '") + name + "'.").c_str());
554 else if (!var->isAssignable())
555 PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
556 else if (var->exprType() != $3->exprType())
557 PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' is of type " + typeStr(var->exprType()) + ", assignment is of type " + typeStr($3->exprType()) + " though.").c_str());
558 $$ = new Assignment(var, $3);
559 }
560 | VARIABLE '[' expr ']' ASSIGNMENT expr {
561 const char* name = $1;
562 VariableRef var = context->variableByName(name);
563 if (!var)
564 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
565 else if (var->exprType() != INT_ARR_EXPR)
566 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
567 else if (var->isConstExpr())
568 PARSE_ERR(@5, (String("Variable assignment: Cannot modify const array variable '") + name + "'.").c_str());
569 else if (!var->isAssignable())
570 PARSE_ERR(@5, (String("Variable assignment: Array variable '") + name + "' is not assignable.").c_str());
571 else if ($3->exprType() != INT_EXPR)
572 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
573 else if ($6->exprType() != INT_EXPR)
574 PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());
575 else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())
576 PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
577 " exceeds size of array variable '" + name +
578 "' which was declared with size " +
579 ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());
580 IntArrayElementRef element = new IntArrayElement(var, $3);
581 $$ = new Assignment(element, $6);
582 }
583
584 unary_expr:
585 INTEGER {
586 $$ = new IntLiteral($1);
587 }
588 | STRING {
589 $$ = new StringLiteral($1);
590 }
591 | VARIABLE {
592 //printf("variable lookup with name '%s' as unary expr\n", $1);
593 VariableRef var = context->variableByName($1);
594 if (var)
595 $$ = var;
596 else {
597 PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
598 $$ = new IntLiteral(0);
599 }
600 }
601 | VARIABLE '[' expr ']' {
602 const char* name = $1;
603 VariableRef var = context->variableByName(name);
604 if (!var) {
605 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
606 $$ = new IntLiteral(0);
607 } else if (var->exprType() != INT_ARR_EXPR) {
608 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
609 $$ = new IntLiteral(0);
610 } else if ($3->exprType() != INT_EXPR) {
611 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
612 $$ = new IntLiteral(0);
613 } else {
614 if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())
615 PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
616 " exceeds size of array variable '" + name +
617 "' which was declared with size " +
618 ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());
619 $$ = new IntArrayElement(var, $3);
620 }
621 }
622 | '(' expr ')' {
623 $$ = $2;
624 }
625 | functioncall {
626 $$ = $1;
627 }
628 | '-' unary_expr {
629 $$ = new Neg($2);
630 }
631 | BITWISE_NOT unary_expr {
632 if ($2->exprType() != INT_EXPR) {
633 PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
634 $$ = new IntLiteral(0);
635 } else {
636 $$ = new BitwiseNot($2);
637 }
638 }
639 | NOT unary_expr {
640 if ($2->exprType() != INT_EXPR) {
641 PARSE_ERR(@2, (String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
642 $$ = new IntLiteral(0);
643 } else {
644 $$ = new Not($2);
645 }
646 }
647
648 expr:
649 concat_expr
650
651 concat_expr:
652 logical_or_expr
653 | concat_expr '&' logical_or_expr {
654 ExpressionRef lhs = $1;
655 ExpressionRef rhs = $3;
656 if (lhs->isConstExpr() && rhs->isConstExpr()) {
657 $$ = new StringLiteral(
658 lhs->evalCastToStr() + rhs->evalCastToStr()
659 );
660 } else {
661 $$ = new ConcatString(lhs, rhs);
662 }
663 }
664
665 logical_or_expr:
666 logical_and_expr
667 | logical_or_expr OR logical_and_expr {
668 ExpressionRef lhs = $1;
669 ExpressionRef rhs = $3;
670 if (lhs->exprType() != INT_EXPR) {
671 PARSE_ERR(@1, (String("Left operand of operator 'or' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
672 $$ = new IntLiteral(0);
673 } else if (rhs->exprType() != INT_EXPR) {
674 PARSE_ERR(@3, (String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
675 $$ = new IntLiteral(0);
676 } else {
677 $$ = new Or(lhs, rhs);
678 }
679 }
680
681 logical_and_expr:
682 bitwise_or_expr {
683 $$ = $1;
684 }
685 | logical_and_expr AND bitwise_or_expr {
686 ExpressionRef lhs = $1;
687 ExpressionRef rhs = $3;
688 if (lhs->exprType() != INT_EXPR) {
689 PARSE_ERR(@1, (String("Left operand of operator 'and' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
690 $$ = new IntLiteral(0);
691 } else if (rhs->exprType() != INT_EXPR) {
692 PARSE_ERR(@3, (String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
693 $$ = new IntLiteral(0);
694 } else {
695 $$ = new And(lhs, rhs);
696 }
697 }
698
699 bitwise_or_expr:
700 bitwise_and_expr
701 | bitwise_or_expr BITWISE_OR bitwise_and_expr {
702 ExpressionRef lhs = $1;
703 ExpressionRef rhs = $3;
704 if (lhs->exprType() != INT_EXPR) {
705 PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
706 $$ = new IntLiteral(0);
707 } else if (rhs->exprType() != INT_EXPR) {
708 PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
709 $$ = new IntLiteral(0);
710 } else {
711 $$ = new BitwiseOr(lhs, rhs);
712 }
713 }
714
715 bitwise_and_expr:
716 rel_expr {
717 $$ = $1;
718 }
719 | bitwise_and_expr BITWISE_AND rel_expr {
720 ExpressionRef lhs = $1;
721 ExpressionRef rhs = $3;
722 if (lhs->exprType() != INT_EXPR) {
723 PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
724 $$ = new IntLiteral(0);
725 } else if (rhs->exprType() != INT_EXPR) {
726 PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
727 $$ = new IntLiteral(0);
728 } else {
729 $$ = new BitwiseAnd(lhs, rhs);
730 }
731 }
732
733 rel_expr:
734 add_expr
735 | rel_expr '<' add_expr {
736 ExpressionRef lhs = $1;
737 ExpressionRef rhs = $3;
738 if (lhs->exprType() != INT_EXPR) {
739 PARSE_ERR(@1, (String("Left operand of operator '<' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
740 $$ = new IntLiteral(0);
741 } else if (rhs->exprType() != INT_EXPR) {
742 PARSE_ERR(@3, (String("Right operand of operator '<' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
743 $$ = new IntLiteral(0);
744 } else {
745 $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
746 }
747 }
748 | rel_expr '>' add_expr {
749 ExpressionRef lhs = $1;
750 ExpressionRef rhs = $3;
751 if (lhs->exprType() != INT_EXPR) {
752 PARSE_ERR(@1, (String("Left operand of operator '>' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
753 $$ = new IntLiteral(0);
754 } else if (rhs->exprType() != INT_EXPR) {
755 PARSE_ERR(@3, (String("Right operand of operator '>' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
756 $$ = new IntLiteral(0);
757 } else {
758 $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
759 }
760 }
761 | rel_expr LE add_expr {
762 ExpressionRef lhs = $1;
763 ExpressionRef rhs = $3;
764 if (lhs->exprType() != INT_EXPR) {
765 PARSE_ERR(@1, (String("Left operand of operator '<=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
766 $$ = new IntLiteral(0);
767 } else if (rhs->exprType() != INT_EXPR) {
768 PARSE_ERR(@3, (String("Right operand of operator '<=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
769 $$ = new IntLiteral(0);
770 } else {
771 $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
772 }
773 }
774 | rel_expr GE add_expr {
775 ExpressionRef lhs = $1;
776 ExpressionRef rhs = $3;
777 if (lhs->exprType() != INT_EXPR) {
778 PARSE_ERR(@1, (String("Left operand of operator '>=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
779 $$ = new IntLiteral(0);
780 } else if (rhs->exprType() != INT_EXPR) {
781 PARSE_ERR(@3, (String("Right operand of operator '>=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
782 $$ = new IntLiteral(0);
783 } else {
784 $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
785 }
786 }
787 | rel_expr '=' add_expr {
788 $$ = new Relation($1, Relation::EQUAL, $3);
789 }
790 | rel_expr '#' add_expr {
791 $$ = new Relation($1, Relation::NOT_EQUAL, $3);
792 }
793
794 add_expr:
795 mul_expr
796 | add_expr '+' mul_expr {
797 ExpressionRef lhs = $1;
798 ExpressionRef rhs = $3;
799 if (lhs->exprType() != INT_EXPR) {
800 PARSE_ERR(@1, (String("Left operand of operator '+' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
801 $$ = new IntLiteral(0);
802 } else if (rhs->exprType() != INT_EXPR) {
803 PARSE_ERR(@3, (String("Right operand of operator '+' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
804 $$ = new IntLiteral(0);
805 } else {
806 $$ = new Add(lhs,rhs);
807 }
808 }
809 | add_expr '-' mul_expr {
810 ExpressionRef lhs = $1;
811 ExpressionRef rhs = $3;
812 if (lhs->exprType() != INT_EXPR) {
813 PARSE_ERR(@1, (String("Left operand of operator '-' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
814 $$ = new IntLiteral(0);
815 } else if (rhs->exprType() != INT_EXPR) {
816 PARSE_ERR(@3, (String("Right operand of operator '-' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
817 $$ = new IntLiteral(0);
818 } else {
819 $$ = new Sub(lhs,rhs);
820 }
821 }
822
823 mul_expr:
824 unary_expr
825 | mul_expr '*' unary_expr {
826 ExpressionRef lhs = $1;
827 ExpressionRef rhs = $3;
828 if (lhs->exprType() != INT_EXPR) {
829 PARSE_ERR(@1, (String("Left operand of operator '*' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
830 $$ = new IntLiteral(0);
831 } else if (rhs->exprType() != INT_EXPR) {
832 PARSE_ERR(@3, (String("Right operand of operator '*' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
833 $$ = new IntLiteral(0);
834 } else {
835 $$ = new Mul(lhs,rhs);
836 }
837 }
838 | mul_expr '/' unary_expr {
839 ExpressionRef lhs = $1;
840 ExpressionRef rhs = $3;
841 if (lhs->exprType() != INT_EXPR) {
842 PARSE_ERR(@1, (String("Left operand of operator '/' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
843 $$ = new IntLiteral(0);
844 } else if (rhs->exprType() != INT_EXPR) {
845 PARSE_ERR(@3, (String("Right operand of operator '/' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
846 $$ = new IntLiteral(0);
847 } else {
848 $$ = new Div(lhs,rhs);
849 }
850 }
851 | mul_expr MOD unary_expr {
852 ExpressionRef lhs = $1;
853 ExpressionRef rhs = $3;
854 if (lhs->exprType() != INT_EXPR) {
855 PARSE_ERR(@1, (String("Left operand of modulo operator must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
856 $$ = new IntLiteral(0);
857 } else if (rhs->exprType() != INT_EXPR) {
858 PARSE_ERR(@3, (String("Right operand of modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
859 $$ = new IntLiteral(0);
860 } else {
861 $$ = new Mod(lhs,rhs);
862 }
863 }
864
865 %%
866
867 void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
868 //fprintf(stderr, "%d: %s\n", locp->first_line, err);
869 context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);
870 }
871
872 void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
873 //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
874 context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
875 }
876
877 /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.
878 int InstrScript_tnamerr(char* yyres, const char* yystr) {
879 if (*yystr == '"') {
880 int yyn = 0;
881 char const *yyp = yystr;
882 for (;;)
883 switch (*++yyp)
884 {
885 /*
886 case '\'':
887 case ',':
888 goto do_not_strip_quotes;
889
890 case '\\':
891 if (*++yyp != '\\')
892 goto do_not_strip_quotes;
893 */
894 /* Fall through. */
895 default:
896 if (yyres)
897 yyres[yyn] = *yyp;
898 yyn++;
899 break;
900
901 case '"':
902 if (yyres)
903 yyres[yyn] = '\0';
904 return yyn;
905 }
906 /*
907 do_not_strip_quotes: ;
908 */
909 }
910
911 if (! yyres)
912 return (int) yystrlen (yystr);
913
914 return int( yystpcpy (yyres, yystr) - yyres );
915 }

  ViewVC Help
Powered by ViewVC