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