/[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 3260 - (hide annotations) (download)
Wed May 31 21:07:44 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 38407 byte(s)
* NKSP language: Added support for "synchronized .. end synchronized"
  code blocks.
* Bumped version (2.0.0.svn60).

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

  ViewVC Help
Powered by ViewVC