git-subtree-dir: software/gecode_on_replay git-subtree-split: 8051d92b9c89e49cccfbd1c201371580d7703ab4
2118 lines
69 KiB
Plaintext
Executable File
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);
|
|
}
|