/[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 3054 - (hide annotations) (download)
Thu Dec 15 12:47:45 2016 UTC (7 years, 4 months ago) by schoenebeck
File size: 34079 byte(s)
* Fixed numerous compiler warnings.
* Bumped version (2.0.0.svn32).

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

  ViewVC Help
Powered by ViewVC