/[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 2945 - (show annotations) (download)
Thu Jul 14 00:22:26 2016 UTC (7 years, 8 months ago) by schoenebeck
File size: 30037 byte(s)
* NKSP: Implemented built-in script function "inc()".
* NKSP: Implemented built-in script function "dec()".
* NKSP language fix: division expressions were evaluated too often.
* NKSP language fix: string concatenation operator was right
  associative instead of left (to right).
* Bumped version (2.0.0.svn15).

1 /*
2 * Copyright (c) 2014-2016 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_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);
22 #define scanner context->scanner
23 #define PARSE_ERR(loc,txt) yyerror(&loc, context, txt)
24 #define PARSE_WRN(loc,txt) InstrScript_warning(&loc, context, txt)
25 %}
26
27 // generate reentrant safe parser
28 %pure-parser
29 %parse-param { LinuxSampler::ParserContext* context }
30 %lex-param { void* scanner }
31 // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners
32 %name-prefix "InstrScript_"
33 %locations
34 %defines
35 %error-verbose
36
37 %token <iValue> INTEGER
38 %token <sValue> STRING
39 %token <sValue> IDENTIFIER
40 %token <sValue> VARIABLE
41 %token ON END INIT NOTE DECLARE ASSIGNMENT WHILE IF OR RELEASE AND ELSE
42 %token BITWISE_OR BITWISE_AND BITWISE_NOT
43 %token CONTROLLER SELECT CASE TO NOT CONST_ POLYPHONIC MOD
44 %token LE GE
45
46 %type <nEventHandlers> script eventhandlers
47 %type <nEventHandler> eventhandler
48 %type <nStatements> statements body
49 %type <nStatement> statement assignment
50 %type <nFunctionCall> functioncall
51 %type <nArgs> args
52 %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
53 %type <nCaseBranch> caseclause
54 %type <nCaseBranches> caseclauses
55
56 %start script
57
58 %%
59
60 script:
61 eventhandlers {
62 $$ = context->handlers = $1;
63 }
64
65 eventhandlers:
66 eventhandler {
67 $$ = new EventHandlers();
68 $$->add($1);
69 }
70 | eventhandlers eventhandler {
71 $$ = $1;
72 $$->add($2);
73 }
74
75 eventhandler:
76 ON NOTE body END ON {
77 if (context->onNote)
78 PARSE_ERR(@2, "Redeclaration of 'note' event handler.");
79 context->onNote = new OnNote($3);
80 $$ = context->onNote;
81 }
82 | ON INIT body END ON {
83 if (context->onInit)
84 PARSE_ERR(@2, "Redeclaration of 'init' event handler.");
85 context->onInit = new OnInit($3);
86 $$ = context->onInit;
87 }
88 | ON RELEASE body END ON {
89 if (context->onRelease)
90 PARSE_ERR(@2, "Redeclaration of 'release' event handler.");
91 context->onRelease = new OnRelease($3);
92 $$ = context->onRelease;
93 }
94 | ON CONTROLLER body END ON {
95 if (context->onController)
96 PARSE_ERR(@2, "Redeclaration of 'controller' event handler.");
97 context->onController = new OnController($3);
98 $$ = context->onController;
99 }
100
101 body:
102 /* epsilon (empty argument) */ {
103 $$ = new Statements();
104 }
105 | statements {
106 $$ = $1;
107 }
108
109 statements:
110 statement {
111 $$ = new Statements();
112 if ($1) {
113 if (!isNoOperation($1)) $$->add($1); // filter out NoOperation statements
114 } else
115 PARSE_WRN(@1, "Not a statement.");
116 }
117 | statements statement {
118 $$ = $1;
119 if ($2) {
120 if (!isNoOperation($2)) $$->add($2); // filter out NoOperation statements
121 } else
122 PARSE_WRN(@2, "Not a statement.");
123 }
124
125 statement:
126 functioncall {
127 $$ = $1;
128 }
129 | DECLARE VARIABLE {
130 const char* name = $2;
131 //printf("declared var '%s'\n", name);
132 if (context->variableByName(name))
133 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
134 if (name[0] == '@') {
135 context->vartable[name] = new StringVariable(context);
136 $$ = new NoOperation;
137 } else {
138 context->vartable[name] = new IntVariable(context);
139 $$ = new NoOperation;
140 }
141 }
142 | DECLARE POLYPHONIC VARIABLE {
143 const char* name = $3;
144 //printf("declared polyphonic var '%s'\n", name);
145 if (context->variableByName(name))
146 PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
147 if (name[0] != '$') {
148 PARSE_ERR(@3, "Polyphonic variables may only be declared as integers.");
149 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
150 } else {
151 context->vartable[name] = new PolyphonicIntVariable(context);
152 $$ = new NoOperation;
153 }
154 }
155 | DECLARE VARIABLE ASSIGNMENT expr {
156 const char* name = $2;
157 //printf("declared assign var '%s'\n", name);
158 if (context->variableByName(name))
159 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
160 if ($4->exprType() == STRING_EXPR) {
161 if (name[0] == '$')
162 PARSE_WRN(@2, (String("Variable '") + name + "' declared as integer, string expression assigned though.").c_str());
163 StringExprRef expr = $4;
164 if (expr->isConstExpr()) {
165 const String s = expr->evalStr();
166 StringVariableRef var = new StringVariable(context);
167 context->vartable[name] = var;
168 $$ = new Assignment(var, new StringLiteral(s));
169 } else {
170 StringVariableRef var = new StringVariable(context);
171 context->vartable[name] = var;
172 $$ = new Assignment(var, expr);
173 }
174 } else {
175 if (name[0] == '@')
176 PARSE_WRN(@2, (String("Variable '") + name + "' declared as string, integer expression assigned though.").c_str());
177 IntExprRef expr = $4;
178 if (expr->isConstExpr()) {
179 const int i = expr->evalInt();
180 IntVariableRef var = new IntVariable(context);
181 context->vartable[name] = var;
182 $$ = new Assignment(var, new IntLiteral(i));
183 } else {
184 IntVariableRef var = new IntVariable(context);
185 context->vartable[name] = var;
186 $$ = new Assignment(var, expr);
187 }
188 }
189 }
190 | DECLARE VARIABLE '[' expr ']' {
191 //printf("declare array without args\n");
192 const char* name = $2;
193 if (!$4->isConstExpr()) {
194 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
195 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
196 } else if ($4->exprType() != INT_EXPR) {
197 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
198 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
199 } else if (context->variableByName(name)) {
200 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
201 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
202 } else {
203 IntExprRef expr = $4;
204 int size = expr->evalInt();
205 if (size <= 0) {
206 PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
207 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
208 } else {
209 context->vartable[name] = new IntArrayVariable(context, size);
210 $$ = new NoOperation;
211 }
212 }
213 }
214 | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')' {
215 const char* name = $2;
216 if (!$4->isConstExpr()) {
217 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
218 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
219 } else if ($4->exprType() != INT_EXPR) {
220 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
221 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
222 } else if (context->variableByName(name)) {
223 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
224 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
225 } else {
226 IntExprRef sizeExpr = $4;
227 ArgsRef args = $8;
228 int size = sizeExpr->evalInt();
229 if (size <= 0) {
230 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
231 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
232 } else if (args->argsCount() > size) {
233 PARSE_ERR(@8, (String("Variable '") + name +
234 "' was declared with size " + ToString(size) +
235 " but " + ToString(args->argsCount()) +
236 " values were assigned." ).c_str());
237 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
238 } else {
239 bool argsOK = true;
240 for (int i = 0; i < args->argsCount(); ++i) {
241 if (args->arg(i)->exprType() != INT_EXPR) {
242 PARSE_ERR(
243 @8,
244 (String("Array variable '") + name +
245 "' declared with invalid assignment values. Assigned element " +
246 ToString(i+1) + " is not an integer expression.").c_str()
247 );
248 argsOK = false;
249 break;
250 }
251 }
252 if (argsOK)
253 $$ = context->vartable[name] = new IntArrayVariable(context, size, args);
254 else
255 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
256 }
257 }
258 }
259 | DECLARE CONST_ VARIABLE ASSIGNMENT expr {
260 const char* name = $3;
261 if ($5->exprType() == STRING_EXPR) {
262 if (name[0] == '$')
263 PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");
264 String s;
265 StringExprRef expr = $5;
266 if (expr->isConstExpr())
267 s = expr->evalStr();
268 else
269 PARSE_ERR(@5, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());
270 ConstStringVariableRef var = new ConstStringVariable(context, s);
271 context->vartable[name] = var;
272 //$$ = new Assignment(var, new StringLiteral(s));
273 $$ = new NoOperation();
274 } else {
275 if (name[0] == '@')
276 PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");
277 int i = 0;
278 IntExprRef expr = $5;
279 if (expr->isConstExpr())
280 i = expr->evalInt();
281 else
282 PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
283 ConstIntVariableRef var = new ConstIntVariable(i);
284 context->vartable[name] = var;
285 //$$ = new Assignment(var, new IntLiteral(i));
286 $$ = new NoOperation();
287 }
288 }
289 | assignment {
290 $$ = $1;
291 }
292 | WHILE '(' expr ')' statements END WHILE {
293 if ($3->exprType() == INT_EXPR) {
294 $$ = new While($3, $5);
295 } else {
296 PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
297 $$ = new While(new IntLiteral(0), $5);
298 }
299 }
300 | IF '(' expr ')' statements ELSE statements END IF {
301 $$ = new If($3, $5, $7);
302 }
303 | IF '(' expr ')' statements END IF {
304 $$ = new If($3, $5);
305 }
306 | SELECT expr caseclauses END SELECT {
307 if ($2->exprType() == INT_EXPR) {
308 $$ = new SelectCase($2, $3);
309 } else {
310 PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
311 $$ = new SelectCase(new IntLiteral(0), $3);
312 }
313 }
314
315 caseclauses:
316 caseclause {
317 $$ = CaseBranches();
318 $$.push_back($1);
319 }
320 | caseclauses caseclause {
321 $$ = $1;
322 $$.push_back($2);
323 }
324
325 caseclause:
326 CASE INTEGER statements {
327 $$ = CaseBranch();
328 $$.from = new IntLiteral($2);
329 $$.statements = $3;
330 }
331 | CASE INTEGER TO INTEGER statements {
332 $$ = CaseBranch();
333 $$.from = new IntLiteral($2);
334 $$.to = new IntLiteral($4);
335 $$.statements = $5;
336 }
337
338 functioncall:
339 IDENTIFIER '(' args ')' {
340 const char* name = $1;
341 //printf("function call of '%s' with args\n", name);
342 ArgsRef args = $3;
343 VMFunction* fn = context->functionProvider->functionByName(name);
344 if (!fn) {
345 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
346 $$ = new FunctionCall(name, args, NULL);
347 } else if (args->argsCount() < fn->minRequiredArgs()) {
348 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
349 $$ = new FunctionCall(name, args, NULL);
350 } else if (args->argsCount() > fn->maxAllowedArgs()) {
351 PARSE_ERR(@3, (String("Built-in function '") + name + "' accepts max. " + ToString(fn->maxAllowedArgs()) + " arguments.").c_str());
352 $$ = new FunctionCall(name, args, NULL);
353 } else {
354 bool argsOK = true;
355 for (int i = 0; i < args->argsCount(); ++i) {
356 if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {
357 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());
358 argsOK = false;
359 break;
360 } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
361 PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
362 argsOK = false;
363 break;
364 }
365 }
366 $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
367 }
368 }
369 | IDENTIFIER '(' ')' {
370 const char* name = $1;
371 //printf("function call of '%s' (with empty args)\n", name);
372 ArgsRef args = new Args;
373 VMFunction* fn = context->functionProvider->functionByName(name);
374 if (!fn) {
375 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
376 $$ = new FunctionCall(name, args, NULL);
377 } else if (fn->minRequiredArgs() > 0) {
378 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
379 $$ = new FunctionCall(name, args, NULL);
380 } else {
381 $$ = new FunctionCall(name, args, fn);
382 }
383 }
384 | IDENTIFIER {
385 const char* name = $1;
386 //printf("function call of '%s' (without args)\n", name);
387 ArgsRef args = new Args;
388 VMFunction* fn = context->functionProvider->functionByName(name);
389 if (!fn) {
390 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
391 $$ = new FunctionCall(name, args, NULL);
392 } else if (fn->minRequiredArgs() > 0) {
393 PARSE_ERR(@1, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
394 $$ = new FunctionCall(name, args, NULL);
395 } else {
396 $$ = new FunctionCall(name, args, fn);
397 }
398 }
399
400 args:
401 arg {
402 $$ = new Args();
403 $$->add($1);
404 }
405 | args ',' arg {
406 $$ = $1;
407 $$->add($3);
408 }
409
410 arg:
411 expr
412
413 assignment:
414 VARIABLE ASSIGNMENT expr {
415 //printf("variable lookup with name '%s' as assignment expr\n", $1);
416 const char* name = $1;
417 VariableRef var = context->variableByName(name);
418 if (!var)
419 PARSE_ERR(@1, (String("Variable assignment: No variable declared with name '") + name + "'.").c_str());
420 else if (var->isConstExpr())
421 PARSE_ERR(@2, (String("Variable assignment: Cannot modify const variable '") + name + "'.").c_str());
422 else if (!var->isAssignable())
423 PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
424 else if (var->exprType() != $3->exprType())
425 PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' is of type " + typeStr(var->exprType()) + ", assignment is of type " + typeStr($3->exprType()) + " though.").c_str());
426 $$ = new Assignment(var, $3);
427 }
428 | VARIABLE '[' expr ']' ASSIGNMENT expr {
429 const char* name = $1;
430 VariableRef var = context->variableByName(name);
431 if (!var)
432 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
433 else if (var->exprType() != INT_ARR_EXPR)
434 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
435 else if ($3->exprType() != INT_EXPR)
436 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
437 else if ($6->exprType() != INT_EXPR)
438 PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());
439 IntArrayElementRef element = new IntArrayElement(var, $3);
440 $$ = new Assignment(element, $6);
441 }
442
443 unary_expr:
444 INTEGER {
445 $$ = new IntLiteral($1);
446 }
447 | STRING {
448 $$ = new StringLiteral($1);
449 }
450 | VARIABLE {
451 //printf("variable lookup with name '%s' as unary expr\n", $1);
452 VariableRef var = context->variableByName($1);
453 if (var)
454 $$ = var;
455 else {
456 PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
457 $$ = new IntLiteral(0);
458 }
459 }
460 | VARIABLE '[' expr ']' {
461 const char* name = $1;
462 VariableRef var = context->variableByName(name);
463 if (!var) {
464 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
465 $$ = new IntLiteral(0);
466 } else if (var->exprType() != INT_ARR_EXPR) {
467 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
468 $$ = new IntLiteral(0);
469 } else if ($3->exprType() != INT_EXPR) {
470 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
471 $$ = new IntLiteral(0);
472 } else {
473 $$ = new IntArrayElement(var, $3);
474 }
475 }
476 | '(' expr ')' {
477 $$ = $2;
478 }
479 | functioncall {
480 $$ = $1;
481 }
482 | '-' unary_expr {
483 $$ = new Neg($2);
484 }
485 | BITWISE_NOT unary_expr {
486 if ($2->exprType() != INT_EXPR) {
487 PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
488 $$ = new IntLiteral(0);
489 } else {
490 $$ = new BitwiseNot($2);
491 }
492 }
493 | NOT unary_expr {
494 if ($2->exprType() != INT_EXPR) {
495 PARSE_ERR(@2, (String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
496 $$ = new IntLiteral(0);
497 } else {
498 $$ = new Not($2);
499 }
500 }
501
502 expr:
503 concat_expr
504
505 concat_expr:
506 logical_or_expr
507 | concat_expr '&' logical_or_expr {
508 ExpressionRef lhs = $1;
509 ExpressionRef rhs = $3;
510 if (lhs->isConstExpr() && rhs->isConstExpr()) {
511 $$ = new StringLiteral(
512 lhs->evalCastToStr() + rhs->evalCastToStr()
513 );
514 } else {
515 $$ = new ConcatString(lhs, rhs);
516 }
517 }
518
519 logical_or_expr:
520 logical_and_expr
521 | logical_or_expr OR logical_and_expr {
522 ExpressionRef lhs = $1;
523 ExpressionRef rhs = $3;
524 if (lhs->exprType() != INT_EXPR) {
525 PARSE_ERR(@1, (String("Left operand of operator 'or' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
526 $$ = new IntLiteral(0);
527 } else if (rhs->exprType() != INT_EXPR) {
528 PARSE_ERR(@3, (String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
529 $$ = new IntLiteral(0);
530 } else {
531 $$ = new Or(lhs, rhs);
532 }
533 }
534
535 logical_and_expr:
536 bitwise_or_expr {
537 $$ = $1;
538 }
539 | logical_and_expr AND bitwise_or_expr {
540 ExpressionRef lhs = $1;
541 ExpressionRef rhs = $3;
542 if (lhs->exprType() != INT_EXPR) {
543 PARSE_ERR(@1, (String("Left operand of operator 'and' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
544 $$ = new IntLiteral(0);
545 } else if (rhs->exprType() != INT_EXPR) {
546 PARSE_ERR(@3, (String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
547 $$ = new IntLiteral(0);
548 } else {
549 $$ = new And(lhs, rhs);
550 }
551 }
552
553 bitwise_or_expr:
554 bitwise_and_expr
555 | bitwise_or_expr BITWISE_OR bitwise_and_expr {
556 ExpressionRef lhs = $1;
557 ExpressionRef rhs = $3;
558 if (lhs->exprType() != INT_EXPR) {
559 PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
560 $$ = new IntLiteral(0);
561 } else if (rhs->exprType() != INT_EXPR) {
562 PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
563 $$ = new IntLiteral(0);
564 } else {
565 $$ = new BitwiseOr(lhs, rhs);
566 }
567 }
568
569 bitwise_and_expr:
570 rel_expr {
571 $$ = $1;
572 }
573 | bitwise_and_expr BITWISE_AND rel_expr {
574 ExpressionRef lhs = $1;
575 ExpressionRef rhs = $3;
576 if (lhs->exprType() != INT_EXPR) {
577 PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
578 $$ = new IntLiteral(0);
579 } else if (rhs->exprType() != INT_EXPR) {
580 PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
581 $$ = new IntLiteral(0);
582 } else {
583 $$ = new BitwiseAnd(lhs, rhs);
584 }
585 }
586
587 rel_expr:
588 add_expr
589 | rel_expr '<' add_expr {
590 ExpressionRef lhs = $1;
591 ExpressionRef rhs = $3;
592 if (lhs->exprType() != INT_EXPR) {
593 PARSE_ERR(@1, (String("Left operand of operator '<' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
594 $$ = new IntLiteral(0);
595 } else if (rhs->exprType() != INT_EXPR) {
596 PARSE_ERR(@3, (String("Right operand of operator '<' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
597 $$ = new IntLiteral(0);
598 } else {
599 $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
600 }
601 }
602 | rel_expr '>' add_expr {
603 ExpressionRef lhs = $1;
604 ExpressionRef rhs = $3;
605 if (lhs->exprType() != INT_EXPR) {
606 PARSE_ERR(@1, (String("Left operand of operator '>' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
607 $$ = new IntLiteral(0);
608 } else if (rhs->exprType() != INT_EXPR) {
609 PARSE_ERR(@3, (String("Right operand of operator '>' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
610 $$ = new IntLiteral(0);
611 } else {
612 $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
613 }
614 }
615 | rel_expr LE add_expr {
616 ExpressionRef lhs = $1;
617 ExpressionRef rhs = $3;
618 if (lhs->exprType() != INT_EXPR) {
619 PARSE_ERR(@1, (String("Left operand of operator '<=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
620 $$ = new IntLiteral(0);
621 } else if (rhs->exprType() != INT_EXPR) {
622 PARSE_ERR(@3, (String("Right operand of operator '<=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
623 $$ = new IntLiteral(0);
624 } else {
625 $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
626 }
627 }
628 | rel_expr GE add_expr {
629 ExpressionRef lhs = $1;
630 ExpressionRef rhs = $3;
631 if (lhs->exprType() != INT_EXPR) {
632 PARSE_ERR(@1, (String("Left operand of operator '>=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
633 $$ = new IntLiteral(0);
634 } else if (rhs->exprType() != INT_EXPR) {
635 PARSE_ERR(@3, (String("Right operand of operator '>=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
636 $$ = new IntLiteral(0);
637 } else {
638 $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
639 }
640 }
641 | rel_expr '=' add_expr {
642 $$ = new Relation($1, Relation::EQUAL, $3);
643 }
644 | rel_expr '#' add_expr {
645 $$ = new Relation($1, Relation::NOT_EQUAL, $3);
646 }
647
648 add_expr:
649 mul_expr
650 | add_expr '+' mul_expr {
651 ExpressionRef lhs = $1;
652 ExpressionRef rhs = $3;
653 if (lhs->exprType() != INT_EXPR) {
654 PARSE_ERR(@1, (String("Left operand of operator '+' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
655 $$ = new IntLiteral(0);
656 } else if (rhs->exprType() != INT_EXPR) {
657 PARSE_ERR(@3, (String("Right operand of operator '+' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
658 $$ = new IntLiteral(0);
659 } else {
660 $$ = new Add(lhs,rhs);
661 }
662 }
663 | add_expr '-' mul_expr {
664 ExpressionRef lhs = $1;
665 ExpressionRef rhs = $3;
666 if (lhs->exprType() != INT_EXPR) {
667 PARSE_ERR(@1, (String("Left operand of operator '-' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
668 $$ = new IntLiteral(0);
669 } else if (rhs->exprType() != INT_EXPR) {
670 PARSE_ERR(@3, (String("Right operand of operator '-' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
671 $$ = new IntLiteral(0);
672 } else {
673 $$ = new Sub(lhs,rhs);
674 }
675 }
676
677 mul_expr:
678 unary_expr
679 | mul_expr '*' unary_expr {
680 ExpressionRef lhs = $1;
681 ExpressionRef rhs = $3;
682 if (lhs->exprType() != INT_EXPR) {
683 PARSE_ERR(@1, (String("Left operand of operator '*' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
684 $$ = new IntLiteral(0);
685 } else if (rhs->exprType() != INT_EXPR) {
686 PARSE_ERR(@3, (String("Right operand of operator '*' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
687 $$ = new IntLiteral(0);
688 } else {
689 $$ = new Mul(lhs,rhs);
690 }
691 }
692 | mul_expr '/' unary_expr {
693 ExpressionRef lhs = $1;
694 ExpressionRef rhs = $3;
695 if (lhs->exprType() != INT_EXPR) {
696 PARSE_ERR(@1, (String("Left operand of operator '/' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
697 $$ = new IntLiteral(0);
698 } else if (rhs->exprType() != INT_EXPR) {
699 PARSE_ERR(@3, (String("Right operand of operator '/' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
700 $$ = new IntLiteral(0);
701 } else {
702 $$ = new Div(lhs,rhs);
703 }
704 }
705 | mul_expr MOD unary_expr {
706 ExpressionRef lhs = $1;
707 ExpressionRef rhs = $3;
708 if (lhs->exprType() != INT_EXPR) {
709 PARSE_ERR(@1, (String("Left operand of modulo operator 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 modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
713 $$ = new IntLiteral(0);
714 } else {
715 $$ = new Mod(lhs,rhs);
716 }
717 }
718
719 %%
720
721 void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
722 //fprintf(stderr, "%d: %s\n", locp->first_line, err);
723 context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);
724 }
725
726 void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
727 //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
728 context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
729 }

  ViewVC Help
Powered by ViewVC