/[svn]/linuxsampler/trunk/src/scriptvm/parser.y
ViewVC logotype

Diff of /linuxsampler/trunk/src/scriptvm/parser.y

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2945 by schoenebeck, Thu Jul 14 00:22:26 2016 UTC revision 3573 by schoenebeck, Tue Aug 27 21:36:53 2019 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014-2016 Christian Schoenebeck and Andreas Persson   * Copyright (c) 2014-2017 Christian Schoenebeck and Andreas Persson
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 18  Line 18 
18    
19      void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err);      void InstrScript_error(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* err);
20      void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt);      void InstrScript_warning(YYLTYPE* locp, LinuxSampler::ParserContext* context, const char* txt);
21        int InstrScript_tnamerr(char* yyres, const char* yystr);
22      int InstrScript_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);      int InstrScript_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);
23      #define scanner context->scanner      #define scanner context->scanner
24      #define PARSE_ERR(loc,txt)  yyerror(&loc, context, txt)      #define PARSE_ERR(loc,txt)  yyerror(&loc, context, txt)
25      #define PARSE_WRN(loc,txt)  InstrScript_warning(&loc, context, txt)      #define PARSE_WRN(loc,txt)  InstrScript_warning(&loc, context, txt)
26        #define PARSE_DROP(loc)     context->addPreprocessorComment(loc.first_line, loc.last_line, loc.first_column+1, loc.last_column+1);
27        #define yytnamerr(res,str)  InstrScript_tnamerr(res, str)
28  %}  %}
29    
30  // generate reentrant safe parser  // generate reentrant safe parser
# Line 29  Line 32 
32  %parse-param { LinuxSampler::ParserContext* context }  %parse-param { LinuxSampler::ParserContext* context }
33  %lex-param { void* scanner }  %lex-param { void* scanner }
34  // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners  // avoid symbol collision with other (i.e. future) auto generated (f)lex scanners
35  %name-prefix "InstrScript_"  // (NOTE: "=" is deprecated here with Bison 3.x, however removing it would cause an error with Bison 2.x)
36    %name-prefix="InstrScript_"
37  %locations  %locations
38  %defines  %defines
39  %error-verbose  %error-verbose
40    
41  %token <iValue> INTEGER  %token <iValue> INTEGER "integer literal"
42  %token <sValue> STRING  %token <fValue> REAL "real number literal"
43  %token <sValue> IDENTIFIER  %token <iUnitValue> INTEGER_UNIT "integer literal with unit"
44  %token <sValue> VARIABLE  %token <fUnitValue> REAL_UNIT "real number literal with unit"
45  %token ON END INIT NOTE DECLARE ASSIGNMENT WHILE IF OR RELEASE AND ELSE  %token <sValue> STRING "string literal"
46  %token BITWISE_OR BITWISE_AND BITWISE_NOT  %token <sValue> IDENTIFIER "function name"
47  %token CONTROLLER SELECT CASE TO NOT CONST_ POLYPHONIC MOD  %token <sValue> VARIABLE "variable name"
48  %token LE GE  %token ON "keyword 'on'"
49    %token END "keyword 'end'"
50  %type <nEventHandlers> script eventhandlers  %token INIT "keyword 'init'"
51  %type <nEventHandler> eventhandler  %token NOTE "keyword 'note'"
52  %type <nStatements> statements body  %token RELEASE "keyword 'release'"
53    %token CONTROLLER "keyword 'controller'"
54    %token DECLARE "keyword 'declare'"
55    %token ASSIGNMENT "operator ':='"
56    %token CONST_ "keyword 'const'"
57    %token POLYPHONIC "keyword 'polyphonic'"
58    %token WHILE "keyword 'while'"
59    %token SYNCHRONIZED "keyword 'synchronized'"
60    %token IF "keyword 'if'"
61    %token ELSE "keyword 'else'"
62    %token SELECT "keyword 'select'"
63    %token CASE "keyword 'case'"
64    %token TO "keyword 'to'"
65    %token OR "operator 'or'"
66    %token AND "operator 'and'"
67    %token NOT "operator 'not'"
68    %token BITWISE_OR "bitwise operator '.or.'"
69    %token BITWISE_AND "bitwise operator '.and.'"
70    %token BITWISE_NOT "bitwise operator '.not.'"
71    %token FUNCTION "keyword 'function'"
72    %token CALL "keyword 'call'"
73    %token MOD "operator 'mod'"
74    %token LE "operator '<='"
75    %token GE "operator '>='"
76    %token END_OF_FILE 0 "end of file"
77    %token UNKNOWN_CHAR "unknown character"
78    
79    %type <nEventHandlers> script sections
80    %type <nEventHandler> section eventhandler
81    %type <nStatements> statements opt_statements userfunctioncall
82  %type <nStatement> statement assignment  %type <nStatement> statement assignment
83  %type <nFunctionCall> functioncall  %type <nFunctionCall> functioncall
84  %type <nArgs> args  %type <nArgs> args
# Line 58  Line 91 
91  %%  %%
92    
93  script:  script:
94      eventhandlers  {      sections  {
95          $$ = context->handlers = $1;          $$ = context->handlers = $1;
96      }      }
97    
98  eventhandlers:  sections:
99      eventhandler  {      section  {
100          $$ = new EventHandlers();          $$ = new EventHandlers();
101          $$->add($1);          if ($1) $$->add($1);
102        }
103        | sections section  {
104            $$ = $1;
105            if ($2) $$->add($2);
106        }
107    
108    section:
109        function_declaration  {
110            $$ = EventHandlerRef();
111      }      }
112      | eventhandlers eventhandler  {      | eventhandler  {
113          $$ = $1;          $$ = $1;
         $$->add($2);  
114      }      }
115    
116  eventhandler:  eventhandler:
117      ON NOTE body END ON  {      ON NOTE opt_statements END ON  {
118          if (context->onNote)          if (context->onNote)
119              PARSE_ERR(@2, "Redeclaration of 'note' event handler.");              PARSE_ERR(@2, "Redeclaration of 'note' event handler.");
120          context->onNote = new OnNote($3);          context->onNote = new OnNote($3);
121          $$ = context->onNote;          $$ = context->onNote;
122      }      }
123      | ON INIT body END ON  {      | ON INIT opt_statements END ON  {
124          if (context->onInit)          if (context->onInit)
125              PARSE_ERR(@2, "Redeclaration of 'init' event handler.");              PARSE_ERR(@2, "Redeclaration of 'init' event handler.");
126          context->onInit = new OnInit($3);          context->onInit = new OnInit($3);
127          $$ = context->onInit;          $$ = context->onInit;
128      }      }
129      | ON RELEASE body END ON  {      | ON RELEASE opt_statements END ON  {
130          if (context->onRelease)          if (context->onRelease)
131              PARSE_ERR(@2, "Redeclaration of 'release' event handler.");              PARSE_ERR(@2, "Redeclaration of 'release' event handler.");
132          context->onRelease = new OnRelease($3);          context->onRelease = new OnRelease($3);
133          $$ = context->onRelease;          $$ = context->onRelease;
134      }      }
135      | ON CONTROLLER body END ON  {      | ON CONTROLLER opt_statements END ON  {
136          if (context->onController)          if (context->onController)
137              PARSE_ERR(@2, "Redeclaration of 'controller' event handler.");              PARSE_ERR(@2, "Redeclaration of 'controller' event handler.");
138          context->onController = new OnController($3);          context->onController = new OnController($3);
139          $$ = context->onController;          $$ = context->onController;
140      }      }
141    
142  body:  function_declaration:
143        FUNCTION IDENTIFIER opt_statements END FUNCTION  {
144            const char* name = $2;
145            if (context->functionProvider->functionByName(name)) {
146                PARSE_ERR(@2, (String("There is already a built-in function with name '") + name + "'.").c_str());
147            } else if (context->userFunctionByName(name)) {
148                PARSE_ERR(@2, (String("There is already a user defined function with name '") + name + "'.").c_str());
149            } else {
150                context->userFnTable[name] = $3;
151            }
152        }
153    
154    opt_statements:
155      /* epsilon (empty argument) */  {      /* epsilon (empty argument) */  {
156          $$ = new Statements();          $$ = new Statements();
157      }      }
# Line 126  statement: Line 179  statement:
179      functioncall  {      functioncall  {
180          $$ = $1;          $$ = $1;
181      }      }
182        | userfunctioncall  {
183            $$ = $1;
184        }
185      | DECLARE VARIABLE  {      | DECLARE VARIABLE  {
186          const char* name = $2;          const char* name = $2;
187          //printf("declared var '%s'\n", name);          //printf("declared var '%s'\n", name);
188          if (context->variableByName(name))          if (context->variableByName(name)) {
189              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
190          if (name[0] == '@') {          } else if (name[0] == '@') {
191              context->vartable[name] = new StringVariable(context);              context->vartable[name] = new StringVariable(context);
192              $$ = new NoOperation;          } else if (name[0] == '~') {
193          } else {              context->vartable[name] = new RealVariable(context);
194            } else if (name[0] == '$') {
195              context->vartable[name] = new IntVariable(context);              context->vartable[name] = new IntVariable(context);
196              $$ = new NoOperation;          } else if (name[0] == '?') {
197                PARSE_ERR(@2, (String("Real number array variable '") + name + "' declaration requires array size.").c_str());
198            } else if (name[0] == '%') {
199                PARSE_ERR(@2, (String("Integer array variable '") + name + "' declaration requires array size.").c_str());
200            } else {
201                PARSE_ERR(@2, (String("Variable '") + name + "' declared with unknown type.").c_str());
202          }          }
203            $$ = new NoOperation;
204      }      }
205      | DECLARE POLYPHONIC VARIABLE  {      | DECLARE POLYPHONIC VARIABLE  {
206          const char* name = $3;          const char* name = $3;
207          //printf("declared polyphonic var '%s'\n", name);          //printf("declared polyphonic var '%s'\n", name);
208          if (context->variableByName(name))          if (context->variableByName(name)) {
209              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
210          if (name[0] != '$') {          } else if (name[0] != '$' && name[0] != '~') {
211              PARSE_ERR(@3, "Polyphonic variables may only be declared as integers.");              PARSE_ERR(@3, "Polyphonic variables must only be declared either as integer or real number type.");
212              $$ = new FunctionCall("nothing", new Args, NULL); // whatever          } else if (name[0] == '~') {
213                context->vartable[name] = new PolyphonicRealVariable(context);
214          } else {          } else {
215              context->vartable[name] = new PolyphonicIntVariable(context);              context->vartable[name] = new PolyphonicIntVariable(context);
             $$ = new NoOperation;  
216          }          }
217            $$ = new NoOperation;
218      }      }
219      | DECLARE VARIABLE ASSIGNMENT expr  {      | DECLARE VARIABLE ASSIGNMENT expr  {
220          const char* name = $2;          const char* name = $2;
221          //printf("declared assign var '%s'\n", name);          //printf("declared assign var '%s'\n", name);
222          if (context->variableByName(name))          const ExprType_t declType = exprTypeOfVarName(name);
223            if (context->variableByName(name)) {
224              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
225          if ($4->exprType() == STRING_EXPR) {              $$ = new NoOperation;
226              if (name[0] == '$')          } else if ($4->exprType() == STRING_EXPR) {
227                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as integer, string expression assigned though.").c_str());              if (name[0] != '@')
228                    PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());
229              StringExprRef expr = $4;              StringExprRef expr = $4;
230              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
231                  const String s = expr->evalStr();                  const String s = expr->evalStr();
# Line 171  statement: Line 237  statement:
237                  context->vartable[name] = var;                  context->vartable[name] = var;
238                  $$ = new Assignment(var, expr);                  $$ = new Assignment(var, expr);
239              }              }
240          } else {          } else if ($4->exprType() == REAL_EXPR) {
241              if (name[0] == '@')              if (name[0] != '~')
242                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as string, integer expression assigned though.").c_str());                  PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
243                RealExprRef expr = $4;
244                RealVariableRef var = new RealVariable(context);
245                if (expr->isConstExpr()) {
246                    const vmfloat f = expr->evalReal();
247                    $$ = new Assignment(var, new RealLiteral(f));
248                } else {
249                    $$ = new Assignment(var, expr);
250                }
251                var->copyUnitFrom(expr);
252                var->setFinal(expr->isFinal());
253                context->vartable[name] = var;
254            } else if ($4->exprType() == INT_EXPR) {
255                if (name[0] != '$')
256                    PARSE_WRN(@2, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
257              IntExprRef expr = $4;              IntExprRef expr = $4;
258                IntVariableRef var = new IntVariable(context);
259              if (expr->isConstExpr()) {              if (expr->isConstExpr()) {
260                  const int i = expr->evalInt();                  const vmint i = expr->evalInt();
                 IntVariableRef var = new IntVariable(context);  
                 context->vartable[name] = var;  
261                  $$ = new Assignment(var, new IntLiteral(i));                  $$ = new Assignment(var, new IntLiteral(i));
262              } else {              } else {
                 IntVariableRef var = new IntVariable(context);  
                 context->vartable[name] = var;  
263                  $$ = new Assignment(var, expr);                  $$ = new Assignment(var, expr);
264              }              }
265                var->copyUnitFrom(expr);
266                var->setFinal(expr->isFinal());
267                context->vartable[name] = var;
268            } else if ($4->exprType() == EMPTY_EXPR) {
269                PARSE_ERR(@4, "Expression does not result in a value.");
270                $$ = new NoOperation;
271            } else if (isArray($4->exprType())) {
272                PARSE_ERR(@2, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
273                $$ = new NoOperation;
274          }          }
275      }      }
276      | DECLARE VARIABLE '[' expr ']'  {      | DECLARE VARIABLE '[' expr ']'  {
# Line 192  statement: Line 278  statement:
278          const char* name = $2;          const char* name = $2;
279          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
280              PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());              PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
281          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
282              PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());              PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
283          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
284              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
285          } else {          } else {
286              IntExprRef expr = $4;              IntExprRef expr = $4;
287              int size = expr->evalInt();              if (expr->unitType() || expr->unitPrefix(0)) {
288              if (size <= 0) {                  PARSE_ERR(@4, "Units are not allowed as array size.");
                 PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());  
                 $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
289              } else {              } else {
290                  context->vartable[name] = new IntArrayVariable(context, size);                  if (expr->isFinal())
291                  $$ = new NoOperation;                      PARSE_WRN(@4, "Final operator '!' is meaningless here.");
292                    vmint size = expr->evalInt();
293                    if (size <= 0) {
294                        PARSE_ERR(@4, (String("Array variable '") + name + "' declared with array size " + ToString(size) + ".").c_str());
295                    } else {
296                        if (name[0] == '?') {
297                            context->vartable[name] = new RealArrayVariable(context, size);
298                        } else if (name[0] == '%') {
299                            context->vartable[name] = new IntArrayVariable(context, size);
300                        } else {
301                            PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
302                        }
303                    }
304              }              }
305          }          }
306            $$ = new NoOperation;
307      }      }
308      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {      | DECLARE VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
309          const char* name = $2;          const char* name = $2;
310          if (!$4->isConstExpr()) {          if (!$4->isConstExpr()) {
311              PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());              PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
312          } else if ($4->exprType() != INT_EXPR) {          } else if ($4->exprType() != INT_EXPR) {
313              PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());              PARSE_ERR(@4, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
314          } else if (context->variableByName(name)) {          } else if (context->variableByName(name)) {
315              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());              PARSE_ERR(@2, (String("Redeclaration of variable '") + name + "'.").c_str());
             $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
316          } else {          } else {
317              IntExprRef sizeExpr = $4;              IntExprRef sizeExpr = $4;
318              ArgsRef args = $8;              ArgsRef args = $8;
319              int size = sizeExpr->evalInt();              vmint size = sizeExpr->evalInt();
320              if (size <= 0) {              if (size <= 0) {
321                  PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());                  PARSE_ERR(@4, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
                 $$ = new FunctionCall("nothing", new Args, NULL); // whatever  
322              } else if (args->argsCount() > size) {              } else if (args->argsCount() > size) {
323                  PARSE_ERR(@8, (String("Variable '") + name +                  PARSE_ERR(@8, (String("Array variable '") + name +
324                            "' was declared with size " + ToString(size) +                            "' was declared with size " + ToString(size) +
325                            " but " + ToString(args->argsCount()) +                            " but " + ToString(args->argsCount()) +
326                            " values were assigned." ).c_str());                            " values were assigned." ).c_str());
327                  $$ = new FunctionCall("nothing", new Args, NULL); // whatever                        } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {
328                    PARSE_ERR(@4, "Units are not allowed as array size.");
329              } else {              } else {
330                    if (sizeExpr->isFinal())
331                        PARSE_WRN(@4, "Final operator '!' is meaningless here.");
332                    ExprType_t declType = EMPTY_EXPR;
333                    if (name[0] == '%') {
334                        declType = INT_EXPR;
335                    } else if (name[0] == '?') {
336                        declType = REAL_EXPR;
337                    } else if (name[0] == '$') {
338                        PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
339                    } else if (name[0] == '~') {
340                        PARSE_ERR(@2, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
341                    } else {
342                        PARSE_ERR(@2, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
343                    }
344                  bool argsOK = true;                  bool argsOK = true;
345                  for (int i = 0; i < args->argsCount(); ++i) {                  if (declType == EMPTY_EXPR) {
346                      if (args->arg(i)->exprType() != INT_EXPR) {                      argsOK = false;
347                          PARSE_ERR(                  } else {
348                              @8,                      for (vmint i = 0; i < args->argsCount(); ++i) {
349                              (String("Array variable '") + name +                          if (args->arg(i)->exprType() != declType) {
350                              "' declared with invalid assignment values. Assigned element " +                              PARSE_ERR(
351                              ToString(i+1) + " is not an integer expression.").c_str()                                  @8,
352                          );                                  (String("Array variable '") + name +
353                          argsOK = false;                                  "' declared with invalid assignment values. Assigned element " +
354                          break;                                  ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
355                                );
356                                argsOK = false;
357                                break;
358                            } else if (args->arg(i)->asInt()->unitType() ||
359                                       args->arg(i)->asInt()->unitPrefix(0))
360                            {
361                                PARSE_ERR(
362                                    @8,
363                                    (String("Array variable '") + name +
364                                    "' declared with invalid assignment values. Assigned element " +
365                                    ToString(i+1) + " contains a unit.").c_str()
366                                );
367                                argsOK = false;
368                                break;
369                            }
370                      }                      }
371                  }                  }
372                  if (argsOK)                  if (argsOK) {
373                      $$ = context->vartable[name] = new IntArrayVariable(context, size, args);                      if (declType == REAL_EXPR)
374                  else                          context->vartable[name] = new RealArrayVariable(context, size, args);
375                      $$ = new FunctionCall("nothing", new Args, NULL); // whatever                      else
376                            context->vartable[name] = new IntArrayVariable(context, size, args);
377                    }
378              }              }
379          }          }
380            $$ = new NoOperation;
381        }
382        | DECLARE CONST_ VARIABLE '[' expr ']' ASSIGNMENT '(' args ')'  {
383            const char* name = $3;
384            if (!$5->isConstExpr()) {
385                PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with constant array size.").c_str());
386            } else if ($5->exprType() != INT_EXPR) {
387                PARSE_ERR(@5, (String("Size of array variable '") + name + "' declared with non integer expression.").c_str());
388            } else if (context->variableByName(name)) {
389                PARSE_ERR(@3, (String("Redeclaration of variable '") + name + "'.").c_str());
390            } else {
391                IntExprRef sizeExpr = $5;
392                ArgsRef args = $9;
393                vmint size = sizeExpr->evalInt();
394                if (size <= 0) {
395                    PARSE_ERR(@5, (String("Array variable '") + name + "' must be declared with positive array size.").c_str());
396                } else if (args->argsCount() > size) {
397                    PARSE_ERR(@9, (String("Array variable '") + name +
398                              "' was declared with size " + ToString(size) +
399                              " but " + ToString(args->argsCount()) +
400                              " values were assigned." ).c_str());
401                } else if (sizeExpr->unitType() || sizeExpr->unitPrefix(0)) {
402                    PARSE_ERR(@5, "Units are not allowed as array size.");
403                } else {
404                    if (sizeExpr->isFinal())
405                        PARSE_WRN(@5, "Final operator '!' is meaningless here.");
406                    ExprType_t declType = EMPTY_EXPR;
407                    if (name[0] == '%') {
408                        declType = INT_EXPR;
409                    } else if (name[0] == '?') {
410                        declType = REAL_EXPR;
411                    } else if (name[0] == '$') {
412                        PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '%' as name prefix for integer arrays instead of '$'.").c_str());
413                    } else if (name[0] == '~') {
414                        PARSE_ERR(@3, (String("Variable '") + name + "' declaration ambiguous: Use '?' as name prefix for real number arrays instead of '~'.").c_str());
415                    } else {
416                        PARSE_ERR(@3, (String("Variable '") + name + "' declared as unknown array type: use either '%' or '?' instead of '" + String(name).substr(0,1) + "'.").c_str());
417                    }
418                    bool argsOK = true;
419                    if (declType == EMPTY_EXPR) {
420                        argsOK = false;
421                    } else {
422                        for (vmint i = 0; i < args->argsCount(); ++i) {
423                            if (args->arg(i)->exprType() != declType) {
424                                PARSE_ERR(
425                                    @9,
426                                    (String("Array variable '") + name +
427                                    "' declared with invalid assignment values. Assigned element " +
428                                    ToString(i+1) + " is not an " + typeStr(declType) + " expression.").c_str()
429                                );
430                                argsOK = false;
431                                break;
432                            }
433                            if (!args->arg(i)->isConstExpr()) {
434                                PARSE_ERR(
435                                    @9,
436                                    (String("const array variable '") + name +
437                                    "' must be defined with const values. Assigned element " +
438                                    ToString(i+1) + " is not a const expression though.").c_str()
439                                );
440                                argsOK = false;
441                                break;
442                            } else if (args->arg(i)->asInt()->unitType() ||
443                                       args->arg(i)->asInt()->unitPrefix(0))
444                            {
445                                PARSE_ERR(
446                                    @9,
447                                    (String("const array variable '") + name +
448                                    "' declared with invalid assignment values. Assigned element " +
449                                    ToString(i+1) + " contains a unit.").c_str()
450                                );
451                                argsOK = false;
452                                break;
453                            }
454                        }
455                    }
456                    if (argsOK) {
457                        if (declType == REAL_EXPR)
458                            context->vartable[name] = new RealArrayVariable(context, size, args, true);
459                        else
460                            context->vartable[name] = new IntArrayVariable(context, size, args, true);
461                    }
462                }
463            }
464            $$ = new NoOperation;
465      }      }
466      | DECLARE CONST_ VARIABLE ASSIGNMENT expr  {      | DECLARE CONST_ VARIABLE ASSIGNMENT expr  {
467          const char* name = $3;          const char* name = $3;
468            const ExprType_t declType = exprTypeOfVarName(name);
469          if ($5->exprType() == STRING_EXPR) {          if ($5->exprType() == STRING_EXPR) {
470              if (name[0] == '$')              if (name[0] != '@')
471                  PARSE_WRN(@5, "Variable declared as integer, string expression assigned though.");                  PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", string expression assigned though.").c_str());
472              String s;              String s;
473              StringExprRef expr = $5;              StringExprRef expr = $5;
474              if (expr->isConstExpr())              if (expr->isConstExpr())
# Line 270  statement: Line 478  statement:
478              ConstStringVariableRef var = new ConstStringVariable(context, s);              ConstStringVariableRef var = new ConstStringVariable(context, s);
479              context->vartable[name] = var;              context->vartable[name] = var;
480              //$$ = new Assignment(var, new StringLiteral(s));              //$$ = new Assignment(var, new StringLiteral(s));
481              $$ = new NoOperation();          } else if ($5->exprType() == REAL_EXPR) {
482          } else {              if (name[0] != '~')
483              if (name[0] == '@')                  PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", real number expression assigned though.").c_str());
484                  PARSE_WRN(@5, "Variable declared as string, integer expression assigned though.");              vmfloat f = 0;
485              int i = 0;              RealExprRef expr = $5;
486                if (expr->isConstExpr())
487                    f = expr->evalReal();
488                else
489                    PARSE_ERR(@5, (String("Assignment to const real number variable '") + name + "' requires const expression.").c_str());
490                ConstRealVariableRef var = new ConstRealVariable(f);
491                var->copyUnitFrom(expr);
492                var->setFinal(expr->isFinal());
493                context->vartable[name] = var;
494                //$$ = new Assignment(var, new IntLiteral(i));
495            } else if ($5->exprType() == INT_EXPR) {
496                if (name[0] != '$')
497                    PARSE_WRN(@5, (String("Variable '") + name + "' declared as " + typeStr(declType) + ", integer expression assigned though.").c_str());
498                vmint i = 0;
499              IntExprRef expr = $5;              IntExprRef expr = $5;
500              if (expr->isConstExpr())              if (expr->isConstExpr())
501                  i = expr->evalInt();                  i = expr->evalInt();
502              else              else
503                  PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());                  PARSE_ERR(@5, (String("Assignment to const integer variable '") + name + "' requires const expression.").c_str());
504              ConstIntVariableRef var = new ConstIntVariable(i);              ConstIntVariableRef var = new ConstIntVariable(i);
505                var->copyUnitFrom(expr);
506                var->setFinal(expr->isFinal());
507              context->vartable[name] = var;              context->vartable[name] = var;
508              //$$ = new Assignment(var, new IntLiteral(i));              //$$ = new Assignment(var, new IntLiteral(i));
509              $$ = new NoOperation();          } else if ($5->exprType() == EMPTY_EXPR) {
510                PARSE_ERR(@5, "Expression does not result in a value.");
511            } else if (isArray($5->exprType())) {
512                PARSE_ERR(@5, (String("Variable '") + name + "' declared as scalar type, array expression assigned though.").c_str());
513          }          }
514            $$ = new NoOperation();
515      }      }
516      | assignment  {      | assignment  {
517          $$ = $1;          $$ = $1;
518      }      }
519      | WHILE '(' expr ')' statements END WHILE  {      | WHILE '(' expr ')' opt_statements END WHILE  {
520          if ($3->exprType() == INT_EXPR) {          if ($3->exprType() == INT_EXPR) {
521              $$ = new While($3, $5);              IntExprRef expr = $3;
522                if (expr->isFinal() && expr->isConstExpr())
523                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
524                $$ = new While(expr, $5);
525          } else {          } else {
526              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");              PARSE_ERR(@3, "Condition for 'while' loops must be integer expression.");
527              $$ = new While(new IntLiteral(0), $5);              $$ = new While(new IntLiteral(0), $5);
528          }          }
529      }      }
530      | IF '(' expr ')' statements ELSE statements END IF  {      | SYNCHRONIZED opt_statements END SYNCHRONIZED  {
531          $$ = new If($3, $5, $7);          $$ = new SyncBlock($2);
532        }
533        | IF '(' expr ')' opt_statements ELSE opt_statements END IF  {
534            if ($3->exprType() == INT_EXPR) {
535                IntExprRef expr = $3;
536                if (expr->isFinal() && expr->isConstExpr())
537                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
538                $$ = new If($3, $5, $7);
539            } else {
540                PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
541                $$ = new If(new IntLiteral(0), $5, $7);
542            }
543      }      }
544      | IF '(' expr ')' statements END IF  {      | IF '(' expr ')' opt_statements END IF  {
545          $$ = new If($3, $5);          if ($3->exprType() == INT_EXPR) {
546                IntExprRef expr = $3;
547                if (expr->isFinal() && expr->isConstExpr())
548                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
549                $$ = new If($3, $5);
550            } else {
551                PARSE_ERR(@3, "Condition for 'if' must be integer expression.");
552                $$ = new If(new IntLiteral(0), $5);
553            }
554      }      }
555      | SELECT expr caseclauses END SELECT  {      | SELECT expr caseclauses END SELECT  {
556          if ($2->exprType() == INT_EXPR) {          if ($2->exprType() == INT_EXPR) {
557              $$ = new SelectCase($2, $3);              IntExprRef expr = $2;
558                if (expr->unitType() || expr->unitPrefix(0)) {
559                    PARSE_ERR(@2, "Units are not allowed here.");
560                } else {
561                    if (expr->isFinal() && expr->isConstExpr())
562                        PARSE_WRN(@2, "Final operator '!' is meaningless here.");
563                    $$ = new SelectCase(expr, $3);
564                }
565          } else {          } else {
566              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");              PARSE_ERR(@2, "Statement 'select' can only by applied to integer expressions.");
567              $$ = new SelectCase(new IntLiteral(0), $3);              $$ = new SelectCase(new IntLiteral(0), $3);
# Line 323  caseclauses: Line 579  caseclauses:
579      }      }
580    
581  caseclause:  caseclause:
582      CASE INTEGER statements  {      CASE INTEGER opt_statements  {
583          $$ = CaseBranch();          $$ = CaseBranch();
584          $$.from = new IntLiteral($2);          $$.from = new IntLiteral($2);
585          $$.statements = $3;          $$.statements = $3;
586      }      }
587      | CASE INTEGER TO INTEGER statements  {      | CASE INTEGER TO INTEGER opt_statements  {
588          $$ = CaseBranch();          $$ = CaseBranch();
589          $$.from = new IntLiteral($2);          $$.from = new IntLiteral($2);
590          $$.to   = new IntLiteral($4);          $$.to   = new IntLiteral($4);
591          $$.statements = $5;          $$.statements = $5;
592      }      }
593    
594    userfunctioncall:
595        CALL IDENTIFIER  {
596            const char* name = $2;
597            StatementsRef fn = context->userFunctionByName(name);
598            if (context->functionProvider->functionByName(name)) {
599                PARSE_ERR(@1, (String("Keyword 'call' must only be used for user defined functions, not for any built-in function like '") + name + "'.").c_str());
600                $$ = StatementsRef();
601            } else if (!fn) {
602                PARSE_ERR(@2, (String("No user defined function with name '") + name + "'.").c_str());
603                $$ = StatementsRef();
604            } else {
605                $$ = fn;
606            }
607        }
608    
609  functioncall:  functioncall:
610      IDENTIFIER '(' args ')'  {      IDENTIFIER '(' args ')'  {
611          const char* name = $1;          const char* name = $1;
612          //printf("function call of '%s' with args\n", name);          //printf("function call of '%s' with args\n", name);
613          ArgsRef args = $3;          ArgsRef args = $3;
614          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
615          if (!fn) {          if (context->userFunctionByName(name)) {
616                PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
617                $$ = new FunctionCall(name, args, NULL);
618            } else if (!fn) {
619              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
620              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
621            } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
622                PARSE_DROP(@$);
623                $$ = new NoFunctionCall;
624          } else if (args->argsCount() < fn->minRequiredArgs()) {          } else if (args->argsCount() < fn->minRequiredArgs()) {
625              PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());              PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
626              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
# Line 352  functioncall: Line 629  functioncall:
629              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
630          } else {          } else {
631              bool argsOK = true;              bool argsOK = true;
632              for (int i = 0; i < args->argsCount(); ++i) {              for (vmint i = 0; i < args->argsCount(); ++i) {
633                  if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {                  if (args->arg(i)->exprType() != fn->argType(i) && !fn->acceptsArgType(i, args->arg(i)->exprType())) {
634                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects " + typeStr(fn->argType(i)) + " type, but type " + typeStr(args->arg(i)->exprType()) + " was given instead.").c_str());                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects " + typeStr(fn->argType(i)) + " type, but type " + typeStr(args->arg(i)->exprType()) + " was given instead.").c_str());
635                      argsOK = false;                      argsOK = false;
# Line 361  functioncall: Line 638  functioncall:
638                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());                      PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects an assignable variable.").c_str());
639                      argsOK = false;                      argsOK = false;
640                      break;                      break;
641                    } else if (isScalarNumber(args->arg(i)->exprType()) && !fn->acceptsArgUnitType(i, args->arg(i)->asScalarNumberExpr()->unitType())) {
642                        if (args->arg(i)->asScalarNumberExpr()->unitType())
643                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect unit " + unitTypeStr(args->arg(i)->asScalarNumberExpr()->unitType()) +  ".").c_str());
644                        else
645                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' expects a unit.").c_str());
646                        argsOK = false;
647                        break;
648                    } else if (isScalarNumber(args->arg(i)->exprType()) && args->arg(i)->asScalarNumberExpr()->unitPrefix(0) && !fn->acceptsArgUnitPrefix(i, args->arg(i)->asScalarNumberExpr()->unitType())) {
649                        if (args->arg(i)->asScalarNumberExpr()->unitType())
650                            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)->asScalarNumberExpr()->unitType()) + ".").c_str());
651                        else
652                            PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a unit prefix.").c_str());
653                        argsOK = false;
654                        break;
655                    } else if (!fn->acceptsArgFinal(i) && isScalarNumber(args->arg(i)->exprType()) && args->arg(i)->asScalarNumberExpr()->isFinal()) {
656                        PARSE_ERR(@3, (String("Argument ") + ToString(i+1) + " of built-in function '" + name + "' does not expect a \"final\" value.").c_str());
657                        argsOK = false;
658                        break;
659                  }                  }
660              }              }
661              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);              $$ = new FunctionCall(name, args, argsOK ? fn : NULL);
# Line 371  functioncall: Line 666  functioncall:
666          //printf("function call of '%s' (with empty args)\n", name);          //printf("function call of '%s' (with empty args)\n", name);
667          ArgsRef args = new Args;          ArgsRef args = new Args;
668          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
669          if (!fn) {          if (context->userFunctionByName(name)) {
670                PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
671                $$ = new FunctionCall(name, args, NULL);
672            } else if (!fn) {
673              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
674              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
675            } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
676                PARSE_DROP(@$);
677                $$ = new NoFunctionCall;
678          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
679              PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());              PARSE_ERR(@3, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
680              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
# Line 386  functioncall: Line 687  functioncall:
687          //printf("function call of '%s' (without args)\n", name);          //printf("function call of '%s' (without args)\n", name);
688          ArgsRef args = new Args;          ArgsRef args = new Args;
689          VMFunction* fn = context->functionProvider->functionByName(name);          VMFunction* fn = context->functionProvider->functionByName(name);
690          if (!fn) {          if (context->userFunctionByName(name)) {
691                PARSE_ERR(@1, (String("Missing 'call' keyword before user defined function name '") + name + "'.").c_str());
692                $$ = new FunctionCall(name, args, NULL);
693            } else if (!fn) {
694              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No built-in function with name '") + name + "'.").c_str());
695              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
696            } else if (context->functionProvider->isFunctionDisabled(fn,context)) {
697                PARSE_DROP(@$);
698                $$ = new NoFunctionCall;
699          } else if (fn->minRequiredArgs() > 0) {          } else if (fn->minRequiredArgs() > 0) {
700              PARSE_ERR(@1, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());              PARSE_ERR(@1, (String("Built-in function '") + name + "' requires at least " + ToString(fn->minRequiredArgs()) + " arguments.").c_str());
701              $$ = new FunctionCall(name, args, NULL);              $$ = new FunctionCall(name, args, NULL);
# Line 423  assignment: Line 730  assignment:
730              PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());              PARSE_ERR(@2, (String("Variable assignment: Variable '") + name + "' is not assignable.").c_str());
731          else if (var->exprType() != $3->exprType())          else if (var->exprType() != $3->exprType())
732              PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' is of type " + typeStr(var->exprType()) + ", assignment is of type " + typeStr($3->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' is of type " + typeStr(var->exprType()) + ", assignment is of type " + typeStr($3->exprType()) + " though.").c_str());
733            else if (isScalarNumber(var->exprType())) {
734                ScalarNumberVariableRef numberVar = var;
735                ScalarNumberExprRef expr = $3;
736                if (numberVar->unitType() != expr->unitType())
737                    PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has unit type " + unitTypeStr(numberVar->unitType()) + ", assignment has unit type " + unitTypeStr(expr->unitType()) + " though.").c_str());
738                else if (numberVar->unitFactor() != expr->unitFactor())
739                    PARSE_ERR(@3, (String("Variable assignment: Variable '") + name + "' has a different unit prefix.").c_str());
740                else if (numberVar->isFinal() != expr->isFinal())
741                    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());
742            }
743          $$ = new Assignment(var, $3);          $$ = new Assignment(var, $3);
744      }      }
745      | VARIABLE '[' expr ']' ASSIGNMENT expr  {      | VARIABLE '[' expr ']' ASSIGNMENT expr  {
# Line 430  assignment: Line 747  assignment:
747          VariableRef var = context->variableByName(name);          VariableRef var = context->variableByName(name);
748          if (!var)          if (!var)
749              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
750          else if (var->exprType() != INT_ARR_EXPR)          else if (!isArray(var->exprType()))
751              PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());              PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
752            else if (var->isConstExpr())
753                PARSE_ERR(@5, (String("Variable assignment: Cannot modify const array variable '") + name + "'.").c_str());
754            else if (!var->isAssignable())
755                PARSE_ERR(@5, (String("Variable assignment: Array variable '") + name + "' is not assignable.").c_str());
756          else if ($3->exprType() != INT_EXPR)          else if ($3->exprType() != INT_EXPR)
757              PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());              PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
758          else if ($6->exprType() != INT_EXPR)          else if ($3->asInt()->unitType())
759              PARSE_ERR(@5, (String("Value assigned to array variable '") + name + "' must be an integer expression.").c_str());              PARSE_ERR(@3, "Unit types are not allowed as array index.");
760          IntArrayElementRef element = new IntArrayElement(var, $3);          else if ($6->exprType() != var->exprType())
761          $$ = new Assignment(element, $6);              PARSE_ERR(@5, (String("Variable '") + name + "' was declared as " + typeStr(var->exprType()) + ", assigned expression is " + typeStr($6->exprType()) + " though.").c_str());
762            else if ($6->asScalarNumberExpr()->unitType())
763                PARSE_ERR(@6, "Unit types are not allowed for array variables.");
764            else if ($6->asScalarNumberExpr()->isFinal())
765                PARSE_ERR(@6, "Final operator '!' not allowed for array variables.");
766            else if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
767                PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
768                              " exceeds size of array variable '" + name +
769                              "' which was declared with size " +
770                              ToString(((ArrayExprRef)var)->arraySize()) + ".").c_str());
771            else if ($3->asInt()->isFinal())
772                PARSE_WRN(@3, "Final operator '!' is meaningless here.");
773            if (var->exprType() == INT_ARR_EXPR) {
774                IntArrayElementRef element = new IntArrayElement(var, $3);
775                $$ = new Assignment(element, $6);
776            } else if (var->exprType() == REAL_ARR_EXPR) {
777                RealArrayElementRef element = new RealArrayElement(var, $3);
778                $$ = new Assignment(element, $6);
779            } else {
780                $$ = new NoOperation;
781            }
782      }      }
783    
784  unary_expr:  unary_expr:
785      INTEGER  {      INTEGER  {
786          $$ = new IntLiteral($1);          $$ = new IntLiteral($1);
787      }      }
788        | REAL  {
789            $$ = new RealLiteral($1);
790        }
791        | INTEGER_UNIT  {
792            IntLiteralRef literal = new IntLiteral($1.iValue);
793            literal->setUnit($1.prefix, $1.unit);
794            $$ = literal;
795        }
796        | REAL_UNIT  {
797            RealLiteralRef literal = new RealLiteral($1.fValue);
798            literal->setUnit($1.prefix, $1.unit);
799            $$ = literal;
800        }
801      | STRING    {      | STRING    {
802          $$ = new StringLiteral($1);          $$ = new StringLiteral($1);
803      }      }
# Line 463  unary_expr: Line 817  unary_expr:
817          if (!var) {          if (!var) {
818              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());              PARSE_ERR(@1, (String("No variable declared with name '") + name + "'.").c_str());
819              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
820          } else if (var->exprType() != INT_ARR_EXPR) {          } else if (!isArray(var->exprType())) {
821              PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());              PARSE_ERR(@2, (String("Variable '") + name + "' is not an array variable.").c_str());
822              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
823          } else if ($3->exprType() != INT_EXPR) {          } else if ($3->exprType() != INT_EXPR) {
824              PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());              PARSE_ERR(@3, (String("Array variable '") + name + "' accessed with non integer expression.").c_str());
825              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
826            } else if ($3->asInt()->unitType() || $3->asInt()->unitPrefix(0)) {
827                PARSE_ERR(@3, "Units are not allowed as array index.");
828                $$ = new IntLiteral(0);
829          } else {          } else {
830              $$ = new IntArrayElement(var, $3);              if ($3->isConstExpr() && $3->asInt()->evalInt() >= ((ArrayExprRef)var)->arraySize())
831                    PARSE_WRN(@3, (String("Index ") + ToString($3->asInt()->evalInt()) +
832                                   " exceeds size of array variable '" + name +
833                                   "' which was declared with size " +
834                                   ToString(((ArrayExprRef)var)->arraySize()) + ".").c_str());
835                else if ($3->asInt()->isFinal())
836                    PARSE_WRN(@3, "Final operator '!' is meaningless here.");
837                if (var->exprType() == REAL_ARR_EXPR) {
838                    $$ = new RealArrayElement(var, $3);
839                } else {
840                    $$ = new IntArrayElement(var, $3);
841                }
842          }          }
843      }      }
844      | '(' expr ')'  {      | '(' expr ')'  {
# Line 486  unary_expr: Line 854  unary_expr:
854          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
855              PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());              PARSE_ERR(@2, (String("Right operand of bitwise operator '.not.' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
856              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
857            } else if ($2->asInt()->unitType() || $2->asInt()->unitPrefix(0)) {
858                PARSE_ERR(@2, "Units are not allowed for operands of bitwise operations.");
859                $$ = new IntLiteral(0);
860          } else {          } else {
861              $$ = new BitwiseNot($2);              $$ = new BitwiseNot($2);
862          }          }
# Line 494  unary_expr: Line 865  unary_expr:
865          if ($2->exprType() != INT_EXPR) {          if ($2->exprType() != INT_EXPR) {
866              PARSE_ERR(@2, (String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());              PARSE_ERR(@2, (String("Right operand of operator 'not' must be an integer expression, is ") + typeStr($2->exprType()) + " though.").c_str());
867              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
868            } else if ($2->asInt()->unitType() || $2->asInt()->unitPrefix(0)) {
869                PARSE_ERR(@2, "Units are not allowed for operands of logical operations.");
870                $$ = new IntLiteral(0);
871          } else {          } else {
872              $$ = new Not($2);              $$ = new Not($2);
873          }          }
874      }      }
875        | '!' unary_expr  {
876            if (!isScalarNumber($2->exprType())) {
877                PARSE_ERR(@2, (String("Right operand of \"final\" operator '!' must be a scalar number expression, is ") + typeStr($2->exprType()) + " though.").c_str());
878                $$ = new IntLiteral(0);
879            } else {
880                $$ = new Final($2);
881            }
882        }
883    
884  expr:  expr:
885      concat_expr      concat_expr
# Line 527  logical_or_expr: Line 909  logical_or_expr:
909          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
910              PARSE_ERR(@3, (String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator 'or' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
911              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
912            } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
913                PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
914                $$ = new IntLiteral(0);
915            } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
916                PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
917                $$ = new IntLiteral(0);
918          } else {          } else {
919              $$ = new Or(lhs, rhs);              $$ = new Or(lhs, rhs);
920          }          }
# Line 545  logical_and_expr: Line 933  logical_and_expr:
933          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
934              PARSE_ERR(@3, (String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator 'and' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
935              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
936            } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
937                PARSE_ERR(@1, "Units are not allowed for operands of logical operations.");
938                $$ = new IntLiteral(0);
939            } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
940                PARSE_ERR(@3, "Units are not allowed for operands of logical operations.");
941                $$ = new IntLiteral(0);
942          } else {          } else {
943              $$ = new And(lhs, rhs);              $$ = new And(lhs, rhs);
944          }          }
# Line 561  bitwise_or_expr: Line 955  bitwise_or_expr:
955          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
956              PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of bitwise operator '.or.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
957              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
958            } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
959                PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
960                $$ = new IntLiteral(0);
961            } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
962                PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
963                $$ = new IntLiteral(0);
964          } else {          } else {
965              $$ = new BitwiseOr(lhs, rhs);              $$ = new BitwiseOr(lhs, rhs);
966          }          }
# Line 579  bitwise_and_expr: Line 979  bitwise_and_expr:
979          } else if (rhs->exprType() != INT_EXPR) {          } else if (rhs->exprType() != INT_EXPR) {
980              PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of bitwise operator '.and.' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
981              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
982            } else if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0)) {
983                PARSE_ERR(@1, "Units are not allowed for operands of bitwise operations.");
984                $$ = new IntLiteral(0);
985            } else if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0)) {
986                PARSE_ERR(@3, "Units are not allowed for operands of bitwise operations.");
987                $$ = new IntLiteral(0);
988          } else {          } else {
989              $$ = new BitwiseAnd(lhs, rhs);              $$ = new BitwiseAnd(lhs, rhs);
990          }          }
# Line 589  rel_expr: Line 995  rel_expr:
995      | rel_expr '<' add_expr  {      | rel_expr '<' add_expr  {
996          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
997          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
998          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
999              PARSE_ERR(@1, (String("Left operand of operator '<' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '<' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1000              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1001          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1002              PARSE_ERR(@3, (String("Right operand of operator '<' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '<' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1003                $$ = new IntLiteral(0);
1004            } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||
1005                       lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())
1006            {
1007                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
1008              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1009          } else {          } else {
1010              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);              $$ = new Relation(lhs, Relation::LESS_THAN, rhs);
# Line 602  rel_expr: Line 1013  rel_expr:
1013      | rel_expr '>' add_expr  {      | rel_expr '>' add_expr  {
1014          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1015          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1016          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1017              PARSE_ERR(@1, (String("Left operand of operator '>' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '>' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1018              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1019          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1020              PARSE_ERR(@3, (String("Right operand of operator '>' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '>' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1021                $$ = new IntLiteral(0);
1022            } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||
1023                       lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())
1024            {
1025                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
1026              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1027          } else {          } else {
1028              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);              $$ = new Relation(lhs, Relation::GREATER_THAN, rhs);
# Line 615  rel_expr: Line 1031  rel_expr:
1031      | rel_expr LE add_expr  {      | rel_expr LE add_expr  {
1032          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1033          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1034          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1035              PARSE_ERR(@1, (String("Left operand of operator '<=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '<=' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1036              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1037          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1038              PARSE_ERR(@3, (String("Right operand of operator '<=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '<=' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1039                $$ = new IntLiteral(0);
1040            } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||
1041                       lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())
1042            {
1043                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
1044              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1045          } else {          } else {
1046              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::LESS_OR_EQUAL, rhs);
# Line 628  rel_expr: Line 1049  rel_expr:
1049      | rel_expr GE add_expr  {      | rel_expr GE add_expr  {
1050          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1051          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1052          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1053              PARSE_ERR(@1, (String("Left operand of operator '>=' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '>=' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1054              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1055          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1056              PARSE_ERR(@3, (String("Right operand of operator '>=' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of operator '>=' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1057                $$ = new IntLiteral(0);
1058            } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||
1059                       lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())
1060            {
1061                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
1062              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1063          } else {          } else {
1064              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);              $$ = new Relation(lhs, Relation::GREATER_OR_EQUAL, rhs);
1065          }          }
1066      }      }
1067      | rel_expr '=' add_expr  {      | rel_expr '=' add_expr  {
1068          $$ = new Relation($1, Relation::EQUAL, $3);          ExpressionRef lhs = $1;
1069            ExpressionRef rhs = $3;
1070            if (!isScalarNumber(lhs->exprType())) {
1071                PARSE_ERR(@1, (String("Left operand of operator '=' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1072                $$ = new IntLiteral(0);
1073            } else if (!isScalarNumber(rhs->exprType())) {
1074                PARSE_ERR(@3, (String("Right operand of operator '=' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1075                $$ = new IntLiteral(0);
1076            } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||
1077                       lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())
1078            {
1079                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
1080                $$ = new IntLiteral(0);
1081            } else {
1082                $$ = new Relation(lhs, Relation::EQUAL, rhs);
1083            }
1084      }      }
1085      | rel_expr '#' add_expr  {      | rel_expr '#' add_expr  {
1086          $$ = new Relation($1, Relation::NOT_EQUAL, $3);          ExpressionRef lhs = $1;
1087            ExpressionRef rhs = $3;
1088            if (!isScalarNumber(lhs->exprType())) {
1089                PARSE_ERR(@1, (String("Left operand of operator '#' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1090                $$ = new IntLiteral(0);
1091            } else if (!isScalarNumber(rhs->exprType())) {
1092                PARSE_ERR(@3, (String("Right operand of operator '#' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1093                $$ = new IntLiteral(0);
1094            } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||
1095                       lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())
1096            {
1097                PARSE_ERR(@2, "Operands of relative operations must have same unit.");
1098                $$ = new IntLiteral(0);
1099            } else {
1100                $$ = new Relation(lhs, Relation::NOT_EQUAL, rhs);
1101            }
1102      }      }
1103    
1104  add_expr:  add_expr:
# Line 650  add_expr: Line 1106  add_expr:
1106      | add_expr '+' mul_expr  {      | add_expr '+' mul_expr  {
1107          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1108          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1109          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1110              PARSE_ERR(@1, (String("Left operand of operator '+' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '+' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1111              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1112          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1113              PARSE_ERR(@3, (String("Right operand of operator '+' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Right operand of operator '+' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1114                $$ = new IntLiteral(0);
1115            } else if (lhs->exprType() != rhs->exprType()) {
1116                PARSE_ERR(@2, (String("Operands of operator '+' must have same type; left operand is ") +
1117                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1118                $$ = new IntLiteral(0);
1119            } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||
1120                       lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())
1121            {
1122                PARSE_ERR(@2, "Operands of '+' operations must have same unit.");
1123              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1124          } else {          } else {
1125              $$ = new Add(lhs,rhs);              $$ = new Add(lhs,rhs);
# Line 663  add_expr: Line 1128  add_expr:
1128      | add_expr '-' mul_expr  {      | add_expr '-' mul_expr  {
1129          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1130          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1131          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1132              PARSE_ERR(@1, (String("Left operand of operator '-' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '-' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1133              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1134          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1135              PARSE_ERR(@3, (String("Right operand of operator '-' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Right operand of operator '-' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1136                $$ = new IntLiteral(0);
1137            } else if (lhs->exprType() != rhs->exprType()) {
1138                PARSE_ERR(@2, (String("Operands of operator '-' must have same type; left operand is ") +
1139                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1140                $$ = new IntLiteral(0);
1141            } else if (lhs->asScalarNumberExpr()->unitType()   != rhs->asScalarNumberExpr()->unitType() ||
1142                       lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor())
1143            {
1144                PARSE_ERR(@2, "Operands of '-' operations must have same unit.");
1145              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1146          } else {          } else {
1147              $$ = new Sub(lhs,rhs);              $$ = new Sub(lhs,rhs);
# Line 679  mul_expr: Line 1153  mul_expr:
1153      | mul_expr '*' unary_expr  {      | mul_expr '*' unary_expr  {
1154          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1155          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1156          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1157              PARSE_ERR(@1, (String("Left operand of operator '*' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '*' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1158              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1159          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1160              PARSE_ERR(@3, (String("Right operand of operator '*' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Right operand of operator '*' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1161                $$ = new IntLiteral(0);
1162            } else if (lhs->asScalarNumberExpr()->unitType() && rhs->asScalarNumberExpr()->unitType()) {
1163                PARSE_ERR(@2, "Only one operand of operator '*' may have a unit type");
1164                $$ = new IntLiteral(0);
1165            } else if (lhs->exprType() != rhs->exprType()) {
1166                PARSE_ERR(@2, (String("Operands of operator '*' must have same type; left operand is ") +
1167                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1168                $$ = new IntLiteral(0);
1169            } else if (lhs->asScalarNumberExpr()->unitPrefix(0) && rhs->asScalarNumberExpr()->unitPrefix(0)) {
1170                PARSE_ERR(@2, "Only one operand of operator '*' may have a unit prefix");
1171              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1172          } else {          } else {
1173              $$ = new Mul(lhs,rhs);              $$ = new Mul(lhs,rhs);
# Line 692  mul_expr: Line 1176  mul_expr:
1176      | mul_expr '/' unary_expr  {      | mul_expr '/' unary_expr  {
1177          ExpressionRef lhs = $1;          ExpressionRef lhs = $1;
1178          ExpressionRef rhs = $3;          ExpressionRef rhs = $3;
1179          if (lhs->exprType() != INT_EXPR) {          if (!isScalarNumber(lhs->exprType())) {
1180              PARSE_ERR(@1, (String("Left operand of operator '/' must be an integer expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Left operand of operator '/' must be a scalar number expression, is ") + typeStr(lhs->exprType()) + " though.").c_str());
1181              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1182          } else if (rhs->exprType() != INT_EXPR) {          } else if (!isScalarNumber(rhs->exprType())) {
1183              PARSE_ERR(@3, (String("Right operand of operator '/' must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@1, (String("Right operand of operator '/' must be a scalar number expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1184                $$ = new IntLiteral(0);
1185            } else if (lhs->asScalarNumberExpr()->unitType() && rhs->asScalarNumberExpr()->unitType() &&
1186                       lhs->asScalarNumberExpr()->unitType() != rhs->asScalarNumberExpr()->unitType())
1187            {
1188                PARSE_ERR(@2, "Operands of operator '/' with two different unit types.");
1189                $$ = new IntLiteral(0);
1190            } else if (!lhs->asScalarNumberExpr()->unitType() && rhs->asScalarNumberExpr()->unitType()) {
1191                PARSE_ERR(@3, ("Dividing left operand without any unit type by right operand with unit type " + typeStr(rhs->exprType()) + " is not possible.").c_str());
1192                $$ = new IntLiteral(0);
1193            } else if (lhs->asScalarNumberExpr()->unitFactor()  != rhs->asScalarNumberExpr()->unitFactor() &&
1194                       lhs->asScalarNumberExpr()->unitPrefix(0) && rhs->asScalarNumberExpr()->unitPrefix(0))
1195            {
1196                PARSE_ERR(@2, "Dividing two operands with two different unit prefixes is not possible.");
1197                $$ = new IntLiteral(0);
1198            } else if (lhs->asScalarNumberExpr()->unitFactor() != rhs->asScalarNumberExpr()->unitFactor() &&
1199                       rhs->asScalarNumberExpr()->unitPrefix(0))
1200            {
1201                PARSE_ERR(@3, "Dividing left operand without any unit prefix by right operand with unit prefix is not possible.");
1202                $$ = new IntLiteral(0);
1203            } else if (lhs->exprType() != rhs->exprType()) {
1204                PARSE_ERR(@2, (String("Operands of operator '/' must have same type; left operand is ") +
1205                          typeStr(lhs->exprType()) + " and right operand is " + typeStr(rhs->exprType()) + " though.").c_str());
1206              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1207          } else {          } else {
1208              $$ = new Div(lhs,rhs);              $$ = new Div(lhs,rhs);
# Line 712  mul_expr: Line 1218  mul_expr:
1218              PARSE_ERR(@3, (String("Right operand of modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());              PARSE_ERR(@3, (String("Right operand of modulo operator must be an integer expression, is ") + typeStr(rhs->exprType()) + " though.").c_str());
1219              $$ = new IntLiteral(0);              $$ = new IntLiteral(0);
1220          } else {          } else {
1221                if (lhs->asInt()->unitType() || lhs->asInt()->unitPrefix(0))
1222                    PARSE_ERR(@1, "Operands of modulo operator must not use any unit.");
1223                if (rhs->asInt()->unitType() || rhs->asInt()->unitPrefix(0))
1224                    PARSE_ERR(@3, "Operands of modulo operator must not use any unit.");
1225              $$ = new Mod(lhs,rhs);              $$ = new Mod(lhs,rhs);
1226          }          }
1227      }      }
# Line 727  void InstrScript_warning(YYLTYPE* locp, Line 1237  void InstrScript_warning(YYLTYPE* locp,
1237      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);      //fprintf(stderr, "WRN %d: %s\n", locp->first_line, txt);
1238      context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);      context->addWrn(locp->first_line, locp->last_line, locp->first_column+1, locp->last_column+1, txt);
1239  }  }
1240    
1241    /// Custom implementation of yytnamerr() to ensure quotation is always stripped from token names before printing them to error messages.
1242    int InstrScript_tnamerr(char* yyres, const char* yystr) {
1243      if (*yystr == '"') {
1244          int yyn = 0;
1245          char const *yyp = yystr;
1246          for (;;)
1247            switch (*++yyp)
1248              {
1249    /*
1250              case '\'':
1251              case ',':
1252                goto do_not_strip_quotes;
1253    
1254              case '\\':
1255                if (*++yyp != '\\')
1256                  goto do_not_strip_quotes;
1257    */
1258                /* Fall through.  */
1259              default:
1260                if (yyres)
1261                  yyres[yyn] = *yyp;
1262                yyn++;
1263                break;
1264    
1265              case '"':
1266                if (yyres)
1267                  yyres[yyn] = '\0';
1268                return yyn;
1269              }
1270    /*
1271        do_not_strip_quotes: ;
1272    */
1273        }
1274    
1275      if (! yyres)
1276        return (int) yystrlen (yystr);
1277    
1278      return int( yystpcpy (yyres, yystr) - yyres );
1279    }

Legend:
Removed from v.2945  
changed lines
  Added in v.3573

  ViewVC Help
Powered by ViewVC