1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.
Jip J. Dekker 981be2067e Squashed 'software/gecode_on_replay/' content from commit 8051d92b9
git-subtree-dir: software/gecode_on_replay
git-subtree-split: 8051d92b9c89e49cccfbd1c201371580d7703ab4
2021-06-16 14:04:29 +10:00

2118 lines
69 KiB
Plaintext
Executable File

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Guido Tack <tack@gecode.org>
*
* Copyright:
* Guido Tack, 2007
*
* This file is part of Gecode, the generic constraint
* development environment:
* http://www.gecode.org
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
%pure-parser
%parse-param {void *parm}
%lex-param {void *YYLEX_PARAM}
%{
#define YYPARSE_PARAM parm
#define YYLEX_PARAM static_cast<ParserState*>(parm)->yyscanner
#include <gecode/flatzinc.hh>
#include <gecode/flatzinc/parser.hh>
#include <gecode/flatzinc/lastval.hh>
#include <iostream>
#include <fstream>
#ifdef HAVE_MMAP
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#endif
using namespace std;
int yyparse(void*);
int yylex(YYSTYPE*, void* scanner);
int yylex_init (void** scanner);
int yylex_destroy (void* scanner);
int yyget_lineno (void* scanner);
void yyset_extra (void* user_defined ,void* yyscanner );
extern int yydebug;
using namespace Gecode;
using namespace Gecode::FlatZinc;
void yyerror(void* parm, const char *str) {
ParserState* pp = static_cast<ParserState*>(parm);
pp->err << "Error: " << str
<< " in line no. " << yyget_lineno(pp->yyscanner)
<< std::endl;
pp->hadError = true;
}
void yyassert(ParserState* pp, bool cond, const char* str)
{
if (!cond) {
pp->err << "Error: " << str
<< " in line no. " << yyget_lineno(pp->yyscanner)
<< std::endl;
pp->hadError = true;
}
}
/*
* The symbol tables
*
*/
AST::Node* getArrayElement(ParserState* pp, string id, int offset,
bool annotation) {
if (offset > 0) {
SymbolEntry e;
if (pp->symbols.get(id,e)) {
switch (e.t) {
case ST_INTVARARRAY:
if (offset > pp->arrays[e.i])
goto error;
{
std::string n;
if (annotation) {
std::ostringstream oss;
oss << id << "[" << offset << "]";
n = oss.str();
}
return new AST::IntVar(pp->arrays[e.i+offset],n);
}
case ST_BOOLVARARRAY:
if (offset > pp->arrays[e.i])
goto error;
{
std::string n;
if (annotation) {
std::ostringstream oss;
oss << id << "[" << offset << "]";
n = oss.str();
}
return new AST::BoolVar(pp->arrays[e.i+offset],n);
}
case ST_SETVARARRAY:
if (offset > pp->arrays[e.i])
goto error;
{
std::string n;
if (annotation) {
std::ostringstream oss;
oss << id << "[" << offset << "]";
n = oss.str();
}
return new AST::SetVar(pp->arrays[e.i+offset],n);
}
case ST_FLOATVARARRAY:
if (offset > pp->arrays[e.i])
goto error;
{
std::string n;
if (annotation) {
std::ostringstream oss;
oss << id << "[" << offset << "]";
n = oss.str();
}
return new AST::FloatVar(pp->arrays[e.i+offset],n);
}
case ST_INTVALARRAY:
if (offset > pp->arrays[e.i])
goto error;
return new AST::IntLit(pp->arrays[e.i+offset]);
case ST_SETVALARRAY:
if (offset > pp->arrays[e.i])
goto error;
return new AST::SetLit(pp->setvals[pp->arrays[e.i+1]+offset-1]);
case ST_FLOATVALARRAY:
if (offset > pp->arrays[e.i])
goto error;
return new AST::FloatLit(pp->floatvals[pp->arrays[e.i+1]+offset-1]);
default:
break;
}
}
}
error:
pp->err << "Error: array access to " << id << " invalid"
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
return new AST::IntVar(0); // keep things consistent
}
AST::Node* getVarRefArg(ParserState* pp, string id, bool annotation = false) {
SymbolEntry e;
string n;
if (annotation)
n = id;
if (pp->symbols.get(id, e)) {
switch (e.t) {
case ST_INTVAR: return new AST::IntVar(e.i,n);
case ST_BOOLVAR: return new AST::BoolVar(e.i,n);
case ST_SETVAR: return new AST::SetVar(e.i,n);
case ST_FLOATVAR: return new AST::FloatVar(e.i,n);
default: break;
}
}
if (annotation)
return new AST::Atom(id);
pp->err << "Error: undefined variable " << id
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
return new AST::IntVar(0); // keep things consistent
}
void addDomainConstraint(ParserState* pp, std::string id, AST::Node* var,
Option<AST::SetLit* >& dom) {
if (!dom())
return;
AST::Array* args = new AST::Array(2);
args->a[0] = var;
args->a[1] = dom.some();
pp->domainConstraints.push_back(new ConExpr(id, args, NULL));
}
void addDomainConstraint(ParserState* pp, AST::Node* var,
Option<std::pair<double,double>* > dom) {
if (!dom())
return;
{
AST::Array* args = new AST::Array(2);
args->a[0] = new AST::FloatLit(dom.some()->first);
args->a[1] = var;
pp->domainConstraints.push_back(new ConExpr("float_le", args, NULL));
}
{
AST::Array* args = new AST::Array(2);
AST::FloatVar* fv = static_cast<AST::FloatVar*>(var);
args->a[0] = new AST::FloatVar(fv->i,fv->n);
args->a[1] = new AST::FloatLit(dom.some()->second);
pp->domainConstraints.push_back(new ConExpr("float_le", args, NULL));
}
delete dom.some();
}
int getBaseIntVar(ParserState* pp, int i) {
int base = i;
IntVarSpec* ivs = static_cast<IntVarSpec*>(pp->intvars[base].second);
while (ivs->alias) {
base = ivs->i;
ivs = static_cast<IntVarSpec*>(pp->intvars[base].second);
}
return base;
}
int getBaseBoolVar(ParserState* pp, int i) {
int base = i;
BoolVarSpec* ivs = static_cast<BoolVarSpec*>(pp->boolvars[base].second);
while (ivs->alias) {
base = ivs->i;
ivs = static_cast<BoolVarSpec*>(pp->boolvars[base].second);
}
return base;
}
int getBaseFloatVar(ParserState* pp, int i) {
int base = i;
FloatVarSpec* ivs = static_cast<FloatVarSpec*>(pp->floatvars[base].second);
while (ivs->alias) {
base = ivs->i;
ivs = static_cast<FloatVarSpec*>(pp->floatvars[base].second);
}
return base;
}
int getBaseSetVar(ParserState* pp, int i) {
int base = i;
SetVarSpec* ivs = static_cast<SetVarSpec*>(pp->setvars[base].second);
while (ivs->alias) {
base = ivs->i;
ivs = static_cast<SetVarSpec*>(pp->setvars[base].second);
}
return base;
}
/*
* Initialize the root gecode space
*
*/
void initfg(ParserState* pp) {
if (!pp->hadError)
pp->fg->init(pp->intvars.size(),
pp->boolvars.size(),
pp->setvars.size(),
pp->floatvars.size());
for (unsigned int i=0; i<pp->intvars.size(); i++) {
if (!pp->hadError) {
try {
pp->fg->newIntVar(static_cast<IntVarSpec*>(pp->intvars[i].second));
} catch (Gecode::FlatZinc::Error& e) {
yyerror(pp, e.toString().c_str());
}
}
delete pp->intvars[i].second;
pp->intvars[i].second = NULL;
}
for (unsigned int i=0; i<pp->boolvars.size(); i++) {
if (!pp->hadError) {
try {
pp->fg->newBoolVar(
static_cast<BoolVarSpec*>(pp->boolvars[i].second));
} catch (Gecode::FlatZinc::Error& e) {
yyerror(pp, e.toString().c_str());
}
}
delete pp->boolvars[i].second;
pp->boolvars[i].second = NULL;
}
for (unsigned int i=0; i<pp->setvars.size(); i++) {
if (!pp->hadError) {
try {
pp->fg->newSetVar(static_cast<SetVarSpec*>(pp->setvars[i].second));
} catch (Gecode::FlatZinc::Error& e) {
yyerror(pp, e.toString().c_str());
}
}
delete pp->setvars[i].second;
pp->setvars[i].second = NULL;
}
for (unsigned int i=0; i<pp->floatvars.size(); i++) {
if (!pp->hadError) {
try {
pp->fg->newFloatVar(
static_cast<FloatVarSpec*>(pp->floatvars[i].second));
} catch (Gecode::FlatZinc::Error& e) {
yyerror(pp, e.toString().c_str());
}
}
delete pp->floatvars[i].second;
pp->floatvars[i].second = NULL;
}
if (pp->status_idx >= 0) {
pp->fg->restart_status = IntVarArray(*(pp->fg), 1);
pp->fg->restart_status[0] = pp->fg->iv[pp->status_idx];
}
if (!(pp->int_uniform.empty())) {
pp->fg->int_uniform_var = IntVarArray(*(pp->fg), pp->int_uniform.size());
pp->fg->int_uniform_lb = new int[pp->int_uniform.size()];
pp->fg->int_uniform_ub = new int[pp->int_uniform.size()];
for (int i = 0; i < pp->int_uniform.size(); ++i) {
pp->fg->int_uniform_lb[i] = pp->int_uniform[i][0];
pp->fg->int_uniform_ub[i] = pp->int_uniform[i][1];
pp->fg->int_uniform_var[i] = pp->fg->iv[pp->int_uniform[i][2]];
}
}
if (!(pp->int_sol.empty())) {
pp->fg->int_sol_orig = IntVarArray(*(pp->fg), pp->int_sol.size());
pp->fg->int_sol_var = IntVarArray(*(pp->fg), pp->int_sol.size());
for (int i = 0; i < pp->int_sol.size(); ++i) {
pp->fg->int_sol_orig[i] = pp->fg->iv[(pp->int_sol[i][0])];
pp->fg->int_sol_var[i] = pp->fg->iv[(pp->int_sol[i][1])];
}
}
if (!(pp->int_lastval.empty())) {
pp->fg->int_lastval_var = IntVarArray(*(pp->fg), pp->int_lastval.size());
pp->fg->int_lastval_val = new std::shared_ptr<int>[pp->int_lastval.size()];
for (int i = 0; i < pp->int_lastval.size(); ++i) {
pp->fg->int_lastval_var[i] = pp->fg->iv[(pp->int_lastval[i][1])];
pp->fg->int_lastval_val[i] = std::make_shared<int>();
LastVal::post(*(pp->fg), pp->fg->iv[(pp->int_lastval[i][0])], pp->fg->int_lastval_val[i]);
}
}
if (!pp->hadError) {
pp->fg->postConstraints(pp->domainConstraints);
pp->fg->postConstraints(pp->constraints);
}
}
void fillPrinter(ParserState& pp, Gecode::FlatZinc::Printer& p) {
p.init(pp.getOutput());
for (unsigned int i=0; i<pp.intvars.size(); i++) {
if (!pp.hadError) {
p.addIntVarName(pp.intvars[i].first);
}
}
for (unsigned int i=0; i<pp.boolvars.size(); i++) {
if (!pp.hadError) {
p.addBoolVarName(pp.boolvars[i].first);
}
}
#ifdef GECODE_HAS_FLOAT_VARS
for (unsigned int i=0; i<pp.floatvars.size(); i++) {
if (!pp.hadError) {
p.addFloatVarName(pp.floatvars[i].first);
}
}
#endif
#ifdef GECODE_HAS_SET_VARS
for (unsigned int i=0; i<pp.setvars.size(); i++) {
if (!pp.hadError) {
p.addSetVarName(pp.setvars[i].first);
}
}
#endif
}
AST::Node* arrayOutput(AST::Call* ann) {
AST::Array* a = NULL;
if (ann->args->isArray()) {
a = ann->args->getArray();
} else {
a = new AST::Array(ann->args);
}
std::ostringstream oss;
oss << "array" << a->a.size() << "d(";
for (unsigned int i=0; i<a->a.size(); i++) {
AST::SetLit* s = a->a[i]->getSet();
if (s->empty())
oss << "{}, ";
else if (s->interval)
oss << s->min << ".." << s->max << ", ";
else {
oss << "{";
for (unsigned int j=0; j<s->s.size(); j++) {
oss << s->s[j];
if (j<s->s.size()-1)
oss << ",";
}
oss << "}, ";
}
}
if (!ann->args->isArray()) {
a->a[0] = NULL;
delete a;
}
return new AST::String(oss.str());
}
/*
* The main program
*
*/
namespace Gecode { namespace FlatZinc {
FlatZincSpace* parse(const std::string& filename, Printer& p, std::ostream& err,
FlatZincSpace* fzs, Rnd& rnd) {
#ifdef HAVE_MMAP
int fd;
char* data;
struct stat sbuf;
fd = open(filename.c_str(), O_RDONLY);
if (fd == -1) {
err << "Cannot open file " << filename << endl;
return NULL;
}
if (stat(filename.c_str(), &sbuf) == -1) {
err << "Cannot stat file " << filename << endl;
return NULL;
}
data = (char*)mmap((caddr_t)0, sbuf.st_size, PROT_READ, MAP_SHARED, fd,0);
if (data == (caddr_t)(-1)) {
err << "Cannot mmap file " << filename << endl;
return NULL;
}
if (fzs == NULL) {
fzs = new FlatZincSpace(rnd);
}
ParserState pp(data, sbuf.st_size, err, fzs);
#else
std::ifstream file;
file.open(filename.c_str());
if (!file.is_open()) {
err << "Cannot open file " << filename << endl;
return NULL;
}
std::string s = string(istreambuf_iterator<char>(file),
istreambuf_iterator<char>());
if (fzs == NULL) {
fzs = new FlatZincSpace(rnd);
}
ParserState pp(s, err, fzs);
#endif
yylex_init(&pp.yyscanner);
yyset_extra(&pp, pp.yyscanner);
// yydebug = 1;
yyparse(&pp);
fillPrinter(pp, p);
if (pp.yyscanner)
yylex_destroy(pp.yyscanner);
return pp.hadError ? NULL : pp.fg;
}
FlatZincSpace* parse(std::istream& is, Printer& p, std::ostream& err,
FlatZincSpace* fzs, Rnd& rnd) {
std::string s = string(istreambuf_iterator<char>(is),
istreambuf_iterator<char>());
if (fzs == NULL) {
fzs = new FlatZincSpace(rnd);
}
ParserState pp(s, err, fzs);
yylex_init(&pp.yyscanner);
yyset_extra(&pp, pp.yyscanner);
// yydebug = 1;
yyparse(&pp);
fillPrinter(pp, p);
if (pp.yyscanner)
yylex_destroy(pp.yyscanner);
return pp.hadError ? NULL : pp.fg;
}
}}
%}
%union { int iValue; char* sValue; bool bValue; double dValue;
std::vector<int>* setValue;
Gecode::FlatZinc::AST::SetLit* setLit;
std::vector<double>* floatSetValue;
std::vector<Gecode::FlatZinc::AST::SetLit>* setValueList;
Gecode::FlatZinc::Option<Gecode::FlatZinc::AST::SetLit* > oSet;
Gecode::FlatZinc::Option<std::pair<double,double>* > oPFloat;
Gecode::FlatZinc::VarSpec* varSpec;
Gecode::FlatZinc::Option<Gecode::FlatZinc::AST::Node*> oArg;
std::vector<Gecode::FlatZinc::VarSpec*>* varSpecVec;
Gecode::FlatZinc::Option<std::vector<Gecode::FlatZinc::VarSpec*>* > oVarSpecVec;
Gecode::FlatZinc::AST::Node* arg;
Gecode::FlatZinc::AST::Array* argVec;
}
%error-verbose
%token <iValue> FZ_INT_LIT FZ_BOOL_LIT
%token <dValue> FZ_FLOAT_LIT
%token <sValue> FZ_ID FZ_U_ID FZ_STRING_LIT
%token <bValue> FZ_VAR FZ_PAR
%token FZ_ANNOTATION
%token FZ_ANY
%token FZ_ARRAY
%token FZ_BOOL
%token FZ_CASE
%token FZ_COLONCOLON
%token FZ_CONSTRAINT
%token FZ_DEFAULT
%token FZ_DOTDOT
%token FZ_ELSE
%token FZ_ELSEIF
%token FZ_ENDIF
%token FZ_ENUM
%token FZ_FLOAT
%token FZ_FUNCTION
%token FZ_IF
%token FZ_INCLUDE
%token FZ_INT
%token FZ_LET
%token <bValue> FZ_MAXIMIZE
%token <bValue> FZ_MINIMIZE
%token FZ_OF
%token FZ_SATISFY
%token FZ_OUTPUT
%token FZ_PREDICATE
%token FZ_RECORD
%token FZ_SET
%token FZ_SHOW
%token FZ_SHOWCOND
%token FZ_SOLVE
%token FZ_STRING
%token FZ_TEST
%token FZ_THEN
%token FZ_TUPLE
%token FZ_TYPE
%token FZ_VARIANT_RECORD
%token FZ_WHERE
%type <sValue> var_par_id
%type <setLit> set_literal
%type <varSpec> int_init bool_init set_init float_init
%type <oSet> int_ti_expr_tail bool_ti_expr_tail
%type <oPFloat> float_ti_expr_tail
%type <oVarSpecVec> vardecl_int_var_array_init
%type <oVarSpecVec> vardecl_bool_var_array_init
%type <oVarSpecVec> vardecl_float_var_array_init
%type <oVarSpecVec> vardecl_set_var_array_init
%type <varSpecVec> int_var_array_literal
%type <varSpecVec> bool_var_array_literal
%type <varSpecVec> float_var_array_literal
%type <varSpecVec> set_var_array_literal
%type <varSpecVec> int_init_list int_init_list_head
%type <varSpecVec> bool_init_list bool_init_list_head
%type <varSpecVec> float_init_list float_init_list_head
%type <varSpecVec> set_init_list set_init_list_head
%type <setValue> int_list int_list_head
%type <setValue> bool_list bool_list_head
%type <setValueList> set_literal_list set_literal_list_head
%type <floatSetValue> float_list float_list_head
%type <arg> flat_expr non_array_expr annotation_expr ann_non_array_expr
%type <oArg> non_array_expr_opt
%type <argVec> flat_expr_list non_array_expr_list non_array_expr_list_head
%type <iValue> solve_expr
%type <bValue> minmax
%type <argVec> annotations annotations_head
%type <arg> annotation annotation_list
%%
/********************************/
/* main goal and item lists */
/********************************/
model : preddecl_items vardecl_items constraint_items solve_item ';'
preddecl_items:
/* empty */
| preddecl_items_head
preddecl_items_head:
preddecl_item ';'
| preddecl_items_head preddecl_item ';'
vardecl_items:
/* emtpy */
| vardecl_items_head
vardecl_items_head:
vardecl_item ';'
| vardecl_items_head vardecl_item ';'
constraint_items:
/* emtpy */
| constraint_items_head
constraint_items_head:
constraint_item ';'
| constraint_items_head constraint_item ';'
/********************************/
/* predicate declarations */
/********************************/
preddecl_item:
FZ_PREDICATE FZ_ID '(' pred_arg_list ')'
{ free($2); }
pred_arg_list:
/* empty */
| pred_arg_list_head list_tail
pred_arg_list_head:
pred_arg
| pred_arg_list_head ',' pred_arg
pred_arg:
pred_arg_type ':' FZ_ID
{ free($3); }
pred_arg_type:
FZ_ARRAY '[' pred_array_init ']' FZ_OF pred_arg_simple_type
| FZ_ARRAY '[' pred_array_init ']' FZ_OF FZ_VAR pred_arg_simple_type
| FZ_VAR pred_arg_simple_type
| pred_arg_simple_type
pred_arg_simple_type:
int_ti_expr_tail
{ if ($1()) delete $1.some(); }
| FZ_SET FZ_OF int_ti_expr_tail
{ if ($3()) delete $3.some(); }
| FZ_BOOL
| FZ_FLOAT
pred_array_init:
pred_array_init_arg
| pred_array_init ',' pred_array_init_arg
pred_array_init_arg:
FZ_INT
| FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT
/********************************/
/* variable declarations */
/********************************/
var_par_id : FZ_ID | FZ_U_ID
vardecl_item:
FZ_VAR int_ti_expr_tail ':' var_par_id annotations non_array_expr_opt
{
ParserState* pp = static_cast<ParserState*>(parm);
bool print = $5 != NULL && $5->hasAtom("output_var");
bool funcDep = $5 != NULL && $5->hasAtom("is_defined_var");
yyassert(pp,
pp->symbols.put($4, se_iv(pp->intvars.size())),
"Duplicate symbol");
if (print) {
pp->output(std::string($4), new AST::IntVar(pp->intvars.size()));
}
if ($6()) {
AST::Node* arg = $6.some();
if (arg->isInt()) {
pp->intvars.push_back(varspec($4,
new IntVarSpec(arg->getInt(),!print,funcDep)));
} else if (arg->isIntVar()) {
pp->intvars.push_back(varspec($4,
new IntVarSpec(Alias(arg->getIntVar()),!print,funcDep)));
} else {
yyassert(pp, false, "Invalid var int initializer");
}
if (!pp->hadError)
addDomainConstraint(pp, "int_in",
new AST::IntVar(pp->intvars.size()-1), $2);
delete arg;
} else {
pp->intvars.push_back(varspec($4,
new IntVarSpec($2,!print,funcDep)));
}
delete $5; free($4);
}
| FZ_VAR bool_ti_expr_tail ':' var_par_id annotations non_array_expr_opt
{
ParserState* pp = static_cast<ParserState*>(parm);
bool print = $5 != NULL && $5->hasAtom("output_var");
bool funcDep = $5 != NULL && $5->hasAtom("is_defined_var");
yyassert(pp,
pp->symbols.put($4, se_bv(pp->boolvars.size())),
"Duplicate symbol");
if (print) {
pp->output(std::string($4), new AST::BoolVar(pp->boolvars.size()));
}
if ($6()) {
AST::Node* arg = $6.some();
if (arg->isBool()) {
pp->boolvars.push_back(varspec($4,
new BoolVarSpec(arg->getBool(),!print,funcDep)));
} else if (arg->isBoolVar()) {
pp->boolvars.push_back(varspec($4,
new BoolVarSpec(Alias(arg->getBoolVar()),!print,funcDep)));
} else {
yyassert(pp, false, "Invalid var bool initializer");
}
if (!pp->hadError)
addDomainConstraint(pp, "int_in",
new AST::BoolVar(pp->boolvars.size()-1), $2);
delete arg;
} else {
pp->boolvars.push_back(varspec($4,
new BoolVarSpec($2,!print,funcDep)));
}
delete $5; free($4);
}
| FZ_VAR float_ti_expr_tail ':' var_par_id annotations non_array_expr_opt
{
ParserState* pp = static_cast<ParserState*>(parm);
bool print = $5 != NULL && $5->hasAtom("output_var");
bool funcDep = $5 != NULL && $5->hasAtom("is_defined_var");
yyassert(pp,
pp->symbols.put($4, se_fv(pp->floatvars.size())),
"Duplicate symbol");
if (print) {
pp->output(std::string($4),
new AST::FloatVar(pp->floatvars.size()));
}
if ($6()) {
AST::Node* arg = $6.some();
if (arg->isFloat()) {
pp->floatvars.push_back(varspec($4,
new FloatVarSpec(arg->getFloat(),!print,funcDep)));
} else if (arg->isFloatVar()) {
pp->floatvars.push_back(varspec($4,
new FloatVarSpec(
Alias(arg->getFloatVar()),!print,funcDep)));
} else {
yyassert(pp, false, "Invalid var float initializer");
}
if (!pp->hadError && $2()) {
AST::FloatVar* fv = new AST::FloatVar(pp->floatvars.size()-1);
addDomainConstraint(pp, fv, $2);
}
delete arg;
} else {
Option<std::pair<double,double> > dom =
$2() ? Option<std::pair<double,double> >::some(*$2.some())
: Option<std::pair<double,double> >::none();
if ($2()) delete $2.some();
pp->floatvars.push_back(varspec($4,
new FloatVarSpec(dom,!print,funcDep)));
}
delete $5; free($4);
}
| FZ_VAR FZ_SET FZ_OF int_ti_expr_tail ':' var_par_id annotations non_array_expr_opt
{
ParserState* pp = static_cast<ParserState*>(parm);
bool print = $7 != NULL && $7->hasAtom("output_var");
bool funcDep = $7 != NULL && $7->hasAtom("is_defined_var");
yyassert(pp,
pp->symbols.put($6, se_sv(pp->setvars.size())),
"Duplicate symbol");
if (print) {
pp->output(std::string($6), new AST::SetVar(pp->setvars.size()));
}
if ($8()) {
AST::Node* arg = $8.some();
if (arg->isSet()) {
pp->setvars.push_back(varspec($6,
new SetVarSpec(arg->getSet(),!print,funcDep)));
} else if (arg->isSetVar()) {
pp->setvars.push_back(varspec($6,
new SetVarSpec(Alias(arg->getSetVar()),!print,funcDep)));
delete arg;
} else {
yyassert(pp, false, "Invalid var set initializer");
delete arg;
}
if (!pp->hadError)
addDomainConstraint(pp, "set_subset",
new AST::SetVar(pp->setvars.size()-1), $4);
} else {
pp->setvars.push_back(varspec($6,
new SetVarSpec($4,!print,funcDep)));
}
delete $7; free($6);
}
| FZ_INT ':' var_par_id annotations '=' non_array_expr
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $6->isInt(), "Invalid int initializer");
yyassert(pp,
pp->symbols.put($3, se_i($6->getInt())),
"Duplicate symbol");
delete $4; free($3);
}
| FZ_FLOAT ':' var_par_id annotations '=' non_array_expr
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $6->isFloat(), "Invalid float initializer");
pp->floatvals.push_back($6->getFloat());
yyassert(pp,
pp->symbols.put($3, se_f(pp->floatvals.size()-1)),
"Duplicate symbol");
delete $4; free($3);
}
| FZ_BOOL ':' var_par_id annotations '=' non_array_expr
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $6->isBool(), "Invalid bool initializer");
yyassert(pp,
pp->symbols.put($3, se_b($6->getBool())),
"Duplicate symbol");
delete $4; free($3);
}
| FZ_SET FZ_OF FZ_INT ':' var_par_id annotations '=' non_array_expr
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $8->isSet(), "Invalid set initializer");
AST::SetLit* set = $8->getSet();
pp->setvals.push_back(*set);
yyassert(pp,
pp->symbols.put($5, se_s(pp->setvals.size()-1)),
"Duplicate symbol");
delete set;
delete $6; free($5);
}
| FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_VAR int_ti_expr_tail ':'
var_par_id annotations vardecl_int_var_array_init
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $3==1, "Arrays must start at 1");
if (!pp->hadError) {
bool print = $12 != NULL && $12->hasCall("output_array");
vector<int> vars($5);
if (!pp->hadError) {
if ($13()) {
vector<VarSpec*>* vsv = $13.some();
yyassert(pp, vsv->size() == static_cast<unsigned int>($5),
"Initializer size does not match array dimension");
if (!pp->hadError) {
for (int i=0; i<$5; i++) {
IntVarSpec* ivsv = static_cast<IntVarSpec*>((*vsv)[i]);
if (ivsv->alias) {
if (print)
static_cast<IntVarSpec*>(pp->intvars[ivsv->i].second)->introduced = false;
vars[i] = ivsv->i;
} else {
if (print)
ivsv->introduced = false;
vars[i] = pp->intvars.size();
pp->intvars.push_back(varspec($11, ivsv));
}
if (!pp->hadError && $9()) {
Option<AST::SetLit*> opt =
Option<AST::SetLit*>::some(new AST::SetLit(*$9.some()));
addDomainConstraint(pp, "int_in",
new AST::IntVar(vars[i]),
opt);
}
}
}
delete vsv;
} else {
if ($5>0) {
for (int i=0; i<$5; i++) {
Option<AST::SetLit*> dom =
$9() ? Option<AST::SetLit*>::some(new AST::SetLit($9.some()))
: Option<AST::SetLit*>::none();
IntVarSpec* ispec = new IntVarSpec(dom,!print,false);
vars[i] = pp->intvars.size();
pp->intvars.push_back(varspec($11, ispec));
}
}
if ($9()) delete $9.some();
}
}
if (print) {
AST::Array* a = new AST::Array();
a->a.push_back(arrayOutput($12->getCall("output_array")));
AST::Array* output = new AST::Array();
for (int i=0; i<$5; i++)
output->a.push_back(new AST::IntVar(vars[i]));
a->a.push_back(output);
a->a.push_back(new AST::String(")"));
pp->output(std::string($11), a);
}
int iva = pp->arrays.size();
pp->arrays.push_back(vars.size());
for (unsigned int i=0; i<vars.size(); i++)
pp->arrays.push_back(vars[i]);
yyassert(pp,
pp->symbols.put($11, se_iva(iva)),
"Duplicate symbol");
}
delete $12; free($11);
}
| FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_VAR bool_ti_expr_tail ':'
var_par_id annotations vardecl_bool_var_array_init
{
ParserState* pp = static_cast<ParserState*>(parm);
bool print = $12 != NULL && $12->hasCall("output_array");
yyassert(pp, $3==1, "Arrays must start at 1");
if (!pp->hadError) {
vector<int> vars($5);
if ($13()) {
vector<VarSpec*>* vsv = $13.some();
yyassert(pp, vsv->size() == static_cast<unsigned int>($5),
"Initializer size does not match array dimension");
if (!pp->hadError) {
for (int i=0; i<$5; i++) {
BoolVarSpec* bvsv = static_cast<BoolVarSpec*>((*vsv)[i]);
if (bvsv->alias) {
if (print)
static_cast<BoolVarSpec*>(pp->boolvars[bvsv->i].second)->introduced = false;
vars[i] = bvsv->i;
} else {
if (print)
bvsv->introduced = false;
vars[i] = pp->boolvars.size();
pp->boolvars.push_back(varspec($11, (*vsv)[i]));
}
if (!pp->hadError && $9()) {
Option<AST::SetLit*> opt =
Option<AST::SetLit*>::some(new AST::SetLit(*$9.some()));
addDomainConstraint(pp, "int_in",
new AST::BoolVar(vars[i]),
opt);
}
}
}
delete vsv;
} else {
for (int i=0; i<$5; i++) {
Option<AST::SetLit*> dom =
$9() ? Option<AST::SetLit*>::some(new AST::SetLit($9.some()))
: Option<AST::SetLit*>::none();
vars[i] = pp->boolvars.size();
pp->boolvars.push_back(varspec($11,
new BoolVarSpec(dom,!print,false)));
}
if ($9()) delete $9.some();
}
if (print) {
AST::Array* a = new AST::Array();
a->a.push_back(arrayOutput($12->getCall("output_array")));
AST::Array* output = new AST::Array();
for (int i=0; i<$5; i++)
output->a.push_back(new AST::BoolVar(vars[i]));
a->a.push_back(output);
a->a.push_back(new AST::String(")"));
pp->output(std::string($11), a);
}
int bva = pp->arrays.size();
pp->arrays.push_back(vars.size());
for (unsigned int i=0; i<vars.size(); i++)
pp->arrays.push_back(vars[i]);
yyassert(pp,
pp->symbols.put($11, se_bva(bva)),
"Duplicate symbol");
}
delete $12; free($11);
}
| FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_VAR
float_ti_expr_tail ':' var_par_id annotations
vardecl_float_var_array_init
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $3==1, "Arrays must start at 1");
if (!pp->hadError) {
bool print = $12 != NULL && $12->hasCall("output_array");
vector<int> vars($5);
if (!pp->hadError) {
if ($13()) {
vector<VarSpec*>* vsv = $13.some();
yyassert(pp, vsv->size() == static_cast<unsigned int>($5),
"Initializer size does not match array dimension");
if (!pp->hadError) {
for (int i=0; i<$5; i++) {
FloatVarSpec* ivsv = static_cast<FloatVarSpec*>((*vsv)[i]);
if (ivsv->alias) {
if (print)
static_cast<FloatVarSpec*>(pp->floatvars[ivsv->i].second)->introduced = false;
vars[i] = ivsv->i;
} else {
if (print)
ivsv->introduced = false;
vars[i] = pp->floatvars.size();
pp->floatvars.push_back(varspec($11, ivsv));
}
if (!pp->hadError && $9()) {
Option<std::pair<double,double>*> opt =
Option<std::pair<double,double>*>::some(
new std::pair<double,double>(*$9.some()));
addDomainConstraint(pp, new AST::FloatVar(vars[i]),
opt);
}
}
}
delete vsv;
} else {
if ($5>0) {
Option<std::pair<double,double> > dom =
$9() ? Option<std::pair<double,double> >::some(*$9.some())
: Option<std::pair<double,double> >::none();
for (int i=0; i<$5; i++) {
FloatVarSpec* ispec = new FloatVarSpec(dom,!print,false);
vars[i] = pp->floatvars.size();
pp->floatvars.push_back(varspec($11, ispec));
}
}
}
}
if (print) {
AST::Array* a = new AST::Array();
a->a.push_back(arrayOutput($12->getCall("output_array")));
AST::Array* output = new AST::Array();
for (int i=0; i<$5; i++)
output->a.push_back(new AST::FloatVar(vars[i]));
a->a.push_back(output);
a->a.push_back(new AST::String(")"));
pp->output(std::string($11), a);
}
int fva = pp->arrays.size();
pp->arrays.push_back(vars.size());
for (unsigned int i=0; i<vars.size(); i++)
pp->arrays.push_back(vars[i]);
yyassert(pp,
pp->symbols.put($11, se_fva(fva)),
"Duplicate symbol");
}
if ($9()) delete $9.some();
delete $12; free($11);
}
| FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_VAR FZ_SET FZ_OF int_ti_expr_tail ':'
var_par_id annotations vardecl_set_var_array_init
{
ParserState* pp = static_cast<ParserState*>(parm);
bool print = $14 != NULL && $14->hasCall("output_array");
yyassert(pp, $3==1, "Arrays must start at 1");
if (!pp->hadError) {
vector<int> vars($5);
if ($15()) {
vector<VarSpec*>* vsv = $15.some();
yyassert(pp, vsv->size() == static_cast<unsigned int>($5),
"Initializer size does not match array dimension");
if (!pp->hadError) {
for (int i=0; i<$5; i++) {
SetVarSpec* svsv = static_cast<SetVarSpec*>((*vsv)[i]);
if (svsv->alias) {
if (print)
static_cast<SetVarSpec*>(pp->setvars[svsv->i].second)->introduced = false;
vars[i] = svsv->i;
} else {
if (print)
svsv->introduced = false;
vars[i] = pp->setvars.size();
pp->setvars.push_back(varspec($13, (*vsv)[i]));
}
if (!pp->hadError && $11()) {
Option<AST::SetLit*> opt =
Option<AST::SetLit*>::some(new AST::SetLit(*$11.some()));
addDomainConstraint(pp, "set_subset",
new AST::SetVar(vars[i]),
opt);
}
}
}
delete vsv;
} else {
if ($5>0) {
for (int i=0; i<$5; i++) {
Option<AST::SetLit*> dom =
$11() ? Option<AST::SetLit*>::some(new AST::SetLit($11.some()))
: Option<AST::SetLit*>::none();
SetVarSpec* ispec = new SetVarSpec(dom,!print,false);
vars[i] = pp->setvars.size();
pp->setvars.push_back(varspec($13, ispec));
}
if ($11()) delete $11.some();
}
}
if (print) {
AST::Array* a = new AST::Array();
a->a.push_back(arrayOutput($14->getCall("output_array")));
AST::Array* output = new AST::Array();
for (int i=0; i<$5; i++)
output->a.push_back(new AST::SetVar(vars[i]));
a->a.push_back(output);
a->a.push_back(new AST::String(")"));
pp->output(std::string($13), a);
}
int sva = pp->arrays.size();
pp->arrays.push_back(vars.size());
for (unsigned int i=0; i<vars.size(); i++)
pp->arrays.push_back(vars[i]);
yyassert(pp,
pp->symbols.put($13, se_sva(sva)),
"Duplicate symbol");
}
delete $14; free($13);
}
| FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_INT ':'
var_par_id annotations '=' '[' int_list ']'
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $3==1, "Arrays must start at 1");
yyassert(pp, $14->size() == static_cast<unsigned int>($5),
"Initializer size does not match array dimension");
if (!pp->hadError) {
int ia = pp->arrays.size();
pp->arrays.push_back($14->size());
for (unsigned int i=0; i<$14->size(); i++)
pp->arrays.push_back((*$14)[i]);
yyassert(pp,
pp->symbols.put($10, se_ia(ia)),
"Duplicate symbol");
}
delete $14;
free($10);
delete $11;
}
| FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_BOOL ':'
var_par_id annotations '=' '[' bool_list ']'
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $3==1, "Arrays must start at 1");
yyassert(pp, $14->size() == static_cast<unsigned int>($5),
"Initializer size does not match array dimension");
if (!pp->hadError) {
int ia = pp->arrays.size();
pp->arrays.push_back($14->size());
for (unsigned int i=0; i<$14->size(); i++)
pp->arrays.push_back((*$14)[i]);
yyassert(pp,
pp->symbols.put($10, se_ba(ia)),
"Duplicate symbol");
}
delete $14;
free($10);
delete $11;
}
| FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_FLOAT ':'
var_par_id annotations '=' '[' float_list ']'
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $3==1, "Arrays must start at 1");
yyassert(pp, $14->size() == static_cast<unsigned int>($5),
"Initializer size does not match array dimension");
if (!pp->hadError) {
int fa = pp->arrays.size();
pp->arrays.push_back($14->size());
pp->arrays.push_back(pp->floatvals.size());
for (unsigned int i=0; i<$14->size(); i++)
pp->floatvals.push_back((*$14)[i]);
yyassert(pp,
pp->symbols.put($10, se_fa(fa)),
"Duplicate symbol");
}
delete $14;
delete $11; free($10);
}
| FZ_ARRAY '[' FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT ']' FZ_OF FZ_SET FZ_OF FZ_INT ':'
var_par_id annotations '=' '[' set_literal_list ']'
{
ParserState* pp = static_cast<ParserState*>(parm);
yyassert(pp, $3==1, "Arrays must start at 1");
yyassert(pp, $16->size() == static_cast<unsigned int>($5),
"Initializer size does not match array dimension");
if (!pp->hadError) {
int sa = pp->arrays.size();
pp->arrays.push_back($16->size());
pp->arrays.push_back(pp->setvals.size());
for (unsigned int i=0; i<$16->size(); i++)
pp->setvals.push_back((*$16)[i]);
yyassert(pp,
pp->symbols.put($12, se_sa(sa)),
"Duplicate symbol");
}
delete $16;
delete $13; free($12);
}
int_init :
FZ_INT_LIT
{
$$ = new IntVarSpec($1,false,false);
}
| var_par_id
{
SymbolEntry e;
ParserState* pp = static_cast<ParserState*>(parm);
if (pp->symbols.get($1, e) && e.t == ST_INTVAR)
$$ = new IntVarSpec(Alias(e.i),false,false);
else {
pp->err << "Error: undefined identifier for type int " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
$$ = new IntVarSpec(0,false,false); // keep things consistent
}
free($1);
}
| var_par_id '[' FZ_INT_LIT ']'
{
vector<int> v;
SymbolEntry e;
ParserState* pp = static_cast<ParserState*>(parm);
if (pp->symbols.get($1, e) && e.t == ST_INTVARARRAY) {
yyassert(pp,$3 > 0 && $3 <= pp->arrays[e.i],
"array access out of bounds");
if (!pp->hadError)
$$ = new IntVarSpec(Alias(pp->arrays[e.i+$3]),false,false);
else
$$ = new IntVarSpec(0,false,false); // keep things consistent
} else {
pp->err << "Error: undefined array identifier for type int " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
$$ = new IntVarSpec(0,false,false); // keep things consistent
}
free($1);
}
int_init_list :
/* empty */
{ $$ = new vector<VarSpec*>(0); }
| int_init_list_head list_tail
{ $$ = $1; }
int_init_list_head :
int_init
{ $$ = new vector<VarSpec*>(1); (*$$)[0] = $1; }
| int_init_list_head ',' int_init
{ $$ = $1; $$->push_back($3); }
list_tail : | ','
int_var_array_literal : '[' int_init_list ']'
{ $$ = $2; }
float_init :
FZ_FLOAT_LIT
{ $$ = new FloatVarSpec($1,false,false); }
| var_par_id
{
SymbolEntry e;
ParserState* pp = static_cast<ParserState*>(parm);
if (pp->symbols.get($1, e) && e.t == ST_FLOATVAR)
$$ = new FloatVarSpec(Alias(e.i),false,false);
else {
pp->err << "Error: undefined identifier for type float " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
$$ = new FloatVarSpec(0.0,false,false);
}
free($1);
}
| var_par_id '[' FZ_INT_LIT ']'
{
SymbolEntry e;
ParserState* pp = static_cast<ParserState*>(parm);
if (pp->symbols.get($1, e) && e.t == ST_FLOATVARARRAY) {
yyassert(pp,$3 > 0 && $3 <= pp->arrays[e.i],
"array access out of bounds");
if (!pp->hadError)
$$ = new FloatVarSpec(Alias(pp->arrays[e.i+$3]),false,false);
else
$$ = new FloatVarSpec(0.0,false,false);
} else {
pp->err << "Error: undefined array identifier for type float " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
$$ = new FloatVarSpec(0.0,false,false);
}
free($1);
}
float_init_list :
/* empty */
{ $$ = new vector<VarSpec*>(0); }
| float_init_list_head list_tail
{ $$ = $1; }
float_init_list_head :
float_init
{ $$ = new vector<VarSpec*>(1); (*$$)[0] = $1; }
| float_init_list_head ',' float_init
{ $$ = $1; $$->push_back($3); }
float_var_array_literal :
'[' float_init_list ']'
{ $$ = $2; }
bool_init :
FZ_BOOL_LIT
{ $$ = new BoolVarSpec($1,false,false); }
| var_par_id
{
SymbolEntry e;
ParserState* pp = static_cast<ParserState*>(parm);
if (pp->symbols.get($1, e) && e.t == ST_BOOLVAR)
$$ = new BoolVarSpec(Alias(e.i),false,false);
else {
pp->err << "Error: undefined identifier for type bool " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
$$ = new BoolVarSpec(false,false,false);
}
free($1);
}
| var_par_id '[' FZ_INT_LIT ']'
{
SymbolEntry e;
ParserState* pp = static_cast<ParserState*>(parm);
if (pp->symbols.get($1, e) && e.t == ST_BOOLVARARRAY) {
yyassert(pp,$3 > 0 && $3 <= pp->arrays[e.i],
"array access out of bounds");
if (!pp->hadError)
$$ = new BoolVarSpec(Alias(pp->arrays[e.i+$3]),false,false);
else
$$ = new BoolVarSpec(false,false,false);
} else {
pp->err << "Error: undefined array identifier for type bool " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
$$ = new BoolVarSpec(false,false,false);
}
free($1);
}
bool_init_list :
/* empty */
{ $$ = new vector<VarSpec*>(0); }
| bool_init_list_head list_tail
{ $$ = $1; }
bool_init_list_head :
bool_init
{ $$ = new vector<VarSpec*>(1); (*$$)[0] = $1; }
| bool_init_list_head ',' bool_init
{ $$ = $1; $$->push_back($3); }
bool_var_array_literal : '[' bool_init_list ']' { $$ = $2; }
set_init :
set_literal
{ $$ = new SetVarSpec($1,false,false); }
| var_par_id
{
ParserState* pp = static_cast<ParserState*>(parm);
SymbolEntry e;
if (pp->symbols.get($1, e) && e.t == ST_SETVAR)
$$ = new SetVarSpec(Alias(e.i),false,false);
else {
pp->err << "Error: undefined identifier for type set " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
$$ = new SetVarSpec(Alias(0),false,false);
}
free($1);
}
| var_par_id '[' FZ_INT_LIT ']'
{
SymbolEntry e;
ParserState* pp = static_cast<ParserState*>(parm);
if (pp->symbols.get($1, e) && e.t == ST_SETVARARRAY) {
yyassert(pp,$3 > 0 && $3 <= pp->arrays[e.i],
"array access out of bounds");
if (!pp->hadError)
$$ = new SetVarSpec(Alias(pp->arrays[e.i+$3]),false,false);
else
$$ = new SetVarSpec(Alias(0),false,false);
} else {
pp->err << "Error: undefined array identifier for type set " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
$$ = new SetVarSpec(Alias(0),false,false);
}
free($1);
}
set_init_list :
/* empty */
{ $$ = new vector<VarSpec*>(0); }
| set_init_list_head list_tail
{ $$ = $1; }
set_init_list_head :
set_init
{ $$ = new vector<VarSpec*>(1); (*$$)[0] = $1; }
| set_init_list_head ',' set_init
{ $$ = $1; $$->push_back($3); }
set_var_array_literal : '[' set_init_list ']'
{ $$ = $2; }
vardecl_int_var_array_init :
/* empty */
{ $$ = Option<vector<VarSpec*>* >::none(); }
| '=' int_var_array_literal
{ $$ = Option<vector<VarSpec*>* >::some($2); }
vardecl_bool_var_array_init :
/* empty */
{ $$ = Option<vector<VarSpec*>* >::none(); }
| '=' bool_var_array_literal
{ $$ = Option<vector<VarSpec*>* >::some($2); }
vardecl_float_var_array_init :
/* empty */
{ $$ = Option<vector<VarSpec*>* >::none(); }
| '=' float_var_array_literal
{ $$ = Option<vector<VarSpec*>* >::some($2); }
vardecl_set_var_array_init :
/* empty */
{ $$ = Option<vector<VarSpec*>* >::none(); }
| '=' set_var_array_literal
{ $$ = Option<vector<VarSpec*>* >::some($2); }
constraint_item :
FZ_CONSTRAINT FZ_ID '(' flat_expr_list ')' annotations
{
ParserState *pp = static_cast<ParserState*>(parm);
if (!pp->hadError) {
std::string cid($2);
if (cid=="status" && $4->a[0]->isIntVar()) {
pp->status_idx = $4->a[0]->getIntVar();
} else if (cid=="int_lastval" && $4->a[0]->isIntVar() && $4->a[1]->isIntVar()) {
int base0 = getBaseIntVar(pp,$4->a[0]->getIntVar());
int base1 = getBaseIntVar(pp,$4->a[1]->getIntVar());
pp->int_lastval.emplace_back(std::array<int, 2>{ base0, base1 });
} else if (cid=="int_uniform" && $4->a[0]->isInt() && $4->a[1]->isInt() && $4->a[2]->isIntVar()) {
int base = getBaseIntVar(pp,$4->a[2]->getIntVar());
pp->int_uniform.emplace_back(std::array<int, 3>{ $4->a[0]->getInt(), $4->a[1]->getInt(), base });
} else if (cid=="int_sol" && $4->a[0]->isIntVar() && $4->a[1]->isIntVar()) {
int base0 = getBaseIntVar(pp,$4->a[0]->getIntVar());
int base1 = getBaseIntVar(pp,$4->a[1]->getIntVar());
pp->int_sol.emplace_back(std::array<int, 2>{ base0, base1 });
} else if (cid=="int_eq" && $4->a[0]->isIntVar() && $4->a[1]->isIntVar()) {
int base0 = getBaseIntVar(pp,$4->a[0]->getIntVar());
int base1 = getBaseIntVar(pp,$4->a[1]->getIntVar());
if (base0 > base1) {
std::swap(base0, base1);
}
if (base0==base1) {
// do nothing, already aliased
} else {
IntVarSpec* ivs1 = static_cast<IntVarSpec*>(pp->intvars[base1].second);
AST::SetLit* sl = NULL;
if (ivs1->assigned) {
sl = new AST::SetLit(ivs1->i,ivs1->i);
} else if (ivs1->domain()) {
sl = new AST::SetLit(ivs1->domain.some()->getSet());
}
if (sl) {
Option<AST::SetLit*> newdom = Option<AST::SetLit*>::some(sl);
addDomainConstraint(pp, "int_in",
new AST::IntVar(base0), newdom);
ivs1->domain = Option<AST::SetLit*>::none();
}
ivs1->alias = true;
ivs1->i = base0;
}
} else if (cid=="bool_eq" && $4->a[0]->isBoolVar() && $4->a[1]->isBoolVar()) {
int base0 = getBaseBoolVar(pp,$4->a[0]->getBoolVar());
int base1 = getBaseBoolVar(pp,$4->a[1]->getBoolVar());
if (base0 > base1) {
std::swap(base0, base1);
}
if (base0==base1) {
// do nothing, already aliased
} else {
BoolVarSpec* ivs1 = static_cast<BoolVarSpec*>(pp->boolvars[base1].second);
AST::SetLit* sl = NULL;
if (ivs1->assigned) {
sl = new AST::SetLit(ivs1->i,ivs1->i);
} else if (ivs1->domain()) {
sl = new AST::SetLit(ivs1->domain.some()->getSet());
}
if (sl) {
Option<AST::SetLit*> newdom = Option<AST::SetLit*>::some(sl);
addDomainConstraint(pp, "int_in",
new AST::BoolVar(base0), newdom);
ivs1->domain = Option<AST::SetLit*>::none();
}
ivs1->alias = true;
ivs1->i = base0;
}
} else if (cid=="float_eq" && $4->a[0]->isFloatVar() && $4->a[1]->isFloatVar()) {
int base0 = getBaseFloatVar(pp,$4->a[0]->getFloatVar());
int base1 = getBaseFloatVar(pp,$4->a[1]->getFloatVar());
if (base0 > base1) {
std::swap(base0, base1);
}
if (base0==base1) {
// do nothing, already aliased
} else {
FloatVarSpec* ivs1 = static_cast<FloatVarSpec*>(pp->floatvars[base1].second);
ivs1->alias = true;
ivs1->i = base0;
if (ivs1->domain()) {
std::pair<double,double>* dom = new std::pair<double,double>(ivs1->domain.some());
addDomainConstraint(pp, new AST::FloatVar(base0), Option<std::pair<double,double>* >::some(dom));
ivs1->domain = Option<std::pair<double,double> >::none();
}
}
} else if (cid=="set_eq" && $4->a[0]->isSetVar() && $4->a[1]->isSetVar()) {
int base0 = getBaseSetVar(pp,$4->a[0]->getSetVar());
int base1 = getBaseSetVar(pp,$4->a[1]->getSetVar());
if (base0 > base1) {
std::swap(base0, base1);
}
if (base0==base1) {
// do nothing, already aliased
} else {
SetVarSpec* ivs1 = static_cast<SetVarSpec*>(pp->setvars[base1].second);
ivs1->alias = true;
ivs1->i = base0;
if (ivs1->upperBound()) {
AST::SetLit* sl = new AST::SetLit(ivs1->upperBound.some()->getSet());
Option<AST::SetLit*> newdom = Option<AST::SetLit*>::some(sl);
if (ivs1->assigned) {
addDomainConstraint(pp, "set_eq",
new AST::SetVar(base0), newdom);
} else {
addDomainConstraint(pp, "set_subset",
new AST::SetVar(base0), newdom);
}
ivs1->upperBound = Option<AST::SetLit*>::none();
}
}
} else if ( (cid=="int_le" || cid=="int_lt" || cid=="int_ge" || cid=="int_gt" ||
cid=="int_eq" || cid=="int_ne") &&
($4->a[0]->isInt() || $4->a[1]->isInt()) ) {
pp->domainConstraints.push_back(new ConExpr($2, $4, $6));
} else if ( cid=="set_in" && ($4->a[0]->isSet() || $4->a[1]->isSet()) ) {
pp->domainConstraints.push_back(new ConExpr($2, $4, $6));
} else {
pp->constraints.push_back(new ConExpr($2, $4, $6));
}
}
free($2);
}
solve_item :
FZ_SOLVE annotations FZ_SATISFY
{
ParserState *pp = static_cast<ParserState*>(parm);
initfg(pp);
if (!pp->hadError) {
try {
pp->fg->solve($2);
} catch (Gecode::FlatZinc::Error& e) {
yyerror(pp, e.toString().c_str());
}
} else {
delete $2;
}
}
| FZ_SOLVE annotations minmax solve_expr
{
ParserState *pp = static_cast<ParserState*>(parm);
initfg(pp);
if (!pp->hadError) {
try {
int v = $4 < 0 ? (-$4-1) : $4;
bool vi = $4 >= 0;
if ($3)
pp->fg->minimize(v,vi,$2);
else
pp->fg->maximize(v,vi,$2);
} catch (Gecode::FlatZinc::Error& e) {
yyerror(pp, e.toString().c_str());
}
} else {
delete $2;
}
}
/********************************/
/* type-insts */
/********************************/
int_ti_expr_tail :
FZ_INT
{ $$ = Option<AST::SetLit* >::none(); }
| '{' int_list '}'
{ $$ = Option<AST::SetLit* >::some(new AST::SetLit(*$2)); }
| FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT
{
$$ = Option<AST::SetLit* >::some(new AST::SetLit($1, $3));
}
bool_ti_expr_tail :
FZ_BOOL
{ $$ = Option<AST::SetLit* >::none(); }
| '{' bool_list_head list_tail '}'
{ bool haveTrue = false;
bool haveFalse = false;
for (int i=$2->size(); i--;) {
haveTrue |= ((*$2)[i] == 1);
haveFalse |= ((*$2)[i] == 0);
}
delete $2;
$$ = Option<AST::SetLit* >::some(
new AST::SetLit(!haveFalse,haveTrue));
}
float_ti_expr_tail :
FZ_FLOAT
{ $$ = Option<std::pair<double,double>* >::none(); }
| FZ_FLOAT_LIT FZ_DOTDOT FZ_FLOAT_LIT
{ std::pair<double,double>* dom = new std::pair<double,double>($1,$3);
$$ = Option<std::pair<double,double>* >::some(dom); }
/********************************/
/* literals */
/********************************/
set_literal :
'{' int_list '}'
{ $$ = new AST::SetLit(*$2); }
| FZ_INT_LIT FZ_DOTDOT FZ_INT_LIT
{ $$ = new AST::SetLit($1, $3); }
/* list containing only primitive literals */
int_list :
/* empty */
{ $$ = new vector<int>(0); }
| int_list_head list_tail
{ $$ = $1; }
int_list_head :
FZ_INT_LIT
{ $$ = new vector<int>(1); (*$$)[0] = $1; }
| int_list_head ',' FZ_INT_LIT
{ $$ = $1; $$->push_back($3); }
bool_list :
/* empty */
{ $$ = new vector<int>(0); }
| bool_list_head list_tail
{ $$ = $1; }
bool_list_head :
FZ_BOOL_LIT
{ $$ = new vector<int>(1); (*$$)[0] = $1; }
| bool_list_head ',' FZ_BOOL_LIT
{ $$ = $1; $$->push_back($3); }
float_list :
/* empty */
{ $$ = new vector<double>(0); }
| float_list_head list_tail
{ $$ = $1; }
float_list_head:
FZ_FLOAT_LIT
{ $$ = new vector<double>(1); (*$$)[0] = $1; }
| float_list_head ',' FZ_FLOAT_LIT
{ $$ = $1; $$->push_back($3); }
set_literal_list :
/* empty */
{ $$ = new vector<AST::SetLit>(0); }
| set_literal_list_head list_tail
{ $$ = $1; }
set_literal_list_head :
set_literal
{ $$ = new vector<AST::SetLit>(1); (*$$)[0] = *$1; delete $1; }
| set_literal_list_head ',' set_literal
{ $$ = $1; $$->push_back(*$3); delete $3; }
/********************************/
/* constraint expressions */
/********************************/
flat_expr_list :
flat_expr
{ $$ = new AST::Array($1); }
| flat_expr_list ',' flat_expr
{ $$ = $1; $$->append($3); }
flat_expr :
non_array_expr
{ $$ = $1; }
| '[' non_array_expr_list ']'
{ $$ = $2; }
non_array_expr_opt :
/* empty */
{ $$ = Option<AST::Node*>::none(); }
| '=' non_array_expr
{ $$ = Option<AST::Node*>::some($2); }
non_array_expr :
FZ_BOOL_LIT
{ $$ = new AST::BoolLit($1); }
| FZ_INT_LIT
{ $$ = new AST::IntLit($1); }
| FZ_FLOAT_LIT
{ $$ = new AST::FloatLit($1); }
| set_literal
{ $$ = $1; }
| var_par_id /* variable, possibly array */
{
ParserState* pp = static_cast<ParserState*>(parm);
SymbolEntry e;
if (pp->symbols.get($1, e)) {
switch (e.t) {
case ST_INTVARARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::IntVar(pp->arrays[e.i+i+1]);
$$ = v;
}
break;
case ST_BOOLVARARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::BoolVar(pp->arrays[e.i+i+1]);
$$ = v;
}
break;
case ST_FLOATVARARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::FloatVar(pp->arrays[e.i+i+1]);
$$ = v;
}
break;
case ST_SETVARARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::SetVar(pp->arrays[e.i+i+1]);
$$ = v;
}
break;
case ST_INTVALARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::IntLit(pp->arrays[e.i+i+1]);
$$ = v;
}
break;
case ST_BOOLVALARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::BoolLit(pp->arrays[e.i+i+1]);
$$ = v;
}
break;
case ST_SETVALARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
int idx = pp->arrays[e.i+1];
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::SetLit(pp->setvals[idx+i]);
$$ = v;
}
break;
case ST_FLOATVALARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
int idx = pp->arrays[e.i+1];
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::FloatLit(pp->floatvals[idx+i]);
$$ = v;
}
break;
case ST_INT:
$$ = new AST::IntLit(e.i);
break;
case ST_BOOL:
$$ = new AST::BoolLit(e.i);
break;
case ST_FLOAT:
$$ = new AST::FloatLit(pp->floatvals[e.i]);
break;
case ST_SET:
$$ = new AST::SetLit(pp->setvals[e.i]);
break;
default:
$$ = getVarRefArg(pp,$1);
}
} else {
pp->err << "Error: undefined identifier " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
$$ = NULL;
}
free($1);
}
| var_par_id '[' non_array_expr ']' /* array access */
{
ParserState* pp = static_cast<ParserState*>(parm);
int i = -1;
yyassert(pp, $3->isInt(i), "Non-integer array index");
if (!pp->hadError)
$$ = getArrayElement(static_cast<ParserState*>(parm),$1,i,false);
else
$$ = new AST::IntLit(0); // keep things consistent
delete $3;
free($1);
}
non_array_expr_list :
/* empty */
{ $$ = new AST::Array(0); }
| non_array_expr_list_head list_tail
{ $$ = $1; }
non_array_expr_list_head :
non_array_expr
{ $$ = new AST::Array($1); }
| non_array_expr_list_head ',' non_array_expr
{ $$ = $1; $$->append($3); }
/********************************/
/* solve expressions */
/********************************/
solve_expr:
var_par_id
{
ParserState *pp = static_cast<ParserState*>(parm);
SymbolEntry e;
bool haveSym = pp->symbols.get($1,e);
if (haveSym) {
switch (e.t) {
case ST_INTVAR:
$$ = e.i;
break;
case ST_FLOATVAR:
$$ = -e.i-1;
break;
case ST_INT:
case ST_FLOAT:
pp->intvars.push_back(varspec("OBJ_CONST_INTRODUCED",
new IntVarSpec(0,true,false)));
$$ = pp->intvars.size()-1;
break;
default:
pp->err << "Error: unknown int or float variable " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
break;
}
} else {
pp->err << "Error: unknown int or float variable " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
}
free($1);
}
| FZ_INT_LIT
{
ParserState *pp = static_cast<ParserState*>(parm);
pp->intvars.push_back(varspec("OBJ_CONST_INTRODUCED",
new IntVarSpec(0,true,false)));
$$ = pp->intvars.size()-1;
}
| FZ_FLOAT_LIT
{
ParserState *pp = static_cast<ParserState*>(parm);
pp->intvars.push_back(varspec("OBJ_CONST_INTRODUCED",
new IntVarSpec(0,true,false)));
$$ = pp->intvars.size()-1;
}
| var_par_id '[' FZ_INT_LIT ']'
{
SymbolEntry e;
ParserState *pp = static_cast<ParserState*>(parm);
if ( (!pp->symbols.get($1, e)) ||
(e.t != ST_INTVARARRAY && e.t != ST_FLOATVARARRAY)) {
pp->err << "Error: unknown int or float variable array " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
}
if ($3 == 0 || $3 > pp->arrays[e.i]) {
pp->err << "Error: array index out of bounds for array " << $1
<< " in line no. "
<< yyget_lineno(pp->yyscanner) << std::endl;
pp->hadError = true;
} else {
if (e.t == ST_INTVARARRAY)
$$ = pp->arrays[e.i+$3];
else
$$ = -pp->arrays[e.i+$3]-1;
}
free($1);
}
minmax:
FZ_MINIMIZE
| FZ_MAXIMIZE
/********************************/
/* annotation expresions */
/********************************/
annotations :
/* empty */
{ $$ = NULL; }
| annotations_head
{ $$ = $1; }
annotations_head :
FZ_COLONCOLON annotation
{ $$ = new AST::Array($2); }
| annotations_head FZ_COLONCOLON annotation
{ $$ = $1; $$->append($3); }
annotation :
FZ_ID '(' annotation_list ')'
{
$$ = new AST::Call($1, AST::extractSingleton($3)); free($1);
}
| annotation_expr
{ $$ = $1; }
annotation_list:
annotation
{ $$ = new AST::Array($1); }
| annotation_list ',' annotation
{ $$ = $1; $$->append($3); }
annotation_expr :
ann_non_array_expr
{ $$ = $1; }
| '[' ']'
{ $$ = new AST::Array(); }
| '[' annotation_list annotation_list_tail ']'
{ $$ = $2; }
annotation_list_tail : | ','
ann_non_array_expr :
FZ_BOOL_LIT
{ $$ = new AST::BoolLit($1); }
| FZ_INT_LIT
{ $$ = new AST::IntLit($1); }
| FZ_FLOAT_LIT
{ $$ = new AST::FloatLit($1); }
| set_literal
{ $$ = $1; }
| var_par_id /* variable, possibly array */
{
ParserState* pp = static_cast<ParserState*>(parm);
SymbolEntry e;
bool gotSymbol = false;
if (pp->symbols.get($1, e)) {
gotSymbol = true;
switch (e.t) {
case ST_INTVARARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;) {
std::ostringstream oss;
oss << $1 << "["<<(i+1)<<"]";
v->a[i] = new AST::IntVar(pp->arrays[e.i+i+1], oss.str());
}
$$ = v;
}
break;
case ST_BOOLVARARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;) {
std::ostringstream oss;
oss << $1 << "["<<(i+1)<<"]";
v->a[i] = new AST::BoolVar(pp->arrays[e.i+i+1], oss.str());
}
$$ = v;
}
break;
case ST_FLOATVARARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;) {
std::ostringstream oss;
oss << $1 << "["<<(i+1)<<"]";
v->a[i] = new AST::FloatVar(pp->arrays[e.i+i+1], oss.str());
}
$$ = v;
}
break;
case ST_SETVARARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;) {
std::ostringstream oss;
oss << $1 << "["<<(i+1)<<"]";
v->a[i] = new AST::SetVar(pp->arrays[e.i+i+1], oss.str());
}
$$ = v;
}
break;
case ST_INTVALARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::IntLit(pp->arrays[e.i+i+1]);
$$ = v;
}
break;
case ST_BOOLVALARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::BoolLit(pp->arrays[e.i+i+1]);
$$ = v;
}
break;
case ST_SETVALARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
int idx = pp->arrays[e.i+1];
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::SetLit(pp->setvals[idx+i]);
$$ = v;
}
break;
case ST_FLOATVALARRAY:
{
AST::Array *v = new AST::Array(pp->arrays[e.i]);
int idx = pp->arrays[e.i+1];
for (int i=pp->arrays[e.i]; i--;)
v->a[i] = new AST::FloatLit(pp->floatvals[idx+i]);
$$ = v;
}
break;
case ST_INT:
$$ = new AST::IntLit(e.i);
break;
case ST_BOOL:
$$ = new AST::BoolLit(e.i);
break;
case ST_FLOAT:
$$ = new AST::FloatLit(pp->floatvals[e.i]);
break;
case ST_SET:
$$ = new AST::SetLit(pp->setvals[e.i]);
break;
default:
gotSymbol = false;
}
}
if (!gotSymbol)
$$ = getVarRefArg(pp,$1,true);
free($1);
}
| var_par_id '[' ann_non_array_expr ']' /* array access */
{
ParserState* pp = static_cast<ParserState*>(parm);
int i = -1;
yyassert(pp, $3->isInt(i), "Non-integer array index");
if (!pp->hadError)
$$ = getArrayElement(static_cast<ParserState*>(parm),$1,i,true);
else
$$ = new AST::IntLit(0); // keep things consistent
free($1);
}
| FZ_STRING_LIT
{
$$ = new AST::String($1);
free($1);
}