/[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 3729 - (hide annotations) (download)
Fri Jan 31 10:57:53 2020 UTC (4 years, 2 months ago) by schoenebeck
File size: 69158 byte(s)
NKSP parser: track code locations also by raw byte position and length.

* NKSP VM API: Added member variables 'firstByte' and 'lengthBytes' to
  struct 'CodeBlock'.

* NKSP Editor API: Added methods firstByte() and lengthBytes() to
  class 'VMSourceToken'.

* NKSP VM language parser: track all positions also by raw byte offset
  and length (along to the already existing tracking by line/column).

* NKSP editor syntax highlighting scanner: track all positions also by
  raw byte offset and length (along to the already existing tracking by
  line/column).

* Bumped version (2.1.1.svn45).

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

  ViewVC Help
Powered by ViewVC