/[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 3013 - (hide annotations) (download)
Sat Oct 15 23:54:27 2016 UTC (7 years, 6 months ago) by schoenebeck
File size: 33954 byte(s)
* NKSP: Fixed NKSP parser warning "Not a statement" when assigning an
  initializer list to an array variable.
* Bumped version (2.0.0.svn27).

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

  ViewVC Help
Powered by ViewVC