/[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 2889 - (show annotations) (download)
Mon Apr 25 17:28:23 2016 UTC (5 years, 3 months ago) by schoenebeck
File size: 27505 byte(s)
* Added new C++ API class "ScriptVMFactory".
* Instrument Scripts: extended parser issues to provide not only first
  line and first column, but also last line and last column of issue
  (thus marking the precise span of the issue within the source code).
* Bumped version (2.0.0.svn7).

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

  ViewVC Help
Powered by ViewVC