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 6719176975 Squashed 'software/gecode/' changes from 313e87646d..70a1cfa856
70a1cfa856 Add reasoning about why a restart happens
5db96c6afc Add initial version of the 'complete' propagator
3410436fc5 Fix include problems on Linux and Windows
0218f3e7be Remove deprecated restart_count from the variables set on restart
7f4a528ced Fix makefile mistake for LastVal constraint
8a39aee00d Initialise LastVal stored as the minimal in the domain
86707c674e Update STATUS to match the new enum
44d672100f Add support for LastVal from FlatZinc
bd8af2e8f6 Subsume after propagation
2f07e027ab Add LastVal propagator
f05cf9daba Output number of copies
707e30c0f0 Update generated parser files
179ee693cc Add restart_number() builtin (to work around the problem that otherwise we can't implement round robin style search)
04a492da17 Fix restart numbers (didn't count incomplete neighbourhoods)
fbaa3529ec Initial implementation of on_restart
6dd39a73dd Update LICENSE
8f5ea30eba Update LICENSE
4236a2e5ec Use std::vector instead of std::array
c53655d685 Dynamically adjust test batch sizes
37248557b6 Require C++11
cc60ea7cde Minor, remove exraneous newline in changelog
74c5f54b9f Make Region pool thread local
6f04ac3514 Use atomic for propagator identifier
2e0c275b07 Add support for parallel testing
3ada422b76 Refactor, extracted run_test function
787c41b8c4 Refactor, move data and logic into Options
120fc512a7 Refactor, extract run_tests function
85dd87a4af Refactoring: Thread rand through calls in test
cece9da4ef Refactor Assignments operator() to has_more
564410e4ee Refactor Assignment operator++ to next()
e1c84af894 Separate test filtering from running
8558856298 Remove empty statement warnings
a9d8cb64fa Fix compilation errors for CPProfiler support
9ec81a69b2 Add RestartStop
REVERT: 313e87646d Fix include problems on Linux and Windows
REVERT: 358b8ca63b Remove deprecated restart_count from the variables set on restart
REVERT: 83508d5de2 Fix makefile mistake for LastVal constraint
REVERT: 530bbaf107 Initialise LastVal stored as the minimal in the domain
REVERT: 96ba0d3d7e Update STATUS to match the new enum
REVERT: 7d772297f9 Add support for LastVal from FlatZinc
REVERT: 98b0162d75 Subsume after propagation
REVERT: 5cd4552144 Add LastVal propagator
REVERT: 9b80e644b7 Output number of copies
REVERT: aaa5301366 Update generated parser files
REVERT: 6ff4efe6a4 Add restart_number() builtin (to work around the problem that otherwise we can't implement round robin style search)
REVERT: 8bcbec5d6e Fix restart numbers (didn't count incomplete neighbourhoods)
REVERT: 3f63e743b2 Initial implementation of on_restart
REVERT: b6ffa462d1 Update LICENSE
REVERT: ad0621c26c Update LICENSE
REVERT: 93caa97684 Use std::vector instead of std::array
REVERT: 32d6399b35 Dynamically adjust test batch sizes
REVERT: e7f00e9977 Require C++11
REVERT: a5ba8e4282 Minor, remove exraneous newline in changelog
REVERT: b24831354d Make Region pool thread local
REVERT: b1a109ac2e Use atomic for propagator identifier
REVERT: 3d77aaad71 Add support for parallel testing
REVERT: b1b9526049 Refactor, extracted run_test function
REVERT: 85b8a57f65 Refactor, move data and logic into Options
REVERT: d2c1961437 Refactor, extract run_tests function
REVERT: 0236327c75 Refactoring: Thread rand through calls in test
REVERT: ba81289b02 Refactor Assignments operator() to has_more
REVERT: 038a554bd8 Refactor Assignment operator++ to next()
REVERT: f34f125131 Separate test filtering from running
REVERT: cec6336ede Remove empty statement warnings
REVERT: d63e1fc042 Fix compilation errors for CPProfiler support

git-subtree-dir: software/gecode
git-subtree-split: 70a1cfa856d138b0845d2681c46ca16f8507aebf
2021-07-11 16:26:15 +10:00

2127 lines
70 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 <gecode/flatzinc/complete.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->complete_idx >= 0) {
pp->fg->restart_complete = BoolVarArray(*(pp->fg), 1);
pp->fg->restart_complete[0] = pp->fg->bv[pp->complete_idx];
pp->fg->complete_marker = std::make_shared<bool>(false);
Complete::post(*(pp->fg), pp->fg->restart_complete[0], pp->fg->complete_marker);
}
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=="complete_reif" && $4->a[0]->isBoolVar()) {
pp->complete_idx = $4->a[0]->getBoolVar();
} 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);
}