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 }