/[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 3561 - (hide annotations) (download)
Fri Aug 23 11:44:00 2019 UTC (4 years, 8 months ago) by schoenebeck
File size: 53275 byte(s)
NKSP: Added standard units support for numbers and final "!" operator:

* NKSP strictness: Variable names, function names and preprocessor condition
  names must start with a regular character (a-z or A-Z); starting them with
  a digit or underscore is no longer allowed.

* NKSP parser fix: equal comparison operator "=" and not equal comparison
  operator "#" must only accept integer operands.

* NKSP language: Implemented support for standard units like Hertz, seconds,
  Bel including support for metric unit prefixes; so one can now e.g.
  conveniently use numbers in scripts like "5us" meaning "5 microseconds",
  or e.g. "12kHz" meaning "12 kilo Hertz", or e.g. "-14mdB" meaning
  "minus 14 Millidecibel", or e.g. "28c" meaning "28 cents" (for tuning).

* NKSP language: Introduced "final" operator "!" which is specifically
  intended for synthesis parameter values to denote that the synthesis
  parameter value is intended to be the "final" value for that synthesis
  parameter that should explicitly be used by the engine and thus causing
  the sampler engine to ignore all other modulation sources for the same
  synthesis parameter (like e.g. LFO, EG); by simply prefixing a value,
  variable or formula with this new "!" operator the expression is marked as
  being "final".

* Bumped version (2.1.1.svn4).

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 3311 #define PARSE_DROP(loc) context->addPreprocessorComment(loc.first_line, loc.last_line, loc.first_column+1, loc.last_column+1);
27 schoenebeck 3008 #define yytnamerr(res,str) InstrScript_tnamerr(res, str)
28 schoenebeck 2581 %}
29    
30     // generate reentrant safe parser
31     %pure-parser
32     %parse-param { LinuxSampler::ParserContext* context }
33     %lex-param { void* scanner }
34     // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners
35 schoenebeck 3052 // (NOTE: "=" is deprecated here with Bison 3.x, however removing it would cause an error with Bison 2.x)
36     %name-prefix="InstrScript_"
37 schoenebeck 2581 %locations
38     %defines
39     %error-verbose
40    
41 schoenebeck 3008 %token <iValue> INTEGER "integer literal"
42 schoenebeck 3561 %token <iUnitValue> INTEGER_UNIT "integer literal with unit"
43 schoenebeck 3008 %token <sValue> STRING "string literal"
44     %token <sValue> IDENTIFIER "function name"
45     %token <sValue> VARIABLE "variable name"
46     %token ON "keyword 'on'"
47     %token END "keyword 'end'"
48     %token INIT "keyword 'init'"
49     %token NOTE "keyword 'note'"
50     %token RELEASE "keyword 'release'"
51     %token CONTROLLER "keyword 'controller'"
52     %token DECLARE "keyword 'declare'"
53     %token ASSIGNMENT "operator ':='"
54     %token CONST_ "keyword 'const'"
55     %token POLYPHONIC "keyword 'polyphonic'"
56     %token WHILE "keyword 'while'"
57 schoenebeck 3260 %token SYNCHRONIZED "keyword 'synchronized'"
58 schoenebeck 3008 %token IF "keyword 'if'"
59     %token ELSE "keyword 'else'"
60     %token SELECT "keyword 'select'"
61     %token CASE "keyword 'case'"
62     %token TO "keyword 'to'"
63     %token OR "operator 'or'"
64     %token AND "operator 'and'"
65     %token NOT "operator 'not'"
66     %token BITWISE_OR "bitwise operator '.or.'"
67     %token BITWISE_AND "bitwise operator '.and.'"
68     %token BITWISE_NOT "bitwise operator '.not.'"
69     %token FUNCTION "keyword 'function'"
70     %token CALL "keyword 'call'"
71     %token MOD "operator 'mod'"
72     %token LE "operator '<='"
73     %token GE "operator '>='"
74     %token END_OF_FILE 0 "end of file"
75 schoenebeck 3259 %token UNKNOWN_CHAR "unknown character"
76 schoenebeck 2581
77 schoenebeck 2951 %type <nEventHandlers> script sections
78     %type <nEventHandler> section eventhandler
79     %type <nStatements> statements opt_statements userfunctioncall
80 schoenebeck 2581 %type <nStatement> statement assignment
81     %type <nFunctionCall> functioncall
82     %type <nArgs> args
83 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
84 schoenebeck 2581 %type <nCaseBranch> caseclause
85     %type <nCaseBranches> caseclauses
86    
87     %start script
88    
89     %%
90    
91     script:
92 schoenebeck 2951 sections {
93 schoenebeck 2581 $$ = context->handlers = $1;
94     }
95    
96 schoenebeck 2951 sections:
97     section {
98 schoenebeck 2581 $$ = new EventHandlers();
99 schoenebeck 2951 if ($1) $$->add($1);
100 schoenebeck 2581 }
101 schoenebeck 2951 | sections section {
102 schoenebeck 2581 $$ = $1;
103 schoenebeck 2951 if ($2) $$->add($2);
104 schoenebeck 2581 }
105    
106 schoenebeck 2951 section:
107     function_declaration {
108     $$ = EventHandlerRef();
109     }
110     | eventhandler {
111     $$ = $1;
112     }
113    
114 schoenebeck 2581 eventhandler:
115 schoenebeck 2947 ON NOTE opt_statements END ON {
116 schoenebeck 2581 if (context->onNote)
117 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'note' event handler.");
118 schoenebeck 2581 context->onNote = new OnNote($3);
119     $$ = context->onNote;
120     }
121 schoenebeck 2947 | ON INIT opt_statements END ON {
122 schoenebeck 2581 if (context->onInit)
123 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'init' event handler.");
124 schoenebeck 2581 context->onInit = new OnInit($3);
125     $$ = context->onInit;
126     }
127 schoenebeck 2947 | ON RELEASE opt_statements END ON {
128 schoenebeck 2581 if (context->onRelease)
129 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'release' event handler.");
130 schoenebeck 2581 context->onRelease = new OnRelease($3);
131     $$ = context->onRelease;
132     }
133 schoenebeck 2947 | ON CONTROLLER opt_statements END ON {
134 schoenebeck 2581 if (context->onController)
135 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'controller' event handler.");
136 schoenebeck 2581 context->onController = new OnController($3);
137     $$ = context->onController;
138     }
139    
140 schoenebeck 2951 function_declaration:
141     FUNCTION IDENTIFIER opt_statements END FUNCTION {
142     const char* name = $2;
143     if (context->functionProvider->functionByName(name)) {
144     PARSE_ERR(@2, (String("There is already a built-in function with name '") + name + "'.").c_str());
145     } else if (context->userFunctionByName(name)) {
146     PARSE_ERR(@2, (String("There is already a user defined function with name '") + name + "'.").c_str());
147     } else {
148     context->userFnTable[name] = $3;
149     }
150     }
151    
152 schoenebeck 2947 opt_statements:
153 schoenebeck 2911 /* epsilon (empty argument) */ {
154     $$ = new Statements();
155     }
156     | statements {
157     $$ = $1;
158     }
159    
160 schoenebeck 2581 statements:
161     statement {
162     $$ = new Statements();
163     if ($1) {
164     if (!isNoOperation($1)) $$->add($1); // filter out NoOperation statements
165     } else
166 schoenebeck 2888 PARSE_WRN(@1, "Not a statement.");
167 schoenebeck 2581 }
168     | statements statement {
169     $$ = $1;
170     if ($2) {
171     if (!isNoOperation($2)) $$->add($2); // filter out NoOperation statements
172     } else
173 schoenebeck 2888 PARSE_WRN(@2, "Not a statement.");
174 schoenebeck 2581 }
175    
176     statement:
177     functioncall {
178     $$ = $1;
179     }
180 schoenebeck 2951 | userfunctioncall {
181     $$ = $1;
182     }
183 schoenebeck 2581 | DECLARE VARIABLE {
184     const char* name = $2;
185     //printf("declared var '%s'\n", name);
186     if (context->variableByName(name))
187 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
188 schoenebeck 2581 if (name[0] == '@') {
189     context->vartable[name] = new StringVariable(context);
190     $$ = new NoOperation;
191     } else {
192     context->vartable[name] = new IntVariable(context);
193     $$ = new NoOperation;
194     }
195     }
196     | DECLARE POLYPHONIC VARIABLE {
197     const char* name = $3;
198     //printf("declared polyphonic var '%s'\n", name);
199     if (context->variableByName(name))
200 schoenebeck 2888 PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
201 schoenebeck 2581 if (name[0] != '$') {
202 schoenebeck 2888 PARSE_ERR(@3, "Polyphonic variables may only be declared as integers.");
203 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
204     } else {
205     context->vartable[name] = new PolyphonicIntVariable(context);
206     $$ = new NoOperation;
207     }
208     }
209     | DECLARE VARIABLE ASSIGNMENT expr {
210     const char* name = $2;
211     //printf("declared assign var '%s'\n", name);
212     if (context->variableByName(name))
213 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
214 schoenebeck 2581 if ($4->exprType() == STRING_EXPR) {
215     if (name[0] == '$')
216 schoenebeck 2888 PARSE_WRN(@2, (String("Variable '") + name + "' declared as integer, string expression assigned though.").c_str());
217 schoenebeck 2581 StringExprRef expr = $4;
218     if (expr->isConstExpr()) {
219     const String s = expr->evalStr();
220     StringVariableRef var = new StringVariable(context);
221     context->vartable[name] = var;
222     $$ = new Assignment(var, new StringLiteral(s));
223     } else {
224     StringVariableRef var = new StringVariable(context);
225     context->vartable[name] = var;
226     $$ = new Assignment(var, expr);
227     }
228     } else {
229     if (name[0] == '@')
230 schoenebeck 2888 PARSE_WRN(@2, (String("Variable '") + name + "' declared as string, integer expression assigned though.").c_str());
231 schoenebeck 2581 IntExprRef expr = $4;
232 schoenebeck 3561 IntVariableRef var = new IntVariable(context);
233 schoenebeck 2581 if (expr->isConstExpr()) {
234 schoenebeck 3557 const vmint i = expr->evalInt();
235 schoenebeck 2581 $$ = new Assignment(var, new IntLiteral(i));
236     } else {
237     $$ = new Assignment(var, expr);
238     }
239 schoenebeck 3561 var->copyUnitFrom(expr);
240     var->setFinal(expr->isFinal());
241     context->vartable[name] = var;
242 schoenebeck 2581 }
243     }
244     | DECLARE VARIABLE '[' expr ']' {
245     //printf("declare array without args\n");
246     const char* name = $2;
247     if (!$4->isConstExpr()) {
248 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
249 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
250     } else if ($4->exprType() != INT_EXPR) {
251 schoenebeck 2888 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
252 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
253     } else if (context->variableByName(name)) {
254 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
255 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
256     } else {
257     IntExprRef expr = $4;
258 schoenebeck 3561 if (expr->unitType() || expr->unitPrefix(0)) {
259     PARSE_ERR(@4, "Units are not allowed as array size.");
260 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
261     } else {
262 schoenebeck 3561 if (expr->isFinal())
263     PARSE_WRN(@4, "Final operator '!' is meaningless here.");
264     vmint size = expr->evalInt();
265     if (size <= 0) {
266     PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
267     $$ = new FunctionCall("nothing", new Args, NULL); // whatever
268     } else {
269     context->vartable[name] = new IntArrayVariable(context, size);
270     $$ = new NoOperation;
271     }
272 schoenebeck 2581 }
273     }
274     }
275     | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')' {
276     const char* name = $2;
277     if (!$4->isConstExpr()) {
278 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
279 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
280     } else if ($4->exprType() != INT_EXPR) {
281 schoenebeck 2888 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
282 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
283     } else if (context->variableByName(name)) {
284 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
285 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
286     } else {
287     IntExprRef sizeExpr = $4;
288     ArgsRef args = $8;
289 schoenebeck 3557 vmint size = sizeExpr->evalInt();
290 schoenebeck 2581 if (size <= 0) {
291 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
292 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
293     } else if (args->argsCount() > size) {
294 schoenebeck 3257 PARSE_ERR(@8, (String("Array variable '") + name +
295 schoenebeck 2581 "' was declared with size " + ToString(size) +
296     " but " + ToString(args->argsCount()) +
297     " values were assigned." ).c_str());
298 schoenebeck 3561 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
299     } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {
300     PARSE_ERR(@4, "Units are not allowed as array size.");
301     $$ = new FunctionCall("nothing", new Args, NULL); // whatever
302 schoenebeck 2581 } else {
303 schoenebeck 3561 if (sizeExpr->isFinal())
304     PARSE_WRN(@4, "Final operator '!' is meaningless here.");
305 schoenebeck 2581 bool argsOK = true;
306 schoenebeck 3557 for (vmint i = 0; i < args->argsCount(); ++i) {
307 schoenebeck 2581 if (args->arg(i)->exprType() != INT_EXPR) {
308     PARSE_ERR(
309 schoenebeck 2888 @8,
310 schoenebeck 2581 (String("Array variable '") + name +
311     "' declared with invalid assignment values. Assigned element " +
312     ToString(i+1) + " is not an integer expression.").c_str()
313     );
314     argsOK = false;
315     break;
316 schoenebeck 3561 } else if (args->arg(i)->asInt()->unitType() ||
317     args->arg(i)->asInt()->unitPrefix(0))
318     {
319     PARSE_ERR(
320     @8,
321     (String("Array variable '") + name +
322     "' declared with invalid assignment values. Assigned element " +
323     ToString(i+1) + " contains a unit.").c_str()
324     );
325     argsOK = false;
326     break;
327 schoenebeck 2581 }
328     }
329 schoenebeck 3013 if (argsOK) {
330     context->vartable[name] = new IntArrayVariable(context, size, args);
331     $$ = new NoOperation;
332     } else
333 schoenebeck 2581 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
334     }
335     }
336     }
337 schoenebeck 3257 | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')' {
338     const char* name = $3;
339     if (!$5->isConstExpr()) {
340     PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
341     $$ = new FunctionCall("nothing", new Args, NULL); // whatever
342     } else if ($5->exprType() != INT_EXPR) {
343     PARSE_ERR(@5, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
344     $$ = new FunctionCall("nothing", new Args, NULL); // whatever
345     } else if (context->variableByName(name)) {
346     PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
347     $$ = new FunctionCall("nothing", new Args, NULL); // whatever
348     } else {
349     IntExprRef sizeExpr = $5;
350     ArgsRef args = $9;
351 schoenebeck 3557 vmint size = sizeExpr->evalInt();
352 schoenebeck 3257 if (size <= 0) {
353     PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
354     $$ = new FunctionCall("nothing", new Args, NULL); // whatever
355     } else if (args->argsCount() > size) {
356     PARSE_ERR(@9, (String("Array variable '") + name +
357     "' was declared with size " + ToString(size) +
358     " but " + ToString(args->argsCount()) +
359     " values were assigned." ).c_str());
360 schoenebeck 3561 $$ = new FunctionCall("nothing", new Args, NULL); // whatever
361     } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {
362     PARSE_ERR(@5, "Units are not allowed as array size.");
363     $$ = new FunctionCall("nothing", new Args, NULL); // whatever
364 schoenebeck 3257 } else {
365 schoenebeck 3561 if (sizeExpr->isFinal())
366     PARSE_WRN(@5, "Final operator '!' is meaningless here.");
367 schoenebeck 3257 bool argsOK = true;
368 schoenebeck 3557 for (vmint i = 0; i < args->argsCount(); ++i) {
369 schoenebeck 3257 if (args->arg(i)->exprType() != INT_EXPR) {
370     PARSE_ERR(
371     @9,
372     (String("Array variable '") + name +
373     "' declared with invalid assignment values. Assigned element " +
374     ToString(i+1) + " is not an integer expression.").c_str()
375     );
376     argsOK = false;
377     break;
378     }
379     if (!args->arg(i)->isConstExpr()) {
380     PARSE_ERR(
381     @9,
382     (String("const array variable '") + name +
383     "' must be defined with const values. Assigned element " +
384     ToString(i+1) + " is not a const expression though.").c_str()
385     );
386     argsOK = false;
387     break;
388 schoenebeck 3561 } else if (args->arg(i)->asInt()->unitType() ||
389     args->arg(i)->asInt()->unitPrefix(0))
390     {
391     PARSE_ERR(
392     @9,
393     (String("const array variable '") + name +
394     "' declared with invalid assignment values. Assigned element " +
395     ToString(i+1) + " contains a unit.").c_str()
396     );
397     argsOK = false;
398     break;
399 schoenebeck 3257 }
400     }
401     if (argsOK) {
402     context->vartable[name] = new IntArrayVariable(context, size, args, true);
403     $$ = new NoOperation;
404     } else
405     $$ = new FunctionCall("nothing", new Args, NULL); // whatever
406     }
407     }
408     }
409 schoenebeck 2585 | DECLARE CONST_ VARIABLE ASSIGNMENT expr {
410 schoenebeck 2581 const char* name = $3;
411     if ($5->exprType() == STRING_EXPR) {
412     if (name[0] == '$')
413 schoenebeck 2888 PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");
414 schoenebeck 2581 String s;
415     StringExprRef expr = $5;
416     if (expr->isConstExpr())
417     s = expr->evalStr();
418     else
419 schoenebeck 2888 PARSE_ERR(@5, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());
420 schoenebeck 2581 ConstStringVariableRef var = new ConstStringVariable(context, s);
421     context->vartable[name] = var;
422     //$$ = new Assignment(var, new StringLiteral(s));
423     $$ = new NoOperation();
424     } else {
425     if (name[0] == '@')
426 schoenebeck 2888 PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");
427 schoenebeck 3557 vmint i = 0;
428 schoenebeck 2581 IntExprRef expr = $5;
429     if (expr->isConstExpr())
430     i = expr->evalInt();
431     else
432 schoenebeck 2888 PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
433 schoenebeck 2581 ConstIntVariableRef var = new ConstIntVariable(i);
434 schoenebeck 3561 var->copyUnitFrom(expr);
435     var->setFinal(expr->isFinal());
436 schoenebeck 2581 context->vartable[name] = var;
437     //$$ = new Assignment(var, new IntLiteral(i));
438     $$ = new NoOperation();
439     }
440     }
441     | assignment {
442     $$ = $1;
443     }
444 schoenebeck 2947 | WHILE '(' expr ')' opt_statements END WHILE {
445 schoenebeck 2581 if ($3->exprType() == INT_EXPR) {
446 schoenebeck 3561 IntExprRef expr = $3;
447     if (expr->isFinal() && expr->isConstExpr())
448     PARSE_WRN(@3, "Final operator '!' is meaningless here.");
449     $$ = new While(expr, $5);
450 schoenebeck 2581 } else {
451 schoenebeck 2888 PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
452 schoenebeck 2581 $$ = new While(new IntLiteral(0), $5);
453     }
454     }
455 schoenebeck 3260 | SYNCHRONIZED opt_statements END SYNCHRONIZED {
456     $$ = new SyncBlock($2);
457     }
458 schoenebeck 2947 | IF '(' expr ')' opt_statements ELSE opt_statements END IF {
459 schoenebeck 3561 if ($3->exprType() == INT_EXPR) {
460     IntExprRef expr = $3;
461     if (expr->isFinal() && expr->isConstExpr())
462     PARSE_WRN(@3, "Final operator '!' is meaningless here.");
463     $$ = new If($3, $5, $7);
464     } else {
465     PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
466     $$ = new If(new IntLiteral(0), $5, $7);
467     }
468 schoenebeck 2581 }
469 schoenebeck 2947 | IF '(' expr ')' opt_statements END IF {
470 schoenebeck 3561 if ($3->exprType() == INT_EXPR) {
471     IntExprRef expr = $3;
472     if (expr->isFinal() && expr->isConstExpr())
473     PARSE_WRN(@3, "Final operator '!' is meaningless here.");
474     $$ = new If($3, $5);
475     } else {
476     PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
477     $$ = new If(new IntLiteral(0), $5);
478     }
479 schoenebeck 2581 }
480     | SELECT expr caseclauses END SELECT {
481     if ($2->exprType() == INT_EXPR) {
482 schoenebeck 3561 IntExprRef expr = $2;
483     if (expr->unitType() || expr->unitPrefix(0)) {
484     PARSE_ERR(@2, "Units are not allowed here.");
485     } else {
486     if (expr->isFinal() && expr->isConstExpr())
487     PARSE_WRN(@2, "Final operator '!' is meaningless here.");
488     $$ = new SelectCase(expr, $3);
489     }
490 schoenebeck 2581 } else {
491 schoenebeck 2888 PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
492 schoenebeck 2581 $$ = new SelectCase(new IntLiteral(0), $3);
493     }
494     }
495    
496     caseclauses:
497     caseclause {
498     $$ = CaseBranches();
499     $$.push_back($1);
500     }
501     | caseclauses caseclause {
502     $$ = $1;
503     $$.push_back($2);
504     }
505    
506     caseclause:
507 schoenebeck 2947 CASE INTEGER opt_statements {
508 schoenebeck 2581 $$ = CaseBranch();
509     $$.from = new IntLiteral($2);
510     $$.statements = $3;
511     }
512 schoenebeck 2947 | CASE INTEGER TO INTEGER opt_statements {
513 schoenebeck 2581 $$ = CaseBranch();
514     $$.from = new IntLiteral($2);
515     $$.to = new IntLiteral($4);
516     $$.statements = $5;
517     }
518    
519 schoenebeck 2951 userfunctioncall:
520     CALL IDENTIFIER {
521     const char* name = $2;
522     StatementsRef fn = context->userFunctionByName(name);
523     if (context->functionProvider->functionByName(name)) {
524     PARSE_ERR(@1, (String("Keyword 'call' must only be used for user defined functions, not for any built-in function like '") + name + "'.").c_str());
525     $$ = StatementsRef();
526     } else if (!fn) {
527     PARSE_ERR(@2, (String("No user defined function with name '") + name + "'.").c_str());
528     $$ = StatementsRef();
529     } else {
530     $$ = fn;
531     }
532     }
533    
534 schoenebeck 2581 functioncall:
535     IDENTIFIER '(' args ')' {
536     const char* name = $1;
537     //printf("function call of '%s' with args\n", name);
538     ArgsRef args = $3;
539     VMFunction* fn = context->functionProvider->functionByName(name);
540 schoenebeck 2951 if (context->userFunctionByName(name)) {
541     PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
542     $$ = new FunctionCall(name, args, NULL);
543     } else if (!fn) {
544 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
545 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
546 schoenebeck 3311 } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
547     PARSE_DROP(@$);
548     $$ = new NoFunctionCall;
549 schoenebeck 2581 } else if (args->argsCount() < fn->minRequiredArgs()) {
550 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
551 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
552     } else if (args->argsCount() > fn->maxAllowedArgs()) {
553 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' accepts max. " + ToString(fn->maxAllowedArgs()) + " arguments.").c_str());
554 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
555     } else {
556     bool argsOK = true;
557 schoenebeck 3557 for (vmint i = 0; i < args->argsCount(); ++i) {
558 schoenebeck 2581 if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {
559 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());
560 schoenebeck 2581 argsOK = false;
561     break;
562 schoenebeck 2945 } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
563     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
564     argsOK = false;
565     break;
566 schoenebeck 3561 } else if (args->arg(i)->exprType() == INT_EXPR && !fn->acceptsArgUnitType(i, args->arg(i)->asInt()->unitType())) {
567     if (args->arg(i)->asInt()->unitType())
568     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect unit " + unitTypeStr(args->arg(i)->asInt()->unitType()) + ".").c_str());
569     else
570     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects a unit.").c_str());
571     argsOK = false;
572     break;
573     } else if (!fn->acceptsArgUnitPrefix(i) && args->arg(i)->exprType() == INT_EXPR && args->arg(i)->asInt()->unitPrefix(0)) {
574     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix.").c_str());
575     argsOK = false;
576     break;
577     } else if (!fn->acceptsArgFinal(i) && args->arg(i)->exprType() == INT_EXPR && args->arg(i)->asInt()->isFinal()) {
578     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a \"final\" value.").c_str());
579     argsOK = false;
580     break;
581 schoenebeck 2581 }
582     }
583     $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
584     }
585     }
586     | IDENTIFIER '(' ')' {
587     const char* name = $1;
588     //printf("function call of '%s' (with empty args)\n", name);
589     ArgsRef args = new Args;
590     VMFunction* fn = context->functionProvider->functionByName(name);
591 schoenebeck 2951 if (context->userFunctionByName(name)) {
592     PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
593     $$ = new FunctionCall(name, args, NULL);
594     } else if (!fn) {
595 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
596 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
597 schoenebeck 3311 } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
598     PARSE_DROP(@$);
599     $$ = new NoFunctionCall;
600 schoenebeck 2581 } else if (fn->minRequiredArgs() > 0) {
601 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
602 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
603     } else {
604     $$ = new FunctionCall(name, args, fn);
605     }
606     }
607     | IDENTIFIER {
608     const char* name = $1;
609     //printf("function call of '%s' (without args)\n", name);
610     ArgsRef args = new Args;
611     VMFunction* fn = context->functionProvider->functionByName(name);
612 schoenebeck 2951 if (context->userFunctionByName(name)) {
613     PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
614     $$ = new FunctionCall(name, args, NULL);
615     } else if (!fn) {
616 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
617 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
618 schoenebeck 3311 } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
619     PARSE_DROP(@$);
620     $$ = new NoFunctionCall;
621 schoenebeck 2581 } else if (fn->minRequiredArgs() > 0) {
622 schoenebeck 2888 PARSE_ERR(@1, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
623 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
624     } else {
625     $$ = new FunctionCall(name, args, fn);
626     }
627     }
628    
629     args:
630     arg {
631     $$ = new Args();
632     $$->add($1);
633     }
634     | args ',' arg {
635     $$ = $1;
636     $$->add($3);
637     }
638    
639     arg:
640     expr
641    
642     assignment:
643     VARIABLE ASSIGNMENT expr {
644     //printf("variable lookup with name '%s' as assignment expr\n", $1);
645     const char* name = $1;
646     VariableRef var = context->variableByName(name);
647     if (!var)
648 schoenebeck 2888 PARSE_ERR(@1, (String("Variable assignment: No variable declared with name '") + name + "'.").c_str());
649 schoenebeck 2581 else if (var->isConstExpr())
650 schoenebeck 2888 PARSE_ERR(@2, (String("Variable assignment: Cannot modify const variable '") + name + "'.").c_str());
651 schoenebeck 2942 else if (!var->isAssignable())
652     PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
653 schoenebeck 2581 else if (var->exprType() != $3->exprType())
654 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());
655 schoenebeck 3561 else if (var->exprType() == INT_EXPR) {
656     IntVariableRef intVar = var;
657     IntExprRef expr = $3;
658     if (intVar->unitType() != expr->unitType())
659     PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has unit type " + unitTypeStr(intVar->unitType()) + ", assignment has unit type " + unitTypeStr(expr->unitType()) + " though.").c_str());
660     else if (intVar->unitFactor() != expr->unitFactor())
661     PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has a different unit prefix.").c_str());
662     else if (intVar->isFinal() != expr->isFinal())
663     PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' was declared as " + String(intVar->isFinal() ? "final" : "not final") + ", assignment is " + String(expr->isFinal() ? "final" : "not final") + " though.").c_str());
664     }
665 schoenebeck 2581 $$ = new Assignment(var, $3);
666     }
667     | VARIABLE '[' expr ']' ASSIGNMENT expr {
668     const char* name = $1;
669     VariableRef var = context->variableByName(name);
670     if (!var)
671 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
672 schoenebeck 2581 else if (var->exprType() != INT_ARR_EXPR)
673 schoenebeck 2888 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
674 schoenebeck 3253 else if (var->isConstExpr())
675     PARSE_ERR(@5, (String("Variable assignment: Cannot modify const array variable '") + name + "'.").c_str());
676     else if (!var->isAssignable())
677     PARSE_ERR(@5, (String("Variable assignment: Array variable '") + name + "' is not assignable.").c_str());
678 schoenebeck 2581 else if ($3->exprType() != INT_EXPR)
679 schoenebeck 2888 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
680 schoenebeck 3561 else if ($3->asInt()->unitType())
681     PARSE_ERR(@3, "Unit types are not allowed as array index.");
682 schoenebeck 2581 else if ($6->exprType() != INT_EXPR)
683 schoenebeck 2888 PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());
684 schoenebeck 3561 else if ($6->asInt()->unitType())
685     PARSE_ERR(@6, "Unit types are not allowed for array variables.");
686     else if ($6->asInt()->isFinal())
687     PARSE_ERR(@6, "Final operator '!' not allowed for array variables.");
688 schoenebeck 3257 else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())
689     PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
690     " exceeds size of array variable '" + name +
691     "' which was declared with size " +
692     ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());
693 schoenebeck 3561 else if ($3->asInt()->isFinal())
694     PARSE_WRN(@3, "Final operator '!' is meaningless here.");
695 schoenebeck 2581 IntArrayElementRef element = new IntArrayElement(var, $3);
696     $$ = new Assignment(element, $6);
697     }
698    
699     unary_expr:
700     INTEGER {
701     $$ = new IntLiteral($1);
702     }
703 schoenebeck 3561 | INTEGER_UNIT {
704     IntLiteralRef literal = new IntLiteral($1.iValue);
705     literal->setUnit($1.prefix, $1.unit);
706     $$ = literal;
707     }
708 schoenebeck 2581 | STRING {
709     $$ = new StringLiteral($1);
710     }
711     | VARIABLE {
712     //printf("variable lookup with name '%s' as unary expr\n", $1);
713     VariableRef var = context->variableByName($1);
714     if (var)
715     $$ = var;
716     else {
717 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
718 schoenebeck 2581 $$ = new IntLiteral(0);
719     }
720     }
721     | VARIABLE '[' expr ']' {
722     const char* name = $1;
723     VariableRef var = context->variableByName(name);
724     if (!var) {
725 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
726 schoenebeck 2581 $$ = new IntLiteral(0);
727     } else if (var->exprType() != INT_ARR_EXPR) {
728 schoenebeck 2888 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
729 schoenebeck 2581 $$ = new IntLiteral(0);
730     } else if ($3->exprType() != INT_EXPR) {
731 schoenebeck 2888 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
732 schoenebeck 2581 $$ = new IntLiteral(0);
733 schoenebeck 3561 } else if ($3->asInt()->unitType() || $3->asInt()->unitPrefix(0)) {
734     PARSE_ERR(@3, "Units are not allowed as array index.");
735     $$ = new IntLiteral(0);
736 schoenebeck 2581 } else {
737 schoenebeck 3257 if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((IntArrayVariableRef)var)->arraySize())
738     PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
739     " exceeds size of array variable '" + name +
740     "' which was declared with size " +
741     ToString(((IntArrayVariableRef)var)->arraySize()) + ".").c_str());
742 schoenebeck 3561 else if ($3->asInt()->isFinal())
743     PARSE_WRN(@3, "Final operator '!' is meaningless here.");
744 schoenebeck 2581 $$ = new IntArrayElement(var, $3);
745     }
746     }
747     | '(' expr ')' {
748     $$ = $2;
749     }
750     | functioncall {
751     $$ = $1;
752     }
753     | '-' unary_expr {
754     $$ = new Neg($2);
755     }
756 schoenebeck 2935 | BITWISE_NOT unary_expr {
757     if ($2->exprType() != INT_EXPR) {
758     PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
759     $$ = new IntLiteral(0);
760 schoenebeck 3561 } else if ($2->asInt()->unitType() || $2->asInt()->unitPrefix(0)) {
761     PARSE_ERR(@2, "Units are not allowed for operands of bitwise operations.");
762     $$ = new IntLiteral(0);
763 schoenebeck 2935 } else {
764     $$ = new BitwiseNot($2);
765     }
766     }
767 schoenebeck 2581 | NOT unary_expr {
768     if ($2->exprType() != INT_EXPR) {
769 schoenebeck 2888 PARSE_ERR(@2, (String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
770 schoenebeck 2581 $$ = new IntLiteral(0);
771 schoenebeck 3561 } else if ($2->asInt()->unitType() || $2->asInt()->unitPrefix(0)) {
772     PARSE_ERR(@2, "Units are not allowed for operands of logical operations.");
773     $$ = new IntLiteral(0);
774 schoenebeck 2581 } else {
775     $$ = new Not($2);
776     }
777     }
778 schoenebeck 3561 | '!' unary_expr {
779     if ($2->exprType() != INT_EXPR) {
780     PARSE_ERR(@2, (String("Right operand of \"final\" operator '!' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
781     $$ = new IntLiteral(0);
782     } else {
783     $$ = new Final($2);
784     }
785     }
786 schoenebeck 2581
787     expr:
788     concat_expr
789    
790     concat_expr:
791 schoenebeck 2935 logical_or_expr
792     | concat_expr '&' logical_or_expr {
793 schoenebeck 2581 ExpressionRef lhs = $1;
794     ExpressionRef rhs = $3;
795     if (lhs->isConstExpr() && rhs->isConstExpr()) {
796     $$ = new StringLiteral(
797     lhs->evalCastToStr() + rhs->evalCastToStr()
798     );
799     } else {
800     $$ = new ConcatString(lhs, rhs);
801     }
802     }
803    
804 schoenebeck 2935 logical_or_expr:
805     logical_and_expr
806     | logical_or_expr OR logical_and_expr {
807 schoenebeck 2581 ExpressionRef lhs = $1;
808     ExpressionRef rhs = $3;
809     if (lhs->exprType() != INT_EXPR) {
810 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator 'or' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
811 schoenebeck 2581 $$ = new IntLiteral(0);
812     } else if (rhs->exprType() != INT_EXPR) {
813 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
814 schoenebeck 2581 $$ = new IntLiteral(0);
815 schoenebeck 3561 } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
816     PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
817     $$ = new IntLiteral(0);
818     } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
819     PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
820     $$ = new IntLiteral(0);
821 schoenebeck 2581 } else {
822     $$ = new Or(lhs, rhs);
823     }
824     }
825    
826 schoenebeck 2935 logical_and_expr:
827     bitwise_or_expr {
828 schoenebeck 2581 $$ = $1;
829     }
830 schoenebeck 2935 | logical_and_expr AND bitwise_or_expr {
831 schoenebeck 2581 ExpressionRef lhs = $1;
832     ExpressionRef rhs = $3;
833     if (lhs->exprType() != INT_EXPR) {
834 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator 'and' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
835 schoenebeck 2581 $$ = new IntLiteral(0);
836     } else if (rhs->exprType() != INT_EXPR) {
837 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
838 schoenebeck 2581 $$ = new IntLiteral(0);
839 schoenebeck 3561 } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
840     PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
841     $$ = new IntLiteral(0);
842     } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
843     PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
844     $$ = new IntLiteral(0);
845 schoenebeck 2581 } else {
846     $$ = new And(lhs, rhs);
847     }
848     }
849    
850 schoenebeck 2935 bitwise_or_expr:
851     bitwise_and_expr
852     | bitwise_or_expr BITWISE_OR bitwise_and_expr {
853     ExpressionRef lhs = $1;
854     ExpressionRef rhs = $3;
855     if (lhs->exprType() != INT_EXPR) {
856     PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
857     $$ = new IntLiteral(0);
858     } else if (rhs->exprType() != INT_EXPR) {
859     PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
860     $$ = new IntLiteral(0);
861 schoenebeck 3561 } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
862     PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
863     $$ = new IntLiteral(0);
864     } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
865     PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
866     $$ = new IntLiteral(0);
867 schoenebeck 2935 } else {
868     $$ = new BitwiseOr(lhs, rhs);
869     }
870     }
871    
872     bitwise_and_expr:
873     rel_expr {
874     $$ = $1;
875     }
876     | bitwise_and_expr BITWISE_AND rel_expr {
877     ExpressionRef lhs = $1;
878     ExpressionRef rhs = $3;
879     if (lhs->exprType() != INT_EXPR) {
880     PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
881     $$ = new IntLiteral(0);
882     } else if (rhs->exprType() != INT_EXPR) {
883     PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
884     $$ = new IntLiteral(0);
885 schoenebeck 3561 } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
886     PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
887     $$ = new IntLiteral(0);
888     } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
889     PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
890     $$ = new IntLiteral(0);
891 schoenebeck 2935 } else {
892     $$ = new BitwiseAnd(lhs, rhs);
893     }
894     }
895    
896 schoenebeck 2581 rel_expr:
897     add_expr
898     | rel_expr '<' add_expr {
899     ExpressionRef lhs = $1;
900     ExpressionRef rhs = $3;
901     if (lhs->exprType() != INT_EXPR) {
902 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '<' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
903 schoenebeck 2581 $$ = new IntLiteral(0);
904     } else if (rhs->exprType() != INT_EXPR) {
905 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '<' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
906 schoenebeck 2581 $$ = new IntLiteral(0);
907 schoenebeck 3561 } else if (lhs->asInt()->unitType() != rhs->asInt()->unitType() ||
908     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
909     {
910     PARSE_ERR(@2, "Operands of relative operations must have same unit.");
911     $$ = new IntLiteral(0);
912 schoenebeck 2581 } else {
913     $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
914     }
915     }
916     | rel_expr '>' add_expr {
917     ExpressionRef lhs = $1;
918     ExpressionRef rhs = $3;
919     if (lhs->exprType() != INT_EXPR) {
920 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '>' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
921 schoenebeck 2581 $$ = new IntLiteral(0);
922     } else if (rhs->exprType() != INT_EXPR) {
923 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '>' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
924 schoenebeck 2581 $$ = new IntLiteral(0);
925 schoenebeck 3561 } else if (lhs->asInt()->unitType() != rhs->asInt()->unitType() ||
926     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
927     {
928     PARSE_ERR(@2, "Operands of relative operations must have same unit.");
929     $$ = new IntLiteral(0);
930 schoenebeck 2581 } else {
931     $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
932     }
933     }
934     | rel_expr LE add_expr {
935     ExpressionRef lhs = $1;
936     ExpressionRef rhs = $3;
937     if (lhs->exprType() != INT_EXPR) {
938 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '<=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
939 schoenebeck 2581 $$ = new IntLiteral(0);
940     } else if (rhs->exprType() != INT_EXPR) {
941 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '<=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
942 schoenebeck 2581 $$ = new IntLiteral(0);
943 schoenebeck 3561 } else if (lhs->asInt()->unitType() != rhs->asInt()->unitType() ||
944     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
945     {
946     PARSE_ERR(@2, "Operands of relative operations must have same unit.");
947     $$ = new IntLiteral(0);
948 schoenebeck 2581 } else {
949     $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
950     }
951     }
952     | rel_expr GE add_expr {
953     ExpressionRef lhs = $1;
954     ExpressionRef rhs = $3;
955     if (lhs->exprType() != INT_EXPR) {
956 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '>=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
957 schoenebeck 2581 $$ = new IntLiteral(0);
958     } else if (rhs->exprType() != INT_EXPR) {
959 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '>=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
960 schoenebeck 2581 $$ = new IntLiteral(0);
961 schoenebeck 3561 } else if (lhs->asInt()->unitType() != rhs->asInt()->unitType() ||
962     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
963     {
964     PARSE_ERR(@2, "Operands of relative operations must have same unit.");
965     $$ = new IntLiteral(0);
966 schoenebeck 2581 } else {
967     $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
968     }
969     }
970     | rel_expr '=' add_expr {
971 schoenebeck 3561 ExpressionRef lhs = $1;
972     ExpressionRef rhs = $3;
973     if (lhs->exprType() != INT_EXPR) {
974     PARSE_ERR(@1, (String("Left operand of operator '=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
975     $$ = new IntLiteral(0);
976     } else if (rhs->exprType() != INT_EXPR) {
977     PARSE_ERR(@3, (String("Right operand of operator '=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
978     $$ = new IntLiteral(0);
979     } else if (lhs->asInt()->unitType() != rhs->asInt()->unitType() ||
980     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
981     {
982     PARSE_ERR(@2, "Operands of relative operations must have same unit.");
983     $$ = new IntLiteral(0);
984     } else {
985     $$ = new Relation(lhs, Relation::EQUAL, rhs);
986     }
987 schoenebeck 2581 }
988     | rel_expr '#' add_expr {
989 schoenebeck 3561 ExpressionRef lhs = $1;
990     ExpressionRef rhs = $3;
991     if (lhs->exprType() != INT_EXPR) {
992     PARSE_ERR(@1, (String("Left operand of operator '#' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
993     $$ = new IntLiteral(0);
994     } else if (rhs->exprType() != INT_EXPR) {
995     PARSE_ERR(@3, (String("Right operand of operator '#' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
996     $$ = new IntLiteral(0);
997     } else if (lhs->asInt()->unitType() != rhs->asInt()->unitType() ||
998     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
999     {
1000     PARSE_ERR(@2, "Operands of relative operations must have same unit.");
1001     $$ = new IntLiteral(0);
1002     } else {
1003     $$ = new Relation(lhs, Relation::NOT_EQUAL, rhs);
1004     }
1005 schoenebeck 2581 }
1006    
1007     add_expr:
1008     mul_expr
1009     | add_expr '+' mul_expr {
1010     ExpressionRef lhs = $1;
1011     ExpressionRef rhs = $3;
1012     if (lhs->exprType() != INT_EXPR) {
1013 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '+' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1014 schoenebeck 2581 $$ = new IntLiteral(0);
1015     } else if (rhs->exprType() != INT_EXPR) {
1016 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '+' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1017 schoenebeck 2581 $$ = new IntLiteral(0);
1018 schoenebeck 3561 } else if (lhs->asInt()->unitType() != rhs->asInt()->unitType() ||
1019     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
1020     {
1021     PARSE_ERR(@2, "Operands of '+' operations must have same unit.");
1022     $$ = new IntLiteral(0);
1023 schoenebeck 2581 } else {
1024     $$ = new Add(lhs,rhs);
1025     }
1026     }
1027     | add_expr '-' mul_expr {
1028     ExpressionRef lhs = $1;
1029     ExpressionRef rhs = $3;
1030     if (lhs->exprType() != INT_EXPR) {
1031 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '-' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1032 schoenebeck 2581 $$ = new IntLiteral(0);
1033     } else if (rhs->exprType() != INT_EXPR) {
1034 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '-' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1035 schoenebeck 2581 $$ = new IntLiteral(0);
1036 schoenebeck 3561 } else if (lhs->asInt()->unitType() != rhs->asInt()->unitType() ||
1037     lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor())
1038     {
1039     PARSE_ERR(@2, "Operands of '-' operations must have same unit.");
1040     $$ = new IntLiteral(0);
1041 schoenebeck 2581 } else {
1042     $$ = new Sub(lhs,rhs);
1043     }
1044     }
1045    
1046     mul_expr:
1047     unary_expr
1048     | mul_expr '*' unary_expr {
1049     ExpressionRef lhs = $1;
1050     ExpressionRef rhs = $3;
1051     if (lhs->exprType() != INT_EXPR) {
1052 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '*' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1053 schoenebeck 2581 $$ = new IntLiteral(0);
1054     } else if (rhs->exprType() != INT_EXPR) {
1055 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '*' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1056 schoenebeck 2581 $$ = new IntLiteral(0);
1057 schoenebeck 3561 } else if (lhs->asInt()->unitType() && rhs->asInt()->unitType()) {
1058     PARSE_ERR(@2, "Only one operand of operator '*' may have a unit type");
1059     $$ = new IntLiteral(0);
1060     } else if (lhs->asInt()->unitPrefix(0) && rhs->asInt()->unitPrefix(0)) {
1061     PARSE_ERR(@2, "Only one operand of operator '*' may have a unit prefix");
1062     $$ = new IntLiteral(0);
1063 schoenebeck 2581 } else {
1064     $$ = new Mul(lhs,rhs);
1065     }
1066     }
1067     | mul_expr '/' unary_expr {
1068     ExpressionRef lhs = $1;
1069     ExpressionRef rhs = $3;
1070     if (lhs->exprType() != INT_EXPR) {
1071 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator '/' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1072 schoenebeck 2581 $$ = new IntLiteral(0);
1073     } else if (rhs->exprType() != INT_EXPR) {
1074 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator '/' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1075 schoenebeck 2581 $$ = new IntLiteral(0);
1076 schoenebeck 3561 } else if (lhs->asInt()->unitType() && rhs->asInt()->unitType() &&
1077     lhs->asInt()->unitType() != rhs->asInt()->unitType())
1078     {
1079     PARSE_ERR(@2, "Operands of operator '/' with two different unit types.");
1080     $$ = new IntLiteral(0);
1081     } else if (!lhs->asInt()->unitType() && rhs->asInt()->unitType()) {
1082     PARSE_ERR(@3, ("Dividing left operand without any unit type by right operand with unit type " + typeStr(rhs->exprType()) + " is not possible.").c_str());
1083     $$ = new IntLiteral(0);
1084     } else if (lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor() &&
1085     lhs->asInt()->unitPrefix(0) && rhs->asInt()->unitPrefix(0))
1086     {
1087     PARSE_ERR(@2, "Dividing two operands with two different unit prefixes is not possible.");
1088     $$ = new IntLiteral(0);
1089     } else if (lhs->asInt()->unitFactor() != rhs->asInt()->unitFactor() &&
1090     rhs->asInt()->unitPrefix(0))
1091     {
1092     PARSE_ERR(@3, "Dividing left operand without any unit prefix by right operand with unit prefix is not possible.");
1093     $$ = new IntLiteral(0);
1094 schoenebeck 2581 } else {
1095     $$ = new Div(lhs,rhs);
1096     }
1097     }
1098     | mul_expr MOD unary_expr {
1099     ExpressionRef lhs = $1;
1100     ExpressionRef rhs = $3;
1101     if (lhs->exprType() != INT_EXPR) {
1102 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of modulo operator must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1103 schoenebeck 2581 $$ = new IntLiteral(0);
1104     } else if (rhs->exprType() != INT_EXPR) {
1105 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1106 schoenebeck 2581 $$ = new IntLiteral(0);
1107     } else {
1108 schoenebeck 3561 if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0))
1109     PARSE_ERR(@1, "Operands of modulo operator must not use any unit.");
1110     if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0))
1111     PARSE_ERR(@3, "Operands of modulo operator must not use any unit.");
1112 schoenebeck 2581 $$ = new Mod(lhs,rhs);
1113     }
1114     }
1115    
1116     %%
1117    
1118     void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
1119     //fprintf(stderr, "%d: %s\n", locp->first_line, err);
1120 schoenebeck 2889 context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);
1121 schoenebeck 2581 }
1122    
1123     void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
1124     //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
1125 schoenebeck 2889 context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
1126 schoenebeck 2581 }
1127 schoenebeck 3008
1128     /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.
1129     int InstrScript_tnamerr(char* yyres, const char* yystr) {
1130     if (*yystr == '"') {
1131     int yyn = 0;
1132     char const *yyp = yystr;
1133     for (;;)
1134     switch (*++yyp)
1135     {
1136     /*
1137     case '\'':
1138     case ',':
1139     goto do_not_strip_quotes;
1140    
1141     case '\\':
1142     if (*++yyp != '\\')
1143     goto do_not_strip_quotes;
1144     */
1145     /* Fall through. */
1146     default:
1147     if (yyres)
1148     yyres[yyn] = *yyp;
1149     yyn++;
1150     break;
1151    
1152     case '"':
1153     if (yyres)
1154     yyres[yyn] = '\0';
1155     return yyn;
1156     }
1157 schoenebeck 3034 /*
1158 schoenebeck 3008 do_not_strip_quotes: ;
1159 schoenebeck 3034 */
1160 schoenebeck 3008 }
1161    
1162     if (! yyres)
1163 schoenebeck 3054 return (int) yystrlen (yystr);
1164 schoenebeck 3008
1165 schoenebeck 3054 return int( yystpcpy (yyres, yystr) - yyres );
1166 schoenebeck 3008 }

  ViewVC Help
Powered by ViewVC