/[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 3690 - (hide annotations) (download)
Fri Jan 3 10:18:21 2020 UTC (4 years, 3 months ago) by schoenebeck
File size: 71995 byte(s)
NKSP: Added support for RPN and NRPN event handlers:

* NKSP language: Added support for RPN event handler
  ("on rpn ... end on" in instrument scripts).

* NKSP language: Added support for NRPN event handler
  ("on nrpn ... end on" in instrument scripts).

* Added built-in read-only variables "$RPN_ADDRESS" and "$RPN_VALUE" which
  may be read from the new RPN/NRPN script handlers to get the (N)RPN
  parameter that had been changed and its new value.

* Added built-in const variables "$NI_CB_TYPE_RPN" and "$NI_CB_TYPE_NRPN"
  which are identifying the new (N)RPN handlers as such at script runtime.

* Bumped version (2.1.1.svn30).

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 3573 %token <fValue> REAL "real number literal"
43 schoenebeck 3561 %token <iUnitValue> INTEGER_UNIT "integer literal with unit"
44 schoenebeck 3573 %token <fUnitValue> REAL_UNIT "real number literal with unit"
45 schoenebeck 3008 %token <sValue> STRING "string literal"
46     %token <sValue> IDENTIFIER "function name"
47     %token <sValue> VARIABLE "variable name"
48     %token ON "keyword 'on'"
49     %token END "keyword 'end'"
50     %token INIT "keyword 'init'"
51     %token NOTE "keyword 'note'"
52     %token RELEASE "keyword 'release'"
53     %token CONTROLLER "keyword 'controller'"
54 schoenebeck 3690 %token RPN "keyword 'rpn'"
55     %token NRPN "keyword 'nrpn'"
56 schoenebeck 3008 %token DECLARE "keyword 'declare'"
57     %token ASSIGNMENT "operator ':='"
58     %token CONST_ "keyword 'const'"
59     %token POLYPHONIC "keyword 'polyphonic'"
60     %token WHILE "keyword 'while'"
61 schoenebeck 3260 %token SYNCHRONIZED "keyword 'synchronized'"
62 schoenebeck 3008 %token IF "keyword 'if'"
63     %token ELSE "keyword 'else'"
64     %token SELECT "keyword 'select'"
65     %token CASE "keyword 'case'"
66     %token TO "keyword 'to'"
67     %token OR "operator 'or'"
68     %token AND "operator 'and'"
69     %token NOT "operator 'not'"
70     %token BITWISE_OR "bitwise operator '.or.'"
71     %token BITWISE_AND "bitwise operator '.and.'"
72     %token BITWISE_NOT "bitwise operator '.not.'"
73     %token FUNCTION "keyword 'function'"
74     %token CALL "keyword 'call'"
75     %token MOD "operator 'mod'"
76     %token LE "operator '<='"
77     %token GE "operator '>='"
78     %token END_OF_FILE 0 "end of file"
79 schoenebeck 3259 %token UNKNOWN_CHAR "unknown character"
80 schoenebeck 2581
81 schoenebeck 2951 %type <nEventHandlers> script sections
82     %type <nEventHandler> section eventhandler
83     %type <nStatements> statements opt_statements userfunctioncall
84 schoenebeck 2581 %type <nStatement> statement assignment
85     %type <nFunctionCall> functioncall
86     %type <nArgs> args
87 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
88 schoenebeck 2581 %type <nCaseBranch> caseclause
89     %type <nCaseBranches> caseclauses
90    
91     %start script
92    
93     %%
94    
95     script:
96 schoenebeck 2951 sections {
97 schoenebeck 2581 $$ = context->handlers = $1;
98     }
99    
100 schoenebeck 2951 sections:
101     section {
102 schoenebeck 2581 $$ = new EventHandlers();
103 schoenebeck 2951 if ($1) $$->add($1);
104 schoenebeck 2581 }
105 schoenebeck 2951 | sections section {
106 schoenebeck 2581 $$ = $1;
107 schoenebeck 2951 if ($2) $$->add($2);
108 schoenebeck 2581 }
109    
110 schoenebeck 2951 section:
111     function_declaration {
112     $$ = EventHandlerRef();
113     }
114     | eventhandler {
115     $$ = $1;
116     }
117    
118 schoenebeck 2581 eventhandler:
119 schoenebeck 2947 ON NOTE opt_statements END ON {
120 schoenebeck 2581 if (context->onNote)
121 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'note' event handler.");
122 schoenebeck 2581 context->onNote = new OnNote($3);
123     $$ = context->onNote;
124     }
125 schoenebeck 2947 | ON INIT opt_statements END ON {
126 schoenebeck 2581 if (context->onInit)
127 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'init' event handler.");
128 schoenebeck 2581 context->onInit = new OnInit($3);
129     $$ = context->onInit;
130     }
131 schoenebeck 2947 | ON RELEASE opt_statements END ON {
132 schoenebeck 2581 if (context->onRelease)
133 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'release' event handler.");
134 schoenebeck 2581 context->onRelease = new OnRelease($3);
135     $$ = context->onRelease;
136     }
137 schoenebeck 2947 | ON CONTROLLER opt_statements END ON {
138 schoenebeck 2581 if (context->onController)
139 schoenebeck 2888 PARSE_ERR(@2, "Redeclaration of 'controller' event handler.");
140 schoenebeck 2581 context->onController = new OnController($3);
141     $$ = context->onController;
142     }
143 schoenebeck 3690 | ON RPN opt_statements END ON {
144     if (context->onRpn)
145     PARSE_ERR(@2, "Redeclaration of 'rpn' event handler.");
146     context->onRpn = new OnRpn($3);
147     $$ = context->onRpn;
148     }
149     | ON NRPN opt_statements END ON {
150     if (context->onNrpn)
151     PARSE_ERR(@2, "Redeclaration of 'nrpn' event handler.");
152     context->onNrpn = new OnNrpn($3);
153     $$ = context->onNrpn;
154     }
155 schoenebeck 2581
156 schoenebeck 2951 function_declaration:
157     FUNCTION IDENTIFIER opt_statements END FUNCTION {
158     const char* name = $2;
159     if (context->functionProvider->functionByName(name)) {
160     PARSE_ERR(@2, (String("There is already a built-in function with name '") + name + "'.").c_str());
161     } else if (context->userFunctionByName(name)) {
162     PARSE_ERR(@2, (String("There is already a user defined function with name '") + name + "'.").c_str());
163     } else {
164     context->userFnTable[name] = $3;
165     }
166     }
167    
168 schoenebeck 2947 opt_statements:
169 schoenebeck 2911 /* epsilon (empty argument) */ {
170     $$ = new Statements();
171     }
172     | statements {
173     $$ = $1;
174     }
175    
176 schoenebeck 2581 statements:
177     statement {
178     $$ = new Statements();
179     if ($1) {
180     if (!isNoOperation($1)) $$->add($1); // filter out NoOperation statements
181     } else
182 schoenebeck 2888 PARSE_WRN(@1, "Not a statement.");
183 schoenebeck 2581 }
184     | statements statement {
185     $$ = $1;
186     if ($2) {
187     if (!isNoOperation($2)) $$->add($2); // filter out NoOperation statements
188     } else
189 schoenebeck 2888 PARSE_WRN(@2, "Not a statement.");
190 schoenebeck 2581 }
191    
192     statement:
193     functioncall {
194     $$ = $1;
195     }
196 schoenebeck 2951 | userfunctioncall {
197     $$ = $1;
198     }
199 schoenebeck 2581 | DECLARE VARIABLE {
200     const char* name = $2;
201     //printf("declared var '%s'\n", name);
202 schoenebeck 3573 if (context->variableByName(name)) {
203 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
204 schoenebeck 3573 } else if (name[0] == '@') {
205 schoenebeck 2581 context->vartable[name] = new StringVariable(context);
206 schoenebeck 3573 } else if (name[0] == '~') {
207 schoenebeck 3581 context->vartable[name] = new RealVariable({
208     .ctx = context
209     });
210 schoenebeck 3573 } else if (name[0] == '$') {
211 schoenebeck 3581 context->vartable[name] = new IntVariable({
212     .ctx = context
213     });
214 schoenebeck 3573 } else if (name[0] == '?') {
215     PARSE_ERR(@2, (String("Real number array variable '") + name + "' declaration requires array size.").c_str());
216     } else if (name[0] == '%') {
217     PARSE_ERR(@2, (String("Integer array variable '") + name + "' declaration requires array size.").c_str());
218 schoenebeck 2581 } else {
219 schoenebeck 3573 PARSE_ERR(@2, (String("Variable '") + name + "' declared with unknown type.").c_str());
220 schoenebeck 2581 }
221 schoenebeck 3573 $$ = new NoOperation;
222 schoenebeck 2581 }
223     | DECLARE POLYPHONIC VARIABLE {
224     const char* name = $3;
225     //printf("declared polyphonic var '%s'\n", name);
226 schoenebeck 3573 if (context->variableByName(name)) {
227 schoenebeck 2888 PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
228 schoenebeck 3573 } else if (name[0] != '$' && name[0] != '~') {
229     PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");
230     } else if (name[0] == '~') {
231 schoenebeck 3581 context->vartable[name] = new PolyphonicRealVariable({
232     .ctx = context
233     });
234 schoenebeck 2581 } else {
235 schoenebeck 3581 context->vartable[name] = new PolyphonicIntVariable({
236     .ctx = context
237     });
238 schoenebeck 2581 }
239 schoenebeck 3573 $$ = new NoOperation;
240 schoenebeck 2581 }
241     | DECLARE VARIABLE ASSIGNMENT expr {
242     const char* name = $2;
243     //printf("declared assign var '%s'\n", name);
244 schoenebeck 3573 const ExprType_t declType = exprTypeOfVarName(name);
245     if (context->variableByName(name)) {
246 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
247 schoenebeck 3573 $$ = new NoOperation;
248     } else if ($4->exprType() == STRING_EXPR) {
249     if (name[0] != '@')
250     PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());
251 schoenebeck 2581 StringExprRef expr = $4;
252     if (expr->isConstExpr()) {
253     const String s = expr->evalStr();
254     StringVariableRef var = new StringVariable(context);
255     context->vartable[name] = var;
256     $$ = new Assignment(var, new StringLiteral(s));
257     } else {
258     StringVariableRef var = new StringVariable(context);
259     context->vartable[name] = var;
260     $$ = new Assignment(var, expr);
261     }
262 schoenebeck 3573 } else if ($4->exprType() == REAL_EXPR) {
263     if (name[0] != '~')
264     PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
265     RealExprRef expr = $4;
266 schoenebeck 3581 RealVariableRef var = new RealVariable({
267     .ctx = context,
268     .unitType = expr->unitType(),
269     .isFinal = expr->isFinal()
270     });
271 schoenebeck 3573 if (expr->isConstExpr()) {
272 schoenebeck 3581 $$ = new Assignment(var, new RealLiteral({
273     .value = expr->evalReal(),
274     .unitFactor = expr->unitFactor(),
275     .unitType = expr->unitType(),
276     .isFinal = expr->isFinal()
277     }));
278 schoenebeck 3573 } else {
279     $$ = new Assignment(var, expr);
280     }
281     context->vartable[name] = var;
282     } else if ($4->exprType() == INT_EXPR) {
283     if (name[0] != '$')
284     PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
285 schoenebeck 2581 IntExprRef expr = $4;
286 schoenebeck 3581 IntVariableRef var = new IntVariable({
287     .ctx = context,
288     .unitType = expr->unitType(),
289     .isFinal = expr->isFinal()
290     });
291 schoenebeck 2581 if (expr->isConstExpr()) {
292 schoenebeck 3581 $$ = new Assignment(var, new IntLiteral({
293     .value = expr->evalInt(),
294     .unitFactor = expr->unitFactor(),
295     .unitType = expr->unitType(),
296     .isFinal = expr->isFinal()
297     }));
298 schoenebeck 2581 } else {
299     $$ = new Assignment(var, expr);
300     }
301 schoenebeck 3561 context->vartable[name] = var;
302 schoenebeck 3573 } else if ($4->exprType() == EMPTY_EXPR) {
303     PARSE_ERR(@4, "Expression does not result in a value.");
304     $$ = new NoOperation;
305     } else if (isArray($4->exprType())) {
306     PARSE_ERR(@2, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
307     $$ = new NoOperation;
308 schoenebeck 2581 }
309     }
310     | DECLARE VARIABLE '[' expr ']' {
311     //printf("declare array without args\n");
312     const char* name = $2;
313     if (!$4->isConstExpr()) {
314 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
315 schoenebeck 2581 } else if ($4->exprType() != INT_EXPR) {
316 schoenebeck 2888 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
317 schoenebeck 2581 } else if (context->variableByName(name)) {
318 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
319 schoenebeck 2581 } else {
320 schoenebeck 3581 IntExprRef sizeExpr = $4;
321     if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
322 schoenebeck 3561 PARSE_ERR(@4, "Units are not allowed as array size.");
323 schoenebeck 2581 } else {
324 schoenebeck 3581 if (sizeExpr->isFinal())
325 schoenebeck 3561 PARSE_WRN(@4, "Final operator '!' is meaningless here.");
326 schoenebeck 3581 vmint size = sizeExpr->evalInt();
327 schoenebeck 3561 if (size <= 0) {
328     PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
329     } else {
330 schoenebeck 3573 if (name[0] == '?') {
331     context->vartable[name] = new RealArrayVariable(context, size);
332     } else if (name[0] == '%') {
333     context->vartable[name] = new IntArrayVariable(context, size);
334     } else {
335     PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
336     }
337 schoenebeck 3561 }
338 schoenebeck 2581 }
339     }
340 schoenebeck 3573 $$ = new NoOperation;
341 schoenebeck 2581 }
342     | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')' {
343     const char* name = $2;
344     if (!$4->isConstExpr()) {
345 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
346 schoenebeck 2581 } else if ($4->exprType() != INT_EXPR) {
347 schoenebeck 2888 PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
348 schoenebeck 2581 } else if (context->variableByName(name)) {
349 schoenebeck 2888 PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
350 schoenebeck 2581 } else {
351     IntExprRef sizeExpr = $4;
352     ArgsRef args = $8;
353 schoenebeck 3557 vmint size = sizeExpr->evalInt();
354 schoenebeck 2581 if (size <= 0) {
355 schoenebeck 2888 PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
356 schoenebeck 2581 } else if (args->argsCount() > size) {
357 schoenebeck 3257 PARSE_ERR(@8, (String("Array variable '") + name +
358 schoenebeck 2581 "' was declared with size " + ToString(size) +
359     " but " + ToString(args->argsCount()) +
360     " values were assigned." ).c_str());
361 schoenebeck 3581 } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
362 schoenebeck 3561 PARSE_ERR(@4, "Units are not allowed as array size.");
363 schoenebeck 2581 } else {
364 schoenebeck 3561 if (sizeExpr->isFinal())
365     PARSE_WRN(@4, "Final operator '!' is meaningless here.");
366 schoenebeck 3573 ExprType_t declType = EMPTY_EXPR;
367     if (name[0] == '%') {
368     declType = INT_EXPR;
369     } else if (name[0] == '?') {
370     declType = REAL_EXPR;
371     } else if (name[0] == '$') {
372     PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
373     } else if (name[0] == '~') {
374     PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
375     } else {
376     PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
377     }
378 schoenebeck 2581 bool argsOK = true;
379 schoenebeck 3573 if (declType == EMPTY_EXPR) {
380     argsOK = false;
381     } else {
382     for (vmint i = 0; i < args->argsCount(); ++i) {
383     if (args->arg(i)->exprType() != declType) {
384     PARSE_ERR(
385     @8,
386     (String("Array variable '") + name +
387     "' declared with invalid assignment values. Assigned element " +
388     ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
389     );
390     argsOK = false;
391     break;
392 schoenebeck 3582 } else if (args->arg(i)->asNumber()->unitType()) {
393 schoenebeck 3573 PARSE_ERR(
394     @8,
395     (String("Array variable '") + name +
396     "' declared with invalid assignment values. Assigned element " +
397 schoenebeck 3581 ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
398 schoenebeck 3573 );
399     argsOK = false;
400     break;
401 schoenebeck 3582 } else if (args->arg(i)->asNumber()->isFinal()) {
402 schoenebeck 3581 PARSE_ERR(
403     @8,
404     (String("Array variable '") + name +
405     "' declared with invalid assignment values. Assigned element " +
406     ToString(i+1) + " declared as 'final' value.").c_str()
407     );
408     argsOK = false;
409     break;
410 schoenebeck 3573 }
411 schoenebeck 2581 }
412     }
413 schoenebeck 3013 if (argsOK) {
414 schoenebeck 3573 if (declType == REAL_EXPR)
415     context->vartable[name] = new RealArrayVariable(context, size, args);
416     else
417     context->vartable[name] = new IntArrayVariable(context, size, args);
418     }
419 schoenebeck 2581 }
420     }
421 schoenebeck 3573 $$ = new NoOperation;
422 schoenebeck 2581 }
423 schoenebeck 3257 | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')' {
424     const char* name = $3;
425     if (!$5->isConstExpr()) {
426     PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
427     } else if ($5->exprType() != INT_EXPR) {
428     PARSE_ERR(@5, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
429     } else if (context->variableByName(name)) {
430     PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
431     } else {
432     IntExprRef sizeExpr = $5;
433     ArgsRef args = $9;
434 schoenebeck 3557 vmint size = sizeExpr->evalInt();
435 schoenebeck 3257 if (size <= 0) {
436     PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
437     } else if (args->argsCount() > size) {
438     PARSE_ERR(@9, (String("Array variable '") + name +
439     "' was declared with size " + ToString(size) +
440     " but " + ToString(args->argsCount()) +
441     " values were assigned." ).c_str());
442 schoenebeck 3581 } else if (sizeExpr->unitType() || sizeExpr->hasUnitFactorNow()) {
443 schoenebeck 3561 PARSE_ERR(@5, "Units are not allowed as array size.");
444 schoenebeck 3257 } else {
445 schoenebeck 3561 if (sizeExpr->isFinal())
446     PARSE_WRN(@5, "Final operator '!' is meaningless here.");
447 schoenebeck 3573 ExprType_t declType = EMPTY_EXPR;
448     if (name[0] == '%') {
449     declType = INT_EXPR;
450     } else if (name[0] == '?') {
451     declType = REAL_EXPR;
452     } else if (name[0] == '$') {
453     PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
454     } else if (name[0] == '~') {
455     PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
456     } else {
457     PARSE_ERR(@3, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
458     }
459 schoenebeck 3257 bool argsOK = true;
460 schoenebeck 3573 if (declType == EMPTY_EXPR) {
461     argsOK = false;
462     } else {
463     for (vmint i = 0; i < args->argsCount(); ++i) {
464     if (args->arg(i)->exprType() != declType) {
465     PARSE_ERR(
466     @9,
467 schoenebeck 3581 (String("const array variable '") + name +
468 schoenebeck 3573 "' declared with invalid assignment values. Assigned element " +
469     ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
470     );
471     argsOK = false;
472     break;
473     }
474     if (!args->arg(i)->isConstExpr()) {
475     PARSE_ERR(
476     @9,
477     (String("const array variable '") + name +
478     "' must be defined with const values. Assigned element " +
479     ToString(i+1) + " is not a const expression though.").c_str()
480     );
481     argsOK = false;
482     break;
483 schoenebeck 3582 } else if (args->arg(i)->asNumber()->unitType()) {
484 schoenebeck 3573 PARSE_ERR(
485     @9,
486     (String("const array variable '") + name +
487     "' declared with invalid assignment values. Assigned element " +
488 schoenebeck 3581 ToString(i+1) + " contains a unit type, only metric prefixes are allowed for arrays.").c_str()
489 schoenebeck 3573 );
490     argsOK = false;
491     break;
492 schoenebeck 3582 } else if (args->arg(i)->asNumber()->isFinal()) {
493 schoenebeck 3581 PARSE_ERR(
494     @9,
495     (String("const array variable '") + name +
496     "' declared with invalid assignment values. Assigned element " +
497     ToString(i+1) + " declared as 'final' value.").c_str()
498     );
499     argsOK = false;
500     break;
501 schoenebeck 3573 }
502 schoenebeck 3257 }
503     }
504     if (argsOK) {
505 schoenebeck 3573 if (declType == REAL_EXPR)
506     context->vartable[name] = new RealArrayVariable(context, size, args, true);
507     else
508     context->vartable[name] = new IntArrayVariable(context, size, args, true);
509     }
510 schoenebeck 3257 }
511     }
512 schoenebeck 3573 $$ = new NoOperation;
513 schoenebeck 3257 }
514 schoenebeck 2585 | DECLARE CONST_ VARIABLE ASSIGNMENT expr {
515 schoenebeck 2581 const char* name = $3;
516 schoenebeck 3573 const ExprType_t declType = exprTypeOfVarName(name);
517 schoenebeck 2581 if ($5->exprType() == STRING_EXPR) {
518 schoenebeck 3573 if (name[0] != '@')
519     PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());
520 schoenebeck 2581 String s;
521     StringExprRef expr = $5;
522     if (expr->isConstExpr())
523     s = expr->evalStr();
524     else
525 schoenebeck 2888 PARSE_ERR(@5, (String("Assignment to const string variable '") + name + "' requires const expression.").c_str());
526 schoenebeck 2581 ConstStringVariableRef var = new ConstStringVariable(context, s);
527     context->vartable[name] = var;
528     //$$ = new Assignment(var, new StringLiteral(s));
529 schoenebeck 3573 } else if ($5->exprType() == REAL_EXPR) {
530     if (name[0] != '~')
531     PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
532     RealExprRef expr = $5;
533 schoenebeck 3581 if (!expr->isConstExpr()) {
534 schoenebeck 3573 PARSE_ERR(@5, (String("Assignment to const real number variable '") + name + "' requires const expression.").c_str());
535 schoenebeck 3581 }
536 schoenebeck 3595 ConstRealVariableRef var = new ConstRealVariable(
537     #if defined(__GNUC__) && !defined(__clang__)
538     (const RealVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
539     #endif
540     {
541 schoenebeck 3581 .value = (expr->isConstExpr()) ? expr->evalReal() : vmfloat(0),
542     .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,
543     .unitType = expr->unitType(),
544     .isFinal = expr->isFinal()
545     });
546 schoenebeck 3573 context->vartable[name] = var;
547     //$$ = new Assignment(var, new IntLiteral(i));
548     } else if ($5->exprType() == INT_EXPR) {
549     if (name[0] != '$')
550     PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
551 schoenebeck 2581 IntExprRef expr = $5;
552 schoenebeck 3581 if (!expr->isConstExpr()) {
553 schoenebeck 2888 PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
554 schoenebeck 3581 }
555 schoenebeck 3595 ConstIntVariableRef var = new ConstIntVariable(
556     #if defined(__GNUC__) && !defined(__clang__)
557     (const IntVarDef&) // GCC 8.x requires this cast here (looks like a GCC bug to me); cast would cause an error with clang though
558     #endif
559     {
560 schoenebeck 3581 .value = (expr->isConstExpr()) ? expr->evalInt() : 0,
561     .unitFactor = (expr->isConstExpr()) ? expr->unitFactor() : VM_NO_FACTOR,
562     .unitType = expr->unitType(),
563     .isFinal = expr->isFinal()
564     });
565 schoenebeck 2581 context->vartable[name] = var;
566     //$$ = new Assignment(var, new IntLiteral(i));
567 schoenebeck 3573 } else if ($5->exprType() == EMPTY_EXPR) {
568     PARSE_ERR(@5, "Expression does not result in a value.");
569     } else if (isArray($5->exprType())) {
570     PARSE_ERR(@5, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
571 schoenebeck 2581 }
572 schoenebeck 3573 $$ = new NoOperation();
573 schoenebeck 2581 }
574     | assignment {
575     $$ = $1;
576     }
577 schoenebeck 2947 | WHILE '(' expr ')' opt_statements END WHILE {
578 schoenebeck 2581 if ($3->exprType() == INT_EXPR) {
579 schoenebeck 3561 IntExprRef expr = $3;
580 schoenebeck 3582 if (expr->asNumber()->unitType() ||
581     expr->asNumber()->hasUnitFactorEver())
582 schoenebeck 3581 PARSE_WRN(@3, "Condition for 'while' loops contains a unit.");
583     else if (expr->isFinal() && expr->isConstExpr())
584 schoenebeck 3561 PARSE_WRN(@3, "Final operator '!' is meaningless here.");
585     $$ = new While(expr, $5);
586 schoenebeck 2581 } else {
587 schoenebeck 2888 PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
588 schoenebeck 3581 $$ = new While(new IntLiteral({ .value = 0 }), $5);
589 schoenebeck 2581 }
590     }
591 schoenebeck 3260 | SYNCHRONIZED opt_statements END SYNCHRONIZED {
592     $$ = new SyncBlock($2);
593     }
594 schoenebeck 2947 | IF '(' expr ')' opt_statements ELSE opt_statements END IF {
595 schoenebeck 3561 if ($3->exprType() == INT_EXPR) {
596     IntExprRef expr = $3;
597 schoenebeck 3582 if (expr->asNumber()->unitType() ||
598     expr->asNumber()->hasUnitFactorEver())
599 schoenebeck 3581 PARSE_WRN(@3, "Condition for 'if' contains a unit.");
600     else if (expr->isFinal() && expr->isConstExpr())
601 schoenebeck 3561 PARSE_WRN(@3, "Final operator '!' is meaningless here.");
602     $$ = new If($3, $5, $7);
603     } else {
604     PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
605 schoenebeck 3581 $$ = new If(new IntLiteral({ .value = 0 }), $5, $7);
606 schoenebeck 3561 }
607 schoenebeck 2581 }
608 schoenebeck 2947 | IF '(' expr ')' opt_statements END IF {
609 schoenebeck 3561 if ($3->exprType() == INT_EXPR) {
610     IntExprRef expr = $3;
611 schoenebeck 3582 if (expr->asNumber()->unitType() ||
612     expr->asNumber()->hasUnitFactorEver())
613 schoenebeck 3581 PARSE_WRN(@3, "Condition for 'if' contains a unit.");
614     else if (expr->isFinal() && expr->isConstExpr())
615 schoenebeck 3561 PARSE_WRN(@3, "Final operator '!' is meaningless here.");
616     $$ = new If($3, $5);
617     } else {
618     PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
619 schoenebeck 3581 $$ = new If(new IntLiteral({ .value = 0 }), $5);
620 schoenebeck 3561 }
621 schoenebeck 2581 }
622     | SELECT expr caseclauses END SELECT {
623     if ($2->exprType() == INT_EXPR) {
624 schoenebeck 3561 IntExprRef expr = $2;
625 schoenebeck 3581 if (expr->unitType() || expr->hasUnitFactorEver()) {
626 schoenebeck 3561 PARSE_ERR(@2, "Units are not allowed here.");
627 schoenebeck 3581 $$ = new SelectCase(new IntLiteral({ .value = 0 }), $3);
628 schoenebeck 3561 } else {
629     if (expr->isFinal() && expr->isConstExpr())
630     PARSE_WRN(@2, "Final operator '!' is meaningless here.");
631     $$ = new SelectCase(expr, $3);
632     }
633 schoenebeck 2581 } else {
634 schoenebeck 2888 PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
635 schoenebeck 3581 $$ = new SelectCase(new IntLiteral({ .value = 0 }), $3);
636 schoenebeck 2581 }
637     }
638    
639     caseclauses:
640     caseclause {
641     $$ = CaseBranches();
642     $$.push_back($1);
643     }
644     | caseclauses caseclause {
645     $$ = $1;
646     $$.push_back($2);
647     }
648    
649     caseclause:
650 schoenebeck 2947 CASE INTEGER opt_statements {
651 schoenebeck 2581 $$ = CaseBranch();
652 schoenebeck 3581 $$.from = new IntLiteral({ .value = $2 });
653 schoenebeck 2581 $$.statements = $3;
654     }
655 schoenebeck 2947 | CASE INTEGER TO INTEGER opt_statements {
656 schoenebeck 2581 $$ = CaseBranch();
657 schoenebeck 3581 $$.from = new IntLiteral({ .value = $2 });
658     $$.to = new IntLiteral({ .value = $4 });
659 schoenebeck 2581 $$.statements = $5;
660     }
661    
662 schoenebeck 2951 userfunctioncall:
663     CALL IDENTIFIER {
664     const char* name = $2;
665     StatementsRef fn = context->userFunctionByName(name);
666     if (context->functionProvider->functionByName(name)) {
667     PARSE_ERR(@1, (String("Keyword 'call' must only be used for user defined functions, not for any built-in function like '") + name + "'.").c_str());
668     $$ = StatementsRef();
669     } else if (!fn) {
670     PARSE_ERR(@2, (String("No user defined function with name '") + name + "'.").c_str());
671     $$ = StatementsRef();
672     } else {
673     $$ = fn;
674     }
675     }
676    
677 schoenebeck 2581 functioncall:
678     IDENTIFIER '(' args ')' {
679     const char* name = $1;
680     //printf("function call of '%s' with args\n", name);
681     ArgsRef args = $3;
682     VMFunction* fn = context->functionProvider->functionByName(name);
683 schoenebeck 2951 if (context->userFunctionByName(name)) {
684     PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
685     $$ = new FunctionCall(name, args, NULL);
686     } else if (!fn) {
687 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
688 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
689 schoenebeck 3311 } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
690     PARSE_DROP(@$);
691     $$ = new NoFunctionCall;
692 schoenebeck 2581 } else if (args->argsCount() < fn->minRequiredArgs()) {
693 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
694 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
695     } else if (args->argsCount() > fn->maxAllowedArgs()) {
696 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' accepts max. " + ToString(fn->maxAllowedArgs()) + " arguments.").c_str());
697 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
698     } else {
699     bool argsOK = true;
700 schoenebeck 3557 for (vmint i = 0; i < args->argsCount(); ++i) {
701 schoenebeck 3585 if (!fn->acceptsArgType(i, args->arg(i)->exprType())) {
702     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects " + acceptedArgTypesStr(fn, i) + " type, but type " + typeStr(args->arg(i)->exprType()) + " was given instead.").c_str());
703 schoenebeck 2581 argsOK = false;
704     break;
705 schoenebeck 2945 } else if (fn->modifiesArg(i) && !args->arg(i)->isModifyable()) {
706     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
707     argsOK = false;
708     break;
709 schoenebeck 3582 } else if (isNumber(args->arg(i)->exprType()) && !fn->acceptsArgUnitType(i, args->arg(i)->asNumber()->unitType())) {
710     if (args->arg(i)->asNumber()->unitType())
711     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect unit " + unitTypeStr(args->arg(i)->asNumber()->unitType()) + ".").c_str());
712 schoenebeck 3561 else
713     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects a unit.").c_str());
714     argsOK = false;
715     break;
716 schoenebeck 3582 } else if (isNumber(args->arg(i)->exprType()) && args->arg(i)->asNumber()->hasUnitFactorEver() && !fn->acceptsArgUnitPrefix(i, args->arg(i)->asNumber()->unitType())) {
717     if (args->arg(i)->asNumber()->unitType())
718     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix for unit" + unitTypeStr(args->arg(i)->asNumber()->unitType()) + ".").c_str());
719 schoenebeck 3564 else
720     PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix.").c_str());
721 schoenebeck 3561 argsOK = false;
722     break;
723 schoenebeck 3582 } else if (!fn->acceptsArgFinal(i) && isNumber(args->arg(i)->exprType()) && args->arg(i)->asNumber()->isFinal()) {
724 schoenebeck 3561 PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a \"final\" value.").c_str());
725     argsOK = false;
726     break;
727 schoenebeck 2581 }
728     }
729 schoenebeck 3581 if (argsOK) {
730     // perform built-in function's own, custom arguments checks (if any)
731     fn->checkArgs(&*args, [&](String err) {
732     PARSE_ERR(@3, (String("Built-in function '") + name + "()': " + err).c_str());
733     argsOK = false;
734     }, [&](String wrn) {
735     PARSE_WRN(@3, (String("Built-in function '") + name + "()': " + wrn).c_str());
736     });
737     }
738 schoenebeck 2581 $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
739     }
740     }
741     | IDENTIFIER '(' ')' {
742     const char* name = $1;
743     //printf("function call of '%s' (with empty args)\n", name);
744     ArgsRef args = new Args;
745     VMFunction* fn = context->functionProvider->functionByName(name);
746 schoenebeck 2951 if (context->userFunctionByName(name)) {
747     PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
748     $$ = new FunctionCall(name, args, NULL);
749     } else if (!fn) {
750 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
751 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
752 schoenebeck 3311 } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
753     PARSE_DROP(@$);
754     $$ = new NoFunctionCall;
755 schoenebeck 2581 } else if (fn->minRequiredArgs() > 0) {
756 schoenebeck 2888 PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
757 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
758     } else {
759     $$ = new FunctionCall(name, args, fn);
760     }
761     }
762     | IDENTIFIER {
763     const char* name = $1;
764     //printf("function call of '%s' (without args)\n", name);
765     ArgsRef args = new Args;
766     VMFunction* fn = context->functionProvider->functionByName(name);
767 schoenebeck 2951 if (context->userFunctionByName(name)) {
768     PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
769     $$ = new FunctionCall(name, args, NULL);
770     } else if (!fn) {
771 schoenebeck 2888 PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
772 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
773 schoenebeck 3311 } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
774     PARSE_DROP(@$);
775     $$ = new NoFunctionCall;
776 schoenebeck 2581 } else if (fn->minRequiredArgs() > 0) {
777 schoenebeck 2888 PARSE_ERR(@1, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
778 schoenebeck 2581 $$ = new FunctionCall(name, args, NULL);
779     } else {
780     $$ = new FunctionCall(name, args, fn);
781     }
782     }
783    
784     args:
785     arg {
786     $$ = new Args();
787     $$->add($1);
788     }
789     | args ',' arg {
790     $$ = $1;
791     $$->add($3);
792     }
793    
794     arg:
795     expr
796    
797     assignment:
798     VARIABLE ASSIGNMENT expr {
799     //printf("variable lookup with name '%s' as assignment expr\n", $1);
800     const char* name = $1;
801     VariableRef var = context->variableByName(name);
802     if (!var)
803 schoenebeck 2888 PARSE_ERR(@1, (String("Variable assignment: No variable declared with name '") + name + "'.").c_str());
804 schoenebeck 2581 else if (var->isConstExpr())
805 schoenebeck 2888 PARSE_ERR(@2, (String("Variable assignment: Cannot modify const variable '") + name + "'.").c_str());
806 schoenebeck 2942 else if (!var->isAssignable())
807     PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
808 schoenebeck 2581 else if (var->exprType() != $3->exprType())
809 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());
810 schoenebeck 3582 else if (isNumber(var->exprType())) {
811     NumberVariableRef numberVar = var;
812     NumberExprRef expr = $3;
813 schoenebeck 3573 if (numberVar->unitType() != expr->unitType())
814     PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has unit type " + unitTypeStr(numberVar->unitType()) + ", assignment has unit type " + unitTypeStr(expr->unitType()) + " though.").c_str());
815     else if (numberVar->isFinal() != expr->isFinal())
816     PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' was declared as " + String(numberVar->isFinal() ? "final" : "not final") + ", assignment is " + String(expr->isFinal() ? "final" : "not final") + " though.").c_str());
817 schoenebeck 3561 }
818 schoenebeck 2581 $$ = new Assignment(var, $3);
819     }
820     | VARIABLE '[' expr ']' ASSIGNMENT expr {
821     const char* name = $1;
822     VariableRef var = context->variableByName(name);
823     if (!var)
824 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
825 schoenebeck 3573 else if (!isArray(var->exprType()))
826 schoenebeck 2888 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
827 schoenebeck 3253 else if (var->isConstExpr())
828     PARSE_ERR(@5, (String("Variable assignment: Cannot modify const array variable '") + name + "'.").c_str());
829     else if (!var->isAssignable())
830     PARSE_ERR(@5, (String("Variable assignment: Array variable '") + name + "' is not assignable.").c_str());
831 schoenebeck 2581 else if ($3->exprType() != INT_EXPR)
832 schoenebeck 2888 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
833 schoenebeck 3561 else if ($3->asInt()->unitType())
834     PARSE_ERR(@3, "Unit types are not allowed as array index.");
835 schoenebeck 3586 else if ($6->exprType() != scalarTypeOfArray(var->exprType()))
836 schoenebeck 3573 PARSE_ERR(@5, (String("Variable '") + name + "' was declared as " + typeStr(var->exprType()) + ", assigned expression is " + typeStr($6->exprType()) + " though.").c_str());
837 schoenebeck 3582 else if ($6->asNumber()->unitType())
838 schoenebeck 3561 PARSE_ERR(@6, "Unit types are not allowed for array variables.");
839 schoenebeck 3582 else if ($6->asNumber()->isFinal())
840 schoenebeck 3561 PARSE_ERR(@6, "Final operator '!' not allowed for array variables.");
841 schoenebeck 3573 else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
842 schoenebeck 3257 PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
843     " exceeds size of array variable '" + name +
844     "' which was declared with size " +
845 schoenebeck 3573 ToString(((ArrayExprRef)var)->arraySize()) + ".").c_str());
846 schoenebeck 3561 else if ($3->asInt()->isFinal())
847     PARSE_WRN(@3, "Final operator '!' is meaningless here.");
848 schoenebeck 3573 if (var->exprType() == INT_ARR_EXPR) {
849     IntArrayElementRef element = new IntArrayElement(var, $3);
850     $$ = new Assignment(element, $6);
851     } else if (var->exprType() == REAL_ARR_EXPR) {
852     RealArrayElementRef element = new RealArrayElement(var, $3);
853     $$ = new Assignment(element, $6);
854     } else {
855 schoenebeck 3581 $$ = new NoOperation; // actually not possible to ever get here
856 schoenebeck 3573 }
857 schoenebeck 2581 }
858    
859     unary_expr:
860     INTEGER {
861 schoenebeck 3581 $$ = new IntLiteral({ .value = $1 });
862 schoenebeck 2581 }
863 schoenebeck 3573 | REAL {
864 schoenebeck 3581 $$ = new RealLiteral({ .value = $1 });
865 schoenebeck 3573 }
866 schoenebeck 3561 | INTEGER_UNIT {
867 schoenebeck 3581 IntLiteralRef literal = new IntLiteral({
868     .value = $1.iValue,
869     .unitFactor = VMUnit::unitFactor($1.prefix),
870     .unitType = $1.unit
871     });
872 schoenebeck 3561 $$ = literal;
873     }
874 schoenebeck 3573 | REAL_UNIT {
875 schoenebeck 3581 RealLiteralRef literal = new RealLiteral({
876     .value = $1.fValue,
877     .unitFactor = VMUnit::unitFactor($1.prefix),
878     .unitType = $1.unit
879     });
880 schoenebeck 3573 $$ = literal;
881     }
882 schoenebeck 2581 | STRING {
883     $$ = new StringLiteral($1);
884     }
885     | VARIABLE {
886     //printf("variable lookup with name '%s' as unary expr\n", $1);
887     VariableRef var = context->variableByName($1);
888     if (var)
889     $$ = var;
890     else {
891 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + $1 + "'.").c_str());
892 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
893 schoenebeck 2581 }
894     }
895     | VARIABLE '[' expr ']' {
896     const char* name = $1;
897     VariableRef var = context->variableByName(name);
898     if (!var) {
899 schoenebeck 2888 PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
900 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
901 schoenebeck 3573 } else if (!isArray(var->exprType())) {
902 schoenebeck 2888 PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
903 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
904 schoenebeck 2581 } else if ($3->exprType() != INT_EXPR) {
905 schoenebeck 2888 PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
906 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
907     } else if ($3->asInt()->unitType() || $3->asInt()->hasUnitFactorEver()) {
908 schoenebeck 3561 PARSE_ERR(@3, "Units are not allowed as array index.");
909 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
910 schoenebeck 2581 } else {
911 schoenebeck 3573 if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
912 schoenebeck 3257 PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
913     " exceeds size of array variable '" + name +
914     "' which was declared with size " +
915 schoenebeck 3573 ToString(((ArrayExprRef)var)->arraySize()) + ".").c_str());
916 schoenebeck 3561 else if ($3->asInt()->isFinal())
917     PARSE_WRN(@3, "Final operator '!' is meaningless here.");
918 schoenebeck 3573 if (var->exprType() == REAL_ARR_EXPR) {
919     $$ = new RealArrayElement(var, $3);
920     } else {
921     $$ = new IntArrayElement(var, $3);
922     }
923 schoenebeck 2581 }
924     }
925     | '(' expr ')' {
926     $$ = $2;
927     }
928     | functioncall {
929     $$ = $1;
930     }
931 schoenebeck 3592 | '+' unary_expr {
932     $$ = $2;
933     }
934 schoenebeck 2581 | '-' unary_expr {
935     $$ = new Neg($2);
936     }
937 schoenebeck 2935 | BITWISE_NOT unary_expr {
938     if ($2->exprType() != INT_EXPR) {
939     PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
940 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
941     } else if ($2->asInt()->unitType() || $2->asInt()->hasUnitFactorEver()) {
942 schoenebeck 3561 PARSE_ERR(@2, "Units are not allowed for operands of bitwise operations.");
943 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
944 schoenebeck 2935 } else {
945     $$ = new BitwiseNot($2);
946     }
947     }
948 schoenebeck 2581 | NOT unary_expr {
949     if ($2->exprType() != INT_EXPR) {
950 schoenebeck 2888 PARSE_ERR(@2, (String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
951 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
952     } else if ($2->asInt()->unitType() || $2->asInt()->hasUnitFactorEver()) {
953 schoenebeck 3561 PARSE_ERR(@2, "Units are not allowed for operands of logical operations.");
954 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
955 schoenebeck 2581 } else {
956     $$ = new Not($2);
957     }
958     }
959 schoenebeck 3561 | '!' unary_expr {
960 schoenebeck 3582 if (!isNumber($2->exprType())) {
961 schoenebeck 3573 PARSE_ERR(@2, (String("Right operand of \"final\" operator '!' must be a scalar number expression, is ") + typeStr($2->exprType()) + " though.").c_str());
962 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
963 schoenebeck 3561 } else {
964     $$ = new Final($2);
965     }
966     }
967 schoenebeck 2581
968     expr:
969     concat_expr
970    
971     concat_expr:
972 schoenebeck 2935 logical_or_expr
973     | concat_expr '&' logical_or_expr {
974 schoenebeck 2581 ExpressionRef lhs = $1;
975     ExpressionRef rhs = $3;
976     if (lhs->isConstExpr() && rhs->isConstExpr()) {
977     $$ = new StringLiteral(
978     lhs->evalCastToStr() + rhs->evalCastToStr()
979     );
980     } else {
981     $$ = new ConcatString(lhs, rhs);
982     }
983     }
984    
985 schoenebeck 2935 logical_or_expr:
986     logical_and_expr
987     | logical_or_expr OR logical_and_expr {
988 schoenebeck 2581 ExpressionRef lhs = $1;
989     ExpressionRef rhs = $3;
990     if (lhs->exprType() != INT_EXPR) {
991 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator 'or' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
992 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
993 schoenebeck 2581 } else if (rhs->exprType() != INT_EXPR) {
994 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
995 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
996     } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
997 schoenebeck 3561 PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
998 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
999     } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1000 schoenebeck 3561 PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
1001 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1002 schoenebeck 2581 } else {
1003 schoenebeck 3581 if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1004     PARSE_WRN(@3, "Right operand of 'or' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1005     else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1006     PARSE_WRN(@1, "Left operand of 'or' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1007 schoenebeck 2581 $$ = new Or(lhs, rhs);
1008     }
1009     }
1010    
1011 schoenebeck 2935 logical_and_expr:
1012     bitwise_or_expr {
1013 schoenebeck 2581 $$ = $1;
1014     }
1015 schoenebeck 2935 | logical_and_expr AND bitwise_or_expr {
1016 schoenebeck 2581 ExpressionRef lhs = $1;
1017     ExpressionRef rhs = $3;
1018     if (lhs->exprType() != INT_EXPR) {
1019 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of operator 'and' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1020 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1021 schoenebeck 2581 } else if (rhs->exprType() != INT_EXPR) {
1022 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1023 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1024     } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1025 schoenebeck 3561 PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
1026 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1027     } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1028 schoenebeck 3561 PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
1029 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1030 schoenebeck 2581 } else {
1031 schoenebeck 3581 if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1032     PARSE_WRN(@3, "Right operand of 'and' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1033     else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1034     PARSE_WRN(@1, "Left operand of 'and' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1035 schoenebeck 2581 $$ = new And(lhs, rhs);
1036     }
1037     }
1038    
1039 schoenebeck 2935 bitwise_or_expr:
1040     bitwise_and_expr
1041     | bitwise_or_expr BITWISE_OR bitwise_and_expr {
1042     ExpressionRef lhs = $1;
1043     ExpressionRef rhs = $3;
1044     if (lhs->exprType() != INT_EXPR) {
1045     PARSE_ERR(@1, (String("Left operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1046 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1047 schoenebeck 2935 } else if (rhs->exprType() != INT_EXPR) {
1048     PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1049 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1050     } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1051 schoenebeck 3561 PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
1052 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1053     } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1054 schoenebeck 3561 PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
1055 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1056 schoenebeck 2935 } else {
1057 schoenebeck 3581 if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1058     PARSE_WRN(@3, "Right operand of '.or.' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1059     else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1060     PARSE_WRN(@1, "Left operand of '.or.' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1061 schoenebeck 2935 $$ = new BitwiseOr(lhs, rhs);
1062     }
1063     }
1064    
1065     bitwise_and_expr:
1066     rel_expr {
1067     $$ = $1;
1068     }
1069     | bitwise_and_expr BITWISE_AND rel_expr {
1070     ExpressionRef lhs = $1;
1071     ExpressionRef rhs = $3;
1072     if (lhs->exprType() != INT_EXPR) {
1073     PARSE_ERR(@1, (String("Left operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1074 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1075 schoenebeck 2935 } else if (rhs->exprType() != INT_EXPR) {
1076     PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1077 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1078     } else if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver()) {
1079 schoenebeck 3561 PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
1080 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1081     } else if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver()) {
1082 schoenebeck 3561 PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
1083 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1084 schoenebeck 2935 } else {
1085 schoenebeck 3581 if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1086     PARSE_WRN(@3, "Right operand of '.and.' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1087     else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1088     PARSE_WRN(@1, "Left operand of '.and.' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1089 schoenebeck 2935 $$ = new BitwiseAnd(lhs, rhs);
1090     }
1091     }
1092    
1093 schoenebeck 2581 rel_expr:
1094     add_expr
1095     | rel_expr '<' add_expr {
1096     ExpressionRef lhs = $1;
1097     ExpressionRef rhs = $3;
1098 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1099 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '<' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1100 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1101 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1102 schoenebeck 3573 PARSE_ERR(@3, (String("Right operand of operator '<' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1103 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1104 schoenebeck 3582 } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1105 schoenebeck 3581 PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1106 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1107     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1108 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1109 schoenebeck 2581 } else {
1110 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1111 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '<' comparison is not 'final', left operand is 'final' though.");
1112 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1113 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '<' comparison is not 'final', right operand is 'final' though.");
1114 schoenebeck 2581 $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
1115     }
1116     }
1117     | rel_expr '>' add_expr {
1118     ExpressionRef lhs = $1;
1119     ExpressionRef rhs = $3;
1120 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1121 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '>' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1122 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1123 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1124 schoenebeck 3573 PARSE_ERR(@3, (String("Right operand of operator '>' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1125 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1126 schoenebeck 3582 } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1127 schoenebeck 3581 PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1128 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1129     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1130 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1131 schoenebeck 2581 } else {
1132 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1133 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '>' comparison is not 'final', left operand is 'final' though.");
1134 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1135 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '>' comparison is not 'final', right operand is 'final' though.");
1136 schoenebeck 2581 $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
1137     }
1138     }
1139     | rel_expr LE add_expr {
1140     ExpressionRef lhs = $1;
1141     ExpressionRef rhs = $3;
1142 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1143 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '<=' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1144 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1145 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1146 schoenebeck 3573 PARSE_ERR(@3, (String("Right operand of operator '<=' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1147 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1148 schoenebeck 3582 } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1149 schoenebeck 3581 PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1150 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1151     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1152 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1153 schoenebeck 2581 } else {
1154 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1155 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '<=' comparison is not 'final', left operand is 'final' though.");
1156 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1157 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '<=' comparison is not 'final', right operand is 'final' though.");
1158 schoenebeck 2581 $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
1159     }
1160     }
1161     | rel_expr GE add_expr {
1162     ExpressionRef lhs = $1;
1163     ExpressionRef rhs = $3;
1164 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1165 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '>=' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1166 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1167 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1168 schoenebeck 3573 PARSE_ERR(@3, (String("Right operand of operator '>=' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1169 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1170 schoenebeck 3582 } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1171 schoenebeck 3581 PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1172 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1173     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1174 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1175 schoenebeck 2581 } else {
1176 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1177 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '>=' comparison is not 'final', left operand is 'final' though.");
1178 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1179 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '>=' comparison is not 'final', right operand is 'final' though.");
1180 schoenebeck 2581 $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
1181     }
1182     }
1183     | rel_expr '=' add_expr {
1184 schoenebeck 3561 ExpressionRef lhs = $1;
1185     ExpressionRef rhs = $3;
1186 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1187 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '=' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1188 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1189 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1190 schoenebeck 3573 PARSE_ERR(@3, (String("Right operand of operator '=' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1191 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1192 schoenebeck 3582 } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1193 schoenebeck 3581 PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1194 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1195     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1196 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1197 schoenebeck 3561 } else {
1198 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1199 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '=' comparison is not 'final', left operand is 'final' though.");
1200 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1201 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '=' comparison is not 'final', right operand is 'final' though.");
1202 schoenebeck 3561 $$ = new Relation(lhs, Relation::EQUAL, rhs);
1203     }
1204 schoenebeck 2581 }
1205     | rel_expr '#' add_expr {
1206 schoenebeck 3561 ExpressionRef lhs = $1;
1207     ExpressionRef rhs = $3;
1208 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1209 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '#' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1210 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1211 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1212 schoenebeck 3573 PARSE_ERR(@3, (String("Right operand of operator '#' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1213 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1214 schoenebeck 3582 } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1215 schoenebeck 3581 PARSE_ERR(@2, (String("Operands of relative operations must have same unit, left operand is ") +
1216 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1217     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1218 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1219 schoenebeck 3561 } else {
1220 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1221 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '#' comparison is not 'final', left operand is 'final' though.");
1222 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1223 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '#' comparison is not 'final', right operand is 'final' though.");
1224 schoenebeck 3561 $$ = new Relation(lhs, Relation::NOT_EQUAL, rhs);
1225     }
1226 schoenebeck 2581 }
1227    
1228     add_expr:
1229     mul_expr
1230     | add_expr '+' mul_expr {
1231     ExpressionRef lhs = $1;
1232     ExpressionRef rhs = $3;
1233 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1234 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '+' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1235 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1236 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1237 schoenebeck 3573 PARSE_ERR(@1, (String("Right operand of operator '+' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1238 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1239 schoenebeck 3573 } else if (lhs->exprType() != rhs->exprType()) {
1240     PARSE_ERR(@2, (String("Operands of operator '+' must have same type; left operand is ") +
1241     typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1242 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1243 schoenebeck 3582 } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1244 schoenebeck 3581 PARSE_ERR(@2, (String("Operands of '+' operations must have same unit, left operand is ") +
1245 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1246     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1247 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1248 schoenebeck 2581 } else {
1249 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1250 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '+' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1251 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1252 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '+' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1253 schoenebeck 2581 $$ = new Add(lhs,rhs);
1254     }
1255     }
1256     | add_expr '-' mul_expr {
1257     ExpressionRef lhs = $1;
1258     ExpressionRef rhs = $3;
1259 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1260 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '-' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1261 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1262 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1263 schoenebeck 3573 PARSE_ERR(@1, (String("Right operand of operator '-' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1264 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1265 schoenebeck 3573 } else if (lhs->exprType() != rhs->exprType()) {
1266     PARSE_ERR(@2, (String("Operands of operator '-' must have same type; left operand is ") +
1267     typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1268 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1269 schoenebeck 3582 } else if (lhs->asNumber()->unitType() != rhs->asNumber()->unitType()) {
1270 schoenebeck 3581 PARSE_ERR(@2, (String("Operands of '-' operations must have same unit, left operand is ") +
1271 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1272     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1273 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1274 schoenebeck 2581 } else {
1275 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1276 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '-' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1277 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1278 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '-' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1279 schoenebeck 2581 $$ = new Sub(lhs,rhs);
1280     }
1281     }
1282    
1283     mul_expr:
1284     unary_expr
1285     | mul_expr '*' unary_expr {
1286     ExpressionRef lhs = $1;
1287     ExpressionRef rhs = $3;
1288 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1289 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '*' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1290 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1291 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1292 schoenebeck 3573 PARSE_ERR(@1, (String("Right operand of operator '*' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1293 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1294 schoenebeck 3582 } else if (lhs->asNumber()->unitType() && rhs->asNumber()->unitType()) {
1295 schoenebeck 3581 PARSE_ERR(@2, (String("Only one operand of operator '*' may have a unit type, left operand is ") +
1296 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1297     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1298 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1299 schoenebeck 3573 } else if (lhs->exprType() != rhs->exprType()) {
1300     PARSE_ERR(@2, (String("Operands of operator '*' must have same type; left operand is ") +
1301     typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1302 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1303 schoenebeck 2581 } else {
1304 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1305 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '*' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1306 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1307 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '*' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1308 schoenebeck 2581 $$ = new Mul(lhs,rhs);
1309     }
1310     }
1311     | mul_expr '/' unary_expr {
1312     ExpressionRef lhs = $1;
1313     ExpressionRef rhs = $3;
1314 schoenebeck 3582 if (!isNumber(lhs->exprType())) {
1315 schoenebeck 3573 PARSE_ERR(@1, (String("Left operand of operator '/' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1316 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1317 schoenebeck 3582 } else if (!isNumber(rhs->exprType())) {
1318 schoenebeck 3573 PARSE_ERR(@1, (String("Right operand of operator '/' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1319 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1320 schoenebeck 3582 } else if (lhs->asNumber()->unitType() && rhs->asNumber()->unitType() &&
1321     lhs->asNumber()->unitType() != rhs->asNumber()->unitType())
1322 schoenebeck 3561 {
1323 schoenebeck 3581 PARSE_ERR(@2, (String("Operands of operator '/' with two different unit types, left operand is ") +
1324 schoenebeck 3582 unitTypeStr(lhs->asNumber()->unitType()) + " and right operand is " +
1325     unitTypeStr(rhs->asNumber()->unitType()) + " though.").c_str());
1326 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1327 schoenebeck 3582 } else if (!lhs->asNumber()->unitType() && rhs->asNumber()->unitType()) {
1328 schoenebeck 3581 PARSE_ERR(@3, ("Dividing left operand without any unit type by right operand with unit type (" +
1329 schoenebeck 3582 unitTypeStr(rhs->asNumber()->unitType()) + ") is not possible.").c_str());
1330 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1331 schoenebeck 3573 } else if (lhs->exprType() != rhs->exprType()) {
1332     PARSE_ERR(@2, (String("Operands of operator '/' must have same type; left operand is ") +
1333     typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1334 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1335 schoenebeck 2581 } else {
1336 schoenebeck 3582 if (lhs->asNumber()->isFinal() && !rhs->asNumber()->isFinal())
1337 schoenebeck 3581 PARSE_WRN(@3, "Right operand of '/' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1338 schoenebeck 3582 else if (!lhs->asNumber()->isFinal() && rhs->asNumber()->isFinal())
1339 schoenebeck 3581 PARSE_WRN(@1, "Left operand of '/' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1340 schoenebeck 2581 $$ = new Div(lhs,rhs);
1341     }
1342     }
1343     | mul_expr MOD unary_expr {
1344     ExpressionRef lhs = $1;
1345     ExpressionRef rhs = $3;
1346     if (lhs->exprType() != INT_EXPR) {
1347 schoenebeck 2888 PARSE_ERR(@1, (String("Left operand of modulo operator must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1348 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1349 schoenebeck 2581 } else if (rhs->exprType() != INT_EXPR) {
1350 schoenebeck 2888 PARSE_ERR(@3, (String("Right operand of modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1351 schoenebeck 3581 $$ = new IntLiteral({ .value = 0 });
1352 schoenebeck 2581 } else {
1353 schoenebeck 3581 if (lhs->asInt()->unitType() || lhs->asInt()->hasUnitFactorEver())
1354 schoenebeck 3561 PARSE_ERR(@1, "Operands of modulo operator must not use any unit.");
1355 schoenebeck 3581 if (rhs->asInt()->unitType() || rhs->asInt()->hasUnitFactorEver())
1356 schoenebeck 3561 PARSE_ERR(@3, "Operands of modulo operator must not use any unit.");
1357 schoenebeck 3581 if (lhs->asInt()->isFinal() && !rhs->asInt()->isFinal())
1358     PARSE_WRN(@3, "Right operand of 'mod' operation is not 'final', result will be 'final' though since left operand is 'final'.");
1359     else if (!lhs->asInt()->isFinal() && rhs->asInt()->isFinal())
1360     PARSE_WRN(@1, "Left operand of 'mod' operation is not 'final', result will be 'final' though since right operand is 'final'.");
1361 schoenebeck 2581 $$ = new Mod(lhs,rhs);
1362     }
1363     }
1364    
1365     %%
1366    
1367     void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err) {
1368     //fprintf(stderr, "%d: %s\n", locp->first_line, err);
1369 schoenebeck 2889 context->addErr(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, err);
1370 schoenebeck 2581 }
1371    
1372     void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt) {
1373     //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
1374 schoenebeck 2889 context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
1375 schoenebeck 2581 }
1376 schoenebeck 3008
1377     /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.
1378     int InstrScript_tnamerr(char* yyres, const char* yystr) {
1379     if (*yystr == '"') {
1380     int yyn = 0;
1381     char const *yyp = yystr;
1382     for (;;)
1383     switch (*++yyp)
1384     {
1385     /*
1386     case '\'':
1387     case ',':
1388     goto do_not_strip_quotes;
1389    
1390     case '\\':
1391     if (*++yyp != '\\')
1392     goto do_not_strip_quotes;
1393     */
1394     /* Fall through. */
1395     default:
1396     if (yyres)
1397     yyres[yyn] = *yyp;
1398     yyn++;
1399     break;
1400    
1401     case '"':
1402     if (yyres)
1403     yyres[yyn] = '\0';
1404     return yyn;
1405     }
1406 schoenebeck 3034 /*
1407 schoenebeck 3008 do_not_strip_quotes: ;
1408 schoenebeck 3034 */
1409 schoenebeck 3008 }
1410    
1411     if (! yyres)
1412 schoenebeck 3054 return (int) yystrlen (yystr);
1413 schoenebeck 3008
1414 schoenebeck 3054 return int( yystpcpy (yyres, yystr) - yyres );
1415 schoenebeck 3008 }

  ViewVC Help
Powered by ViewVC