/[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 3253 - (hide annotations) (download)
Tue May 30 12:08:45 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 34393 byte(s)
* NKSP: built-in "play_note()" function now accepts -2 for its fourth
  argument (note duration) which means the life time of the note shall
  be sticked to the requested note number of argument 1.
* NKSP Fix: built-in "play_note()" function now returns 0 as result
  value if -1 was passed for its fourth argument (note duration) and
  the respective parent note is already gone.
* NKSP: Built-in array variable %KEY_DOWN[] is now a read-only
  variable.
* Built-in variable $EVENT_NOTE is now a read-only variable.
* Built-in variable $EVENT_VELOCITY is now a read-only variable.
* Bumped version (2.0.0.svn56).

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

  ViewVC Help
Powered by ViewVC