/[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 2888 - (show annotations) (download)
Sun Apr 24 18:16:10 2016 UTC (7 years, 11 months ago) by schoenebeck
File size: 27429 byte(s)
* Instrument Scripts: Fixed line numbers on parser error/warning messages.
* Instrument Scripts: Added output of precise column on parser
  error/warning messages.
* Shut up some irrelevant errors of parser generating shell scripts.
* Bumped version (2.0.0.svn6).

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->first_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->first_column+1, txt);
672 }

  ViewVC Help
Powered by ViewVC