/[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 2889 - (hide annotations) (download)
Mon Apr 25 17:28:23 2016 UTC (7 years, 11 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 schoenebeck 2581 /*
2 schoenebeck 2888 * Copyright (c) 2014-2016 Christian Schoenebeck and Andreas Persson
3 schoenebeck 2581 *
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 schoenebeck 2888
10     /* Parser for NKSP real-time instrument script language. */
11 schoenebeck 2581
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 schoenebeck 2888 #define PARSE_ERR(loc,txt) yyerror(&loc, context, txt)
24     #define PARSE_WRN(loc,txt) InstrScript_warning(&loc, context, txt)
25 schoenebeck 2581 %}
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 schoenebeck 2585 %token CONTROLLER SELECT CASE TO NOT CONST_ POLYPHONIC MOD
43 schoenebeck 2581 %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 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'note' event handler.");
78 schoenebeck 2581 context->onNote = new OnNote($3);
79     $$ = context->onNote;
80     }
81     | ON INIT statements END ON {
82     if (context->onInit)
83 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'init' event handler.");
84 schoenebeck 2581 context->onInit = new OnInit($3);
85     $$ = context->onInit;
86     }
87     | ON RELEASE statements END ON {
88     if (context->onRelease)
89 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'release' event handler.");
90 schoenebeck 2581 context->onRelease = new OnRelease($3);
91     $$ = context->onRelease;
92     }
93     | ON CONTROLLER statements END ON {
94     if (context->onController)
95 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'controller' event handler.");
96 schoenebeck 2581 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 schoenebeck 2888 PARSE_WRN(@1, "Not a statement.");
107 schoenebeck 2581 }
108     | statements statement {
109     $$ = $1;
110     if ($2) {
111     if (!isNoOperation($2)) $$->add($2); // filter out NoOperation statements
112     } else
113 schoenebeck 2888 PARSE_WRN(@2, "Not a statement.");
114 schoenebeck 2581 }
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 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
125 schoenebeck 2581 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 schoenebeck 2888 PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
138 schoenebeck 2581 if (name[0] != '$') {
139 schoenebeck 2888 PARSE_ERR(@3, "Polyphonic variables may only be declared as integers.");
140 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
151 schoenebeck 2581 if ($4->exprType() == STRING_EXPR) {
152     if (name[0] == '$')
153 schoenebeck 2888 PARSE_WRN(@2, (String("Variable '") + name + "' declared as integer, string expression assigned though.").c_str());
154 schoenebeck 2581 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 schoenebeck 2888 PARSE_WRN(@2, (String("Variable '") + name + "' declared as string, integer expression assigned though.").c_str());
168 schoenebeck 2581 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 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
186 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
187     } else if ($4->exprType() != INT_EXPR) {
188 schoenebeck 2888 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
189 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
190     } else if (context->variableByName(name)) {
191 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
192 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
193     } else {
194     IntExprRef expr = $4;
195     int size = expr->evalInt();
196     if (size <= 0) {
197 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
198 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
209 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
210     } else if ($4->exprType() != INT_EXPR) {
211 schoenebeck 2888 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
212 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
213     } else if (context->variableByName(name)) {
214 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
215 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
222 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
223     } else if (args->argsCount() > size) {
224 schoenebeck 2888 PARSE_ERR(@8, (String("Variable '") + name +
225 schoenebeck 2581 "' 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 schoenebeck 2888 @8,
235 schoenebeck 2581 (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 schoenebeck 2585 | DECLARE CONST_ VARIABLE ASSIGNMENT expr {
251 schoenebeck 2581 const char* name = $3;
252     if ($5->exprType() == STRING_EXPR) {
253     if (name[0] == '$')
254 schoenebeck 2888 PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");
255 schoenebeck 2581 String s;
256     StringExprRef expr = $5;
257     if (expr->isConstExpr())
258     s = expr->evalStr();
259     else
260 schoenebeck 2888 PARSE_ERR(@5, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());
261 schoenebeck 2581 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 schoenebeck 2888 PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");
268 schoenebeck 2581 int i = 0;
269     IntExprRef expr = $5;
270     if (expr->isConstExpr())
271     i = expr->evalInt();
272     else
273 schoenebeck 2888 PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
274 schoenebeck 2581 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 schoenebeck 2888 PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
288 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
302 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
337 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
338     } else if (args->argsCount() < fn->minRequiredArgs()) {
339 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
340 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
341     } else if (args->argsCount() > fn->maxAllowedArgs()) {
342 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' accepts max. " + ToString(fn->maxAllowedArgs()) + " arguments.").c_str());
343 schoenebeck 2581 $$ = 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 schoenebeck 2888 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 schoenebeck 2581 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 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
363 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
364     } else if (fn->minRequiredArgs() > 0) {
365 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
366 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
378 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
379     } else if (fn->minRequiredArgs() > 0) {
380 schoenebeck 2888 PARSE_ERR(@1, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
381 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Variable assignment: No variable declared with name '") + name + "'.").c_str());
407 schoenebeck 2581 else if (var->isConstExpr())
408 schoenebeck 2888 PARSE_ERR(@2, (String("Variable assignment: Cannot modify const variable '") + name + "'.").c_str());
409 schoenebeck 2581 else if (var->exprType() != $3->exprType())
410 schoenebeck 2888 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 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
418 schoenebeck 2581 else if (var->exprType() != INT_ARR_EXPR)
419 schoenebeck 2888 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
420 schoenebeck 2581 else if ($3->exprType() != INT_EXPR)
421 schoenebeck 2888 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
422 schoenebeck 2581 else if ($6->exprType() != INT_EXPR)
423 schoenebeck 2888 PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());
424 schoenebeck 2581 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 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
442 schoenebeck 2581 $$ = new IntLiteral(0);
443     }
444     }
445     | VARIABLE '[' expr ']' {
446     const char* name = $1;
447     VariableRef var = context->variableByName(name);
448     if (!var) {
449 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
450 schoenebeck 2581 $$ = new IntLiteral(0);
451     } else if (var->exprType() != INT_ARR_EXPR) {
452 schoenebeck 2888 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
453 schoenebeck 2581 $$ = new IntLiteral(0);
454     } else if ($3->exprType() != INT_EXPR) {
455 schoenebeck 2888 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
456 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@2, (String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
473 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator 'or' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
503 schoenebeck 2581 $$ = new IntLiteral(0);
504     } else if (rhs->exprType() != INT_EXPR) {
505 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
506 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator 'and' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
521 schoenebeck 2581 $$ = new IntLiteral(0);
522     } else if (rhs->exprType() != INT_EXPR) {
523 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
524 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '<' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
537 schoenebeck 2581 $$ = new IntLiteral(0);
538     } else if (rhs->exprType() != INT_EXPR) {
539 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '<' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
540 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '>' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
550 schoenebeck 2581 $$ = new IntLiteral(0);
551     } else if (rhs->exprType() != INT_EXPR) {
552 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '>' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
553 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '<=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
563 schoenebeck 2581 $$ = new IntLiteral(0);
564     } else if (rhs->exprType() != INT_EXPR) {
565 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '<=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
566 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '>=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
576 schoenebeck 2581 $$ = new IntLiteral(0);
577     } else if (rhs->exprType() != INT_EXPR) {
578 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '>=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
579 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '+' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
598 schoenebeck 2581 $$ = new IntLiteral(0);
599     } else if (rhs->exprType() != INT_EXPR) {
600 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '+' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
601 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '-' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
611 schoenebeck 2581 $$ = new IntLiteral(0);
612     } else if (rhs->exprType() != INT_EXPR) {
613 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '-' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
614 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '*' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
627 schoenebeck 2581 $$ = new IntLiteral(0);
628     } else if (rhs->exprType() != INT_EXPR) {
629 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '*' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
630 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '/' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
640 schoenebeck 2581 $$ = new IntLiteral(0);
641     } else if (rhs->exprType() != INT_EXPR) {
642 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '/' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
643 schoenebeck 2581 $$ = 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 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of modulo operator must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
653 schoenebeck 2581 $$ = new IntLiteral(0);
654     } else if (rhs->exprType() != INT_EXPR) {
655 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
656 schoenebeck 2581 $$ = 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 schoenebeck 2889 context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);
667 schoenebeck 2581 }
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 schoenebeck 2889 context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
672 schoenebeck 2581 }

  ViewVC Help
Powered by ViewVC