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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2581 - (hide annotations) (download)
Fri May 30 12:48:05 2014 UTC (9 years, 10 months ago) by schoenebeck
File size: 27005 byte(s)
* (WIP) Implemented parser and VM for upcoming new real-time instrument
  script support. It needs yet to be integrated into the sampler's
  sampler engines. You can toy around for now with the command line tool
  "ls_instr_script" and i.e. examples showing the core language features
  under src/scriptvm/examples/.
* Bumped version (1.0.0.svn41).

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

  ViewVC Help
Powered by ViewVC