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