this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3/*
4 * Main authors:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7
8/* This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12%define api.pure
13
14%parse-param {void *parm}
15
16%define api.header.include {<minizinc/parser.tab.hh>}
17
18%lex-param {void* SCANNER}
19%{
20#define SCANNER static_cast<ParserState*>(parm)->yyscanner
21#include <iostream>
22#include <fstream>
23#include <map>
24#include <cerrno>
25
26namespace MiniZinc{ class ParserLocation; }
27#define YYLTYPE MiniZinc::ParserLocation
28#define YYLTYPE_IS_DECLARED 1
29#define YYLTYPE_IS_TRIVIAL 0
30
31#define YYMAXDEPTH 10000
32#define YYINITDEPTH 10000
33
34#include <minizinc/parser.hh>
35#include <minizinc/file_utils.hh>
36
37using namespace std;
38using namespace MiniZinc;
39
40#define YYLLOC_DEFAULT(Current, Rhs, N) \
41 (Current).filename(Rhs[1].filename()); \
42 (Current).first_line(Rhs[1].first_line()); \
43 (Current).first_column(Rhs[1].first_column()); \
44 (Current).last_line(Rhs[N].last_line()); \
45 (Current).last_column(Rhs[N].last_column());
46
47int mzn_yyparse(void*);
48int mzn_yylex(YYSTYPE*, YYLTYPE*, void* scanner);
49int mzn_yylex_init (void** scanner);
50int mzn_yylex_destroy (void* scanner);
51int mzn_yyget_lineno (void* scanner);
52void mzn_yyset_extra (void* user_defined ,void* yyscanner );
53
54extern int yydebug;
55
56void yyerror(YYLTYPE* location, void* parm, const string& str) {
57 ParserState* pp = static_cast<ParserState*>(parm);
58 Model* m = pp->model;
59 while (m->parent() != NULL) {
60 m = m->parent();
61 pp->err << "(included from file '" << m->filename() << "')" << endl;
62 }
63 pp->err << location->toString() << ":" << endl;
64 pp->printCurrentLine(location->first_column(),location->last_column());
65 pp->err << "Error: " << str << std::endl;
66 pp->hadError = true;
67 pp->syntaxErrors.push_back(SyntaxError(Location(*location), str));
68}
69
70bool notInDatafile(YYLTYPE* location, void* parm, const string& item) {
71 ParserState* pp = static_cast<ParserState*>(parm);
72 if (pp->isDatafile) {
73 yyerror(location,parm,item+" item not allowed in data file");
74 return false;
75 }
76 return true;
77}
78
79Expression* createDocComment(const ParserLocation& loc, const std::string& s) {
80 std::vector<Expression*> args(1);
81 args[0] = new StringLit(loc, s);
82 Call* c = new Call(Location(loc), constants().ann.doc_comment, args);
83 c->type(Type::ann());
84 return c;
85}
86
87Expression* createArrayAccess(const ParserLocation& loc, Expression* e, std::vector<std::vector<Expression*> >& idx) {
88 Expression* ret = e;
89 for (unsigned int i=0; i<idx.size(); i++) {
90 ret = new ArrayAccess(Location(loc), ret, idx[i]);
91 }
92 return ret;
93}
94
95
96
97%}
98
99%union { long long int iValue; char* sValue; bool bValue; double dValue;
100 MiniZinc::Item* item;
101 MiniZinc::VarDecl* vardeclexpr;
102 std::vector<MiniZinc::VarDecl*>* vardeclexpr_v;
103 MiniZinc::TypeInst* tiexpr;
104 std::vector<MiniZinc::TypeInst*>* tiexpr_v;
105 MiniZinc::Expression* expression;
106 std::vector<MiniZinc::Expression*>* expression_v;
107 std::vector<std::vector<MiniZinc::Expression*> >* expression_vv;
108 std::vector<std::vector<std::vector<MiniZinc::Expression*> > >* expression_vvv;
109 MiniZinc::Generator* generator;
110 std::vector<MiniZinc::Generator>* generator_v;
111 std::vector<std::string>* string_v;
112 std::vector<std::pair<MiniZinc::Expression*,MiniZinc::Expression*> >* expression_p;
113 MiniZinc::Generators* generators;
114 }
115
116%locations
117%define parse.error verbose
118
119%initial-action
120{
121 GCLock lock;
122 @$.filename(ASTString(static_cast<ParserState*>(parm)->filename));
123}
124
125%token <iValue> MZN_INTEGER_LITERAL "integer literal" MZN_BOOL_LITERAL "bool literal"
126%token <dValue> MZN_FLOAT_LITERAL "float literal"
127%token <sValue> MZN_IDENTIFIER "identifier" MZN_QUOTED_IDENTIFIER "quoted identifier" MZN_STRING_LITERAL "string literal"
128%token <sValue> MZN_STRING_QUOTE_START "interpolated string start" MZN_STRING_QUOTE_MID "interpolated string middle" MZN_STRING_QUOTE_END "interpolated string end"
129%token <sValue> MZN_TI_IDENTIFIER "type-inst identifier" MZN_TI_ENUM_IDENTIFIER "type-inst enum identifier" MZN_DOC_COMMENT "documentation comment" MZN_DOC_FILE_COMMENT "file-level documentation comment"
130
131%token MZN_VAR "var" MZN_PAR "par"
132
133%token MZN_ABSENT "<>"
134%token MZN_ANN "ann"
135%token MZN_ANNOTATION "annotation"
136%token MZN_ANY "any"
137%token MZN_ARRAY "array"
138%token MZN_BOOL "bool"
139%token MZN_CASE "case"
140%token MZN_CONSTRAINT "constraint"
141%token MZN_DEFAULT "default"
142%token MZN_ELSE "else"
143%token MZN_ELSEIF "elseif"
144%token MZN_ENDIF "endif"
145%token MZN_ENUM "enum"
146%token MZN_FLOAT "float"
147%token MZN_FUNCTION "function"
148%token MZN_IF "if"
149%token MZN_INCLUDE "include"
150%token MZN_INFINITY "infinity"
151%token MZN_INT "int"
152%token MZN_LET "let"
153%token MZN_LIST "list"
154%token <bValue> MZN_MAXIMIZE "maximize"
155%token <bValue> MZN_MINIMIZE "minimize"
156%token MZN_OF "of"
157%token MZN_OPT "opt"
158%token MZN_SATISFY "satisfy"
159%token MZN_OUTPUT "output"
160%token MZN_PREDICATE "predicate"
161%token MZN_RECORD "record"
162%token MZN_SET "set"
163%token MZN_SOLVE "solve"
164%token MZN_STRING "string"
165%token MZN_TEST "test"
166%token MZN_THEN "then"
167%token MZN_TUPLE "tuple"
168%token MZN_TYPE "type"
169%token MZN_UNDERSCORE "_"
170%token MZN_VARIANT_RECORD "variant_record"
171%token MZN_WHERE "where"
172
173%token MZN_LEFT_BRACKET "["
174%token MZN_LEFT_2D_BRACKET "[|"
175%token MZN_RIGHT_BRACKET "]"
176%token MZN_RIGHT_2D_BRACKET "|]"
177
178// Used to signal an error when parsing a MiniZinc file
179// that contains identifiers starting with _
180%token FLATZINC_IDENTIFIER
181
182%token MZN_INVALID_INTEGER_LITERAL "invalid integer literal"
183%token MZN_INVALID_FLOAT_LITERAL "invalid float literal"
184%token MZN_UNTERMINATED_STRING "unterminated string"
185%token MZN_END_OF_LINE_IN_STRING "end of line inside string literal"
186%token MZN_INVALID_NULL "null character"
187
188%token END 0 "end of file"
189
190%token MZN_EQUIV "<->"
191%token MZN_IMPL "->" MZN_RIMPL "<-"
192%token MZN_OR "\\/" MZN_XOR "xor"
193%token MZN_AND "/\\"
194%token MZN_LE "<" MZN_GR ">" MZN_LQ "<=" MZN_GQ ">=" MZN_EQ "=" MZN_NQ "!=" MZN_WEAK_EQ "~="
195%token MZN_IN "in" MZN_SUBSET "subset" MZN_SUPERSET "superset"
196%token MZN_UNION "union" MZN_DIFF "diff" MZN_SYMDIFF "symdiff"
197%token MZN_DOTDOT ".."
198%token MZN_PLUS "+" MZN_MINUS "-" MZN_WEAK_PLUS "~+" MZN_WEAK_MINUS "~-"
199%token MZN_MULT "*" MZN_DIV "/" MZN_IDIV "div" MZN_MOD "mod" MZN_INTERSECT "intersect" MZN_WEAK_MULT "~*"
200%token MZN_POW "^"
201%token MZN_NOT "not"
202%token MZN_PLUSPLUS "++"
203%token MZN_COLONCOLON "::"
204
205%right PREC_ANNO
206%left MZN_EQUIV
207%left MZN_IMPL MZN_RIMPL
208%left MZN_OR MZN_XOR
209%left MZN_AND
210%nonassoc MZN_LE MZN_GR MZN_LQ MZN_GQ MZN_EQ MZN_NQ MZN_WEAK_EQ
211%nonassoc MZN_IN MZN_SUBSET MZN_SUPERSET
212%left MZN_UNION MZN_DIFF MZN_SYMDIFF MZN_INTERSECT
213%nonassoc MZN_DOTDOT
214%left MZN_PLUS MZN_MINUS MZN_WEAK_PLUS MZN_WEAK_MINUS
215%left MZN_MULT MZN_DIV MZN_IDIV MZN_MOD MZN_WEAK_MULT
216%left MZN_POW
217%nonassoc MZN_NOT
218%left MZN_PLUSPLUS
219%left MZN_QUOTED_IDENTIFIER
220%left MZN_COLONCOLON
221
222%token MZN_EQUIV_QUOTED "'<->'"
223%token MZN_IMPL_QUOTED "'->'" MZN_RIMPL_QUOTED "'<-'"
224%token MZN_OR_QUOTED "'\\/'" MZN_XOR_QUOTED "'xor'"
225%token MZN_AND_QUOTED "'/\\'"
226%token MZN_LE_QUOTED "'<'" MZN_GR_QUOTED "'>'" MZN_LQ_QUOTED "'<='" MZN_GQ_QUOTED "'>='" MZN_EQ_QUOTED "'='" MZN_NQ_QUOTED "'!='"
227%token MZN_IN_QUOTED "'in'" MZN_SUBSET_QUOTED "'subset'" MZN_SUPERSET_QUOTED "'superset'"
228%token MZN_UNION_QUOTED "'union'" MZN_DIFF_QUOTED "'diff'" MZN_SYMDIFF_QUOTED "'symdiff'"
229%token MZN_DOTDOT_QUOTED "'..'"
230%token MZN_PLUS_QUOTED "'+'" MZN_MINUS_QUOTED "'-'"
231%token MZN_MULT_QUOTED "'*'" MZN_DIV_QUOTED "'/'" MZN_IDIV_QUOTED "'div'" MZN_MOD_QUOTED "'mod'" MZN_INTERSECT_QUOTED "'intersect'"
232%token MZN_POW_QUOTED "'^'"
233%token MZN_NOT_QUOTED "'not'"
234%token MZN_COLONCOLON_QUOTED "'::'"
235%token MZN_PLUSPLUS_QUOTED "'++'"
236
237%type <item> item item_tail include_item vardecl_item assign_item constraint_item solve_item output_item predicate_item annotation_item function_item
238
239%type <vardeclexpr> ti_expr_and_id ti_expr_and_id_or_anon let_vardecl_item
240%type <vardeclexpr_v> params params_list params_list_head
241%type <tiexpr> ti_expr base_ti_expr base_ti_expr_tail
242%type <tiexpr_v> ti_expr_list ti_expr_list_head
243
244%type <expression> expr expr_atom_head expr_atom_head_nonstring array_access_expr
245%type <expression> set_expr string_expr string_quote_rest annotation_expr
246%type <expression> simple_array_literal simple_array_literal_2d simple_array_comp if_then_else_expr call_expr quoted_op_call let_expr operation_item_tail set_literal set_comp
247
248%type <expression_v> expr_list expr_list_head array_access_expr_list array_access_expr_list_head elseif_list let_vardecl_item_list enum_id_list string_lit_list
249%type <expression_vv> simple_array_literal_2d_list array_access_tail
250%type <expression_vvv> simple_array_literal_3d_list
251
252%type <generators> comp_tail
253%type <generator> generator generator_eq
254%type <generator_v> generator_list generator_list_head
255%type <string_v> id_list id_list_head
256
257%type <expression_p> comp_or_expr comp_or_expr_head
258
259%type <expression_v> annotations ne_annotations
260
261%type <iValue> quoted_op
262
263%type <sValue> id_or_quoted_op
264
265%type <bValue> opt_opt
266
267%%
268
269/********************************/
270/* main goal and item lists */
271/********************************/
272
273model : item_list
274
275item_list :
276 /* empty */
277 | item_list_head semi_or_none
278
279item_list_head:
280 item
281 {
282 ParserState* pp = static_cast<ParserState*>(parm);
283 if ($1) {
284 pp->model->addItem($1);
285 GC::unlock();
286 GC::lock();
287 }
288 }
289 | doc_file_comments item
290 {
291 ParserState* pp = static_cast<ParserState*>(parm);
292 if ($2) {
293 pp->model->addItem($2);
294 GC::unlock();
295 GC::lock();
296 }
297 }
298 | item_list_head ';' item
299 {
300 ParserState* pp = static_cast<ParserState*>(parm);
301 if ($3) {
302 pp->model->addItem($3);
303 GC::unlock();
304 GC::lock();
305 }
306 }
307 | item_list_head ';' doc_file_comments item
308 {
309 ParserState* pp = static_cast<ParserState*>(parm);
310 if ($4) {
311 pp->model->addItem($4);
312 GC::unlock();
313 GC::lock();
314 }
315 }
316 | item error_item_start
317{ yyerror(&@2, parm, "unexpected item, expecting ';' or end of file"); YYERROR; }
318 | error ';' item
319
320doc_file_comments:
321 MZN_DOC_FILE_COMMENT
322 {
323 ParserState* pp = static_cast<ParserState*>(parm);
324 if (pp->parseDocComments && $1) {
325 pp->model->addDocComment($1);
326 }
327 free($1);
328 }
329 | doc_file_comments MZN_DOC_FILE_COMMENT
330 {
331 ParserState* pp = static_cast<ParserState*>(parm);
332 if (pp->parseDocComments && $2) {
333 pp->model->addDocComment($2);
334 }
335 free($2);
336 }
337
338semi_or_none : | ';'
339
340item : MZN_DOC_COMMENT item_tail
341 { $$ = $2;
342 ParserState* pp = static_cast<ParserState*>(parm);
343 if (FunctionI* fi = Item::dyn_cast<FunctionI>($$)) {
344 if (pp->parseDocComments) {
345 fi->ann().add(createDocComment(@1,$1));
346 }
347 } else if (VarDeclI* vdi = Item::dyn_cast<VarDeclI>($$)) {
348 if (pp->parseDocComments) {
349 vdi->e()->addAnnotation(createDocComment(@1,$1));
350 }
351 } else {
352 yyerror(&@2, parm, "documentation comments are only supported for function, predicate and variable declarations");
353 }
354 free($1);
355 }
356 | item_tail
357 { $$ = $1; }
358
359item_tail :
360 include_item
361 { $$=notInDatafile(&@$,parm,"include") ? $1 : NULL; }
362 | vardecl_item
363 { $$=notInDatafile(&@$,parm,"variable declaration") ? $1 : NULL; }
364 | assign_item
365 | constraint_item
366 { $$=notInDatafile(&@$,parm,"constraint") ? $1 : NULL; }
367 | solve_item
368 { $$=notInDatafile(&@$,parm,"solve") ? $1 : NULL; }
369 | output_item
370 { $$=notInDatafile(&@$,parm,"output") ? $1 : NULL; }
371 | predicate_item
372 { $$=notInDatafile(&@$,parm,"predicate") ? $1 : NULL; }
373 | function_item
374 { $$=notInDatafile(&@$,parm,"predicate") ? $1 : NULL; }
375 | annotation_item
376 { $$=notInDatafile(&@$,parm,"annotation") ? $1 : NULL; }
377
378error_item_start : MZN_INCLUDE | MZN_ENUM | MZN_OUTPUT
379 | MZN_CONSTRAINT | MZN_SOLVE | MZN_PREDICATE | MZN_FUNCTION | MZN_TEST
380 | MZN_ANNOTATION
381
382include_item :
383 MZN_INCLUDE MZN_STRING_LITERAL
384 { ParserState* pp = static_cast<ParserState*>(parm);
385 map<string,Model*>::iterator ret = pp->seenModels.find($2);
386 IncludeI* ii = new IncludeI(@$,ASTString($2));
387 $$ = ii;
388 if (ret == pp->seenModels.end()) {
389 Model* im = new Model;
390 im->setParent(pp->model);
391 im->setFilename($2);
392 string fpath = FileUtils::dir_name(pp->filename);
393 string fbase = FileUtils::base_name(pp->filename);
394 if (fpath=="")
395 fpath="./";
396 ParseWorkItem pm(im, ii, fpath, $2);
397 pp->files.push_back(pm);
398 ii->m(im);
399 pp->seenModels.insert(pair<string,Model*>($2,im));
400 } else {
401 ii->m(ret->second, false);
402 }
403 free($2);
404 }
405
406vardecl_item :
407 ti_expr_and_id annotations
408 { if ($1 && $2) $1->addAnnotations(*$2);
409 if ($1)
410 $$ = new VarDeclI(@$,$1);
411 delete $2;
412 }
413 | ti_expr_and_id annotations MZN_EQ expr
414 { if ($1) $1->e($4);
415 if ($1 && $2) $1->addAnnotations(*$2);
416 if ($1)
417 $$ = new VarDeclI(@$,$1);
418 delete $2;
419 }
420 | MZN_ENUM MZN_IDENTIFIER
421 {
422 TypeInst* ti = new TypeInst(@$,Type::parsetint());
423 ti->setIsEnum(true);
424 VarDecl* vd = new VarDecl(@$,ti,$2);
425 free($2);
426 $$ = new VarDeclI(@$,vd);
427 }
428 | MZN_ENUM MZN_IDENTIFIER MZN_EQ '{' enum_id_list '}'
429 {
430 TypeInst* ti = new TypeInst(@$,Type::parsetint());
431 ti->setIsEnum(true);
432 SetLit* sl = new SetLit(@$, *$5);
433 VarDecl* vd = new VarDecl(@$,ti,$2,sl);
434 free($2);
435 delete $5;
436 $$ = new VarDeclI(@$,vd);
437 }
438 | MZN_ENUM MZN_IDENTIFIER MZN_EQ MZN_LEFT_BRACKET string_lit_list MZN_RIGHT_BRACKET
439 {
440 TypeInst* ti = new TypeInst(@$,Type::parsetint());
441 ti->setIsEnum(true);
442 vector<Expression*> args;
443 args.push_back(new ArrayLit(@$,*$5));
444 Call* sl = new Call(@$, constants().ids.anonEnumFromStrings, args);
445 VarDecl* vd = new VarDecl(@$,ti,$2,sl);
446 free($2);
447 delete $5;
448 $$ = new VarDeclI(@$,vd);
449 }
450 | MZN_ENUM MZN_IDENTIFIER MZN_EQ MZN_IDENTIFIER '(' expr ')'
451 {
452 TypeInst* ti = new TypeInst(@$,Type::parsetint());
453 ti->setIsEnum(true);
454 vector<Expression*> args;
455 args.push_back($6);
456 Call* sl = new Call(@$, ASTString($4), args);
457 VarDecl* vd = new VarDecl(@$,ti,$2,sl);
458 free($2);
459 free($4);
460 $$ = new VarDeclI(@$,vd);
461 }
462
463string_lit_list :
464 // empty
465 { $$ = new std::vector<Expression*>(); }
466 | MZN_STRING_LITERAL
467 { $$ = new std::vector<Expression*>();
468 $$->push_back(new StringLit(@$, $1)); free($1);
469 }
470 | string_lit_list ',' MZN_STRING_LITERAL
471 { $$ = $1;
472 if ($$) $$->push_back(new StringLit(@$, $3));
473 free($3);
474 }
475
476enum_id_list :
477 // empty
478 { $$ = new std::vector<Expression*>(); }
479 | MZN_IDENTIFIER
480 { $$ = new std::vector<Expression*>();
481 $$->push_back(new Id(@$,$1,NULL)); free($1);
482 }
483 | enum_id_list ',' MZN_IDENTIFIER
484 { $$ = $1; if ($$) $$->push_back(new Id(@$,$3,NULL)); free($3); }
485
486assign_item :
487 MZN_IDENTIFIER MZN_EQ expr
488 { $$ = new AssignI(@$,$1,$3);
489 free($1);
490 }
491
492constraint_item :
493 MZN_CONSTRAINT expr
494 { $$ = new ConstraintI(@$,$2);}
495 | MZN_CONSTRAINT MZN_COLONCOLON string_expr expr
496 { $$ = new ConstraintI(@$,$4);
497 if ($4 && $3)
498 $$->cast<ConstraintI>()->e()->ann().add(new Call(@2, ASTString("mzn_constraint_name"), {$3}));
499 }
500
501solve_item :
502 MZN_SOLVE annotations MZN_SATISFY
503 { $$ = SolveI::sat(@$);
504 if ($$ && $2) $$->cast<SolveI>()->ann().add(*$2);
505 delete $2;
506 }
507 | MZN_SOLVE annotations MZN_MINIMIZE expr
508 { $$ = SolveI::min(@$,$4);
509 if ($$ && $2) $$->cast<SolveI>()->ann().add(*$2);
510 delete $2;
511 }
512 | MZN_SOLVE annotations MZN_MAXIMIZE expr
513 { $$ = SolveI::max(@$,$4);
514 if ($$ && $2) $$->cast<SolveI>()->ann().add(*$2);
515 delete $2;
516 }
517
518output_item :
519 MZN_OUTPUT expr
520 { $$ = new OutputI(@$,$2);}
521
522predicate_item :
523 MZN_PREDICATE MZN_IDENTIFIER params annotations operation_item_tail
524 { if ($3) $$ = new FunctionI(@$,$2,new TypeInst(@$,
525 Type::varbool()),*$3,$5);
526 if ($$ && $4) $$->cast<FunctionI>()->ann().add(*$4);
527 free($2);
528 delete $3;
529 delete $4;
530 }
531 | MZN_TEST MZN_IDENTIFIER params annotations operation_item_tail
532 { if ($3) $$ = new FunctionI(@$,$2,new TypeInst(@$,
533 Type::parbool()),*$3,$5);
534 if ($$ && $4) $$->cast<FunctionI>()->ann().add(*$4);
535 free($2);
536 delete $3;
537 delete $4;
538 }
539
540function_item :
541 MZN_FUNCTION ti_expr ':' id_or_quoted_op params annotations operation_item_tail
542 { if ($5) $$ = new FunctionI(@$,$4,$2,*$5,$7);
543 if ($$ && $6) $$->cast<FunctionI>()->ann().add(*$6);
544 free($4);
545 delete $5;
546 delete $6;
547 }
548 | ti_expr ':' MZN_IDENTIFIER '(' params_list ')' annotations operation_item_tail
549 { if ($5) $$ = new FunctionI(@$,$3,$1,*$5,$8);
550 if ($$ && $7) $$->cast<FunctionI>()->ann().add(*$7);
551 free($3);
552 delete $5;
553 delete $7;
554 }
555
556annotation_item :
557 MZN_ANNOTATION MZN_IDENTIFIER params
558 {
559 TypeInst* ti=new TypeInst(@1,Type::ann());
560 if ($3==NULL || $3->empty()) {
561 VarDecl* vd = new VarDecl(@$,ti,$2);
562 $$ = new VarDeclI(@$,vd);
563 } else {
564 $$ = new FunctionI(@$,$2,ti,*$3,NULL);
565 }
566 free($2);
567 delete $3;
568 }
569 | MZN_ANNOTATION MZN_IDENTIFIER params MZN_EQ expr
570 { TypeInst* ti=new TypeInst(@1,Type::ann());
571 if ($3) $$ = new FunctionI(@$,$2,ti,*$3,$5);
572 delete $3;
573 }
574
575operation_item_tail :
576 /*empty*/
577 { $$=NULL; }
578 | MZN_EQ expr
579 { $$=$2; }
580
581params :
582 /* empty */
583 { $$=new vector<VarDecl*>(); }
584 | '(' params_list ')'
585 { $$=$2; }
586 | '(' error ')'
587 { $$=new vector<VarDecl*>(); }
588
589params_list :
590 /* empty */
591 { $$=new vector<VarDecl*>(); }
592 | params_list_head comma_or_none
593 { $$=$1; }
594
595params_list_head :
596 ti_expr_and_id_or_anon
597 { $$=new vector<VarDecl*>();
598 if ($1) $1->toplevel(false);
599 if ($1) $$->push_back($1); }
600 | params_list_head ',' ti_expr_and_id_or_anon
601 { $$=$1;
602 if ($3) $3->toplevel(false);
603 if ($1 && $3) $1->push_back($3); }
604
605comma_or_none : | ','
606
607ti_expr_and_id_or_anon :
608 ti_expr_and_id
609 { $$=$1; }
610 | ti_expr
611 { if ($1) $$=new VarDecl(@$, $1, ""); }
612
613ti_expr_and_id :
614 ti_expr ':' MZN_IDENTIFIER
615 { if ($1 && $3) $$ = new VarDecl(@$, $1, $3);
616 free($3);
617 }
618
619ti_expr_list : ti_expr_list_head comma_or_none
620 { $$=$1; }
621
622ti_expr_list_head :
623 ti_expr
624 { $$=new vector<TypeInst*>(); $$->push_back($1); }
625 | ti_expr_list_head ',' ti_expr
626 { $$=$1; if ($1 && $3) $1->push_back($3); }
627
628ti_expr :
629 base_ti_expr
630 | MZN_ARRAY MZN_LEFT_BRACKET ti_expr_list MZN_RIGHT_BRACKET MZN_OF base_ti_expr
631 {
632 $$ = $6;
633 if ($$ && $3) $$->setRanges(*$3);
634 delete $3;
635 }
636 | MZN_LIST MZN_OF base_ti_expr
637 {
638 $$ = $3;
639 std::vector<TypeInst*> ti(1);
640 ti[0] = new TypeInst(@$,Type::parint());
641 if ($$) $$->setRanges(ti);
642 }
643
644base_ti_expr :
645 base_ti_expr_tail
646 { $$ = $1;
647 }
648 | MZN_OPT base_ti_expr_tail
649 { $$ = $2;
650 if ($$) {
651 Type tt = $$->type();
652 tt.ot(Type::OT_OPTIONAL);
653 $$->type(tt);
654 }
655 }
656 | MZN_PAR opt_opt base_ti_expr_tail
657 { $$ = $3;
658 if ($$ && $2) {
659 Type tt = $$->type();
660 tt.ot(Type::OT_OPTIONAL);
661 $$->type(tt);
662 }
663 }
664 | MZN_VAR opt_opt base_ti_expr_tail
665 { $$ = $3;
666 if ($$) {
667 Type tt = $$->type();
668 tt.ti(Type::TI_VAR);
669 if ($2) tt.ot(Type::OT_OPTIONAL);
670 $$->type(tt);
671 }
672 }
673 | opt_opt MZN_SET MZN_OF base_ti_expr_tail
674 { $$ = $4;
675 if ($$) {
676 Type tt = $$->type();
677 tt.st(Type::ST_SET);
678 if ($1) tt.ot(Type::OT_OPTIONAL);
679 $$->type(tt);
680 }
681 }
682 | MZN_PAR opt_opt MZN_SET MZN_OF base_ti_expr_tail
683 { $$ = $5;
684 if ($$) {
685 Type tt = $$->type();
686 tt.st(Type::ST_SET);
687 if ($2) tt.ot(Type::OT_OPTIONAL);
688 $$->type(tt);
689 }
690 }
691 | MZN_VAR opt_opt MZN_SET MZN_OF base_ti_expr_tail
692 { $$ = $5;
693 if ($$) {
694 Type tt = $$->type();
695 tt.ti(Type::TI_VAR);
696 tt.st(Type::ST_SET);
697 if ($2) tt.ot(Type::OT_OPTIONAL);
698 $$->type(tt);
699 }
700 }
701
702opt_opt:
703 /* nothing */
704 { $$ = false; }
705 | MZN_OPT
706 { $$ = true; }
707
708base_ti_expr_tail :
709 MZN_INT
710 { $$ = new TypeInst(@$,Type::parint()); }
711 | MZN_BOOL
712 { $$ = new TypeInst(@$,Type::parbool()); }
713 | MZN_FLOAT
714 { $$ = new TypeInst(@$,Type::parfloat()); }
715 | MZN_STRING
716 { $$ = new TypeInst(@$,Type::parstring()); }
717 | MZN_ANN
718 { $$ = new TypeInst(@$,Type::ann()); }
719 | set_expr
720 { if ($1) $$ = new TypeInst(@$,Type(),$1); }
721 | MZN_TI_IDENTIFIER
722 { $$ = new TypeInst(@$,Type::top(),
723 new TIId(@$, $1));
724 free($1);
725 }
726 | MZN_TI_ENUM_IDENTIFIER
727 { $$ = new TypeInst(@$,Type::parint(),
728 new TIId(@$, $1));
729 free($1);
730 }
731
732array_access_expr_list : array_access_expr_list_head comma_or_none
733
734array_access_expr_list_head :
735 array_access_expr
736 { $$=new std::vector<MiniZinc::Expression*>; $$->push_back($1); }
737 | array_access_expr_list_head ',' array_access_expr
738 { $$=$1; if ($$ && $3) $$->push_back($3); }
739
740array_access_expr :
741 expr
742 { $$ = $1; }
743 | MZN_DOTDOT
744 { $$=new SetLit(@$, IntSetVal::a(-IntVal::infinity(),IntVal::infinity())); }
745 | MZN_DOTDOT expr
746 { if ($2==NULL) {
747 $$ = NULL;
748 } else if ($2->isa<IntLit>()) {
749 $$=new SetLit(@$, IntSetVal::a(-IntVal::infinity(),$2->cast<IntLit>()->v()));
750 } else {
751 $$=new BinOp(@$, IntLit::a(-IntVal::infinity()), BOT_DOTDOT, $2);
752 }
753 }
754 | expr MZN_DOTDOT
755 { if ($1==NULL) {
756 $$ = NULL;
757 } else if ($1->isa<IntLit>()) {
758 $$=new SetLit(@$, IntSetVal::a($1->cast<IntLit>()->v(),IntVal::infinity()));
759 } else {
760 $$=new BinOp(@$, $1, BOT_DOTDOT, IntLit::a(IntVal::infinity()));
761 }
762 }
763
764
765expr_list : expr_list_head comma_or_none
766
767expr_list_head :
768 expr
769 { $$=new std::vector<MiniZinc::Expression*>; $$->push_back($1); }
770 | expr_list_head ',' expr
771 { $$=$1; if ($$ && $3) $$->push_back($3); }
772
773///
774
775set_expr :
776 expr_atom_head
777 | set_expr MZN_COLONCOLON annotation_expr
778 { if ($1 && $3) $1->addAnnotation($3); $$=$1; }
779 | set_expr MZN_UNION set_expr
780 { $$=new BinOp(@$, $1, BOT_UNION, $3); }
781 | set_expr MZN_DIFF set_expr
782 { $$=new BinOp(@$, $1, BOT_DIFF, $3); }
783 | set_expr MZN_SYMDIFF set_expr
784 { $$=new BinOp(@$, $1, BOT_SYMDIFF, $3); }
785 | set_expr MZN_DOTDOT set_expr
786 { if ($1==NULL || $3==NULL) {
787 $$ = NULL;
788 } else if ($1->isa<IntLit>() && $3->isa<IntLit>()) {
789 $$=new SetLit(@$, IntSetVal::a($1->cast<IntLit>()->v(),$3->cast<IntLit>()->v()));
790 } else {
791 $$=new BinOp(@$, $1, BOT_DOTDOT, $3);
792 }
793 }
794 | MZN_DOTDOT_QUOTED '(' expr ',' expr ')'
795 { if ($3==NULL || $5==NULL) {
796 $$ = NULL;
797 } else if ($3->isa<IntLit>() && $5->isa<IntLit>()) {
798 $$=new SetLit(@$, IntSetVal::a($3->cast<IntLit>()->v(),$5->cast<IntLit>()->v()));
799 } else {
800 $$=new BinOp(@$, $3, BOT_DOTDOT, $5);
801 }
802 }
803 | set_expr MZN_INTERSECT set_expr
804 { $$=new BinOp(@$, $1, BOT_INTERSECT, $3); }
805 | set_expr MZN_PLUSPLUS set_expr
806 { $$=new BinOp(@$, $1, BOT_PLUSPLUS, $3); }
807 | set_expr MZN_PLUS set_expr
808 { $$=new BinOp(@$, $1, BOT_PLUS, $3); }
809 | set_expr MZN_MINUS set_expr
810 { $$=new BinOp(@$, $1, BOT_MINUS, $3); }
811 | set_expr MZN_MULT set_expr
812 { $$=new BinOp(@$, $1, BOT_MULT, $3); }
813 | set_expr MZN_DIV set_expr
814 { $$=new BinOp(@$, $1, BOT_DIV, $3); }
815 | set_expr MZN_IDIV set_expr
816 { $$=new BinOp(@$, $1, BOT_IDIV, $3); }
817 | set_expr MZN_MOD set_expr
818 { $$=new BinOp(@$, $1, BOT_MOD, $3); }
819 | set_expr MZN_POW set_expr
820 { $$=new BinOp(@$, $1, BOT_POW, $3); }
821 | set_expr MZN_WEAK_PLUS set_expr
822 { vector<Expression*> args;
823 args.push_back($1); args.push_back($3);
824 $$=new Call(@$, ASTString("~+"), args);
825 }
826 | set_expr MZN_WEAK_MINUS set_expr
827 { vector<Expression*> args;
828 args.push_back($1); args.push_back($3);
829 $$=new Call(@$, ASTString("~-"), args);
830 }
831 | set_expr MZN_WEAK_MULT set_expr
832 { vector<Expression*> args;
833 args.push_back($1); args.push_back($3);
834 $$=new Call(@$, ASTString("~*"), args);
835 }
836 | set_expr MZN_WEAK_EQ set_expr
837 { vector<Expression*> args;
838 args.push_back($1); args.push_back($3);
839 $$=new Call(@$, ASTString("~="), args);
840 }
841 | set_expr MZN_QUOTED_IDENTIFIER set_expr
842 { vector<Expression*> args;
843 args.push_back($1); args.push_back($3);
844 $$=new Call(@$, $2, args);
845 free($2);
846 }
847 | MZN_PLUS set_expr %prec MZN_NOT
848 { $$=new UnOp(@$, UOT_PLUS, $2); }
849 | MZN_MINUS set_expr %prec MZN_NOT
850 { if ($2 && $2->isa<IntLit>()) {
851 $$ = IntLit::a(-$2->cast<IntLit>()->v());
852 } else if ($2 && $2->isa<FloatLit>()) {
853 $$ = FloatLit::a(-$2->cast<FloatLit>()->v());
854 } else {
855 $$=new UnOp(@$, UOT_MINUS, $2);
856 }
857 }
858
859///
860
861expr :
862 expr_atom_head
863 | expr MZN_COLONCOLON annotation_expr
864 { if ($1 && $3) $1->addAnnotation($3); $$=$1; }
865 | expr MZN_EQUIV expr
866 { $$=new BinOp(@$, $1, BOT_EQUIV, $3); }
867 | expr MZN_IMPL expr
868 { $$=new BinOp(@$, $1, BOT_IMPL, $3); }
869 | expr MZN_RIMPL expr
870 { $$=new BinOp(@$, $1, BOT_RIMPL, $3); }
871 | expr MZN_OR expr
872 { $$=new BinOp(@$, $1, BOT_OR, $3); }
873 | expr MZN_XOR expr
874 { $$=new BinOp(@$, $1, BOT_XOR, $3); }
875 | expr MZN_AND expr
876 { $$=new BinOp(@$, $1, BOT_AND, $3); }
877 | expr MZN_LE expr
878 { $$=new BinOp(@$, $1, BOT_LE, $3); }
879 | expr MZN_GR expr
880 { $$=new BinOp(@$, $1, BOT_GR, $3); }
881 | expr MZN_LQ expr
882 { $$=new BinOp(@$, $1, BOT_LQ, $3); }
883 | expr MZN_GQ expr
884 { $$=new BinOp(@$, $1, BOT_GQ, $3); }
885 | expr MZN_EQ expr
886 { $$=new BinOp(@$, $1, BOT_EQ, $3); }
887 | expr MZN_NQ expr
888 { $$=new BinOp(@$, $1, BOT_NQ, $3); }
889 | expr MZN_IN expr
890 { $$=new BinOp(@$, $1, BOT_IN, $3); }
891 | expr MZN_SUBSET expr
892 { $$=new BinOp(@$, $1, BOT_SUBSET, $3); }
893 | expr MZN_SUPERSET expr
894 { $$=new BinOp(@$, $1, BOT_SUPERSET, $3); }
895 | expr MZN_UNION expr
896 { $$=new BinOp(@$, $1, BOT_UNION, $3); }
897 | expr MZN_DIFF expr
898 { $$=new BinOp(@$, $1, BOT_DIFF, $3); }
899 | expr MZN_SYMDIFF expr
900 { $$=new BinOp(@$, $1, BOT_SYMDIFF, $3); }
901 | expr MZN_DOTDOT expr
902 { if ($1==NULL || $3==NULL) {
903 $$ = NULL;
904 } else if ($1->isa<IntLit>() && $3->isa<IntLit>()) {
905 $$=new SetLit(@$, IntSetVal::a($1->cast<IntLit>()->v(),$3->cast<IntLit>()->v()));
906 } else {
907 $$=new BinOp(@$, $1, BOT_DOTDOT, $3);
908 }
909 }
910 | MZN_DOTDOT_QUOTED '(' expr ',' expr ')'
911 { if ($3==NULL || $5==NULL) {
912 $$ = NULL;
913 } else if ($3->isa<IntLit>() && $5->isa<IntLit>()) {
914 $$=new SetLit(@$, IntSetVal::a($3->cast<IntLit>()->v(),$5->cast<IntLit>()->v()));
915 } else {
916 $$=new BinOp(@$, $3, BOT_DOTDOT, $5);
917 }
918 }
919 | expr MZN_INTERSECT expr
920 { $$=new BinOp(@$, $1, BOT_INTERSECT, $3); }
921 | expr MZN_PLUSPLUS expr
922 { $$=new BinOp(@$, $1, BOT_PLUSPLUS, $3); }
923 | expr MZN_PLUS expr
924 { $$=new BinOp(@$, $1, BOT_PLUS, $3); }
925 | expr MZN_MINUS expr
926 { $$=new BinOp(@$, $1, BOT_MINUS, $3); }
927 | expr MZN_MULT expr
928 { $$=new BinOp(@$, $1, BOT_MULT, $3); }
929 | expr MZN_DIV expr
930 { $$=new BinOp(@$, $1, BOT_DIV, $3); }
931 | expr MZN_IDIV expr
932 { $$=new BinOp(@$, $1, BOT_IDIV, $3); }
933 | expr MZN_MOD expr
934 { $$=new BinOp(@$, $1, BOT_MOD, $3); }
935 | expr MZN_POW expr
936 { $$=new BinOp(@$, $1, BOT_POW, $3); }
937 | expr MZN_WEAK_PLUS expr
938 { vector<Expression*> args;
939 args.push_back($1); args.push_back($3);
940 $$=new Call(@$, ASTString("~+"), args);
941 }
942 | expr MZN_WEAK_MINUS expr
943 { vector<Expression*> args;
944 args.push_back($1); args.push_back($3);
945 $$=new Call(@$, ASTString("~-"), args);
946 }
947 | expr MZN_WEAK_MULT expr
948 { vector<Expression*> args;
949 args.push_back($1); args.push_back($3);
950 $$=new Call(@$, ASTString("~*"), args);
951 }
952 | expr MZN_WEAK_EQ expr
953 { vector<Expression*> args;
954 args.push_back($1); args.push_back($3);
955 $$=new Call(@$, ASTString("~="), args);
956 }
957 | expr MZN_QUOTED_IDENTIFIER expr
958 { vector<Expression*> args;
959 args.push_back($1); args.push_back($3);
960 $$=new Call(@$, $2, args);
961 free($2);
962 }
963 | MZN_NOT expr %prec MZN_NOT
964 { $$=new UnOp(@$, UOT_NOT, $2); }
965 | MZN_PLUS expr %prec MZN_NOT
966 { if (($2 && $2->isa<IntLit>()) || ($2 && $2->isa<FloatLit>())) {
967 $$ = $2;
968 } else {
969 $$=new UnOp(@$, UOT_PLUS, $2);
970 }
971 }
972 | MZN_MINUS expr %prec MZN_NOT
973 { if ($2 && $2->isa<IntLit>()) {
974 $$ = IntLit::a(-$2->cast<IntLit>()->v());
975 } else if ($2 && $2->isa<FloatLit>()) {
976 $$ = FloatLit::a(-$2->cast<FloatLit>()->v());
977 } else {
978 $$=new UnOp(@$, UOT_MINUS, $2);
979 }
980 }
981
982
983expr_atom_head :
984 expr_atom_head_nonstring
985 { $$=$1; }
986 | string_expr
987 { $$=$1; }
988
989expr_atom_head_nonstring :
990 '(' expr ')'
991 { $$=$2; }
992 | '(' expr ')' array_access_tail
993 { if ($4) $$=createArrayAccess(@$, $2, *$4); delete $4; }
994 | MZN_IDENTIFIER
995 { $$=new Id(@$, $1, NULL); free($1); }
996 | MZN_IDENTIFIER array_access_tail
997 { if ($2) $$=createArrayAccess(@$, new Id(@1,$1,NULL), *$2);
998 free($1); delete $2; }
999 | MZN_UNDERSCORE
1000 { $$=new AnonVar(@$); }
1001 | MZN_UNDERSCORE array_access_tail
1002 { if ($2) $$=createArrayAccess(@$, new AnonVar(@$), *$2);
1003 delete $2; }
1004 | MZN_BOOL_LITERAL
1005 { $$=constants().boollit(($1!=0)); }
1006 | MZN_INTEGER_LITERAL
1007 { $$=IntLit::a($1); }
1008 | MZN_INFINITY
1009 { $$=IntLit::a(IntVal::infinity()); }
1010 | MZN_FLOAT_LITERAL
1011 { $$=FloatLit::a($1); }
1012 | MZN_ABSENT
1013 { $$=constants().absent; }
1014 | set_literal
1015 | set_literal array_access_tail
1016 { if ($2) $$=createArrayAccess(@$, $1, *$2);
1017 delete $2; }
1018 | set_comp
1019 | set_comp array_access_tail
1020 { if ($2) $$=createArrayAccess(@$, $1, *$2);
1021 delete $2; }
1022 | simple_array_literal
1023 | simple_array_literal array_access_tail
1024 { if ($2) $$=createArrayAccess(@$, $1, *$2);
1025 delete $2; }
1026 | simple_array_literal_2d
1027 | simple_array_literal_2d array_access_tail
1028 { if ($2) $$=createArrayAccess(@$, $1, *$2);
1029 delete $2; }
1030 | simple_array_comp
1031 | simple_array_comp array_access_tail
1032 { if ($2) $$=createArrayAccess(@$, $1, *$2);
1033 delete $2; }
1034 | if_then_else_expr
1035 | if_then_else_expr array_access_tail
1036 { if ($2) $$=createArrayAccess(@$, $1, *$2);
1037 delete $2; }
1038 | let_expr
1039 | call_expr
1040 | call_expr array_access_tail
1041 { if ($2) $$=createArrayAccess(@$, $1, *$2);
1042 delete $2; }
1043
1044string_expr:
1045 MZN_STRING_LITERAL
1046 { $$=new StringLit(@$, $1); free($1); }
1047 | MZN_STRING_QUOTE_START string_quote_rest
1048 { $$=new BinOp(@$, new StringLit(@$, $1), BOT_PLUSPLUS, $2);
1049 free($1);
1050 }
1051
1052string_quote_rest:
1053 expr_list_head MZN_STRING_QUOTE_END
1054 { if ($1) $$=new BinOp(@$, new Call(@$, ASTString("format"), *$1), BOT_PLUSPLUS, new StringLit(@$,$2));
1055 free($2);
1056 delete $1;
1057 }
1058 | expr_list_head MZN_STRING_QUOTE_MID string_quote_rest
1059 { if ($1) $$=new BinOp(@$, new Call(@$, ASTString("format"), *$1), BOT_PLUSPLUS,
1060 new BinOp(@$, new StringLit(@$,$2), BOT_PLUSPLUS, $3));
1061 free($2);
1062 delete $1;
1063 }
1064
1065array_access_tail :
1066 MZN_LEFT_BRACKET array_access_expr_list MZN_RIGHT_BRACKET
1067 { $$=new std::vector<std::vector<Expression*> >();
1068 if ($2) {
1069 $$->push_back(*$2);
1070 delete $2;
1071 }
1072 }
1073 | array_access_tail MZN_LEFT_BRACKET array_access_expr_list MZN_RIGHT_BRACKET
1074 { $$=$1;
1075 if ($$ && $3) {
1076 $$->push_back(*$3);
1077 delete $3;
1078 }
1079 }
1080
1081set_literal :
1082 '{' '}'
1083 { $$ = new SetLit(@$, std::vector<Expression*>()); }
1084 | '{' expr_list '}'
1085 { if ($2) $$ = new SetLit(@$, *$2);
1086 delete $2; }
1087
1088set_comp :
1089 '{' expr '|' comp_tail '}'
1090 { if ($4) $$ = new Comprehension(@$, $2, *$4, true);
1091 delete $4;
1092 }
1093
1094comp_tail :
1095 generator_list
1096 { if ($1) $$=new Generators; $$->_g = *$1; delete $1; }
1097
1098generator_list : generator_list_head comma_or_none
1099
1100generator_list_head :
1101 generator
1102 { $$=new std::vector<Generator>; if ($1) $$->push_back(*$1); delete $1; }
1103 | generator_eq
1104 { $$=new std::vector<Generator>; if ($1) $$->push_back(*$1); delete $1; }
1105 | generator_eq MZN_WHERE expr
1106 { $$=new std::vector<Generator>;
1107 if ($1) $$->push_back(*$1);
1108 if ($1 && $3) $$->push_back(Generator($$->size(),$3));
1109 delete $1;
1110 }
1111 | generator_list_head ',' generator
1112 { $$=$1; if ($$ && $3) $$->push_back(*$3); delete $3; }
1113 | generator_list_head ',' generator_eq
1114 { $$=$1; if ($$ && $3) $$->push_back(*$3); delete $3; }
1115 | generator_list_head ',' generator_eq MZN_WHERE expr
1116 { $$=$1;
1117 if ($$ && $3) $$->push_back(*$3);
1118 if ($$ && $3 && $5) $$->push_back(Generator($$->size(),$5));
1119 delete $3;
1120 }
1121
1122generator :
1123 id_list MZN_IN expr
1124 { if ($1 && $3) $$=new Generator(*$1,$3,NULL); else $$=NULL; delete $1; }
1125 | id_list MZN_IN expr MZN_WHERE expr
1126 { if ($1 && $3) $$=new Generator(*$1,$3,$5); else $$=NULL; delete $1; }
1127generator_eq :
1128 MZN_IDENTIFIER MZN_EQ expr
1129 { if ($3) $$=new Generator({$1},NULL,$3); else $$=NULL; free($1); }
1130
1131id_list : id_list_head comma_or_none
1132
1133id_list_head :
1134 MZN_IDENTIFIER
1135 { $$=new std::vector<std::string>; $$->push_back($1); free($1); }
1136 | id_list_head ',' MZN_IDENTIFIER
1137 { $$=$1; if ($$ && $3) $$->push_back($3); free($3); }
1138
1139simple_array_literal :
1140 MZN_LEFT_BRACKET MZN_RIGHT_BRACKET
1141 { $$=new ArrayLit(@$, std::vector<MiniZinc::Expression*>()); }
1142 | MZN_LEFT_BRACKET expr_list MZN_RIGHT_BRACKET
1143 { if ($2) $$=new ArrayLit(@$, *$2); delete $2; }
1144
1145simple_array_literal_2d :
1146 MZN_LEFT_2D_BRACKET MZN_RIGHT_2D_BRACKET
1147 { $$=new ArrayLit(@$, std::vector<std::vector<Expression*> >()); }
1148 | MZN_LEFT_2D_BRACKET simple_array_literal_2d_list MZN_RIGHT_2D_BRACKET
1149 { if ($2) {
1150 $$=new ArrayLit(@$, *$2);
1151 for (unsigned int i=1; i<$2->size(); i++)
1152 if ((*$2)[i].size() != (*$2)[i-1].size())
1153 yyerror(&@2, parm, "syntax error, all sub-arrays of 2d array literal must have the same length");
1154 delete $2;
1155 } else {
1156 $$ = NULL;
1157 }
1158 }
1159 | MZN_LEFT_2D_BRACKET simple_array_literal_2d_list '|' MZN_RIGHT_2D_BRACKET
1160 { if ($2) {
1161 $$=new ArrayLit(@$, *$2);
1162 for (unsigned int i=1; i<$2->size(); i++)
1163 if ((*$2)[i].size() != (*$2)[i-1].size())
1164 yyerror(&@2, parm, "syntax error, all sub-arrays of 2d array literal must have the same length");
1165 delete $2;
1166 } else {
1167 $$ = NULL;
1168 }
1169 }
1170 | MZN_LEFT_2D_BRACKET simple_array_literal_3d_list MZN_RIGHT_2D_BRACKET
1171 {
1172 if ($2) {
1173 std::vector<std::pair<int,int> > dims(3);
1174 dims[0] = std::pair<int,int>(1,static_cast<int>($2->size()));
1175 if ($2->size()==0) {
1176 dims[1] = std::pair<int,int>(1,0);
1177 dims[2] = std::pair<int,int>(1,0);
1178 } else {
1179 dims[1] = std::pair<int,int>(1,static_cast<int>((*$2)[0].size()));
1180 if ((*$2)[0].size()==0) {
1181 dims[2] = std::pair<int,int>(1,0);
1182 } else {
1183 dims[2] = std::pair<int,int>(1,static_cast<int>((*$2)[0][0].size()));
1184 }
1185 }
1186 std::vector<Expression*> a;
1187 for (int i=0; i<dims[0].second; i++) {
1188 if ((*$2)[i].size() != dims[1].second) {
1189 yyerror(&@2, parm, "syntax error, all sub-arrays of 3d array literal must have the same length");
1190 } else {
1191 for (int j=0; j<dims[1].second; j++) {
1192 if ((*$2)[i][j].size() != dims[2].second) {
1193 yyerror(&@2, parm, "syntax error, all sub-arrays of 3d array literal must have the same length");
1194 } else {
1195 for (int k=0; k<dims[2].second; k++) {
1196 a.push_back((*$2)[i][j][k]);
1197 }
1198 }
1199 }
1200 }
1201 }
1202 $$ = new ArrayLit(@$,a,dims);
1203 delete $2;
1204 } else {
1205 $$ = NULL;
1206 }
1207 }
1208
1209simple_array_literal_3d_list :
1210 '|' '|'
1211 { $$=new std::vector<std::vector<std::vector<MiniZinc::Expression*> > >;
1212 }
1213 | '|' simple_array_literal_2d_list '|'
1214 { $$=new std::vector<std::vector<std::vector<MiniZinc::Expression*> > >;
1215 if ($2) $$->push_back(*$2);
1216 delete $2;
1217 }
1218 | simple_array_literal_3d_list ',' '|' simple_array_literal_2d_list '|'
1219 { $$=$1;
1220 if ($$ && $4) $$->push_back(*$4);
1221 delete $4;
1222 }
1223
1224simple_array_literal_2d_list :
1225 expr_list
1226 { $$=new std::vector<std::vector<MiniZinc::Expression*> >;
1227 if ($1) $$->push_back(*$1);
1228 delete $1;
1229 }
1230 | simple_array_literal_2d_list '|' expr_list
1231 { $$=$1; if ($$ && $3) $$->push_back(*$3); delete $3; }
1232
1233simple_array_comp :
1234 MZN_LEFT_BRACKET expr '|' comp_tail MZN_RIGHT_BRACKET
1235 { if ($4) $$=new Comprehension(@$, $2, *$4, false);
1236 delete $4;
1237 }
1238
1239if_then_else_expr :
1240 MZN_IF expr MZN_THEN expr MZN_ENDIF
1241 {
1242 std::vector<Expression*> iexps;
1243 iexps.push_back($2);
1244 iexps.push_back($4);
1245 $$=new ITE(@$, iexps, NULL);
1246 }
1247 | MZN_IF expr MZN_THEN expr elseif_list MZN_ELSE expr MZN_ENDIF
1248 {
1249 std::vector<Expression*> iexps;
1250 iexps.push_back($2);
1251 iexps.push_back($4);
1252 if ($5) {
1253 for (unsigned int i=0; i<$5->size(); i+=2) {
1254 iexps.push_back((*$5)[i]);
1255 iexps.push_back((*$5)[i+1]);
1256 }
1257 }
1258 $$=new ITE(@$, iexps,$7);
1259 delete $5;
1260 }
1261
1262elseif_list :
1263 { $$=new std::vector<MiniZinc::Expression*>; }
1264 | elseif_list MZN_ELSEIF expr MZN_THEN expr
1265 { $$=$1; if ($$ && $3 && $5) { $$->push_back($3); $$->push_back($5); } }
1266
1267quoted_op :
1268 MZN_EQUIV_QUOTED
1269 { $$=BOT_EQUIV; }
1270 | MZN_IMPL_QUOTED
1271 { $$=BOT_IMPL; }
1272 | MZN_RIMPL_QUOTED
1273 { $$=BOT_RIMPL; }
1274 | MZN_OR_QUOTED
1275 { $$=BOT_OR; }
1276 | MZN_XOR_QUOTED
1277 { $$=BOT_XOR; }
1278 | MZN_AND_QUOTED
1279 { $$=BOT_AND; }
1280 | MZN_LE_QUOTED
1281 { $$=BOT_LE; }
1282 | MZN_GR_QUOTED
1283 { $$=BOT_GR; }
1284 | MZN_LQ_QUOTED
1285 { $$=BOT_LQ; }
1286 | MZN_GQ_QUOTED
1287 { $$=BOT_GQ; }
1288 | MZN_EQ_QUOTED
1289 { $$=BOT_EQ; }
1290 | MZN_NQ_QUOTED
1291 { $$=BOT_NQ; }
1292 | MZN_IN_QUOTED
1293 { $$=BOT_IN; }
1294 | MZN_SUBSET_QUOTED
1295 { $$=BOT_SUBSET; }
1296 | MZN_SUPERSET_QUOTED
1297 { $$=BOT_SUPERSET; }
1298 | MZN_UNION_QUOTED
1299 { $$=BOT_UNION; }
1300 | MZN_DIFF_QUOTED
1301 { $$=BOT_DIFF; }
1302 | MZN_SYMDIFF_QUOTED
1303 { $$=BOT_SYMDIFF; }
1304 | MZN_PLUS_QUOTED
1305 { $$=BOT_PLUS; }
1306 | MZN_MINUS_QUOTED
1307 { $$=BOT_MINUS; }
1308 | MZN_MULT_QUOTED
1309 { $$=BOT_MULT; }
1310 | MZN_POW_QUOTED
1311 { $$=BOT_POW; }
1312 | MZN_DIV_QUOTED
1313 { $$=BOT_DIV; }
1314 | MZN_IDIV_QUOTED
1315 { $$=BOT_IDIV; }
1316 | MZN_MOD_QUOTED
1317 { $$=BOT_MOD; }
1318 | MZN_INTERSECT_QUOTED
1319 { $$=BOT_INTERSECT; }
1320 | MZN_PLUSPLUS_QUOTED
1321 { $$=BOT_PLUSPLUS; }
1322 | MZN_NOT_QUOTED
1323 { $$=-1; }
1324
1325quoted_op_call :
1326 quoted_op '(' expr ',' expr ')'
1327 { if ($1==-1) {
1328 $$=NULL;
1329 yyerror(&@3, parm, "syntax error, unary operator with two arguments");
1330 } else {
1331 $$=new BinOp(@$, $3,static_cast<BinOpType>($1),$5);
1332 }
1333 }
1334 | quoted_op '(' expr ')'
1335 { int uot=-1;
1336 switch ($1) {
1337 case -1:
1338 uot = UOT_NOT;
1339 break;
1340 case BOT_MINUS:
1341 uot = UOT_MINUS;
1342 break;
1343 case BOT_PLUS:
1344 uot = UOT_PLUS;
1345 break;
1346 default:
1347 yyerror(&@3, parm, "syntax error, binary operator with unary argument list");
1348 break;
1349 }
1350 if (uot==-1)
1351 $$=NULL;
1352 else {
1353 if (uot==UOT_PLUS && $3 && ($3->isa<IntLit>() || $3->isa<FloatLit>())) {
1354 $$ = $3;
1355 } else if (uot==UOT_MINUS && $3 && $3->isa<IntLit>()) {
1356 $$ = IntLit::a(-$3->cast<IntLit>()->v());
1357 } else if (uot==UOT_MINUS && $3 && $3->isa<FloatLit>()) {
1358 $$ = FloatLit::a(-$3->cast<FloatLit>()->v());
1359 } else {
1360 $$=new UnOp(@$, static_cast<UnOpType>(uot),$3);
1361 }
1362 }
1363 }
1364
1365call_expr :
1366 MZN_IDENTIFIER '(' ')'
1367 { $$=new Call(@$, $1, std::vector<Expression*>()); free($1); }
1368 | quoted_op_call
1369 | MZN_IDENTIFIER '(' comp_or_expr ')'
1370 {
1371 if ($3!=NULL) {
1372 bool hadWhere = false;
1373 std::vector<Expression*> args;
1374 for (unsigned int i=0; i<$3->size(); i++) {
1375 if ((*$3)[i].second) {
1376 yyerror(&@3, parm, "syntax error, 'where' expression outside generator call");
1377 hadWhere = true;
1378 $$=NULL;
1379 }
1380 args.push_back((*$3)[i].first);
1381 }
1382 if (!hadWhere) {
1383 $$=new Call(@$, $1, args);
1384 }
1385 }
1386 free($1);
1387 delete $3;
1388 }
1389 | MZN_IDENTIFIER '(' comp_or_expr ')' '(' expr ')'
1390 {
1391 vector<Generator> gens;
1392 vector<Id*> ids;
1393 if ($3) {
1394 for (unsigned int i=0; i<$3->size(); i++) {
1395 if (Id* id = Expression::dyn_cast<Id>((*$3)[i].first)) {
1396 if ((*$3)[i].second) {
1397 ParserLocation loc = (*$3)[i].second->loc().parserLocation();
1398 yyerror(&loc, parm, "illegal where expression in generator call");
1399 }
1400 ids.push_back(id);
1401 } else {
1402 if (BinOp* boe = Expression::dyn_cast<BinOp>((*$3)[i].first)) {
1403 if (boe->lhs() && boe->rhs()) {
1404 Id* id = Expression::dyn_cast<Id>(boe->lhs());
1405 if (id && boe->op() == BOT_IN) {
1406 ids.push_back(id);
1407 gens.push_back(Generator(ids,boe->rhs(),(*$3)[i].second));
1408 ids = vector<Id*>();
1409 } else if (id && boe->op() == BOT_EQ && ids.empty()) {
1410 ids.push_back(id);
1411 gens.push_back(Generator(ids,NULL,boe->rhs()));
1412 if ((*$3)[i].second) {
1413 gens.push_back(Generator(gens.size(),(*$3)[i].second));
1414 }
1415 ids = vector<Id*>();
1416 } else {
1417 ParserLocation loc = (*$3)[i].first->loc().parserLocation();
1418 yyerror(&loc, parm, "illegal expression in generator call");
1419 }
1420 }
1421 } else {
1422 ParserLocation loc = (*$3)[i].first->loc().parserLocation();
1423 yyerror(&loc, parm, "illegal expression in generator call");
1424 }
1425 }
1426 }
1427 }
1428 if (ids.size() != 0) {
1429 yyerror(&@3, parm, "illegal expression in generator call");
1430 }
1431 ParserState* pp = static_cast<ParserState*>(parm);
1432 if (pp->hadError) {
1433 $$=NULL;
1434 } else {
1435 Generators g; g._g = gens;
1436 Comprehension* ac = new Comprehension(@$, $6,g,false);
1437 vector<Expression*> args; args.push_back(ac);
1438 $$=new Call(@$, $1, args);
1439 }
1440 free($1);
1441 delete $3;
1442 }
1443
1444comp_or_expr : comp_or_expr_head comma_or_none
1445
1446comp_or_expr_head :
1447 expr
1448 { $$=new vector<pair<Expression*,Expression*> >;
1449 if ($1) {
1450 $$->push_back(pair<Expression*,Expression*>($1,NULL));
1451 }
1452 }
1453 | expr MZN_WHERE expr
1454 { $$=new vector<pair<Expression*,Expression*> >;
1455 if ($1 && $3) {
1456 $$->push_back(pair<Expression*,Expression*>($1,$3));
1457 }
1458 }
1459 | comp_or_expr_head ',' expr
1460 { $$=$1; if ($$ && $3) $$->push_back(pair<Expression*,Expression*>($3,NULL)); }
1461 | comp_or_expr_head ',' expr MZN_WHERE expr
1462 { $$=$1; if ($$ && $3 && $5) $$->push_back(pair<Expression*,Expression*>($3,$5)); }
1463
1464let_expr :
1465 MZN_LET '{' let_vardecl_item_list '}' MZN_IN expr %prec PREC_ANNO
1466 { if ($3 && $6) {
1467 $$=new Let(@$, *$3, $6); delete $3;
1468 } else {
1469 $$=NULL;
1470 }
1471 }
1472 | MZN_LET '{' let_vardecl_item_list comma_or_semi '}' MZN_IN expr %prec PREC_ANNO
1473 { if ($3 && $7) {
1474 $$=new Let(@$, *$3, $7); delete $3;
1475 } else {
1476 $$=NULL;
1477 }
1478 }
1479
1480let_vardecl_item_list :
1481 let_vardecl_item
1482 { $$=new vector<Expression*>; $$->push_back($1); }
1483 | constraint_item
1484 { $$=new vector<Expression*>;
1485 if ($1) {
1486 ConstraintI* ce = $1->cast<ConstraintI>();
1487 $$->push_back(ce->e());
1488 ce->e(NULL);
1489 }
1490 }
1491 | let_vardecl_item_list comma_or_semi let_vardecl_item
1492 { $$=$1; if ($$ && $3) $$->push_back($3); }
1493 | let_vardecl_item_list comma_or_semi constraint_item
1494 { $$=$1;
1495 if ($$ && $3) {
1496 ConstraintI* ce = $3->cast<ConstraintI>();
1497 $$->push_back(ce->e());
1498 ce->e(NULL);
1499 }
1500 }
1501
1502comma_or_semi : ',' | ';'
1503
1504let_vardecl_item :
1505 ti_expr_and_id annotations
1506 { $$ = $1;
1507 if ($$) $$->toplevel(false);
1508 if ($$ && $2) $$->addAnnotations(*$2);
1509 delete $2;
1510 }
1511 | ti_expr_and_id annotations MZN_EQ expr
1512 { if ($1) $1->e($4);
1513 $$ = $1;
1514 if ($$) $$->loc(@$);
1515 if ($$) $$->toplevel(false);
1516 if ($$ && $2) $$->addAnnotations(*$2);
1517 delete $2;
1518 }
1519
1520annotations :
1521 /* empty */
1522 { $$=NULL; }
1523 | ne_annotations
1524
1525annotation_expr :
1526 expr_atom_head_nonstring
1527 { $$ = $1; }
1528 | string_expr
1529 { $$ = new Call(@1, ASTString("mzn_expression_name"), {$1}); }
1530
1531ne_annotations :
1532 MZN_COLONCOLON annotation_expr
1533 { $$=new std::vector<Expression*>(1);
1534 (*$$)[0] = $2;
1535 }
1536 | ne_annotations MZN_COLONCOLON annotation_expr
1537 { $$=$1; if ($$) $$->push_back($3); }
1538
1539id_or_quoted_op :
1540 MZN_IDENTIFIER
1541 { $$=$1; }
1542 | MZN_EQUIV_QUOTED
1543 { $$=strdup("'<->'"); }
1544 | MZN_IMPL_QUOTED
1545 { $$=strdup("'->'"); }
1546 | MZN_RIMPL_QUOTED
1547 { $$=strdup("'<-'"); }
1548 | MZN_OR_QUOTED
1549 { $$=strdup("'\\/'"); }
1550 | MZN_XOR_QUOTED
1551 { $$=strdup("'xor'"); }
1552 | MZN_AND_QUOTED
1553 { $$=strdup("'/\\'"); }
1554 | MZN_LE_QUOTED
1555 { $$=strdup("'<'"); }
1556 | MZN_GR_QUOTED
1557 { $$=strdup("'>'"); }
1558 | MZN_LQ_QUOTED
1559 { $$=strdup("'<='"); }
1560 | MZN_GQ_QUOTED
1561 { $$=strdup("'>='"); }
1562 | MZN_EQ_QUOTED
1563 { $$=strdup("'='"); }
1564 | MZN_NQ_QUOTED
1565 { $$=strdup("'!='"); }
1566 | MZN_IN_QUOTED
1567 { $$=strdup("'in'"); }
1568 | MZN_SUBSET_QUOTED
1569 { $$=strdup("'subset'"); }
1570 | MZN_SUPERSET_QUOTED
1571 { $$=strdup("'superset'"); }
1572 | MZN_UNION_QUOTED
1573 { $$=strdup("'union'"); }
1574 | MZN_DIFF_QUOTED
1575 { $$=strdup("'diff'"); }
1576 | MZN_SYMDIFF_QUOTED
1577 { $$=strdup("'symdiff'"); }
1578 | MZN_DOTDOT_QUOTED
1579 { $$=strdup("'..'"); }
1580 | MZN_PLUS_QUOTED
1581 { $$=strdup("'+'"); }
1582 | MZN_MINUS_QUOTED
1583 { $$=strdup("'-'"); }
1584 | MZN_MULT_QUOTED
1585 { $$=strdup("'*'"); }
1586 | MZN_POW_QUOTED
1587 { $$=strdup("'^'"); }
1588 | MZN_DIV_QUOTED
1589 { $$=strdup("'/'"); }
1590 | MZN_IDIV_QUOTED
1591 { $$=strdup("'div'"); }
1592 | MZN_MOD_QUOTED
1593 { $$=strdup("'mod'"); }
1594 | MZN_INTERSECT_QUOTED
1595 { $$=strdup("'intersect'"); }
1596 | MZN_NOT_QUOTED
1597 { $$=strdup("'not'"); }
1598 | MZN_PLUSPLUS_QUOTED
1599 { $$=strdup("'++'"); }