/[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 3260 - (show annotations) (download)
Wed May 31 21:07:44 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 38407 byte(s)
* NKSP language: Added support for "synchronized .. end synchronized"
  code blocks.
* Bumped version (2.0.0.svn60).

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

  ViewVC Help
Powered by ViewVC