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