/[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 3008 - (hide annotations) (download)
Tue Oct 11 18:25:12 2016 UTC (7 years, 6 months ago) by schoenebeck
File size: 33913 byte(s)
* NKSP: Provide more user friendly error messages on syntax errors.
* Bumped version (2.0.0.svn26).

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     if (argsOK)
302     $$ = context->vartable[name] = new IntArrayVariable(context, size, args);
303     else
304     $$ = new FunctionCall("nothing", new Args, NULL); // whatever
305     }
306     }
307     }
308 schoenebeck 2585 | DECLARE CONST_ VARIABLE ASSIGNMENT expr {
309 schoenebeck 2581 const char* name = $3;
310     if ($5->exprType() == STRING_EXPR) {
311     if (name[0] == '$')
312 schoenebeck 2888 PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");
313 schoenebeck 2581 String s;
314     StringExprRef expr = $5;
315     if (expr->isConstExpr())
316     s = expr->evalStr();
317     else
318 schoenebeck 2888 PARSE_ERR(@5, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());
319 schoenebeck 2581 ConstStringVariableRef var = new ConstStringVariable(context, s);
320     context->vartable[name] = var;
321     //$$ = new Assignment(var, new StringLiteral(s));
322     $$ = new NoOperation();
323     } else {
324     if (name[0] == '@')
325 schoenebeck 2888 PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");
326 schoenebeck 2581 int i = 0;
327     IntExprRef expr = $5;
328     if (expr->isConstExpr())
329     i = expr->evalInt();
330     else
331 schoenebeck 2888 PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
332 schoenebeck 2581 ConstIntVariableRef var = new ConstIntVariable(i);
333     context->vartable[name] = var;
334     //$$ = new Assignment(var, new IntLiteral(i));
335     $$ = new NoOperation();
336     }
337     }
338     | assignment {
339     $$ = $1;
340     }
341 schoenebeck 2947 | WHILE '(' expr ')' opt_statements END WHILE {
342 schoenebeck 2581 if ($3->exprType() == INT_EXPR) {
343     $$ = new While($3, $5);
344     } else {
345 schoenebeck 2888 PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
346 schoenebeck 2581 $$ = new While(new IntLiteral(0), $5);
347     }
348     }
349 schoenebeck 2947 | IF '(' expr ')' opt_statements ELSE opt_statements END IF {
350 schoenebeck 2581 $$ = new If($3, $5, $7);
351     }
352 schoenebeck 2947 | IF '(' expr ')' opt_statements END IF {
353 schoenebeck 2581 $$ = new If($3, $5);
354     }
355     | SELECT expr caseclauses END SELECT {
356     if ($2->exprType() == INT_EXPR) {
357     $$ = new SelectCase($2, $3);
358     } else {
359 schoenebeck 2888 PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
360 schoenebeck 2581 $$ = new SelectCase(new IntLiteral(0), $3);
361     }
362     }
363    
364     caseclauses:
365     caseclause {
366     $$ = CaseBranches();
367     $$.push_back($1);
368     }
369     | caseclauses caseclause {
370     $$ = $1;
371     $$.push_back($2);
372     }
373    
374     caseclause:
375 schoenebeck 2947 CASE INTEGER opt_statements {
376 schoenebeck 2581 $$ = CaseBranch();
377     $$.from = new IntLiteral($2);
378     $$.statements = $3;
379     }
380 schoenebeck 2947 | CASE INTEGER TO INTEGER opt_statements {
381 schoenebeck 2581 $$ = CaseBranch();
382     $$.from = new IntLiteral($2);
383     $$.to = new IntLiteral($4);
384     $$.statements = $5;
385     }
386    
387 schoenebeck 2951 userfunctioncall:
388     CALL IDENTIFIER {
389     const char* name = $2;
390     StatementsRef fn = context->userFunctionByName(name);
391     if (context->functionProvider->functionByName(name)) {
392     PARSE_ERR(@1, (String("Keyword 'call' must only be used for user defined functions, not for any built-in function like '") + name + "'.").c_str());
393     $$ = StatementsRef();
394     } else if (!fn) {
395     PARSE_ERR(@2, (String("No user defined function with name '") + name + "'.").c_str());
396     $$ = StatementsRef();
397     } else {
398     $$ = fn;
399     }
400     }
401    
402 schoenebeck 2581 functioncall:
403     IDENTIFIER '(' args ')' {
404     const char* name = $1;
405     //printf("function call of '%s' with args\n", name);
406     ArgsRef args = $3;
407     VMFunction* fn = context->functionProvider->functionByName(name);
408 schoenebeck 2951 if (context->userFunctionByName(name)) {
409     PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
410     $$ = new FunctionCall(name, args, NULL);
411     } else if (!fn) {
412 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
413 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
414     } else if (args->argsCount() < fn->minRequiredArgs()) {
415 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
416 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
417     } else if (args->argsCount() > fn->maxAllowedArgs()) {
418 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' accepts max. " + ToString(fn->maxAllowedArgs()) + " arguments.").c_str());
419 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
420     } else {
421     bool argsOK = true;
422     for (int i = 0; i < args->argsCount(); ++i) {
423     if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {
424 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());
425 schoenebeck 2581 argsOK = false;
426     break;
427 schoenebeck 2945 } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
428     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
429     argsOK = false;
430     break;
431 schoenebeck 2581 }
432     }
433     $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
434     }
435     }
436     | IDENTIFIER '(' ')' {
437     const char* name = $1;
438     //printf("function call of '%s' (with empty args)\n", name);
439     ArgsRef args = new Args;
440     VMFunction* fn = context->functionProvider->functionByName(name);
441 schoenebeck 2951 if (context->userFunctionByName(name)) {
442     PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
443     $$ = new FunctionCall(name, args, NULL);
444     } else if (!fn) {
445 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
446 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
447     } else if (fn->minRequiredArgs() > 0) {
448 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
449 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
450     } else {
451     $$ = new FunctionCall(name, args, fn);
452     }
453     }
454     | IDENTIFIER {
455     const char* name = $1;
456     //printf("function call of '%s' (without args)\n", name);
457     ArgsRef args = new Args;
458     VMFunction* fn = context->functionProvider->functionByName(name);
459 schoenebeck 2951 if (context->userFunctionByName(name)) {
460     PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
461     $$ = new FunctionCall(name, args, NULL);
462     } else if (!fn) {
463 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
464 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
465     } else if (fn->minRequiredArgs() > 0) {
466 schoenebeck 2888 PARSE_ERR(@1, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
467 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
468     } else {
469     $$ = new FunctionCall(name, args, fn);
470     }
471     }
472    
473     args:
474     arg {
475     $$ = new Args();
476     $$->add($1);
477     }
478     | args ',' arg {
479     $$ = $1;
480     $$->add($3);
481     }
482    
483     arg:
484     expr
485    
486     assignment:
487     VARIABLE ASSIGNMENT expr {
488     //printf("variable lookup with name '%s' as assignment expr\n", $1);
489     const char* name = $1;
490     VariableRef var = context->variableByName(name);
491     if (!var)
492 schoenebeck 2888 PARSE_ERR(@1, (String("Variable assignment: No variable declared with name '") + name + "'.").c_str());
493 schoenebeck 2581 else if (var->isConstExpr())
494 schoenebeck 2888 PARSE_ERR(@2, (String("Variable assignment: Cannot modify const variable '") + name + "'.").c_str());
495 schoenebeck 2942 else if (!var->isAssignable())
496     PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
497 schoenebeck 2581 else if (var->exprType() != $3->exprType())
498 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());
499 schoenebeck 2581 $$ = new Assignment(var, $3);
500     }
501     | VARIABLE '[' expr ']' ASSIGNMENT expr {
502     const char* name = $1;
503     VariableRef var = context->variableByName(name);
504     if (!var)
505 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
506 schoenebeck 2581 else if (var->exprType() != INT_ARR_EXPR)
507 schoenebeck 2888 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
508 schoenebeck 2581 else if ($3->exprType() != INT_EXPR)
509 schoenebeck 2888 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
510 schoenebeck 2581 else if ($6->exprType() != INT_EXPR)
511 schoenebeck 2888 PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());
512 schoenebeck 2581 IntArrayElementRef element = new IntArrayElement(var, $3);
513     $$ = new Assignment(element, $6);
514     }
515    
516     unary_expr:
517     INTEGER {
518     $$ = new IntLiteral($1);
519     }
520     | STRING {
521     $$ = new StringLiteral($1);
522     }
523     | VARIABLE {
524     //printf("variable lookup with name '%s' as unary expr\n", $1);
525     VariableRef var = context->variableByName($1);
526     if (var)
527     $$ = var;
528     else {
529 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
530 schoenebeck 2581 $$ = new IntLiteral(0);
531     }
532     }
533     | VARIABLE '[' expr ']' {
534     const char* name = $1;
535     VariableRef var = context->variableByName(name);
536     if (!var) {
537 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
538 schoenebeck 2581 $$ = new IntLiteral(0);
539     } else if (var->exprType() != INT_ARR_EXPR) {
540 schoenebeck 2888 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
541 schoenebeck 2581 $$ = new IntLiteral(0);
542     } else if ($3->exprType() != INT_EXPR) {
543 schoenebeck 2888 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
544 schoenebeck 2581 $$ = new IntLiteral(0);
545     } else {
546     $$ = new IntArrayElement(var, $3);
547     }
548     }
549     | '(' expr ')' {
550     $$ = $2;
551     }
552     | functioncall {
553     $$ = $1;
554     }
555     | '-' unary_expr {
556     $$ = new Neg($2);
557     }
558 schoenebeck 2935 | BITWISE_NOT unary_expr {
559     if ($2->exprType() != INT_EXPR) {
560     PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
561     $$ = new IntLiteral(0);
562     } else {
563     $$ = new BitwiseNot($2);
564     }
565     }
566 schoenebeck 2581 | NOT unary_expr {
567     if ($2->exprType() != INT_EXPR) {
568 schoenebeck 2888 PARSE_ERR(@2, (String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
569 schoenebeck 2581 $$ = new IntLiteral(0);
570     } else {
571     $$ = new Not($2);
572     }
573     }
574    
575     expr:
576     concat_expr
577    
578     concat_expr:
579 schoenebeck 2935 logical_or_expr
580     | concat_expr '&' logical_or_expr {
581 schoenebeck 2581 ExpressionRef lhs = $1;
582     ExpressionRef rhs = $3;
583     if (lhs->isConstExpr() && rhs->isConstExpr()) {
584     $$ = new StringLiteral(
585     lhs->evalCastToStr() + rhs->evalCastToStr()
586     );
587     } else {
588     $$ = new ConcatString(lhs, rhs);
589     }
590     }
591    
592 schoenebeck 2935 logical_or_expr:
593     logical_and_expr
594     | logical_or_expr OR logical_and_expr {
595 schoenebeck 2581 ExpressionRef lhs = $1;
596     ExpressionRef rhs = $3;
597     if (lhs->exprType() != INT_EXPR) {
598 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator 'or' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
599 schoenebeck 2581 $$ = new IntLiteral(0);
600     } else if (rhs->exprType() != INT_EXPR) {
601 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
602 schoenebeck 2581 $$ = new IntLiteral(0);
603     } else {
604     $$ = new Or(lhs, rhs);
605     }
606     }
607    
608 schoenebeck 2935 logical_and_expr:
609     bitwise_or_expr {
610 schoenebeck 2581 $$ = $1;
611     }
612 schoenebeck 2935 | logical_and_expr AND bitwise_or_expr {
613 schoenebeck 2581 ExpressionRef lhs = $1;
614     ExpressionRef rhs = $3;
615     if (lhs->exprType() != INT_EXPR) {
616 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator 'and' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
617 schoenebeck 2581 $$ = new IntLiteral(0);
618     } else if (rhs->exprType() != INT_EXPR) {
619 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
620 schoenebeck 2581 $$ = new IntLiteral(0);
621     } else {
622     $$ = new And(lhs, rhs);
623     }
624     }
625    
626 schoenebeck 2935 bitwise_or_expr:
627     bitwise_and_expr
628     | bitwise_or_expr BITWISE_OR bitwise_and_expr {
629     ExpressionRef lhs = $1;
630     ExpressionRef rhs = $3;
631     if (lhs->exprType() != INT_EXPR) {
632     PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
633     $$ = new IntLiteral(0);
634     } else if (rhs->exprType() != INT_EXPR) {
635     PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
636     $$ = new IntLiteral(0);
637     } else {
638     $$ = new BitwiseOr(lhs, rhs);
639     }
640     }
641    
642     bitwise_and_expr:
643     rel_expr {
644     $$ = $1;
645     }
646     | bitwise_and_expr BITWISE_AND rel_expr {
647     ExpressionRef lhs = $1;
648     ExpressionRef rhs = $3;
649     if (lhs->exprType() != INT_EXPR) {
650     PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
651     $$ = new IntLiteral(0);
652     } else if (rhs->exprType() != INT_EXPR) {
653     PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
654     $$ = new IntLiteral(0);
655     } else {
656     $$ = new BitwiseAnd(lhs, rhs);
657     }
658     }
659    
660 schoenebeck 2581 rel_expr:
661     add_expr
662     | rel_expr '<' add_expr {
663     ExpressionRef lhs = $1;
664     ExpressionRef rhs = $3;
665     if (lhs->exprType() != INT_EXPR) {
666 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '<' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
667 schoenebeck 2581 $$ = new IntLiteral(0);
668     } else if (rhs->exprType() != INT_EXPR) {
669 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '<' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
670 schoenebeck 2581 $$ = new IntLiteral(0);
671     } else {
672     $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
673     }
674     }
675     | rel_expr '>' add_expr {
676     ExpressionRef lhs = $1;
677     ExpressionRef rhs = $3;
678     if (lhs->exprType() != INT_EXPR) {
679 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '>' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
680 schoenebeck 2581 $$ = new IntLiteral(0);
681     } else if (rhs->exprType() != INT_EXPR) {
682 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '>' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
683 schoenebeck 2581 $$ = new IntLiteral(0);
684     } else {
685     $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
686     }
687     }
688     | rel_expr LE add_expr {
689     ExpressionRef lhs = $1;
690     ExpressionRef rhs = $3;
691     if (lhs->exprType() != INT_EXPR) {
692 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '<=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
693 schoenebeck 2581 $$ = new IntLiteral(0);
694     } else if (rhs->exprType() != INT_EXPR) {
695 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '<=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
696 schoenebeck 2581 $$ = new IntLiteral(0);
697     } else {
698     $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
699     }
700     }
701     | rel_expr GE add_expr {
702     ExpressionRef lhs = $1;
703     ExpressionRef rhs = $3;
704     if (lhs->exprType() != INT_EXPR) {
705 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '>=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
706 schoenebeck 2581 $$ = new IntLiteral(0);
707     } else if (rhs->exprType() != INT_EXPR) {
708 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '>=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
709 schoenebeck 2581 $$ = new IntLiteral(0);
710     } else {
711     $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
712     }
713     }
714     | rel_expr '=' add_expr {
715     $$ = new Relation($1, Relation::EQUAL, $3);
716     }
717     | rel_expr '#' add_expr {
718     $$ = new Relation($1, Relation::NOT_EQUAL, $3);
719     }
720    
721     add_expr:
722     mul_expr
723     | add_expr '+' mul_expr {
724     ExpressionRef lhs = $1;
725     ExpressionRef rhs = $3;
726     if (lhs->exprType() != INT_EXPR) {
727 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '+' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
728 schoenebeck 2581 $$ = new IntLiteral(0);
729     } else if (rhs->exprType() != INT_EXPR) {
730 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '+' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
731 schoenebeck 2581 $$ = new IntLiteral(0);
732     } else {
733     $$ = new Add(lhs,rhs);
734     }
735     }
736     | add_expr '-' mul_expr {
737     ExpressionRef lhs = $1;
738     ExpressionRef rhs = $3;
739     if (lhs->exprType() != INT_EXPR) {
740 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '-' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
741 schoenebeck 2581 $$ = new IntLiteral(0);
742     } else if (rhs->exprType() != INT_EXPR) {
743 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '-' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
744 schoenebeck 2581 $$ = new IntLiteral(0);
745     } else {
746     $$ = new Sub(lhs,rhs);
747     }
748     }
749    
750     mul_expr:
751     unary_expr
752     | mul_expr '*' unary_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 Mul(lhs,rhs);
763     }
764     }
765     | mul_expr '/' unary_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 Div(lhs,rhs);
776     }
777     }
778     | mul_expr MOD unary_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 modulo 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 modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
786 schoenebeck 2581 $$ = new IntLiteral(0);
787     } else {
788     $$ = new Mod(lhs,rhs);
789     }
790     }
791    
792     %%
793    
794     void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
795     //fprintf(stderr, "%d: %s\n", locp->first_line, err);
796 schoenebeck 2889 context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);
797 schoenebeck 2581 }
798    
799     void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
800     //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
801 schoenebeck 2889 context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
802 schoenebeck 2581 }
803 schoenebeck 3008
804     /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.
805     int InstrScript_tnamerr(char* yyres, const char* yystr) {
806     if (*yystr == '"') {
807     int yyn = 0;
808     char const *yyp = yystr;
809     for (;;)
810     switch (*++yyp)
811     {
812     /*
813     case '\'':
814     case ',':
815     goto do_not_strip_quotes;
816    
817     case '\\':
818     if (*++yyp != '\\')
819     goto do_not_strip_quotes;
820     */
821     /* Fall through. */
822     default:
823     if (yyres)
824     yyres[yyn] = *yyp;
825     yyn++;
826     break;
827    
828     case '"':
829     if (yyres)
830     yyres[yyn] = '\0';
831     return yyn;
832     }
833     do_not_strip_quotes: ;
834     }
835    
836     if (! yyres)
837     return yystrlen (yystr);
838    
839     return yystpcpy (yyres, yystr) - yyres;
840     }

  ViewVC Help
Powered by ViewVC