reorganize more code
This commit is contained in:
@@ -542,24 +542,27 @@ FLATZINC_LIB_OBJS=\
|
||||
$(OBJ_DIR)/flatzinc.$O\
|
||||
$(OBJ_DIR)/lexer.yy.$O\
|
||||
$(OBJ_DIR)/parser.tab.$O\
|
||||
$(OBJ_DIR)/parser.$O\
|
||||
$(OBJ_DIR)/registry.$O
|
||||
|
||||
$(SRC_DIR)/flatzinc/lexer.yy.cc: $(SRC_DIR)/flatzinc/lexer.lxx $(SRC_DIR)/flatzinc/parser.tab.h
|
||||
$(SRC_DIR)/flatzinc/lexer.yy.cc: $(SRC_DIR)/flatzinc/lexer.lxx $(SRC_DIR)/flatzinc/parser.tab.h $(SRC_DIR)/flatzinc/parser.h $(SRC_DIR)/flatzinc/spec.h $(SRC_DIR)/flatzinc/flatzinc.h
|
||||
flex -o$(SRC_DIR)/flatzinc/lexer.yy.cc $(SRC_DIR)/flatzinc/lexer.lxx
|
||||
|
||||
$(SRC_DIR)/flatzinc/parser.tab.cc: $(SRC_DIR)/flatzinc/parser.yxx
|
||||
$(SRC_DIR)/flatzinc/parser.tab.cc: $(SRC_DIR)/flatzinc/parser.yxx $(SRC_DIR)/flatzinc/parser.h $(SRC_DIR)/flatzinc/spec.h $(SRC_DIR)/flatzinc/flatzinc.h
|
||||
bison -t -o $(SRC_DIR)/flatzinc/parser.tab.cc -d $<
|
||||
mv $(SRC_DIR)/flatzinc/parser.tab.hh $(SRC_DIR)/flatzinc/parser.tab.h
|
||||
|
||||
$(SRC_DIR)/flatzinc/parser.tab.h: $(SRC_DIR)/flatzinc/parser.tab.cc
|
||||
|
||||
$(OBJ_DIR)/flatzinc.$O:$(SRC_DIR)/flatzinc/flatzinc.cc $(SRC_DIR)/flatzinc/flatzinc.h
|
||||
$(OBJ_DIR)/flatzinc.$O:$(SRC_DIR)/flatzinc/flatzinc.cc $(SRC_DIR)/flatzinc/flatzinc.h $(SRC_DIR)/flatzinc/spec.h
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)$Sflatzinc$Sflatzinc.cc $(OBJ_OUT)flatzinc.$O
|
||||
$(OBJ_DIR)/lexer.yy.$O:$(SRC_DIR)/flatzinc/lexer.yy.cc
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)$Sflatzinc$Slexer.yy.cc $(OBJ_OUT)lexer.yy.$O
|
||||
$(OBJ_DIR)/parser.$O:$(SRC_DIR)/flatzinc/parser.cc $(SRC_DIR)/flatzinc/flatzinc.h $(SRC_DIR)/flatzinc/parser.h $(SRC_DIR)/flatzinc/spec.h
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)$Sflatzinc$Sparser.cc $(OBJ_OUT)parser.$O
|
||||
$(OBJ_DIR)/parser.tab.$O:$(SRC_DIR)/flatzinc/parser.tab.cc $(SRC_DIR)/flatzinc/flatzinc.h
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)$Sflatzinc$Sparser.tab.cc $(OBJ_OUT)parser.tab.$O
|
||||
$(OBJ_DIR)/registry.$O:$(SRC_DIR)/flatzinc/registry.cc $(SRC_DIR)/flatzinc/registry.h $(SRC_DIR)/flatzinc/flatzinc.h
|
||||
$(OBJ_DIR)/registry.$O:$(SRC_DIR)/flatzinc/registry.cc $(SRC_DIR)/flatzinc/flatzinc.h $(SRC_DIR)/flatzinc/spec.h
|
||||
$(CCC) $(CFLAGS) -c $(SRC_DIR)$Sflatzinc$Sregistry.cc $(OBJ_OUT)registry.$O
|
||||
|
||||
$(LIB_DIR)/$(LIBPREFIX)fz.$(LIBSUFFIX): $(FLATZINC_LIB_OBJS)
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
#include "base/stringprintf.h"
|
||||
#include "flatzinc/flatzinc.h"
|
||||
//#include "flatzinc/registry.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
249
src/flatzinc/parser.cc
Normal file
249
src/flatzinc/parser.cc
Normal file
@@ -0,0 +1,249 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/stringprintf.h"
|
||||
#include "flatzinc/flatzinc.h"
|
||||
#include "flatzinc/parser.h"
|
||||
|
||||
using namespace std;
|
||||
extern int yyparse(void*);
|
||||
extern int yylex(YYSTYPE*, void* scanner);
|
||||
extern int yylex_init (void** scanner);
|
||||
extern int yylex_destroy (void* scanner);
|
||||
extern int yyget_lineno (void* scanner);
|
||||
extern void yyset_extra (void* user_defined ,void* yyscanner );
|
||||
extern void yyerror(void* parm, const char *str);
|
||||
|
||||
namespace operations_research {
|
||||
AST::Node* ParserState::ArrayElement(string id, unsigned int offset) {
|
||||
if (offset > 0) {
|
||||
vector<int> tmp;
|
||||
if (intvararrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::IntVar(tmp[offset-1]);
|
||||
if (boolvararrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::BoolVar(tmp[offset-1]);
|
||||
if (setvararrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::SetVar(tmp[offset-1]);
|
||||
|
||||
if (intvalarrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::IntLit(tmp[offset-1]);
|
||||
if (boolvalarrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::BoolLit(tmp[offset-1]);
|
||||
vector<AST::SetLit> tmpS;
|
||||
if (setvalarrays.get(id, tmpS) && offset<=tmpS.size())
|
||||
return new AST::SetLit(tmpS[offset-1]);
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Error: array access to " << id << " invalid"
|
||||
<< " in line no. " << yyget_lineno(yyscanner);
|
||||
hadError = true;
|
||||
return new AST::IntVar(0); // keep things consistent
|
||||
}
|
||||
|
||||
AST::Node* ParserState::VarRefArg(string id, bool annotation) {
|
||||
int tmp;
|
||||
if (intvarTable.get(id, tmp))
|
||||
return new AST::IntVar(tmp);
|
||||
if (boolvarTable.get(id, tmp))
|
||||
return new AST::BoolVar(tmp);
|
||||
if (setvarTable.get(id, tmp))
|
||||
return new AST::SetVar(tmp);
|
||||
if (annotation)
|
||||
return new AST::Atom(id);
|
||||
LOG(ERROR) << "Error: undefined variable " << id
|
||||
<< " in line no. " << yyget_lineno(yyscanner);
|
||||
hadError = true;
|
||||
return new AST::IntVar(0); // keep things consistent
|
||||
}
|
||||
|
||||
void ParserState::AddDomainConstraint(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();
|
||||
domain_constraints_.push_back(new CtSpec(-1, id, args, NULL));
|
||||
}
|
||||
|
||||
void ParserState::AddConstraint(const std::string& id,
|
||||
AST::Array* const args,
|
||||
AST::Node* const annotations) {
|
||||
constraints_.push_back(new CtSpec(constraints_.size(),
|
||||
id,
|
||||
args,
|
||||
annotations));
|
||||
}
|
||||
|
||||
void ParserState::InitModel() {
|
||||
if (!hadError)
|
||||
model->Init(intvars.size(),
|
||||
boolvars.size(),
|
||||
setvars.size());
|
||||
|
||||
int array_index = 0;
|
||||
for (unsigned int i=0; i<intvars.size(); i++) {
|
||||
if (!hadError) {
|
||||
const std::string& raw_name = intvars[i].first;
|
||||
std::string name;
|
||||
if (raw_name[0] == '[') {
|
||||
name = StringPrintf("%s[%d]", raw_name.c_str() + 1, ++array_index);
|
||||
} else {
|
||||
if (array_index == 0) {
|
||||
name = raw_name;
|
||||
} else {
|
||||
name = StringPrintf("%s[%d]", raw_name.c_str(), array_index + 1);
|
||||
array_index = 0;
|
||||
}
|
||||
}
|
||||
model->NewIntVar(name, static_cast<IntVarSpec*>(intvars[i].second));
|
||||
}
|
||||
if (intvars[i].first[0] != '[') {
|
||||
delete intvars[i].second;
|
||||
intvars[i].second = NULL;
|
||||
}
|
||||
}
|
||||
array_index = 0;
|
||||
for (unsigned int i=0; i<boolvars.size(); i++) {
|
||||
if (!hadError) {
|
||||
const std::string& raw_name = boolvars[i].first;
|
||||
std::string name;
|
||||
if (raw_name[0] == '[') {
|
||||
name = StringPrintf("%s[%d]", raw_name.c_str() + 1, ++array_index);
|
||||
} else {
|
||||
if (array_index == 0) {
|
||||
name = raw_name;
|
||||
} else {
|
||||
name = StringPrintf("%s[%d]", raw_name.c_str(), array_index + 1);
|
||||
array_index = 0;
|
||||
}
|
||||
}
|
||||
model->NewBoolVar(name, static_cast<BoolVarSpec*>(boolvars[i].second));
|
||||
}
|
||||
if (boolvars[i].first[0] != '[') {
|
||||
delete boolvars[i].second;
|
||||
boolvars[i].second = NULL;
|
||||
}
|
||||
}
|
||||
for (unsigned int i=0; i<setvars.size(); i++) {
|
||||
if (!hadError) {
|
||||
// model->newSetVar(static_cast<SetVarSpec*>(setvars[i].second));
|
||||
}
|
||||
if (setvars[i].first[0] != '[') {
|
||||
delete setvars[i].second;
|
||||
setvars[i].second = NULL;
|
||||
}
|
||||
}
|
||||
for (unsigned int i=domain_constraints_.size(); i--;) {
|
||||
if (!hadError) {
|
||||
try {
|
||||
assert(domain_constraints_[i]->NumArgs() == 2);
|
||||
model->PostConstraint(domain_constraints_[i]);
|
||||
delete domain_constraints_[i];
|
||||
} catch (operations_research::Error& e) {
|
||||
yyerror(this, e.DebugString().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParserState::FillOutput(operations_research::FlatZincModel& m) {
|
||||
m.InitOutput(Output());
|
||||
}
|
||||
|
||||
void FlatZincModel::Parse(const std::string& filename) {
|
||||
#ifdef HAVE_MMAP
|
||||
int fd;
|
||||
char* data;
|
||||
struct stat sbuf;
|
||||
fd = open(filename.c_str(), O_RDONLY);
|
||||
if (fd == -1) {
|
||||
LOG(ERROR) << "Cannot open file " << filename;
|
||||
return NULL;
|
||||
}
|
||||
if (stat(filename.c_str(), &sbuf) == -1) {
|
||||
LOG(ERROR) << "Cannot stat file " << filename;
|
||||
return NULL;
|
||||
}
|
||||
data = (char*)mmap((caddr_t)0, sbuf.st_size, PROT_READ, MAP_SHARED, fd,0);
|
||||
if (data == (caddr_t)(-1)) {
|
||||
LOG(ERROR) << "Cannot mmap file " << filename;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ParserState pp(data, sbuf.st_size, this);
|
||||
#else
|
||||
std::ifstream file;
|
||||
file.open(filename.c_str());
|
||||
if (!file.is_open()) {
|
||||
LOG(FATAL) << "Cannot open file " << filename;
|
||||
}
|
||||
std::string s = string(istreambuf_iterator<char>(file),
|
||||
istreambuf_iterator<char>());
|
||||
ParserState pp(s, this);
|
||||
#endif
|
||||
yylex_init(&pp.yyscanner);
|
||||
yyset_extra(&pp, pp.yyscanner);
|
||||
// yydebug = 1;
|
||||
yyparse(&pp);
|
||||
pp.FillOutput(*this);
|
||||
|
||||
if (pp.yyscanner)
|
||||
yylex_destroy(pp.yyscanner);
|
||||
}
|
||||
|
||||
void FlatZincModel::Parse(std::istream& is) {
|
||||
std::string s = string(istreambuf_iterator<char>(is),
|
||||
istreambuf_iterator<char>());
|
||||
|
||||
ParserState pp(s, this);
|
||||
yylex_init(&pp.yyscanner);
|
||||
yyset_extra(&pp, pp.yyscanner);
|
||||
// yydebug = 1;
|
||||
yyparse(&pp);
|
||||
pp.FillOutput(*this);
|
||||
|
||||
if (pp.yyscanner)
|
||||
yylex_destroy(pp.yyscanner);
|
||||
}
|
||||
|
||||
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::string out;
|
||||
|
||||
out = StringPrintf("array%dd(", a->a.size());;
|
||||
for (unsigned int i = 0; i < a->a.size(); i++) {
|
||||
AST::SetLit* s = a->a[i]->getSet();
|
||||
if (s->empty()) {
|
||||
out += "{}, ";
|
||||
} else if (s->interval) {
|
||||
out += StringPrintf("%d..%d, ", s->min, s->max);
|
||||
} else {
|
||||
out += "{";
|
||||
for (unsigned int j = 0; j < s->s.size(); j++) {
|
||||
out += s->s[j];
|
||||
if (j < s->s.size() - 1) {
|
||||
out += ",";
|
||||
}
|
||||
}
|
||||
out += "}, ";
|
||||
}
|
||||
}
|
||||
|
||||
if (!ann->args->isArray()) {
|
||||
a->a[0] = NULL;
|
||||
delete a;
|
||||
}
|
||||
return new AST::String(out);
|
||||
}
|
||||
} // namespace operations_research
|
||||
@@ -144,8 +144,8 @@ class ParserState {
|
||||
std::vector<varspec> boolvars;
|
||||
std::vector<varspec> setvars;
|
||||
|
||||
std::vector<CtSpec*> domainConstraints;
|
||||
std::vector<CtSpec*> constraints;
|
||||
std::vector<CtSpec*> domain_constraints_;
|
||||
std::vector<CtSpec*> constraints_;
|
||||
|
||||
bool hadError;
|
||||
|
||||
@@ -184,14 +184,26 @@ class ParserState {
|
||||
}
|
||||
|
||||
void AddConstraints() {
|
||||
for (unsigned int i=constraints.size(); i--;) {
|
||||
for (unsigned int i = constraints_.size(); i--;) {
|
||||
if (!hadError) {
|
||||
model->PostConstraint(constraints[i]);
|
||||
delete constraints[i];
|
||||
model->PostConstraint(constraints_[i]);
|
||||
delete constraints_[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AST::Node* ArrayElement(string id, unsigned int offset);
|
||||
AST::Node* VarRefArg(string id, bool annotation);
|
||||
void AddDomainConstraint(std::string id, AST::Node* var,
|
||||
Option<AST::SetLit*>& dom);
|
||||
void AddConstraint(const std::string& id,
|
||||
AST::Array* const args,
|
||||
AST::Node* const annotations);
|
||||
void InitModel();
|
||||
void FillOutput(operations_research::FlatZincModel& m);
|
||||
};
|
||||
|
||||
AST::Node* ArrayOutput(AST::Call* ann);
|
||||
} // namespace operations_research
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -138,7 +138,7 @@
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
#line 341 "src/flatzinc/parser.yxx"
|
||||
#line 79 "src/flatzinc/parser.yxx"
|
||||
{ int iValue; char* sValue; bool bValue; double dValue;
|
||||
std::vector<int>* setValue;
|
||||
operations_research::AST::SetLit* setLit;
|
||||
|
||||
@@ -42,9 +42,6 @@
|
||||
#define YYLEX_PARAM static_cast<ParserState*>(parm)->yyscanner
|
||||
#include "flatzinc/flatzinc.h"
|
||||
#include "flatzinc/parser.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -56,13 +53,8 @@
|
||||
|
||||
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 yylex(YYSTYPE*, void* scanner);
|
||||
extern int yyget_lineno (void* scanner);
|
||||
extern int yydebug;
|
||||
|
||||
using namespace operations_research;
|
||||
@@ -82,260 +74,6 @@ void yyassert(ParserState* pp, bool cond, const char* str)
|
||||
pp->hadError = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The symbol tables
|
||||
*
|
||||
*/
|
||||
|
||||
AST::Node* getArrayElement(ParserState* pp, string id, unsigned int offset) {
|
||||
if (offset > 0) {
|
||||
vector<int> tmp;
|
||||
if (pp->intvararrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::IntVar(tmp[offset-1]);
|
||||
if (pp->boolvararrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::BoolVar(tmp[offset-1]);
|
||||
if (pp->setvararrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::SetVar(tmp[offset-1]);
|
||||
|
||||
if (pp->intvalarrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::IntLit(tmp[offset-1]);
|
||||
if (pp->boolvalarrays.get(id, tmp) && offset<=tmp.size())
|
||||
return new AST::BoolLit(tmp[offset-1]);
|
||||
vector<AST::SetLit> tmpS;
|
||||
if (pp->setvalarrays.get(id, tmpS) && offset<=tmpS.size())
|
||||
return new AST::SetLit(tmpS[offset-1]);
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Error: array access to " << id << " invalid"
|
||||
<< " in line no. " << yyget_lineno(pp->yyscanner);
|
||||
pp->hadError = true;
|
||||
return new AST::IntVar(0); // keep things consistent
|
||||
}
|
||||
AST::Node* getVarRefArg(ParserState* pp, string id, bool annotation = false) {
|
||||
int tmp;
|
||||
if (pp->intvarTable.get(id, tmp))
|
||||
return new AST::IntVar(tmp);
|
||||
if (pp->boolvarTable.get(id, tmp))
|
||||
return new AST::BoolVar(tmp);
|
||||
if (pp->setvarTable.get(id, tmp))
|
||||
return new AST::SetVar(tmp);
|
||||
if (annotation)
|
||||
return new AST::Atom(id);
|
||||
LOG(ERROR) << "Error: undefined variable " << id
|
||||
<< " in line no. " << yyget_lineno(pp->yyscanner);
|
||||
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 CtSpec(id, args, NULL));
|
||||
}
|
||||
|
||||
void addConstraint(ParserState* const pp,
|
||||
const std::string& id,
|
||||
AST::Array* const args,
|
||||
AST::Node* const annotations) {
|
||||
pp->constraints.push_back(new CtSpec(id, args, annotations));
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the root or-tools space
|
||||
*
|
||||
*/
|
||||
|
||||
void initmodel(ParserState* pp) {
|
||||
if (!pp->hadError)
|
||||
pp->model->Init(pp->intvars.size(),
|
||||
pp->boolvars.size(),
|
||||
pp->setvars.size());
|
||||
|
||||
int array_index = 0;
|
||||
for (unsigned int i=0; i<pp->intvars.size(); i++) {
|
||||
if (!pp->hadError) {
|
||||
try {
|
||||
const std::string& raw_name = pp->intvars[i].first;
|
||||
std::string name;
|
||||
if (raw_name[0] == '[') {
|
||||
name = StringPrintf("%s[%d]", raw_name.c_str() + 1, ++array_index);
|
||||
} else {
|
||||
if (array_index == 0) {
|
||||
name = raw_name;
|
||||
} else {
|
||||
name = StringPrintf("%s[%d]", raw_name.c_str(), array_index + 1);
|
||||
array_index = 0;
|
||||
}
|
||||
}
|
||||
pp->model->NewIntVar(name,
|
||||
static_cast<IntVarSpec*>(pp->intvars[i].second));
|
||||
} catch (operations_research::Error& e) {
|
||||
yyerror(pp, e.DebugString().c_str());
|
||||
}
|
||||
}
|
||||
if (pp->intvars[i].first[0] != '[') {
|
||||
delete pp->intvars[i].second;
|
||||
pp->intvars[i].second = NULL;
|
||||
}
|
||||
}
|
||||
array_index = 0;
|
||||
for (unsigned int i=0; i<pp->boolvars.size(); i++) {
|
||||
if (!pp->hadError) {
|
||||
try {
|
||||
const std::string& raw_name = pp->boolvars[i].first;
|
||||
std::string name;
|
||||
if (raw_name[0] == '[') {
|
||||
name = StringPrintf("%s[%d]", raw_name.c_str() + 1, ++array_index);
|
||||
} else {
|
||||
if (array_index == 0) {
|
||||
name = raw_name;
|
||||
} else {
|
||||
name = StringPrintf("%s[%d]", raw_name.c_str(), array_index + 1);
|
||||
array_index = 0;
|
||||
}
|
||||
}
|
||||
pp->model->NewBoolVar(name,
|
||||
static_cast<BoolVarSpec*>(pp->boolvars[i].second));
|
||||
} catch (operations_research::Error& e) {
|
||||
yyerror(pp, e.DebugString().c_str());
|
||||
}
|
||||
}
|
||||
if (pp->boolvars[i].first[0] != '[') {
|
||||
delete pp->boolvars[i].second;
|
||||
pp->boolvars[i].second = NULL;
|
||||
}
|
||||
}
|
||||
for (unsigned int i=0; i<pp->setvars.size(); i++) {
|
||||
if (!pp->hadError) {
|
||||
// pp->model->newSetVar(static_cast<SetVarSpec*>(pp->setvars[i].second));
|
||||
}
|
||||
if (pp->setvars[i].first[0] != '[') {
|
||||
delete pp->setvars[i].second;
|
||||
pp->setvars[i].second = NULL;
|
||||
}
|
||||
}
|
||||
for (unsigned int i=pp->domainConstraints.size(); i--;) {
|
||||
if (!pp->hadError) {
|
||||
try {
|
||||
assert(pp->domainConstraints[i]->NumArgs() == 2);
|
||||
pp->model->PostConstraint(pp->domainConstraints[i]);
|
||||
delete pp->domainConstraints[i];
|
||||
} catch (operations_research::Error& e) {
|
||||
yyerror(pp, e.DebugString().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FillOutput(ParserState& pp, operations_research::FlatZincModel& m) {
|
||||
m.InitOutput(pp.Output());
|
||||
}
|
||||
|
||||
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 operations_research {
|
||||
|
||||
void FlatZincModel::Parse(const std::string& filename) {
|
||||
#ifdef HAVE_MMAP
|
||||
int fd;
|
||||
char* data;
|
||||
struct stat sbuf;
|
||||
fd = open(filename.c_str(), O_RDONLY);
|
||||
if (fd == -1) {
|
||||
LOG(ERROR) << "Cannot open file " << filename;
|
||||
return NULL;
|
||||
}
|
||||
if (stat(filename.c_str(), &sbuf) == -1) {
|
||||
LOG(ERROR) << "Cannot stat file " << filename;
|
||||
return NULL;
|
||||
}
|
||||
data = (char*)mmap((caddr_t)0, sbuf.st_size, PROT_READ, MAP_SHARED, fd,0);
|
||||
if (data == (caddr_t)(-1)) {
|
||||
LOG(ERROR) << "Cannot mmap file " << filename;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ParserState pp(data, sbuf.st_size, this);
|
||||
#else
|
||||
std::ifstream file;
|
||||
file.open(filename.c_str());
|
||||
if (!file.is_open()) {
|
||||
LOG(FATAL) << "Cannot open file " << filename;
|
||||
}
|
||||
std::string s = string(istreambuf_iterator<char>(file),
|
||||
istreambuf_iterator<char>());
|
||||
ParserState pp(s, this);
|
||||
#endif
|
||||
yylex_init(&pp.yyscanner);
|
||||
yyset_extra(&pp, pp.yyscanner);
|
||||
// yydebug = 1;
|
||||
yyparse(&pp);
|
||||
FillOutput(pp, *this);
|
||||
|
||||
if (pp.yyscanner)
|
||||
yylex_destroy(pp.yyscanner);
|
||||
}
|
||||
|
||||
void FlatZincModel::Parse(std::istream& is) {
|
||||
std::string s = string(istreambuf_iterator<char>(is),
|
||||
istreambuf_iterator<char>());
|
||||
|
||||
ParserState pp(s, this);
|
||||
yylex_init(&pp.yyscanner);
|
||||
yyset_extra(&pp, pp.yyscanner);
|
||||
// yydebug = 1;
|
||||
yyparse(&pp);
|
||||
FillOutput(pp, *this);
|
||||
|
||||
if (pp.yyscanner)
|
||||
yylex_destroy(pp.yyscanner);
|
||||
}
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%union { int iValue; char* sValue; bool bValue; double dValue;
|
||||
@@ -450,9 +188,9 @@ preddecl_items_head:
|
||||
|
||||
vardecl_items:
|
||||
/* emtpy */
|
||||
{ initmodel(static_cast<ParserState*>(parm)); }
|
||||
{ static_cast<ParserState*>(parm)->InitModel(); }
|
||||
| vardecl_items_head
|
||||
{ initmodel(static_cast<ParserState*>(parm)); }
|
||||
{ static_cast<ParserState*>(parm)->InitModel(); }
|
||||
|
||||
vardecl_items_head:
|
||||
vardecl_item ';'
|
||||
@@ -532,10 +270,9 @@ vardecl_item:
|
||||
yyassert(pp, false, "Invalid var int initializer.");
|
||||
}
|
||||
if (!pp->hadError)
|
||||
addDomainConstraint(pp,
|
||||
"int_in",
|
||||
new AST::IntVar(pp->intvars.size() - 1),
|
||||
$2);
|
||||
pp->AddDomainConstraint("int_in",
|
||||
new AST::IntVar(pp->intvars.size() - 1),
|
||||
$2);
|
||||
delete arg;
|
||||
} else {
|
||||
pp->intvars.push_back(varspec($4, new IntVarSpec($2, introduced)));
|
||||
@@ -563,8 +300,9 @@ vardecl_item:
|
||||
yyassert(pp, false, "Invalid var bool initializer.");
|
||||
}
|
||||
if (!pp->hadError)
|
||||
addDomainConstraint(pp, "int_in",
|
||||
new AST::BoolVar(pp->boolvars.size()-1), $2);
|
||||
pp->AddDomainConstraint("int_in",
|
||||
new AST::BoolVar(pp->boolvars.size()-1),
|
||||
$2);
|
||||
delete arg;
|
||||
} else {
|
||||
pp->boolvars.push_back(varspec($4, new BoolVarSpec($2,introduced)));
|
||||
@@ -599,8 +337,9 @@ vardecl_item:
|
||||
delete arg;
|
||||
}
|
||||
if (!pp->hadError)
|
||||
addDomainConstraint(pp, "set_subset",
|
||||
new AST::SetVar(pp->setvars.size()-1), $4);
|
||||
pp->AddDomainConstraint("set_subset",
|
||||
new AST::SetVar(pp->setvars.size()-1),
|
||||
$4);
|
||||
} else {
|
||||
pp->setvars.push_back(varspec($6, new SetVarSpec($4,introduced)));
|
||||
}
|
||||
@@ -654,9 +393,9 @@ vardecl_item:
|
||||
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);
|
||||
pp->AddDomainConstraint("int_in",
|
||||
new AST::IntVar(vars[i]),
|
||||
opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -676,7 +415,7 @@ vardecl_item:
|
||||
}
|
||||
if (print) {
|
||||
AST::Array* a = new AST::Array();
|
||||
a->a.push_back(arrayOutput($12->getCall("output_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]));
|
||||
@@ -712,9 +451,9 @@ vardecl_item:
|
||||
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);
|
||||
pp->AddDomainConstraint("int_in",
|
||||
new AST::BoolVar(vars[i]),
|
||||
opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -728,7 +467,7 @@ vardecl_item:
|
||||
}
|
||||
if (print) {
|
||||
AST::Array* a = new AST::Array();
|
||||
a->a.push_back(arrayOutput($12->getCall("output_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]));
|
||||
@@ -771,9 +510,9 @@ vardecl_item:
|
||||
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);
|
||||
pp->AddDomainConstraint("set_subset",
|
||||
new AST::SetVar(vars[i]),
|
||||
opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -792,7 +531,7 @@ vardecl_item:
|
||||
}
|
||||
if (print) {
|
||||
AST::Array* a = new AST::Array();
|
||||
a->a.push_back(arrayOutput($14->getCall("output_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]));
|
||||
@@ -1096,7 +835,7 @@ constraint_item :
|
||||
ParserState *pp = static_cast<ParserState*>(parm);
|
||||
if (!pp->hadError) {
|
||||
try {
|
||||
addConstraint(pp, $2, $4, $6);
|
||||
pp->AddConstraint($2, $4, $6);
|
||||
} catch (operations_research::Error& e) {
|
||||
yyerror(pp, e.DebugString().c_str());
|
||||
}
|
||||
@@ -1304,7 +1043,7 @@ non_array_expr :
|
||||
} else if (pp->boolvals.get($1, bval)) {
|
||||
$$ = new AST::BoolLit(bval);
|
||||
} else {
|
||||
$$ = getVarRefArg(pp,$1);
|
||||
$$ = pp->VarRefArg($1, false);
|
||||
}
|
||||
}
|
||||
free($1);
|
||||
@@ -1315,7 +1054,7 @@ non_array_expr :
|
||||
int i = -1;
|
||||
yyassert(pp, $3->isInt(i), "Non-integer array index.");
|
||||
if (!pp->hadError)
|
||||
$$ = getArrayElement(static_cast<ParserState*>(parm),$1,i);
|
||||
$$ = static_cast<ParserState*>(parm)->ArrayElement($1, i);
|
||||
else
|
||||
$$ = new AST::IntLit(0); // keep things consistent
|
||||
free($1);
|
||||
@@ -1454,7 +1193,7 @@ ann_non_array_expr :
|
||||
} else if (pp->boolvals.get($1, bval)) {
|
||||
$$ = new AST::BoolLit(bval);
|
||||
} else {
|
||||
$$ = getVarRefArg(pp,$1,true);
|
||||
$$ = pp->VarRefArg($1, true);
|
||||
}
|
||||
}
|
||||
free($1);
|
||||
@@ -1465,7 +1204,7 @@ ann_non_array_expr :
|
||||
int i = -1;
|
||||
yyassert(pp, $3->isInt(i), "Non-integer array index.");
|
||||
if (!pp->hadError)
|
||||
$$ = getArrayElement(static_cast<ParserState*>(parm),$1,i);
|
||||
$$ = pp->ArrayElement($1, i);
|
||||
else
|
||||
$$ = new AST::IntLit(0); // keep things consistent
|
||||
free($1);
|
||||
|
||||
@@ -61,10 +61,10 @@ class Registry {
|
||||
static Registry global_registry;
|
||||
|
||||
void Registry::Post(FlatZincModel& s, CtSpec* const spec) {
|
||||
std::map<std::string, poster>::iterator i = r.find(spec->id());
|
||||
std::map<std::string, poster>::iterator i = r.find(spec->Id());
|
||||
if (i == r.end()) {
|
||||
throw Error("Registry",
|
||||
std::string("Constraint ") + spec->id() + " not found");
|
||||
std::string("Constraint ") + spec->Id() + " not found");
|
||||
}
|
||||
i->second(s, spec);
|
||||
}
|
||||
|
||||
@@ -180,24 +180,30 @@ class SetVarSpec : public VarSpec {
|
||||
|
||||
class CtSpec {
|
||||
public:
|
||||
CtSpec(const std::string& id0,
|
||||
AST::Array* const args0,
|
||||
AST::Node* const an0)
|
||||
: id_(id0),
|
||||
args_(args0),
|
||||
annotations_(an0) {}
|
||||
CtSpec(const int index,
|
||||
const std::string& id,
|
||||
AST::Array* const args,
|
||||
AST::Node* const annotations)
|
||||
: index_(index),
|
||||
id_(id),
|
||||
args_(args),
|
||||
annotations_(annotations) {}
|
||||
|
||||
~CtSpec() {
|
||||
delete args_;
|
||||
delete annotations_;
|
||||
}
|
||||
|
||||
AST::Node* Arg(int index) const {
|
||||
return args_->a[index];
|
||||
const std::string& Id() const {
|
||||
return id_;
|
||||
}
|
||||
|
||||
const std::string& id() const {
|
||||
return id_;
|
||||
int Index() const {
|
||||
return index_;
|
||||
}
|
||||
|
||||
AST::Node* Arg(int index) const {
|
||||
return args_->a[index];
|
||||
}
|
||||
|
||||
int NumArgs() const {
|
||||
@@ -209,6 +215,7 @@ class CtSpec {
|
||||
}
|
||||
|
||||
private:
|
||||
const int index_;
|
||||
const std::string id_;
|
||||
AST::Array* const args_;
|
||||
AST::Node* const annotations_;
|
||||
|
||||
Reference in New Issue
Block a user