/[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 3259 - (hide annotations) (download)
Wed May 31 14:41:04 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 38270 byte(s)
* NKSP language fix: Unknown characters were not handled correctly.
* Bumped version (2.0.0.svn59).

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

  ViewVC Help
Powered by ViewVC