this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Guido Tack <tack@gecode.org> 5 * 6 * Copyright: 7 * Guido Tack, 2007 8 * 9 * This file is part of Gecode, the generic constraint 10 * development environment: 11 * http://www.gecode.org 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining 14 * a copy of this software and associated documentation files (the 15 * "Software"), to deal in the Software without restriction, including 16 * without limitation the rights to use, copy, modify, merge, publish, 17 * distribute, sublicense, and/or sell copies of the Software, and to 18 * permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be 22 * included in all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 * 32 */ 33 34%pure-parser 35%parse-param {void *parm} 36%lex-param {void *YYLEX_PARAM} 37%{ 38#define YYPARSE_PARAM parm 39#define YYLEX_PARAM static_cast<ParserState*>(parm)->yyscanner 40#include <gecode/flatzinc.hh> 41#include <gecode/flatzinc/parser.hh> 42#include <iostream> 43#include <fstream> 44 45#ifdef HAVE_MMAP 46#include <stdio.h> 47#include <stdlib.h> 48#include <fcntl.h> 49#include <unistd.h> 50#include <sys/types.h> 51#include <sys/mman.h> 52#include <sys/stat.h> 53#endif 54 55using namespace std; 56 57int yyparse(void*); 58int yylex(YYSTYPE*, void* scanner); 59int yylex_init (void** scanner); 60int yylex_destroy (void* scanner); 61int yyget_lineno (void* scanner); 62void yyset_extra (void* user_defined ,void* yyscanner ); 63 64extern int yydebug; 65 66using namespace Gecode; 67using namespace Gecode::FlatZinc; 68 69void yyerror(void* parm, const char *str) { 70 ParserState* pp = static_cast<ParserState*>(parm); 71 pp->err << "Error: " << str 72 << " in line no. " << yyget_lineno(pp->yyscanner) 73 << std::endl; 74 pp->hadError = true; 75} 76 77void yyassert(ParserState* pp, bool cond, const char* str) 78{ 79 if (!cond) { 80 pp->err << "Error: " << str 81 << " in line no. " << yyget_lineno(pp->yyscanner) 82 << std::endl; 83 pp->hadError = true; 84 } 85} 86 87/* 88 * The symbol tables 89 * 90 */ 91 92AST::Node* getArrayElement(ParserState* pp, string id, int offset, 93 bool annotation) { 94 if (offset > 0) { 95 SymbolEntry e; 96 if (pp->symbols.get(id,e)) { 97 switch (e.t) { 98 case ST_INTVARARRAY: 99 if (offset > pp->arrays[e.i]) 100 goto error; 101 { 102 std::string n; 103 if (annotation) { 104 std::ostringstream oss; 105 oss << id << "[" << offset << "]"; 106 n = oss.str(); 107 } 108 return new AST::IntVar(pp->arrays[e.i+offset],n); 109 } 110 case ST_BOOLVARARRAY: 111 if (offset > pp->arrays[e.i]) 112 goto error; 113 { 114 std::string n; 115 if (annotation) { 116 std::ostringstream oss; 117 oss << id << "[" << offset << "]"; 118 n = oss.str(); 119 } 120 return new AST::BoolVar(pp->arrays[e.i+offset],n); 121 } 122 case ST_SETVARARRAY: 123 if (offset > pp->arrays[e.i]) 124 goto error; 125 { 126 std::string n; 127 if (annotation) { 128 std::ostringstream oss; 129 oss << id << "[" << offset << "]"; 130 n = oss.str(); 131 } 132 return new AST::SetVar(pp->arrays[e.i+offset],n); 133 } 134 case ST_FLOATVARARRAY: 135 if (offset > pp->arrays[e.i]) 136 goto error; 137 { 138 std::string n; 139 if (annotation) { 140 std::ostringstream oss; 141 oss << id << "[" << offset << "]"; 142 n = oss.str(); 143 } 144 return new AST::FloatVar(pp->arrays[e.i+offset],n); 145 } 146 case ST_INTVALARRAY: 147 if (offset > pp->arrays[e.i]) 148 goto error; 149 return new AST::IntLit(pp->arrays[e.i+offset]); 150 case ST_SETVALARRAY: 151 if (offset > pp->arrays[e.i]) 152 goto error; 153 return new AST::SetLit(pp->setvals[pp->arrays[e.i+1]+offset-1]); 154 case ST_FLOATVALARRAY: 155 if (offset > pp->arrays[e.i]) 156 goto error; 157 return new AST::FloatLit(pp->floatvals[pp->arrays[e.i+1]+offset-1]); 158 default: 159 break; 160 } 161 } 162 } 163error: 164 pp->err << "Error: array access to " << id << " invalid" 165 << " in line no. " 166 << yyget_lineno(pp->yyscanner) << std::endl; 167 pp->hadError = true; 168 return new AST::IntVar(0); // keep things consistent 169} 170AST::Node* getVarRefArg(ParserState* pp, string id, bool annotation = false) { 171 SymbolEntry e; 172 string n; 173 if (annotation) 174 n = id; 175 if (pp->symbols.get(id, e)) { 176 switch (e.t) { 177 case ST_INTVAR: return new AST::IntVar(e.i,n); 178 case ST_BOOLVAR: return new AST::BoolVar(e.i,n); 179 case ST_SETVAR: return new AST::SetVar(e.i,n); 180 case ST_FLOATVAR: return new AST::FloatVar(e.i,n); 181 default: break; 182 } 183 } 184 185 if (annotation) 186 return new AST::Atom(id); 187 pp->err << "Error: undefined variable " << id 188 << " in line no. " 189 << yyget_lineno(pp->yyscanner) << std::endl; 190 pp->hadError = true; 191 return new AST::IntVar(0); // keep things consistent 192} 193 194void addDomainConstraint(ParserState* pp, std::string id, AST::Node* var, 195 Option<AST::SetLit* >& dom) { 196 if (!dom()) 197 return; 198 AST::Array* args = new AST::Array(2); 199 args->a[0] = var; 200 args->a[1] = dom.some(); 201 pp->domainConstraints.push_back(new ConExpr(id, args, NULL)); 202} 203 204void addDomainConstraint(ParserState* pp, AST::Node* var, 205 Option<std::pair<double,double>* > dom) { 206 if (!dom()) 207 return; 208 { 209 AST::Array* args = new AST::Array(2); 210 args->a[0] = new AST::FloatLit(dom.some()->first); 211 args->a[1] = var; 212 pp->domainConstraints.push_back(new ConExpr("float_le", args, NULL)); 213 } 214 { 215 AST::Array* args = new AST::Array(2); 216 AST::FloatVar* fv = static_cast<AST::FloatVar*>(var); 217 args->a[0] = new AST::FloatVar(fv->i,fv->n); 218 args->a[1] = new AST::FloatLit(dom.some()->second); 219 pp->domainConstraints.push_back(new ConExpr("float_le", args, NULL)); 220 } 221 delete dom.some(); 222} 223 224int getBaseIntVar(ParserState* pp, int i) { 225 int base = i; 226 IntVarSpec* ivs = static_cast<IntVarSpec*>(pp->intvars[base].second); 227 while (ivs->alias) { 228 base = ivs->i; 229 ivs = static_cast<IntVarSpec*>(pp->intvars[base].second); 230 } 231 return base; 232} 233int getBaseBoolVar(ParserState* pp, int i) { 234 int base = i; 235 BoolVarSpec* ivs = static_cast<BoolVarSpec*>(pp->boolvars[base].second); 236 while (ivs->alias) { 237 base = ivs->i; 238 ivs = static_cast<BoolVarSpec*>(pp->boolvars[base].second); 239 } 240 return base; 241} 242int getBaseFloatVar(ParserState* pp, int i) { 243 int base = i; 244 FloatVarSpec* ivs = static_cast<FloatVarSpec*>(pp->floatvars[base].second); 245 while (ivs->alias) { 246 base = ivs->i; 247 ivs = static_cast<FloatVarSpec*>(pp->floatvars[base].second); 248 } 249 return base; 250} 251int getBaseSetVar(ParserState* pp, int i) { 252 int base = i; 253 SetVarSpec* ivs = static_cast<SetVarSpec*>(pp->setvars[base].second); 254 while (ivs->alias) { 255 base = ivs->i; 256 ivs = static_cast<SetVarSpec*>(pp->setvars[base].second); 257 } 258 return base; 259} 260 261/* 262 * Initialize the root gecode space 263 * 264 */ 265 266void initfg(ParserState* pp) { 267 if (!pp->hadError) 268 pp->fg->init(pp->intvars.size(), 269 pp->boolvars.size(), 270 pp->setvars.size(), 271 pp->floatvars.size()); 272 273 for (unsigned int i=0; i<pp->intvars.size(); i++) { 274 if (!pp->hadError) { 275 try { 276 pp->fg->newIntVar(static_cast<IntVarSpec*>(pp->intvars[i].second)); 277 } catch (Gecode::FlatZinc::Error& e) { 278 yyerror(pp, e.toString().c_str()); 279 } 280 } 281 delete pp->intvars[i].second; 282 pp->intvars[i].second = NULL; 283 } 284 for (unsigned int i=0; i<pp->boolvars.size(); i++) { 285 if (!pp->hadError) { 286 try { 287 pp->fg->newBoolVar( 288 static_cast<BoolVarSpec*>(pp->boolvars[i].second)); 289 } catch (Gecode::FlatZinc::Error& e) { 290 yyerror(pp, e.toString().c_str()); 291 } 292 } 293 delete pp->boolvars[i].second; 294 pp->boolvars[i].second = NULL; 295 } 296 for (unsigned int i=0; i<pp->setvars.size(); i++) { 297 if (!pp->hadError) { 298 try { 299 pp->fg->newSetVar(static_cast<SetVarSpec*>(pp->setvars[i].second)); 300 } catch (Gecode::FlatZinc::Error& e) { 301 yyerror(pp, e.toString().c_str()); 302 } 303 } 304 delete pp->setvars[i].second; 305 pp->setvars[i].second = NULL; 306 } 307 for (unsigned int i=0; i<pp->floatvars.size(); i++) { 308 if (!pp->hadError) { 309 try { 310 pp->fg->newFloatVar( 311 static_cast<FloatVarSpec*>(pp->floatvars[i].second)); 312 } catch (Gecode::FlatZinc::Error& e) { 313 yyerror(pp, e.toString().c_str()); 314 } 315 } 316 delete pp->floatvars[i].second; 317 pp->floatvars[i].second = NULL; 318 } 319 if (!pp->hadError) { 320 pp->fg->postConstraints(pp->domainConstraints); 321 pp->fg->postConstraints(pp->constraints); 322 } 323} 324 325void fillPrinter(ParserState& pp, Gecode::FlatZinc::Printer& p) { 326 p.init(pp.getOutput()); 327 for (unsigned int i=0; i<pp.intvars.size(); i++) { 328 if (!pp.hadError) { 329 p.addIntVarName(pp.intvars[i].first); 330 } 331 } 332 for (unsigned int i=0; i<pp.boolvars.size(); i++) { 333 if (!pp.hadError) { 334 p.addBoolVarName(pp.boolvars[i].first); 335 } 336 } 337#ifdef GECODE_HAS_FLOAT_VARS 338 for (unsigned int i=0; i<pp.floatvars.size(); i++) { 339 if (!pp.hadError) { 340 p.addFloatVarName(pp.floatvars[i].first); 341 } 342 } 343#endif 344#ifdef GECODE_HAS_SET_VARS 345 for (unsigned int i=0; i<pp.setvars.size(); i++) { 346 if (!pp.hadError) { 347 p.addSetVarName(pp.setvars[i].first); 348 } 349 } 350#endif 351} 352 353AST::Node* arrayOutput(AST::Call* ann) { 354 AST::Array* a = NULL; 355 356 if (ann->args->isArray()) { 357 a = ann->args->getArray(); 358 } else { 359 a = new AST::Array(ann->args); 360 } 361 362 std::ostringstream oss; 363 364 oss << "array" << a->a.size() << "d("; 365 for (unsigned int i=0; i<a->a.size(); i++) { 366 AST::SetLit* s = a->a[i]->getSet(); 367 if (s->empty()) 368 oss << "{}, "; 369 else if (s->interval) 370 oss << s->min << ".." << s->max << ", "; 371 else { 372 oss << "{"; 373 for (unsigned int j=0; j<s->s.size(); j++) { 374 oss << s->s[j]; 375 if (j<s->s.size()-1) 376 oss << ","; 377 } 378 oss << "}, "; 379 } 380 } 381 382 if (!ann->args->isArray()) { 383 a->a[0] = NULL; 384 delete a; 385 } 386 return new AST::String(oss.str()); 387} 388 389/* 390 * The main program 391 * 392 */ 393 394namespace Gecode { namespace FlatZinc { 395 396 FlatZincSpace* parse(const std::string& filename, Printer& p, std::ostream& err, 397 FlatZincSpace* fzs, Rnd& rnd) { 398#ifdef HAVE_MMAP 399 int fd; 400 char* data; 401 struct stat sbuf; 402 fd = open(filename.c_str(), O_RDONLY); 403 if (fd == -1) { 404 err << "Cannot open file " << filename << endl; 405 return NULL; 406 } 407 if (stat(filename.c_str(), &sbuf) == -1) { 408 err << "Cannot stat file " << filename << endl; 409 return NULL; 410 } 411 data = (char*)mmap((caddr_t)0, sbuf.st_size, PROT_READ, MAP_SHARED, fd,0); 412 if (data == (caddr_t)(-1)) { 413 err << "Cannot mmap file " << filename << endl; 414 return NULL; 415 } 416 417 if (fzs == NULL) { 418 fzs = new FlatZincSpace(rnd); 419 } 420 ParserState pp(data, sbuf.st_size, err, fzs); 421#else 422 std::ifstream file; 423 file.open(filename.c_str()); 424 if (!file.is_open()) { 425 err << "Cannot open file " << filename << endl; 426 return NULL; 427 } 428 std::string s = string(istreambuf_iterator<char>(file), 429 istreambuf_iterator<char>()); 430 if (fzs == NULL) { 431 fzs = new FlatZincSpace(rnd); 432 } 433 ParserState pp(s, err, fzs); 434#endif 435 yylex_init(&pp.yyscanner); 436 yyset_extra(&pp, pp.yyscanner); 437 // yydebug = 1; 438 yyparse(&pp); 439 fillPrinter(pp, p); 440 441 if (pp.yyscanner) 442 yylex_destroy(pp.yyscanner); 443 return pp.hadError ? NULL : pp.fg; 444 } 445 446 FlatZincSpace* parse(std::istream& is, Printer& p, std::ostream& err, 447 FlatZincSpace* fzs, Rnd& rnd) { 448 std::string s = string(istreambuf_iterator<char>(is), 449 istreambuf_iterator<char>()); 450 451 if (fzs == NULL) { 452 fzs = new FlatZincSpace(rnd); 453 } 454 ParserState pp(s, err, fzs); 455 yylex_init(&pp.yyscanner); 456 yyset_extra(&pp, pp.yyscanner); 457 // yydebug = 1; 458 yyparse(&pp); 459 fillPrinter(pp, p); 460 461 if (pp.yyscanner) 462 yylex_destroy(pp.yyscanner); 463 return pp.hadError ? NULL : pp.fg; 464 } 465 466}} 467 468%} 469 470%union { int iValue; char* sValue; bool bValue; double dValue; 471 std::vector<int>* setValue; 472 Gecode::FlatZinc::AST::SetLit* setLit; 473 std::vector<double>* floatSetValue; 474 std::vector<Gecode::FlatZinc::AST::SetLit>* setValueList; 475 Gecode::FlatZinc::Option<Gecode::FlatZinc::AST::SetLit* > oSet; 476 Gecode::FlatZinc::Option<std::pair<double,double>* > oPFloat; 477 Gecode::FlatZinc::VarSpec* varSpec; 478 Gecode::FlatZinc::Option<Gecode::FlatZinc::AST::Node*> oArg; 479 std::vector<Gecode::FlatZinc::VarSpec*>* varSpecVec; 480 Gecode::FlatZinc::Option<std::vector<Gecode::FlatZinc::VarSpec*>* > oVarSpecVec; 481 Gecode::FlatZinc::AST::Node* arg; 482 Gecode::FlatZinc::AST::Array* argVec; 483 } 484 485%error-verbose 486 487%token <iValue> FZ_INT_LIT FZ_BOOL_LIT 488%token <dValue> FZ_FLOAT_LIT 489%token <sValue> FZ_ID FZ_U_ID FZ_STRING_LIT 490 491%token <bValue> FZ_VAR FZ_PAR 492 493%token FZ_ANNOTATION 494%token FZ_ANY 495%token FZ_ARRAY 496%token FZ_BOOL 497%token FZ_CASE 498%token FZ_COLONCOLON 499%token FZ_CONSTRAINT 500%token FZ_DEFAULT 501%token FZ_DOTDOT 502%token FZ_ELSE 503%token FZ_ELSEIF 504%token FZ_ENDIF 505%token FZ_ENUM 506%token FZ_FLOAT 507%token FZ_FUNCTION 508%token FZ_IF 509%token FZ_INCLUDE 510%token FZ_INT 511%token FZ_LET 512%token <bValue> FZ_MAXIMIZE 513%token <bValue> FZ_MINIMIZE 514%token FZ_OF 515%token FZ_SATISFY 516%token FZ_OUTPUT 517%token FZ_PREDICATE 518%token FZ_RECORD 519%token FZ_SET 520%token FZ_SHOW 521%token FZ_SHOWCOND 522%token FZ_SOLVE 523%token FZ_STRING 524%token FZ_TEST 525%token FZ_THEN 526%token FZ_TUPLE 527%token FZ_TYPE 528%token FZ_VARIANT_RECORD 529%token FZ_WHERE 530 531%type <sValue> var_par_id 532%type <setLit> set_literal 533 534%type <varSpec> int_init bool_init set_init float_init 535%type <oSet> int_ti_expr_tail bool_ti_expr_tail 536%type <oPFloat> float_ti_expr_tail 537 538%type <oVarSpecVec> vardecl_int_var_array_init 539%type <oVarSpecVec> vardecl_bool_var_array_init 540%type <oVarSpecVec> vardecl_float_var_array_init 541%type <oVarSpecVec> vardecl_set_var_array_init 542%type <varSpecVec> int_var_array_literal 543%type <varSpecVec> bool_var_array_literal 544%type <varSpecVec> float_var_array_literal 545%type <varSpecVec> set_var_array_literal 546%type <varSpecVec> int_init_list int_init_list_head 547%type <varSpecVec> bool_init_list bool_init_list_head 548%type <varSpecVec> float_init_list float_init_list_head 549%type <varSpecVec> set_init_list set_init_list_head 550 551%type <setValue> int_list int_list_head 552%type <setValue> bool_list bool_list_head 553%type <setValueList> set_literal_list set_literal_list_head 554%type <floatSetValue> float_list float_list_head 555 556%type <arg> flat_expr non_array_expr annotation_expr ann_non_array_expr 557%type <oArg> non_array_expr_opt 558%type <argVec> flat_expr_list non_array_expr_list non_array_expr_list_head 559 560%type <iValue> solve_expr 561%type <bValue> minmax 562 563%type <argVec> annotations annotations_head 564%type <arg> annotation annotation_list 565 566%% 567 568/********************************/ 569/* main goal and item lists */ 570/********************************/ 571 572model : preddecl_items vardecl_items constraint_items solve_item ';' 573 574preddecl_items: 575 /* empty */ 576 | preddecl_items_head 577 578preddecl_items_head: 579 preddecl_item ';' 580 | preddecl_items_head preddecl_item ';' 581 582vardecl_items: 583 /* emtpy */ 584 | vardecl_items_head 585 586vardecl_items_head: 587 vardecl_item ';' 588 | vardecl_items_head vardecl_item ';' 589 590constraint_items: 591 /* emtpy */ 592 | constraint_items_head 593 594constraint_items_head: 595 constraint_item ';' 596 | constraint_items_head constraint_item ';' 597 598/********************************/ 599/* predicate declarations */ 600/********************************/ 601 602preddecl_item: 603 FZ_PREDICATE FZ_ID '(' pred_arg_list ')' 604 { free($2); } 605 606pred_arg_list: 607 /* empty */ 608 | pred_arg_list_head list_tail 609 610pred_arg_list_head: 611 pred_arg 612 | pred_arg_list_head ',' pred_arg 613 614pred_arg: 615 pred_arg_type ':' FZ_ID 616 { free($3); } 617 618pred_arg_type: 619 FZ_ARRAY '[' pred_array_init ']' FZ_OF pred_arg_simple_type 620 | FZ_ARRAY '[' pred_array_init ']' FZ_OF FZ_VAR pred_arg_simple_type 621 | FZ_VAR pred_arg_simple_type 622 | pred_arg_simple_type 623 624pred_arg_simple_type: 625 int_ti_expr_tail 626 { if ($1()) delete $1.some(); } 627 | FZ_SET FZ_OF int_ti_expr_tail 628 { if ($3()) delete $3.some(); } 629 | FZ_BOOL 630 | FZ_FLOAT 631 632pred_array_init: 633 pred_array_init_arg 634 | pred_array_init ',' pred_array_init_arg 635 636pred_array_init_arg: 637 FZ_INT 638 | FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT 639 640/********************************/ 641/* variable declarations */ 642/********************************/ 643 644var_par_id : FZ_ID | FZ_U_ID 645 646vardecl_item: 647 FZ_VAR int_ti_expr_tail ':' var_par_id annotations non_array_expr_opt 648 { 649 ParserState* pp = static_cast<ParserState*>(parm); 650 bool print = $5 != NULL && $5->hasAtom("output_var"); 651 bool funcDep = $5 != NULL && $5->hasAtom("is_defined_var"); 652 yyassert(pp, 653 pp->symbols.put($4, se_iv(pp->intvars.size())), 654 "Duplicate symbol"); 655 if (print) { 656 pp->output(std::string($4), new AST::IntVar(pp->intvars.size())); 657 } 658 if ($6()) { 659 AST::Node* arg = $6.some(); 660 if (arg->isInt()) { 661 pp->intvars.push_back(varspec($4, 662 new IntVarSpec(arg->getInt(),!print,funcDep))); 663 } else if (arg->isIntVar()) { 664 pp->intvars.push_back(varspec($4, 665 new IntVarSpec(Alias(arg->getIntVar()),!print,funcDep))); 666 } else { 667 yyassert(pp, false, "Invalid var int initializer"); 668 } 669 if (!pp->hadError) 670 addDomainConstraint(pp, "int_in", 671 new AST::IntVar(pp->intvars.size()-1), $2); 672 delete arg; 673 } else { 674 pp->intvars.push_back(varspec($4, 675 new IntVarSpec($2,!print,funcDep))); 676 } 677 delete $5; free($4); 678 } 679 | FZ_VAR bool_ti_expr_tail ':' var_par_id annotations non_array_expr_opt 680 { 681 ParserState* pp = static_cast<ParserState*>(parm); 682 bool print = $5 != NULL && $5->hasAtom("output_var"); 683 bool funcDep = $5 != NULL && $5->hasAtom("is_defined_var"); 684 yyassert(pp, 685 pp->symbols.put($4, se_bv(pp->boolvars.size())), 686 "Duplicate symbol"); 687 if (print) { 688 pp->output(std::string($4), new AST::BoolVar(pp->boolvars.size())); 689 } 690 if ($6()) { 691 AST::Node* arg = $6.some(); 692 if (arg->isBool()) { 693 pp->boolvars.push_back(varspec($4, 694 new BoolVarSpec(arg->getBool(),!print,funcDep))); 695 } else if (arg->isBoolVar()) { 696 pp->boolvars.push_back(varspec($4, 697 new BoolVarSpec(Alias(arg->getBoolVar()),!print,funcDep))); 698 } else { 699 yyassert(pp, false, "Invalid var bool initializer"); 700 } 701 if (!pp->hadError) 702 addDomainConstraint(pp, "int_in", 703 new AST::BoolVar(pp->boolvars.size()-1), $2); 704 delete arg; 705 } else { 706 pp->boolvars.push_back(varspec($4, 707 new BoolVarSpec($2,!print,funcDep))); 708 } 709 delete $5; free($4); 710 } 711 | FZ_VAR float_ti_expr_tail ':' var_par_id annotations non_array_expr_opt 712 { 713 ParserState* pp = static_cast<ParserState*>(parm); 714 bool print = $5 != NULL && $5->hasAtom("output_var"); 715 bool funcDep = $5 != NULL && $5->hasAtom("is_defined_var"); 716 yyassert(pp, 717 pp->symbols.put($4, se_fv(pp->floatvars.size())), 718 "Duplicate symbol"); 719 if (print) { 720 pp->output(std::string($4), 721 new AST::FloatVar(pp->floatvars.size())); 722 } 723 if ($6()) { 724 AST::Node* arg = $6.some(); 725 if (arg->isFloat()) { 726 pp->floatvars.push_back(varspec($4, 727 new FloatVarSpec(arg->getFloat(),!print,funcDep))); 728 } else if (arg->isFloatVar()) { 729 pp->floatvars.push_back(varspec($4, 730 new FloatVarSpec( 731 Alias(arg->getFloatVar()),!print,funcDep))); 732 } else { 733 yyassert(pp, false, "Invalid var float initializer"); 734 } 735 if (!pp->hadError && $2()) { 736 AST::FloatVar* fv = new AST::FloatVar(pp->floatvars.size()-1); 737 addDomainConstraint(pp, fv, $2); 738 } 739 delete arg; 740 } else { 741 Option<std::pair<double,double> > dom = 742 $2() ? Option<std::pair<double,double> >::some(*$2.some()) 743 : Option<std::pair<double,double> >::none(); 744 if ($2()) delete $2.some(); 745 pp->floatvars.push_back(varspec($4, 746 new FloatVarSpec(dom,!print,funcDep))); 747 } 748 delete $5; free($4); 749 } 750 | FZ_VAR FZ_SET FZ_OF int_ti_expr_tail ':' var_par_id annotations non_array_expr_opt 751 { 752 ParserState* pp = static_cast<ParserState*>(parm); 753 bool print = $7 != NULL && $7->hasAtom("output_var"); 754 bool funcDep = $7 != NULL && $7->hasAtom("is_defined_var"); 755 yyassert(pp, 756 pp->symbols.put($6, se_sv(pp->setvars.size())), 757 "Duplicate symbol"); 758 if (print) { 759 pp->output(std::string($6), new AST::SetVar(pp->setvars.size())); 760 } 761 if ($8()) { 762 AST::Node* arg = $8.some(); 763 if (arg->isSet()) { 764 pp->setvars.push_back(varspec($6, 765 new SetVarSpec(arg->getSet(),!print,funcDep))); 766 } else if (arg->isSetVar()) { 767 pp->setvars.push_back(varspec($6, 768 new SetVarSpec(Alias(arg->getSetVar()),!print,funcDep))); 769 delete arg; 770 } else { 771 yyassert(pp, false, "Invalid var set initializer"); 772 delete arg; 773 } 774 if (!pp->hadError) 775 addDomainConstraint(pp, "set_subset", 776 new AST::SetVar(pp->setvars.size()-1), $4); 777 } else { 778 pp->setvars.push_back(varspec($6, 779 new SetVarSpec($4,!print,funcDep))); 780 } 781 delete $7; free($6); 782 } 783 | FZ_INT ':' var_par_id annotations '=' non_array_expr 784 { 785 ParserState* pp = static_cast<ParserState*>(parm); 786 yyassert(pp, $6->isInt(), "Invalid int initializer"); 787 yyassert(pp, 788 pp->symbols.put($3, se_i($6->getInt())), 789 "Duplicate symbol"); 790 delete $4; free($3); 791 } 792 | FZ_FLOAT ':' var_par_id annotations '=' non_array_expr 793 { 794 ParserState* pp = static_cast<ParserState*>(parm); 795 yyassert(pp, $6->isFloat(), "Invalid float initializer"); 796 pp->floatvals.push_back($6->getFloat()); 797 yyassert(pp, 798 pp->symbols.put($3, se_f(pp->floatvals.size()-1)), 799 "Duplicate symbol"); 800 delete $4; free($3); 801 } 802 | FZ_BOOL ':' var_par_id annotations '=' non_array_expr 803 { 804 ParserState* pp = static_cast<ParserState*>(parm); 805 yyassert(pp, $6->isBool(), "Invalid bool initializer"); 806 yyassert(pp, 807 pp->symbols.put($3, se_b($6->getBool())), 808 "Duplicate symbol"); 809 delete $4; free($3); 810 } 811 | FZ_SET FZ_OF FZ_INT ':' var_par_id annotations '=' non_array_expr 812 { 813 ParserState* pp = static_cast<ParserState*>(parm); 814 yyassert(pp, $8->isSet(), "Invalid set initializer"); 815 AST::SetLit* set = $8->getSet(); 816 pp->setvals.push_back(*set); 817 yyassert(pp, 818 pp->symbols.put($5, se_s(pp->setvals.size()-1)), 819 "Duplicate symbol"); 820 delete set; 821 delete $6; free($5); 822 } 823 | FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_VAR int_ti_expr_tail ':' 824 var_par_id annotations vardecl_int_var_array_init 825 { 826 ParserState* pp = static_cast<ParserState*>(parm); 827 yyassert(pp, $3==1, "Arrays must start at 1"); 828 if (!pp->hadError) { 829 bool print = $12 != NULL && $12->hasCall("output_array"); 830 vector<int> vars($5); 831 if (!pp->hadError) { 832 if ($13()) { 833 vector<VarSpec*>* vsv = $13.some(); 834 yyassert(pp, vsv->size() == static_cast<unsigned int>($5), 835 "Initializer size does not match array dimension"); 836 if (!pp->hadError) { 837 for (int i=0; i<$5; i++) { 838 IntVarSpec* ivsv = static_cast<IntVarSpec*>((*vsv)[i]); 839 if (ivsv->alias) { 840 if (print) 841 static_cast<IntVarSpec*>(pp->intvars[ivsv->i].second)->introduced = false; 842 vars[i] = ivsv->i; 843 } else { 844 if (print) 845 ivsv->introduced = false; 846 vars[i] = pp->intvars.size(); 847 pp->intvars.push_back(varspec($11, ivsv)); 848 } 849 if (!pp->hadError && $9()) { 850 Option<AST::SetLit*> opt = 851 Option<AST::SetLit*>::some(new AST::SetLit(*$9.some())); 852 addDomainConstraint(pp, "int_in", 853 new AST::IntVar(vars[i]), 854 opt); 855 } 856 } 857 } 858 delete vsv; 859 } else { 860 if ($5>0) { 861 for (int i=0; i<$5; i++) { 862 Option<AST::SetLit*> dom = 863 $9() ? Option<AST::SetLit*>::some(new AST::SetLit($9.some())) 864 : Option<AST::SetLit*>::none(); 865 IntVarSpec* ispec = new IntVarSpec(dom,!print,false); 866 vars[i] = pp->intvars.size(); 867 pp->intvars.push_back(varspec($11, ispec)); 868 } 869 } 870 if ($9()) delete $9.some(); 871 } 872 } 873 if (print) { 874 AST::Array* a = new AST::Array(); 875 a->a.push_back(arrayOutput($12->getCall("output_array"))); 876 AST::Array* output = new AST::Array(); 877 for (int i=0; i<$5; i++) 878 output->a.push_back(new AST::IntVar(vars[i])); 879 a->a.push_back(output); 880 a->a.push_back(new AST::String(")")); 881 pp->output(std::string($11), a); 882 } 883 int iva = pp->arrays.size(); 884 pp->arrays.push_back(vars.size()); 885 for (unsigned int i=0; i<vars.size(); i++) 886 pp->arrays.push_back(vars[i]); 887 yyassert(pp, 888 pp->symbols.put($11, se_iva(iva)), 889 "Duplicate symbol"); 890 } 891 delete $12; free($11); 892 } 893 | FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_VAR bool_ti_expr_tail ':' 894 var_par_id annotations vardecl_bool_var_array_init 895 { 896 ParserState* pp = static_cast<ParserState*>(parm); 897 bool print = $12 != NULL && $12->hasCall("output_array"); 898 yyassert(pp, $3==1, "Arrays must start at 1"); 899 if (!pp->hadError) { 900 vector<int> vars($5); 901 if ($13()) { 902 vector<VarSpec*>* vsv = $13.some(); 903 yyassert(pp, vsv->size() == static_cast<unsigned int>($5), 904 "Initializer size does not match array dimension"); 905 if (!pp->hadError) { 906 for (int i=0; i<$5; i++) { 907 BoolVarSpec* bvsv = static_cast<BoolVarSpec*>((*vsv)[i]); 908 if (bvsv->alias) { 909 if (print) 910 static_cast<BoolVarSpec*>(pp->boolvars[bvsv->i].second)->introduced = false; 911 vars[i] = bvsv->i; 912 } else { 913 if (print) 914 bvsv->introduced = false; 915 vars[i] = pp->boolvars.size(); 916 pp->boolvars.push_back(varspec($11, (*vsv)[i])); 917 } 918 if (!pp->hadError && $9()) { 919 Option<AST::SetLit*> opt = 920 Option<AST::SetLit*>::some(new AST::SetLit(*$9.some())); 921 addDomainConstraint(pp, "int_in", 922 new AST::BoolVar(vars[i]), 923 opt); 924 } 925 } 926 } 927 delete vsv; 928 } else { 929 for (int i=0; i<$5; i++) { 930 Option<AST::SetLit*> dom = 931 $9() ? Option<AST::SetLit*>::some(new AST::SetLit($9.some())) 932 : Option<AST::SetLit*>::none(); 933 vars[i] = pp->boolvars.size(); 934 pp->boolvars.push_back(varspec($11, 935 new BoolVarSpec(dom,!print,false))); 936 } 937 if ($9()) delete $9.some(); 938 } 939 if (print) { 940 AST::Array* a = new AST::Array(); 941 a->a.push_back(arrayOutput($12->getCall("output_array"))); 942 AST::Array* output = new AST::Array(); 943 for (int i=0; i<$5; i++) 944 output->a.push_back(new AST::BoolVar(vars[i])); 945 a->a.push_back(output); 946 a->a.push_back(new AST::String(")")); 947 pp->output(std::string($11), a); 948 } 949 int bva = pp->arrays.size(); 950 pp->arrays.push_back(vars.size()); 951 for (unsigned int i=0; i<vars.size(); i++) 952 pp->arrays.push_back(vars[i]); 953 yyassert(pp, 954 pp->symbols.put($11, se_bva(bva)), 955 "Duplicate symbol"); 956 } 957 delete $12; free($11); 958 } 959 | FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_VAR 960 float_ti_expr_tail ':' var_par_id annotations 961 vardecl_float_var_array_init 962 { 963 ParserState* pp = static_cast<ParserState*>(parm); 964 yyassert(pp, $3==1, "Arrays must start at 1"); 965 if (!pp->hadError) { 966 bool print = $12 != NULL && $12->hasCall("output_array"); 967 vector<int> vars($5); 968 if (!pp->hadError) { 969 if ($13()) { 970 vector<VarSpec*>* vsv = $13.some(); 971 yyassert(pp, vsv->size() == static_cast<unsigned int>($5), 972 "Initializer size does not match array dimension"); 973 if (!pp->hadError) { 974 for (int i=0; i<$5; i++) { 975 FloatVarSpec* ivsv = static_cast<FloatVarSpec*>((*vsv)[i]); 976 if (ivsv->alias) { 977 if (print) 978 static_cast<FloatVarSpec*>(pp->floatvars[ivsv->i].second)->introduced = false; 979 vars[i] = ivsv->i; 980 } else { 981 if (print) 982 ivsv->introduced = false; 983 vars[i] = pp->floatvars.size(); 984 pp->floatvars.push_back(varspec($11, ivsv)); 985 } 986 if (!pp->hadError && $9()) { 987 Option<std::pair<double,double>*> opt = 988 Option<std::pair<double,double>*>::some( 989 new std::pair<double,double>(*$9.some())); 990 addDomainConstraint(pp, new AST::FloatVar(vars[i]), 991 opt); 992 } 993 } 994 } 995 delete vsv; 996 } else { 997 if ($5>0) { 998 Option<std::pair<double,double> > dom = 999 $9() ? Option<std::pair<double,double> >::some(*$9.some()) 1000 : Option<std::pair<double,double> >::none(); 1001 for (int i=0; i<$5; i++) { 1002 FloatVarSpec* ispec = new FloatVarSpec(dom,!print,false); 1003 vars[i] = pp->floatvars.size(); 1004 pp->floatvars.push_back(varspec($11, ispec)); 1005 } 1006 } 1007 } 1008 } 1009 if (print) { 1010 AST::Array* a = new AST::Array(); 1011 a->a.push_back(arrayOutput($12->getCall("output_array"))); 1012 AST::Array* output = new AST::Array(); 1013 for (int i=0; i<$5; i++) 1014 output->a.push_back(new AST::FloatVar(vars[i])); 1015 a->a.push_back(output); 1016 a->a.push_back(new AST::String(")")); 1017 pp->output(std::string($11), a); 1018 } 1019 int fva = pp->arrays.size(); 1020 pp->arrays.push_back(vars.size()); 1021 for (unsigned int i=0; i<vars.size(); i++) 1022 pp->arrays.push_back(vars[i]); 1023 yyassert(pp, 1024 pp->symbols.put($11, se_fva(fva)), 1025 "Duplicate symbol"); 1026 } 1027 if ($9()) delete $9.some(); 1028 delete $12; free($11); 1029 } 1030 | FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_VAR FZ_SET FZ_OF int_ti_expr_tail ':' 1031 var_par_id annotations vardecl_set_var_array_init 1032 { 1033 ParserState* pp = static_cast<ParserState*>(parm); 1034 bool print = $14 != NULL && $14->hasCall("output_array"); 1035 yyassert(pp, $3==1, "Arrays must start at 1"); 1036 if (!pp->hadError) { 1037 vector<int> vars($5); 1038 if ($15()) { 1039 vector<VarSpec*>* vsv = $15.some(); 1040 yyassert(pp, vsv->size() == static_cast<unsigned int>($5), 1041 "Initializer size does not match array dimension"); 1042 if (!pp->hadError) { 1043 for (int i=0; i<$5; i++) { 1044 SetVarSpec* svsv = static_cast<SetVarSpec*>((*vsv)[i]); 1045 if (svsv->alias) { 1046 if (print) 1047 static_cast<SetVarSpec*>(pp->setvars[svsv->i].second)->introduced = false; 1048 vars[i] = svsv->i; 1049 } else { 1050 if (print) 1051 svsv->introduced = false; 1052 vars[i] = pp->setvars.size(); 1053 pp->setvars.push_back(varspec($13, (*vsv)[i])); 1054 } 1055 if (!pp->hadError && $11()) { 1056 Option<AST::SetLit*> opt = 1057 Option<AST::SetLit*>::some(new AST::SetLit(*$11.some())); 1058 addDomainConstraint(pp, "set_subset", 1059 new AST::SetVar(vars[i]), 1060 opt); 1061 } 1062 } 1063 } 1064 delete vsv; 1065 } else { 1066 if ($5>0) { 1067 for (int i=0; i<$5; i++) { 1068 Option<AST::SetLit*> dom = 1069 $11() ? Option<AST::SetLit*>::some(new AST::SetLit($11.some())) 1070 : Option<AST::SetLit*>::none(); 1071 SetVarSpec* ispec = new SetVarSpec(dom,!print,false); 1072 vars[i] = pp->setvars.size(); 1073 pp->setvars.push_back(varspec($13, ispec)); 1074 } 1075 if ($11()) delete $11.some(); 1076 } 1077 } 1078 if (print) { 1079 AST::Array* a = new AST::Array(); 1080 a->a.push_back(arrayOutput($14->getCall("output_array"))); 1081 AST::Array* output = new AST::Array(); 1082 for (int i=0; i<$5; i++) 1083 output->a.push_back(new AST::SetVar(vars[i])); 1084 a->a.push_back(output); 1085 a->a.push_back(new AST::String(")")); 1086 pp->output(std::string($13), a); 1087 } 1088 int sva = pp->arrays.size(); 1089 pp->arrays.push_back(vars.size()); 1090 for (unsigned int i=0; i<vars.size(); i++) 1091 pp->arrays.push_back(vars[i]); 1092 yyassert(pp, 1093 pp->symbols.put($13, se_sva(sva)), 1094 "Duplicate symbol"); 1095 } 1096 delete $14; free($13); 1097 } 1098 | FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_INT ':' 1099 var_par_id annotations '=' '[' int_list ']' 1100 { 1101 ParserState* pp = static_cast<ParserState*>(parm); 1102 yyassert(pp, $3==1, "Arrays must start at 1"); 1103 yyassert(pp, $14->size() == static_cast<unsigned int>($5), 1104 "Initializer size does not match array dimension"); 1105 1106 if (!pp->hadError) { 1107 int ia = pp->arrays.size(); 1108 pp->arrays.push_back($14->size()); 1109 for (unsigned int i=0; i<$14->size(); i++) 1110 pp->arrays.push_back((*$14)[i]); 1111 yyassert(pp, 1112 pp->symbols.put($10, se_ia(ia)), 1113 "Duplicate symbol"); 1114 } 1115 delete $14; 1116 free($10); 1117 delete $11; 1118 } 1119 | FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_BOOL ':' 1120 var_par_id annotations '=' '[' bool_list ']' 1121 { 1122 ParserState* pp = static_cast<ParserState*>(parm); 1123 yyassert(pp, $3==1, "Arrays must start at 1"); 1124 yyassert(pp, $14->size() == static_cast<unsigned int>($5), 1125 "Initializer size does not match array dimension"); 1126 if (!pp->hadError) { 1127 int ia = pp->arrays.size(); 1128 pp->arrays.push_back($14->size()); 1129 for (unsigned int i=0; i<$14->size(); i++) 1130 pp->arrays.push_back((*$14)[i]); 1131 yyassert(pp, 1132 pp->symbols.put($10, se_ba(ia)), 1133 "Duplicate symbol"); 1134 } 1135 delete $14; 1136 free($10); 1137 delete $11; 1138 } 1139 | FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_FLOAT ':' 1140 var_par_id annotations '=' '[' float_list ']' 1141 { 1142 ParserState* pp = static_cast<ParserState*>(parm); 1143 yyassert(pp, $3==1, "Arrays must start at 1"); 1144 yyassert(pp, $14->size() == static_cast<unsigned int>($5), 1145 "Initializer size does not match array dimension"); 1146 if (!pp->hadError) { 1147 int fa = pp->arrays.size(); 1148 pp->arrays.push_back($14->size()); 1149 pp->arrays.push_back(pp->floatvals.size()); 1150 for (unsigned int i=0; i<$14->size(); i++) 1151 pp->floatvals.push_back((*$14)[i]); 1152 yyassert(pp, 1153 pp->symbols.put($10, se_fa(fa)), 1154 "Duplicate symbol"); 1155 } 1156 delete $14; 1157 delete $11; free($10); 1158 } 1159 | FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_SET FZ_OF FZ_INT ':' 1160 var_par_id annotations '=' '[' set_literal_list ']' 1161 { 1162 ParserState* pp = static_cast<ParserState*>(parm); 1163 yyassert(pp, $3==1, "Arrays must start at 1"); 1164 yyassert(pp, $16->size() == static_cast<unsigned int>($5), 1165 "Initializer size does not match array dimension"); 1166 if (!pp->hadError) { 1167 int sa = pp->arrays.size(); 1168 pp->arrays.push_back($16->size()); 1169 pp->arrays.push_back(pp->setvals.size()); 1170 for (unsigned int i=0; i<$16->size(); i++) 1171 pp->setvals.push_back((*$16)[i]); 1172 yyassert(pp, 1173 pp->symbols.put($12, se_sa(sa)), 1174 "Duplicate symbol"); 1175 } 1176 1177 delete $16; 1178 delete $13; free($12); 1179 } 1180 1181int_init : 1182 FZ_INT_LIT 1183 { 1184 $$ = new IntVarSpec($1,false,false); 1185 } 1186 | var_par_id 1187 { 1188 SymbolEntry e; 1189 ParserState* pp = static_cast<ParserState*>(parm); 1190 if (pp->symbols.get($1, e) && e.t == ST_INTVAR) 1191 $$ = new IntVarSpec(Alias(e.i),false,false); 1192 else { 1193 pp->err << "Error: undefined identifier for type int " << $1 1194 << " in line no. " 1195 << yyget_lineno(pp->yyscanner) << std::endl; 1196 pp->hadError = true; 1197 $$ = new IntVarSpec(0,false,false); // keep things consistent 1198 } 1199 free($1); 1200 } 1201 | var_par_id '[' FZ_INT_LIT ']' 1202 { 1203 vector<int> v; 1204 SymbolEntry e; 1205 ParserState* pp = static_cast<ParserState*>(parm); 1206 if (pp->symbols.get($1, e) && e.t == ST_INTVARARRAY) { 1207 yyassert(pp,$3 > 0 && $3 <= pp->arrays[e.i], 1208 "array access out of bounds"); 1209 if (!pp->hadError) 1210 $$ = new IntVarSpec(Alias(pp->arrays[e.i+$3]),false,false); 1211 else 1212 $$ = new IntVarSpec(0,false,false); // keep things consistent 1213 } else { 1214 pp->err << "Error: undefined array identifier for type int " << $1 1215 << " in line no. " 1216 << yyget_lineno(pp->yyscanner) << std::endl; 1217 pp->hadError = true; 1218 $$ = new IntVarSpec(0,false,false); // keep things consistent 1219 } 1220 free($1); 1221 } 1222 1223int_init_list : 1224 /* empty */ 1225 { $$ = new vector<VarSpec*>(0); } 1226 | int_init_list_head list_tail 1227 { $$ = $1; } 1228 1229int_init_list_head : 1230 int_init 1231 { $$ = new vector<VarSpec*>(1); (*$$)[0] = $1; } 1232 | int_init_list_head ',' int_init 1233 { $$ = $1; $$->push_back($3); } 1234 1235list_tail : | ',' 1236 1237int_var_array_literal : '[' int_init_list ']' 1238 { $$ = $2; } 1239 1240float_init : 1241 FZ_FLOAT_LIT 1242 { $$ = new FloatVarSpec($1,false,false); } 1243 | var_par_id 1244 { 1245 SymbolEntry e; 1246 ParserState* pp = static_cast<ParserState*>(parm); 1247 if (pp->symbols.get($1, e) && e.t == ST_FLOATVAR) 1248 $$ = new FloatVarSpec(Alias(e.i),false,false); 1249 else { 1250 pp->err << "Error: undefined identifier for type float " << $1 1251 << " in line no. " 1252 << yyget_lineno(pp->yyscanner) << std::endl; 1253 pp->hadError = true; 1254 $$ = new FloatVarSpec(0.0,false,false); 1255 } 1256 free($1); 1257 } 1258 | var_par_id '[' FZ_INT_LIT ']' 1259 { 1260 SymbolEntry e; 1261 ParserState* pp = static_cast<ParserState*>(parm); 1262 if (pp->symbols.get($1, e) && e.t == ST_FLOATVARARRAY) { 1263 yyassert(pp,$3 > 0 && $3 <= pp->arrays[e.i], 1264 "array access out of bounds"); 1265 if (!pp->hadError) 1266 $$ = new FloatVarSpec(Alias(pp->arrays[e.i+$3]),false,false); 1267 else 1268 $$ = new FloatVarSpec(0.0,false,false); 1269 } else { 1270 pp->err << "Error: undefined array identifier for type float " << $1 1271 << " in line no. " 1272 << yyget_lineno(pp->yyscanner) << std::endl; 1273 pp->hadError = true; 1274 $$ = new FloatVarSpec(0.0,false,false); 1275 } 1276 free($1); 1277 } 1278 1279float_init_list : 1280 /* empty */ 1281 { $$ = new vector<VarSpec*>(0); } 1282 | float_init_list_head list_tail 1283 { $$ = $1; } 1284 1285float_init_list_head : 1286 float_init 1287 { $$ = new vector<VarSpec*>(1); (*$$)[0] = $1; } 1288 | float_init_list_head ',' float_init 1289 { $$ = $1; $$->push_back($3); } 1290 1291float_var_array_literal : 1292 '[' float_init_list ']' 1293 { $$ = $2; } 1294 1295bool_init : 1296 FZ_BOOL_LIT 1297 { $$ = new BoolVarSpec($1,false,false); } 1298 | var_par_id 1299 { 1300 SymbolEntry e; 1301 ParserState* pp = static_cast<ParserState*>(parm); 1302 if (pp->symbols.get($1, e) && e.t == ST_BOOLVAR) 1303 $$ = new BoolVarSpec(Alias(e.i),false,false); 1304 else { 1305 pp->err << "Error: undefined identifier for type bool " << $1 1306 << " in line no. " 1307 << yyget_lineno(pp->yyscanner) << std::endl; 1308 pp->hadError = true; 1309 $$ = new BoolVarSpec(false,false,false); 1310 } 1311 free($1); 1312 } 1313 | var_par_id '[' FZ_INT_LIT ']' 1314 { 1315 SymbolEntry e; 1316 ParserState* pp = static_cast<ParserState*>(parm); 1317 if (pp->symbols.get($1, e) && e.t == ST_BOOLVARARRAY) { 1318 yyassert(pp,$3 > 0 && $3 <= pp->arrays[e.i], 1319 "array access out of bounds"); 1320 if (!pp->hadError) 1321 $$ = new BoolVarSpec(Alias(pp->arrays[e.i+$3]),false,false); 1322 else 1323 $$ = new BoolVarSpec(false,false,false); 1324 } else { 1325 pp->err << "Error: undefined array identifier for type bool " << $1 1326 << " in line no. " 1327 << yyget_lineno(pp->yyscanner) << std::endl; 1328 pp->hadError = true; 1329 $$ = new BoolVarSpec(false,false,false); 1330 } 1331 free($1); 1332 } 1333 1334bool_init_list : 1335 /* empty */ 1336 { $$ = new vector<VarSpec*>(0); } 1337 | bool_init_list_head list_tail 1338 { $$ = $1; } 1339 1340bool_init_list_head : 1341 bool_init 1342 { $$ = new vector<VarSpec*>(1); (*$$)[0] = $1; } 1343 | bool_init_list_head ',' bool_init 1344 { $$ = $1; $$->push_back($3); } 1345 1346bool_var_array_literal : '[' bool_init_list ']' { $$ = $2; } 1347 1348set_init : 1349 set_literal 1350 { $$ = new SetVarSpec($1,false,false); } 1351 | var_par_id 1352 { 1353 ParserState* pp = static_cast<ParserState*>(parm); 1354 SymbolEntry e; 1355 if (pp->symbols.get($1, e) && e.t == ST_SETVAR) 1356 $$ = new SetVarSpec(Alias(e.i),false,false); 1357 else { 1358 pp->err << "Error: undefined identifier for type set " << $1 1359 << " in line no. " 1360 << yyget_lineno(pp->yyscanner) << std::endl; 1361 pp->hadError = true; 1362 $$ = new SetVarSpec(Alias(0),false,false); 1363 } 1364 free($1); 1365 } 1366 | var_par_id '[' FZ_INT_LIT ']' 1367 { 1368 SymbolEntry e; 1369 ParserState* pp = static_cast<ParserState*>(parm); 1370 if (pp->symbols.get($1, e) && e.t == ST_SETVARARRAY) { 1371 yyassert(pp,$3 > 0 && $3 <= pp->arrays[e.i], 1372 "array access out of bounds"); 1373 if (!pp->hadError) 1374 $$ = new SetVarSpec(Alias(pp->arrays[e.i+$3]),false,false); 1375 else 1376 $$ = new SetVarSpec(Alias(0),false,false); 1377 } else { 1378 pp->err << "Error: undefined array identifier for type set " << $1 1379 << " in line no. " 1380 << yyget_lineno(pp->yyscanner) << std::endl; 1381 pp->hadError = true; 1382 $$ = new SetVarSpec(Alias(0),false,false); 1383 } 1384 free($1); 1385 } 1386 1387set_init_list : 1388 /* empty */ 1389 { $$ = new vector<VarSpec*>(0); } 1390 | set_init_list_head list_tail 1391 { $$ = $1; } 1392 1393set_init_list_head : 1394 set_init 1395 { $$ = new vector<VarSpec*>(1); (*$$)[0] = $1; } 1396 | set_init_list_head ',' set_init 1397 { $$ = $1; $$->push_back($3); } 1398 1399set_var_array_literal : '[' set_init_list ']' 1400 { $$ = $2; } 1401 1402vardecl_int_var_array_init : 1403 /* empty */ 1404 { $$ = Option<vector<VarSpec*>* >::none(); } 1405 | '=' int_var_array_literal 1406 { $$ = Option<vector<VarSpec*>* >::some($2); } 1407 1408vardecl_bool_var_array_init : 1409 /* empty */ 1410 { $$ = Option<vector<VarSpec*>* >::none(); } 1411 | '=' bool_var_array_literal 1412 { $$ = Option<vector<VarSpec*>* >::some($2); } 1413 1414vardecl_float_var_array_init : 1415 /* empty */ 1416 { $$ = Option<vector<VarSpec*>* >::none(); } 1417 | '=' float_var_array_literal 1418 { $$ = Option<vector<VarSpec*>* >::some($2); } 1419 1420vardecl_set_var_array_init : 1421 /* empty */ 1422 { $$ = Option<vector<VarSpec*>* >::none(); } 1423 | '=' set_var_array_literal 1424 { $$ = Option<vector<VarSpec*>* >::some($2); } 1425 1426constraint_item : 1427 FZ_CONSTRAINT FZ_ID '(' flat_expr_list ')' annotations 1428 { 1429 ParserState *pp = static_cast<ParserState*>(parm); 1430 if (!pp->hadError) { 1431 std::string cid($2); 1432 if (cid=="int_eq" && $4->a[0]->isIntVar() && $4->a[1]->isIntVar()) { 1433 int base0 = getBaseIntVar(pp,$4->a[0]->getIntVar()); 1434 int base1 = getBaseIntVar(pp,$4->a[1]->getIntVar()); 1435 if (base0 > base1) { 1436 std::swap(base0, base1); 1437 } 1438 if (base0==base1) { 1439 // do nothing, already aliased 1440 } else { 1441 IntVarSpec* ivs1 = static_cast<IntVarSpec*>(pp->intvars[base1].second); 1442 AST::SetLit* sl = NULL; 1443 if (ivs1->assigned) { 1444 sl = new AST::SetLit(ivs1->i,ivs1->i); 1445 } else if (ivs1->domain()) { 1446 sl = new AST::SetLit(ivs1->domain.some()->getSet()); 1447 } 1448 if (sl) { 1449 Option<AST::SetLit*> newdom = Option<AST::SetLit*>::some(sl); 1450 addDomainConstraint(pp, "int_in", 1451 new AST::IntVar(base0), newdom); 1452 ivs1->domain = Option<AST::SetLit*>::none(); 1453 } 1454 ivs1->alias = true; 1455 ivs1->i = base0; 1456 } 1457 } else if (cid=="bool_eq" && $4->a[0]->isBoolVar() && $4->a[1]->isBoolVar()) { 1458 int base0 = getBaseBoolVar(pp,$4->a[0]->getBoolVar()); 1459 int base1 = getBaseBoolVar(pp,$4->a[1]->getBoolVar()); 1460 if (base0 > base1) { 1461 std::swap(base0, base1); 1462 } 1463 if (base0==base1) { 1464 // do nothing, already aliased 1465 } else { 1466 BoolVarSpec* ivs1 = static_cast<BoolVarSpec*>(pp->boolvars[base1].second); 1467 AST::SetLit* sl = NULL; 1468 if (ivs1->assigned) { 1469 sl = new AST::SetLit(ivs1->i,ivs1->i); 1470 } else if (ivs1->domain()) { 1471 sl = new AST::SetLit(ivs1->domain.some()->getSet()); 1472 } 1473 if (sl) { 1474 Option<AST::SetLit*> newdom = Option<AST::SetLit*>::some(sl); 1475 addDomainConstraint(pp, "int_in", 1476 new AST::BoolVar(base0), newdom); 1477 ivs1->domain = Option<AST::SetLit*>::none(); 1478 } 1479 ivs1->alias = true; 1480 ivs1->i = base0; 1481 } 1482 } else if (cid=="float_eq" && $4->a[0]->isFloatVar() && $4->a[1]->isFloatVar()) { 1483 int base0 = getBaseFloatVar(pp,$4->a[0]->getFloatVar()); 1484 int base1 = getBaseFloatVar(pp,$4->a[1]->getFloatVar()); 1485 if (base0 > base1) { 1486 std::swap(base0, base1); 1487 } 1488 if (base0==base1) { 1489 // do nothing, already aliased 1490 } else { 1491 FloatVarSpec* ivs1 = static_cast<FloatVarSpec*>(pp->floatvars[base1].second); 1492 ivs1->alias = true; 1493 ivs1->i = base0; 1494 if (ivs1->domain()) { 1495 std::pair<double,double>* dom = new std::pair<double,double>(ivs1->domain.some()); 1496 addDomainConstraint(pp, new AST::FloatVar(base0), Option<std::pair<double,double>* >::some(dom)); 1497 ivs1->domain = Option<std::pair<double,double> >::none(); 1498 } 1499 } 1500 } else if (cid=="set_eq" && $4->a[0]->isSetVar() && $4->a[1]->isSetVar()) { 1501 int base0 = getBaseSetVar(pp,$4->a[0]->getSetVar()); 1502 int base1 = getBaseSetVar(pp,$4->a[1]->getSetVar()); 1503 if (base0 > base1) { 1504 std::swap(base0, base1); 1505 } 1506 if (base0==base1) { 1507 // do nothing, already aliased 1508 } else { 1509 SetVarSpec* ivs1 = static_cast<SetVarSpec*>(pp->setvars[base1].second); 1510 ivs1->alias = true; 1511 ivs1->i = base0; 1512 if (ivs1->upperBound()) { 1513 AST::SetLit* sl = new AST::SetLit(ivs1->upperBound.some()->getSet()); 1514 Option<AST::SetLit*> newdom = Option<AST::SetLit*>::some(sl); 1515 if (ivs1->assigned) { 1516 addDomainConstraint(pp, "set_eq", 1517 new AST::SetVar(base0), newdom); 1518 } else { 1519 addDomainConstraint(pp, "set_subset", 1520 new AST::SetVar(base0), newdom); 1521 } 1522 ivs1->upperBound = Option<AST::SetLit*>::none(); 1523 } 1524 } 1525 } else if ( (cid=="int_le" || cid=="int_lt" || cid=="int_ge" || cid=="int_gt" || 1526 cid=="int_eq" || cid=="int_ne") && 1527 ($4->a[0]->isInt() || $4->a[1]->isInt()) ) { 1528 pp->domainConstraints.push_back(new ConExpr($2, $4, $6)); 1529 } else if ( cid=="set_in" && ($4->a[0]->isSet() || $4->a[1]->isSet()) ) { 1530 pp->domainConstraints.push_back(new ConExpr($2, $4, $6)); 1531 } else { 1532 pp->constraints.push_back(new ConExpr($2, $4, $6)); 1533 } 1534 } 1535 free($2); 1536 } 1537solve_item : 1538 FZ_SOLVE annotations FZ_SATISFY 1539 { 1540 ParserState *pp = static_cast<ParserState*>(parm); 1541 initfg(pp); 1542 if (!pp->hadError) { 1543 try { 1544 pp->fg->solve($2); 1545 } catch (Gecode::FlatZinc::Error& e) { 1546 yyerror(pp, e.toString().c_str()); 1547 } 1548 } else { 1549 delete $2; 1550 } 1551 } 1552 | FZ_SOLVE annotations minmax solve_expr 1553 { 1554 ParserState *pp = static_cast<ParserState*>(parm); 1555 initfg(pp); 1556 if (!pp->hadError) { 1557 try { 1558 int v = $4 < 0 ? (-$4-1) : $4; 1559 bool vi = $4 >= 0; 1560 if ($3) 1561 pp->fg->minimize(v,vi,$2); 1562 else 1563 pp->fg->maximize(v,vi,$2); 1564 } catch (Gecode::FlatZinc::Error& e) { 1565 yyerror(pp, e.toString().c_str()); 1566 } 1567 } else { 1568 delete $2; 1569 } 1570 } 1571 1572/********************************/ 1573/* type-insts */ 1574/********************************/ 1575 1576int_ti_expr_tail : 1577 FZ_INT 1578 { $$ = Option<AST::SetLit* >::none(); } 1579 | '{' int_list '}' 1580 { $$ = Option<AST::SetLit* >::some(new AST::SetLit(*$2)); } 1581 | FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT 1582 { 1583 $$ = Option<AST::SetLit* >::some(new AST::SetLit($1, $3)); 1584 } 1585 1586bool_ti_expr_tail : 1587 FZ_BOOL 1588 { $$ = Option<AST::SetLit* >::none(); } 1589 | '{' bool_list_head list_tail '}' 1590 { bool haveTrue = false; 1591 bool haveFalse = false; 1592 for (int i=$2->size(); i--;) { 1593 haveTrue |= ((*$2)[i] == 1); 1594 haveFalse |= ((*$2)[i] == 0); 1595 } 1596 delete $2; 1597 $$ = Option<AST::SetLit* >::some( 1598 new AST::SetLit(!haveFalse,haveTrue)); 1599 } 1600 1601float_ti_expr_tail : 1602 FZ_FLOAT 1603 { $$ = Option<std::pair<double,double>* >::none(); } 1604 | FZ_FLOAT_LIT FZ_DOTDOT FZ_FLOAT_LIT 1605 { std::pair<double,double>* dom = new std::pair<double,double>($1,$3); 1606 $$ = Option<std::pair<double,double>* >::some(dom); } 1607 1608/********************************/ 1609/* literals */ 1610/********************************/ 1611 1612set_literal : 1613 '{' int_list '}' 1614 { $$ = new AST::SetLit(*$2); } 1615 | FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT 1616 { $$ = new AST::SetLit($1, $3); } 1617 1618/* list containing only primitive literals */ 1619 1620int_list : 1621 /* empty */ 1622 { $$ = new vector<int>(0); } 1623 | int_list_head list_tail 1624 { $$ = $1; } 1625 1626int_list_head : 1627 FZ_INT_LIT 1628 { $$ = new vector<int>(1); (*$$)[0] = $1; } 1629 | int_list_head ',' FZ_INT_LIT 1630 { $$ = $1; $$->push_back($3); } 1631 1632bool_list : 1633 /* empty */ 1634 { $$ = new vector<int>(0); } 1635 | bool_list_head list_tail 1636 { $$ = $1; } 1637 1638bool_list_head : 1639 FZ_BOOL_LIT 1640 { $$ = new vector<int>(1); (*$$)[0] = $1; } 1641 | bool_list_head ',' FZ_BOOL_LIT 1642 { $$ = $1; $$->push_back($3); } 1643 1644float_list : 1645 /* empty */ 1646 { $$ = new vector<double>(0); } 1647 | float_list_head list_tail 1648 { $$ = $1; } 1649 1650float_list_head: 1651 FZ_FLOAT_LIT 1652 { $$ = new vector<double>(1); (*$$)[0] = $1; } 1653 | float_list_head ',' FZ_FLOAT_LIT 1654 { $$ = $1; $$->push_back($3); } 1655 1656set_literal_list : 1657 /* empty */ 1658 { $$ = new vector<AST::SetLit>(0); } 1659 | set_literal_list_head list_tail 1660 { $$ = $1; } 1661 1662set_literal_list_head : 1663 set_literal 1664 { $$ = new vector<AST::SetLit>(1); (*$$)[0] = *$1; delete $1; } 1665 | set_literal_list_head ',' set_literal 1666 { $$ = $1; $$->push_back(*$3); delete $3; } 1667 1668/********************************/ 1669/* constraint expressions */ 1670/********************************/ 1671 1672flat_expr_list : 1673 flat_expr 1674 { $$ = new AST::Array($1); } 1675 | flat_expr_list ',' flat_expr 1676 { $$ = $1; $$->append($3); } 1677 1678flat_expr : 1679 non_array_expr 1680 { $$ = $1; } 1681 | '[' non_array_expr_list ']' 1682 { $$ = $2; } 1683 1684non_array_expr_opt : 1685 /* empty */ 1686 { $$ = Option<AST::Node*>::none(); } 1687 | '=' non_array_expr 1688 { $$ = Option<AST::Node*>::some($2); } 1689 1690non_array_expr : 1691 FZ_BOOL_LIT 1692 { $$ = new AST::BoolLit($1); } 1693 | FZ_INT_LIT 1694 { $$ = new AST::IntLit($1); } 1695 | FZ_FLOAT_LIT 1696 { $$ = new AST::FloatLit($1); } 1697 | set_literal 1698 { $$ = $1; } 1699 | var_par_id /* variable, possibly array */ 1700 { 1701 ParserState* pp = static_cast<ParserState*>(parm); 1702 SymbolEntry e; 1703 if (pp->symbols.get($1, e)) { 1704 switch (e.t) { 1705 case ST_INTVARARRAY: 1706 { 1707 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1708 for (int i=pp->arrays[e.i]; i--;) 1709 v->a[i] = new AST::IntVar(pp->arrays[e.i+i+1]); 1710 $$ = v; 1711 } 1712 break; 1713 case ST_BOOLVARARRAY: 1714 { 1715 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1716 for (int i=pp->arrays[e.i]; i--;) 1717 v->a[i] = new AST::BoolVar(pp->arrays[e.i+i+1]); 1718 $$ = v; 1719 } 1720 break; 1721 case ST_FLOATVARARRAY: 1722 { 1723 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1724 for (int i=pp->arrays[e.i]; i--;) 1725 v->a[i] = new AST::FloatVar(pp->arrays[e.i+i+1]); 1726 $$ = v; 1727 } 1728 break; 1729 case ST_SETVARARRAY: 1730 { 1731 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1732 for (int i=pp->arrays[e.i]; i--;) 1733 v->a[i] = new AST::SetVar(pp->arrays[e.i+i+1]); 1734 $$ = v; 1735 } 1736 break; 1737 case ST_INTVALARRAY: 1738 { 1739 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1740 for (int i=pp->arrays[e.i]; i--;) 1741 v->a[i] = new AST::IntLit(pp->arrays[e.i+i+1]); 1742 $$ = v; 1743 } 1744 break; 1745 case ST_BOOLVALARRAY: 1746 { 1747 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1748 for (int i=pp->arrays[e.i]; i--;) 1749 v->a[i] = new AST::BoolLit(pp->arrays[e.i+i+1]); 1750 $$ = v; 1751 } 1752 break; 1753 case ST_SETVALARRAY: 1754 { 1755 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1756 int idx = pp->arrays[e.i+1]; 1757 for (int i=pp->arrays[e.i]; i--;) 1758 v->a[i] = new AST::SetLit(pp->setvals[idx+i]); 1759 $$ = v; 1760 } 1761 break; 1762 case ST_FLOATVALARRAY: 1763 { 1764 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1765 int idx = pp->arrays[e.i+1]; 1766 for (int i=pp->arrays[e.i]; i--;) 1767 v->a[i] = new AST::FloatLit(pp->floatvals[idx+i]); 1768 $$ = v; 1769 } 1770 break; 1771 case ST_INT: 1772 $$ = new AST::IntLit(e.i); 1773 break; 1774 case ST_BOOL: 1775 $$ = new AST::BoolLit(e.i); 1776 break; 1777 case ST_FLOAT: 1778 $$ = new AST::FloatLit(pp->floatvals[e.i]); 1779 break; 1780 case ST_SET: 1781 $$ = new AST::SetLit(pp->setvals[e.i]); 1782 break; 1783 default: 1784 $$ = getVarRefArg(pp,$1); 1785 } 1786 } else { 1787 pp->err << "Error: undefined identifier " << $1 1788 << " in line no. " 1789 << yyget_lineno(pp->yyscanner) << std::endl; 1790 pp->hadError = true; 1791 $$ = NULL; 1792 } 1793 free($1); 1794 } 1795 | var_par_id '[' non_array_expr ']' /* array access */ 1796 { 1797 ParserState* pp = static_cast<ParserState*>(parm); 1798 int i = -1; 1799 yyassert(pp, $3->isInt(i), "Non-integer array index"); 1800 if (!pp->hadError) 1801 $$ = getArrayElement(static_cast<ParserState*>(parm),$1,i,false); 1802 else 1803 $$ = new AST::IntLit(0); // keep things consistent 1804 delete $3; 1805 free($1); 1806 } 1807 1808non_array_expr_list : 1809 /* empty */ 1810 { $$ = new AST::Array(0); } 1811 | non_array_expr_list_head list_tail 1812 { $$ = $1; } 1813 1814non_array_expr_list_head : 1815 non_array_expr 1816 { $$ = new AST::Array($1); } 1817 | non_array_expr_list_head ',' non_array_expr 1818 { $$ = $1; $$->append($3); } 1819 1820/********************************/ 1821/* solve expressions */ 1822/********************************/ 1823 1824solve_expr: 1825 var_par_id 1826 { 1827 ParserState *pp = static_cast<ParserState*>(parm); 1828 SymbolEntry e; 1829 bool haveSym = pp->symbols.get($1,e); 1830 if (haveSym) { 1831 switch (e.t) { 1832 case ST_INTVAR: 1833 $$ = e.i; 1834 break; 1835 case ST_FLOATVAR: 1836 $$ = -e.i-1; 1837 break; 1838 case ST_INT: 1839 case ST_FLOAT: 1840 pp->intvars.push_back(varspec("OBJ_CONST_INTRODUCED", 1841 new IntVarSpec(0,true,false))); 1842 $$ = pp->intvars.size()-1; 1843 break; 1844 default: 1845 pp->err << "Error: unknown int or float variable " << $1 1846 << " in line no. " 1847 << yyget_lineno(pp->yyscanner) << std::endl; 1848 pp->hadError = true; 1849 break; 1850 } 1851 } else { 1852 pp->err << "Error: unknown int or float variable " << $1 1853 << " in line no. " 1854 << yyget_lineno(pp->yyscanner) << std::endl; 1855 pp->hadError = true; 1856 } 1857 free($1); 1858 } 1859 | FZ_INT_LIT 1860 { 1861 ParserState *pp = static_cast<ParserState*>(parm); 1862 pp->intvars.push_back(varspec("OBJ_CONST_INTRODUCED", 1863 new IntVarSpec(0,true,false))); 1864 $$ = pp->intvars.size()-1; 1865 } 1866 | FZ_FLOAT_LIT 1867 { 1868 ParserState *pp = static_cast<ParserState*>(parm); 1869 pp->intvars.push_back(varspec("OBJ_CONST_INTRODUCED", 1870 new IntVarSpec(0,true,false))); 1871 $$ = pp->intvars.size()-1; 1872 } 1873 | var_par_id '[' FZ_INT_LIT ']' 1874 { 1875 SymbolEntry e; 1876 ParserState *pp = static_cast<ParserState*>(parm); 1877 if ( (!pp->symbols.get($1, e)) || 1878 (e.t != ST_INTVARARRAY && e.t != ST_FLOATVARARRAY)) { 1879 pp->err << "Error: unknown int or float variable array " << $1 1880 << " in line no. " 1881 << yyget_lineno(pp->yyscanner) << std::endl; 1882 pp->hadError = true; 1883 } 1884 if ($3 == 0 || $3 > pp->arrays[e.i]) { 1885 pp->err << "Error: array index out of bounds for array " << $1 1886 << " in line no. " 1887 << yyget_lineno(pp->yyscanner) << std::endl; 1888 pp->hadError = true; 1889 } else { 1890 if (e.t == ST_INTVARARRAY) 1891 $$ = pp->arrays[e.i+$3]; 1892 else 1893 $$ = -pp->arrays[e.i+$3]-1; 1894 } 1895 free($1); 1896 } 1897 1898minmax: 1899 FZ_MINIMIZE 1900 | FZ_MAXIMIZE 1901 1902/********************************/ 1903/* annotation expresions */ 1904/********************************/ 1905 1906annotations : 1907 /* empty */ 1908 { $$ = NULL; } 1909 | annotations_head 1910 { $$ = $1; } 1911 1912annotations_head : 1913 FZ_COLONCOLON annotation 1914 { $$ = new AST::Array($2); } 1915 | annotations_head FZ_COLONCOLON annotation 1916 { $$ = $1; $$->append($3); } 1917 1918annotation : 1919 FZ_ID '(' annotation_list ')' 1920 { 1921 $$ = new AST::Call($1, AST::extractSingleton($3)); free($1); 1922 } 1923 | annotation_expr 1924 { $$ = $1; } 1925 1926annotation_list: 1927 annotation 1928 { $$ = new AST::Array($1); } 1929 | annotation_list ',' annotation 1930 { $$ = $1; $$->append($3); } 1931 1932annotation_expr : 1933 ann_non_array_expr 1934 { $$ = $1; } 1935 | '[' ']' 1936 { $$ = new AST::Array(); } 1937 | '[' annotation_list annotation_list_tail ']' 1938 { $$ = $2; } 1939 1940annotation_list_tail : | ',' 1941 1942ann_non_array_expr : 1943 FZ_BOOL_LIT 1944 { $$ = new AST::BoolLit($1); } 1945 | FZ_INT_LIT 1946 { $$ = new AST::IntLit($1); } 1947 | FZ_FLOAT_LIT 1948 { $$ = new AST::FloatLit($1); } 1949 | set_literal 1950 { $$ = $1; } 1951 | var_par_id /* variable, possibly array */ 1952 { 1953 ParserState* pp = static_cast<ParserState*>(parm); 1954 SymbolEntry e; 1955 bool gotSymbol = false; 1956 if (pp->symbols.get($1, e)) { 1957 gotSymbol = true; 1958 switch (e.t) { 1959 case ST_INTVARARRAY: 1960 { 1961 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1962 for (int i=pp->arrays[e.i]; i--;) { 1963 std::ostringstream oss; 1964 oss << $1 << "["<<(i+1)<<"]"; 1965 v->a[i] = new AST::IntVar(pp->arrays[e.i+i+1], oss.str()); 1966 } 1967 $$ = v; 1968 } 1969 break; 1970 case ST_BOOLVARARRAY: 1971 { 1972 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1973 for (int i=pp->arrays[e.i]; i--;) { 1974 std::ostringstream oss; 1975 oss << $1 << "["<<(i+1)<<"]"; 1976 v->a[i] = new AST::BoolVar(pp->arrays[e.i+i+1], oss.str()); 1977 } 1978 $$ = v; 1979 } 1980 break; 1981 case ST_FLOATVARARRAY: 1982 { 1983 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1984 for (int i=pp->arrays[e.i]; i--;) { 1985 std::ostringstream oss; 1986 oss << $1 << "["<<(i+1)<<"]"; 1987 v->a[i] = new AST::FloatVar(pp->arrays[e.i+i+1], oss.str()); 1988 } 1989 $$ = v; 1990 } 1991 break; 1992 case ST_SETVARARRAY: 1993 { 1994 AST::Array *v = new AST::Array(pp->arrays[e.i]); 1995 for (int i=pp->arrays[e.i]; i--;) { 1996 std::ostringstream oss; 1997 oss << $1 << "["<<(i+1)<<"]"; 1998 v->a[i] = new AST::SetVar(pp->arrays[e.i+i+1], oss.str()); 1999 } 2000 $$ = v; 2001 } 2002 break; 2003 case ST_INTVALARRAY: 2004 { 2005 AST::Array *v = new AST::Array(pp->arrays[e.i]); 2006 for (int i=pp->arrays[e.i]; i--;) 2007 v->a[i] = new AST::IntLit(pp->arrays[e.i+i+1]); 2008 $$ = v; 2009 } 2010 break; 2011 case ST_BOOLVALARRAY: 2012 { 2013 AST::Array *v = new AST::Array(pp->arrays[e.i]); 2014 for (int i=pp->arrays[e.i]; i--;) 2015 v->a[i] = new AST::BoolLit(pp->arrays[e.i+i+1]); 2016 $$ = v; 2017 } 2018 break; 2019 case ST_SETVALARRAY: 2020 { 2021 AST::Array *v = new AST::Array(pp->arrays[e.i]); 2022 int idx = pp->arrays[e.i+1]; 2023 for (int i=pp->arrays[e.i]; i--;) 2024 v->a[i] = new AST::SetLit(pp->setvals[idx+i]); 2025 $$ = v; 2026 } 2027 break; 2028 case ST_FLOATVALARRAY: 2029 { 2030 AST::Array *v = new AST::Array(pp->arrays[e.i]); 2031 int idx = pp->arrays[e.i+1]; 2032 for (int i=pp->arrays[e.i]; i--;) 2033 v->a[i] = new AST::FloatLit(pp->floatvals[idx+i]); 2034 $$ = v; 2035 } 2036 break; 2037 case ST_INT: 2038 $$ = new AST::IntLit(e.i); 2039 break; 2040 case ST_BOOL: 2041 $$ = new AST::BoolLit(e.i); 2042 break; 2043 case ST_FLOAT: 2044 $$ = new AST::FloatLit(pp->floatvals[e.i]); 2045 break; 2046 case ST_SET: 2047 $$ = new AST::SetLit(pp->setvals[e.i]); 2048 break; 2049 default: 2050 gotSymbol = false; 2051 } 2052 } 2053 if (!gotSymbol) 2054 $$ = getVarRefArg(pp,$1,true); 2055 free($1); 2056 } 2057 | var_par_id '[' ann_non_array_expr ']' /* array access */ 2058 { 2059 ParserState* pp = static_cast<ParserState*>(parm); 2060 int i = -1; 2061 yyassert(pp, $3->isInt(i), "Non-integer array index"); 2062 if (!pp->hadError) 2063 $$ = getArrayElement(static_cast<ParserState*>(parm),$1,i,true); 2064 else 2065 $$ = new AST::IntLit(0); // keep things consistent 2066 free($1); 2067 } 2068 | FZ_STRING_LIT 2069 { 2070 $$ = new AST::String($1); 2071 free($1); 2072 }