1600 lines
48 KiB
Plaintext
1600 lines
48 KiB
Plaintext
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
|
|
/*
|
|
* Main authors:
|
|
* Guido Tack <guido.tack@monash.edu>
|
|
*/
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
%define api.pure
|
|
|
|
%parse-param {void *parm}
|
|
|
|
%define api.header.include {<minizinc/parser.tab.hh>}
|
|
|
|
%lex-param {void* SCANNER}
|
|
%{
|
|
#define SCANNER static_cast<ParserState*>(parm)->yyscanner
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <map>
|
|
#include <cerrno>
|
|
|
|
namespace MiniZinc{ class ParserLocation; }
|
|
#define YYLTYPE MiniZinc::ParserLocation
|
|
#define YYLTYPE_IS_DECLARED 1
|
|
#define YYLTYPE_IS_TRIVIAL 0
|
|
|
|
#define YYMAXDEPTH 10000
|
|
#define YYINITDEPTH 10000
|
|
|
|
#include <minizinc/parser.hh>
|
|
#include <minizinc/file_utils.hh>
|
|
|
|
using namespace std;
|
|
using namespace MiniZinc;
|
|
|
|
#define YYLLOC_DEFAULT(Current, Rhs, N) \
|
|
(Current).filename(Rhs[1].filename()); \
|
|
(Current).first_line(Rhs[1].first_line()); \
|
|
(Current).first_column(Rhs[1].first_column()); \
|
|
(Current).last_line(Rhs[N].last_line()); \
|
|
(Current).last_column(Rhs[N].last_column());
|
|
|
|
int mzn_yyparse(void*);
|
|
int mzn_yylex(YYSTYPE*, YYLTYPE*, void* scanner);
|
|
int mzn_yylex_init (void** scanner);
|
|
int mzn_yylex_destroy (void* scanner);
|
|
int mzn_yyget_lineno (void* scanner);
|
|
void mzn_yyset_extra (void* user_defined ,void* yyscanner );
|
|
|
|
extern int yydebug;
|
|
|
|
void yyerror(YYLTYPE* location, void* parm, const string& str) {
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
Model* m = pp->model;
|
|
while (m->parent() != NULL) {
|
|
m = m->parent();
|
|
pp->err << "(included from file '" << m->filename() << "')" << endl;
|
|
}
|
|
pp->err << location->toString() << ":" << endl;
|
|
pp->printCurrentLine(location->first_column(),location->last_column());
|
|
pp->err << "Error: " << str << std::endl;
|
|
pp->hadError = true;
|
|
pp->syntaxErrors.push_back(SyntaxError(Location(*location), str));
|
|
}
|
|
|
|
bool notInDatafile(YYLTYPE* location, void* parm, const string& item) {
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
if (pp->isDatafile) {
|
|
yyerror(location,parm,item+" item not allowed in data file");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Expression* createDocComment(const ParserLocation& loc, const std::string& s) {
|
|
std::vector<Expression*> args(1);
|
|
args[0] = new StringLit(loc, s);
|
|
Call* c = new Call(Location(loc), constants().ann.doc_comment, args);
|
|
c->type(Type::ann());
|
|
return c;
|
|
}
|
|
|
|
Expression* createArrayAccess(const ParserLocation& loc, Expression* e, std::vector<std::vector<Expression*> >& idx) {
|
|
Expression* ret = e;
|
|
for (unsigned int i=0; i<idx.size(); i++) {
|
|
ret = new ArrayAccess(Location(loc), ret, idx[i]);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
%}
|
|
|
|
%union { long long int iValue; char* sValue; bool bValue; double dValue;
|
|
MiniZinc::Item* item;
|
|
MiniZinc::VarDecl* vardeclexpr;
|
|
std::vector<MiniZinc::VarDecl*>* vardeclexpr_v;
|
|
MiniZinc::TypeInst* tiexpr;
|
|
std::vector<MiniZinc::TypeInst*>* tiexpr_v;
|
|
MiniZinc::Expression* expression;
|
|
std::vector<MiniZinc::Expression*>* expression_v;
|
|
std::vector<std::vector<MiniZinc::Expression*> >* expression_vv;
|
|
std::vector<std::vector<std::vector<MiniZinc::Expression*> > >* expression_vvv;
|
|
MiniZinc::Generator* generator;
|
|
std::vector<MiniZinc::Generator>* generator_v;
|
|
std::vector<std::string>* string_v;
|
|
std::vector<std::pair<MiniZinc::Expression*,MiniZinc::Expression*> >* expression_p;
|
|
MiniZinc::Generators* generators;
|
|
}
|
|
|
|
%locations
|
|
%define parse.error verbose
|
|
|
|
%initial-action
|
|
{
|
|
GCLock lock;
|
|
@$.filename(ASTString(static_cast<ParserState*>(parm)->filename));
|
|
}
|
|
|
|
%token <iValue> MZN_INTEGER_LITERAL "integer literal" MZN_BOOL_LITERAL "bool literal"
|
|
%token <dValue> MZN_FLOAT_LITERAL "float literal"
|
|
%token <sValue> MZN_IDENTIFIER "identifier" MZN_QUOTED_IDENTIFIER "quoted identifier" MZN_STRING_LITERAL "string literal"
|
|
%token <sValue> MZN_STRING_QUOTE_START "interpolated string start" MZN_STRING_QUOTE_MID "interpolated string middle" MZN_STRING_QUOTE_END "interpolated string end"
|
|
%token <sValue> MZN_TI_IDENTIFIER "type-inst identifier" MZN_TI_ENUM_IDENTIFIER "type-inst enum identifier" MZN_DOC_COMMENT "documentation comment" MZN_DOC_FILE_COMMENT "file-level documentation comment"
|
|
|
|
%token MZN_VAR "var" MZN_PAR "par"
|
|
|
|
%token MZN_ABSENT "<>"
|
|
%token MZN_ANN "ann"
|
|
%token MZN_ANNOTATION "annotation"
|
|
%token MZN_ANY "any"
|
|
%token MZN_ARRAY "array"
|
|
%token MZN_BOOL "bool"
|
|
%token MZN_CASE "case"
|
|
%token MZN_CONSTRAINT "constraint"
|
|
%token MZN_DEFAULT "default"
|
|
%token MZN_ELSE "else"
|
|
%token MZN_ELSEIF "elseif"
|
|
%token MZN_ENDIF "endif"
|
|
%token MZN_ENUM "enum"
|
|
%token MZN_FLOAT "float"
|
|
%token MZN_FUNCTION "function"
|
|
%token MZN_IF "if"
|
|
%token MZN_INCLUDE "include"
|
|
%token MZN_INFINITY "infinity"
|
|
%token MZN_INT "int"
|
|
%token MZN_LET "let"
|
|
%token MZN_LIST "list"
|
|
%token <bValue> MZN_MAXIMIZE "maximize"
|
|
%token <bValue> MZN_MINIMIZE "minimize"
|
|
%token MZN_OF "of"
|
|
%token MZN_OPT "opt"
|
|
%token MZN_SATISFY "satisfy"
|
|
%token MZN_OUTPUT "output"
|
|
%token MZN_PREDICATE "predicate"
|
|
%token MZN_RECORD "record"
|
|
%token MZN_SET "set"
|
|
%token MZN_SOLVE "solve"
|
|
%token MZN_STRING "string"
|
|
%token MZN_TEST "test"
|
|
%token MZN_THEN "then"
|
|
%token MZN_TUPLE "tuple"
|
|
%token MZN_TYPE "type"
|
|
%token MZN_UNDERSCORE "_"
|
|
%token MZN_VARIANT_RECORD "variant_record"
|
|
%token MZN_WHERE "where"
|
|
|
|
%token MZN_LEFT_BRACKET "["
|
|
%token MZN_LEFT_2D_BRACKET "[|"
|
|
%token MZN_RIGHT_BRACKET "]"
|
|
%token MZN_RIGHT_2D_BRACKET "|]"
|
|
|
|
// Used to signal an error when parsing a MiniZinc file
|
|
// that contains identifiers starting with _
|
|
%token FLATZINC_IDENTIFIER
|
|
|
|
%token MZN_INVALID_INTEGER_LITERAL "invalid integer literal"
|
|
%token MZN_INVALID_FLOAT_LITERAL "invalid float literal"
|
|
%token MZN_UNTERMINATED_STRING "unterminated string"
|
|
%token MZN_END_OF_LINE_IN_STRING "end of line inside string literal"
|
|
%token MZN_INVALID_NULL "null character"
|
|
|
|
%token END 0 "end of file"
|
|
|
|
%token MZN_EQUIV "<->"
|
|
%token MZN_IMPL "->" MZN_RIMPL "<-"
|
|
%token MZN_OR "\\/" MZN_XOR "xor"
|
|
%token MZN_AND "/\\"
|
|
%token MZN_LE "<" MZN_GR ">" MZN_LQ "<=" MZN_GQ ">=" MZN_EQ "=" MZN_NQ "!=" MZN_WEAK_EQ "~="
|
|
%token MZN_IN "in" MZN_SUBSET "subset" MZN_SUPERSET "superset"
|
|
%token MZN_UNION "union" MZN_DIFF "diff" MZN_SYMDIFF "symdiff"
|
|
%token MZN_DOTDOT ".."
|
|
%token MZN_PLUS "+" MZN_MINUS "-" MZN_WEAK_PLUS "~+" MZN_WEAK_MINUS "~-"
|
|
%token MZN_MULT "*" MZN_DIV "/" MZN_IDIV "div" MZN_MOD "mod" MZN_INTERSECT "intersect" MZN_WEAK_MULT "~*"
|
|
%token MZN_POW "^"
|
|
%token MZN_NOT "not"
|
|
%token MZN_PLUSPLUS "++"
|
|
%token MZN_COLONCOLON "::"
|
|
|
|
%right PREC_ANNO
|
|
%left MZN_EQUIV
|
|
%left MZN_IMPL MZN_RIMPL
|
|
%left MZN_OR MZN_XOR
|
|
%left MZN_AND
|
|
%nonassoc MZN_LE MZN_GR MZN_LQ MZN_GQ MZN_EQ MZN_NQ MZN_WEAK_EQ
|
|
%nonassoc MZN_IN MZN_SUBSET MZN_SUPERSET
|
|
%left MZN_UNION MZN_DIFF MZN_SYMDIFF MZN_INTERSECT
|
|
%nonassoc MZN_DOTDOT
|
|
%left MZN_PLUS MZN_MINUS MZN_WEAK_PLUS MZN_WEAK_MINUS
|
|
%left MZN_MULT MZN_DIV MZN_IDIV MZN_MOD MZN_WEAK_MULT
|
|
%left MZN_POW
|
|
%nonassoc MZN_NOT
|
|
%left MZN_PLUSPLUS
|
|
%left MZN_QUOTED_IDENTIFIER
|
|
%left MZN_COLONCOLON
|
|
|
|
%token MZN_EQUIV_QUOTED "'<->'"
|
|
%token MZN_IMPL_QUOTED "'->'" MZN_RIMPL_QUOTED "'<-'"
|
|
%token MZN_OR_QUOTED "'\\/'" MZN_XOR_QUOTED "'xor'"
|
|
%token MZN_AND_QUOTED "'/\\'"
|
|
%token MZN_LE_QUOTED "'<'" MZN_GR_QUOTED "'>'" MZN_LQ_QUOTED "'<='" MZN_GQ_QUOTED "'>='" MZN_EQ_QUOTED "'='" MZN_NQ_QUOTED "'!='"
|
|
%token MZN_IN_QUOTED "'in'" MZN_SUBSET_QUOTED "'subset'" MZN_SUPERSET_QUOTED "'superset'"
|
|
%token MZN_UNION_QUOTED "'union'" MZN_DIFF_QUOTED "'diff'" MZN_SYMDIFF_QUOTED "'symdiff'"
|
|
%token MZN_DOTDOT_QUOTED "'..'"
|
|
%token MZN_PLUS_QUOTED "'+'" MZN_MINUS_QUOTED "'-'"
|
|
%token MZN_MULT_QUOTED "'*'" MZN_DIV_QUOTED "'/'" MZN_IDIV_QUOTED "'div'" MZN_MOD_QUOTED "'mod'" MZN_INTERSECT_QUOTED "'intersect'"
|
|
%token MZN_POW_QUOTED "'^'"
|
|
%token MZN_NOT_QUOTED "'not'"
|
|
%token MZN_COLONCOLON_QUOTED "'::'"
|
|
%token MZN_PLUSPLUS_QUOTED "'++'"
|
|
|
|
%type <item> item item_tail include_item vardecl_item assign_item constraint_item solve_item output_item predicate_item annotation_item function_item
|
|
|
|
%type <vardeclexpr> ti_expr_and_id ti_expr_and_id_or_anon let_vardecl_item
|
|
%type <vardeclexpr_v> params params_list params_list_head
|
|
%type <tiexpr> ti_expr base_ti_expr base_ti_expr_tail
|
|
%type <tiexpr_v> ti_expr_list ti_expr_list_head
|
|
|
|
%type <expression> expr expr_atom_head expr_atom_head_nonstring array_access_expr
|
|
%type <expression> set_expr string_expr string_quote_rest annotation_expr
|
|
%type <expression> simple_array_literal simple_array_literal_2d simple_array_comp if_then_else_expr call_expr quoted_op_call let_expr operation_item_tail set_literal set_comp
|
|
|
|
%type <expression_v> expr_list expr_list_head array_access_expr_list array_access_expr_list_head elseif_list let_vardecl_item_list enum_id_list string_lit_list
|
|
%type <expression_vv> simple_array_literal_2d_list array_access_tail
|
|
%type <expression_vvv> simple_array_literal_3d_list
|
|
|
|
%type <generators> comp_tail
|
|
%type <generator> generator generator_eq
|
|
%type <generator_v> generator_list generator_list_head
|
|
%type <string_v> id_list id_list_head
|
|
|
|
%type <expression_p> comp_or_expr comp_or_expr_head
|
|
|
|
%type <expression_v> annotations ne_annotations
|
|
|
|
%type <iValue> quoted_op
|
|
|
|
%type <sValue> id_or_quoted_op
|
|
|
|
%type <bValue> opt_opt
|
|
|
|
%%
|
|
|
|
/********************************/
|
|
/* main goal and item lists */
|
|
/********************************/
|
|
|
|
model : item_list
|
|
|
|
item_list :
|
|
/* empty */
|
|
| item_list_head semi_or_none
|
|
|
|
item_list_head:
|
|
item
|
|
{
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
if ($1) {
|
|
pp->model->addItem($1);
|
|
GC::unlock();
|
|
GC::lock();
|
|
}
|
|
}
|
|
| doc_file_comments item
|
|
{
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
if ($2) {
|
|
pp->model->addItem($2);
|
|
GC::unlock();
|
|
GC::lock();
|
|
}
|
|
}
|
|
| item_list_head ';' item
|
|
{
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
if ($3) {
|
|
pp->model->addItem($3);
|
|
GC::unlock();
|
|
GC::lock();
|
|
}
|
|
}
|
|
| item_list_head ';' doc_file_comments item
|
|
{
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
if ($4) {
|
|
pp->model->addItem($4);
|
|
GC::unlock();
|
|
GC::lock();
|
|
}
|
|
}
|
|
| item error_item_start
|
|
{ yyerror(&@2, parm, "unexpected item, expecting ';' or end of file"); YYERROR; }
|
|
| error ';' item
|
|
|
|
doc_file_comments:
|
|
MZN_DOC_FILE_COMMENT
|
|
{
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
if (pp->parseDocComments && $1) {
|
|
pp->model->addDocComment($1);
|
|
}
|
|
free($1);
|
|
}
|
|
| doc_file_comments MZN_DOC_FILE_COMMENT
|
|
{
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
if (pp->parseDocComments && $2) {
|
|
pp->model->addDocComment($2);
|
|
}
|
|
free($2);
|
|
}
|
|
|
|
semi_or_none : | ';'
|
|
|
|
item : MZN_DOC_COMMENT item_tail
|
|
{ $$ = $2;
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
if (FunctionI* fi = Item::dyn_cast<FunctionI>($$)) {
|
|
if (pp->parseDocComments) {
|
|
fi->ann().add(createDocComment(@1,$1));
|
|
}
|
|
} else if (VarDeclI* vdi = Item::dyn_cast<VarDeclI>($$)) {
|
|
if (pp->parseDocComments) {
|
|
vdi->e()->addAnnotation(createDocComment(@1,$1));
|
|
}
|
|
} else {
|
|
yyerror(&@2, parm, "documentation comments are only supported for function, predicate and variable declarations");
|
|
}
|
|
free($1);
|
|
}
|
|
| item_tail
|
|
{ $$ = $1; }
|
|
|
|
item_tail :
|
|
include_item
|
|
{ $$=notInDatafile(&@$,parm,"include") ? $1 : NULL; }
|
|
| vardecl_item
|
|
{ $$=notInDatafile(&@$,parm,"variable declaration") ? $1 : NULL; }
|
|
| assign_item
|
|
| constraint_item
|
|
{ $$=notInDatafile(&@$,parm,"constraint") ? $1 : NULL; }
|
|
| solve_item
|
|
{ $$=notInDatafile(&@$,parm,"solve") ? $1 : NULL; }
|
|
| output_item
|
|
{ $$=notInDatafile(&@$,parm,"output") ? $1 : NULL; }
|
|
| predicate_item
|
|
{ $$=notInDatafile(&@$,parm,"predicate") ? $1 : NULL; }
|
|
| function_item
|
|
{ $$=notInDatafile(&@$,parm,"predicate") ? $1 : NULL; }
|
|
| annotation_item
|
|
{ $$=notInDatafile(&@$,parm,"annotation") ? $1 : NULL; }
|
|
|
|
error_item_start : MZN_INCLUDE | MZN_ENUM | MZN_OUTPUT
|
|
| MZN_CONSTRAINT | MZN_SOLVE | MZN_PREDICATE | MZN_FUNCTION | MZN_TEST
|
|
| MZN_ANNOTATION
|
|
|
|
include_item :
|
|
MZN_INCLUDE MZN_STRING_LITERAL
|
|
{ ParserState* pp = static_cast<ParserState*>(parm);
|
|
map<string,Model*>::iterator ret = pp->seenModels.find($2);
|
|
IncludeI* ii = new IncludeI(@$,ASTString($2));
|
|
$$ = ii;
|
|
if (ret == pp->seenModels.end()) {
|
|
Model* im = new Model;
|
|
im->setParent(pp->model);
|
|
im->setFilename($2);
|
|
string fpath = FileUtils::dir_name(pp->filename);
|
|
string fbase = FileUtils::base_name(pp->filename);
|
|
if (fpath=="")
|
|
fpath="./";
|
|
ParseWorkItem pm(im, ii, fpath, $2);
|
|
pp->files.push_back(pm);
|
|
ii->m(im);
|
|
pp->seenModels.insert(pair<string,Model*>($2,im));
|
|
} else {
|
|
ii->m(ret->second, false);
|
|
}
|
|
free($2);
|
|
}
|
|
|
|
vardecl_item :
|
|
ti_expr_and_id annotations
|
|
{ if ($1 && $2) $1->addAnnotations(*$2);
|
|
if ($1)
|
|
$$ = new VarDeclI(@$,$1);
|
|
delete $2;
|
|
}
|
|
| ti_expr_and_id annotations MZN_EQ expr
|
|
{ if ($1) $1->e($4);
|
|
if ($1 && $2) $1->addAnnotations(*$2);
|
|
if ($1)
|
|
$$ = new VarDeclI(@$,$1);
|
|
delete $2;
|
|
}
|
|
| MZN_ENUM MZN_IDENTIFIER
|
|
{
|
|
TypeInst* ti = new TypeInst(@$,Type::parsetint());
|
|
ti->setIsEnum(true);
|
|
VarDecl* vd = new VarDecl(@$,ti,$2);
|
|
free($2);
|
|
$$ = new VarDeclI(@$,vd);
|
|
}
|
|
| MZN_ENUM MZN_IDENTIFIER MZN_EQ '{' enum_id_list '}'
|
|
{
|
|
TypeInst* ti = new TypeInst(@$,Type::parsetint());
|
|
ti->setIsEnum(true);
|
|
SetLit* sl = new SetLit(@$, *$5);
|
|
VarDecl* vd = new VarDecl(@$,ti,$2,sl);
|
|
free($2);
|
|
delete $5;
|
|
$$ = new VarDeclI(@$,vd);
|
|
}
|
|
| MZN_ENUM MZN_IDENTIFIER MZN_EQ MZN_LEFT_BRACKET string_lit_list MZN_RIGHT_BRACKET
|
|
{
|
|
TypeInst* ti = new TypeInst(@$,Type::parsetint());
|
|
ti->setIsEnum(true);
|
|
vector<Expression*> args;
|
|
args.push_back(new ArrayLit(@$,*$5));
|
|
Call* sl = new Call(@$, constants().ids.anonEnumFromStrings, args);
|
|
VarDecl* vd = new VarDecl(@$,ti,$2,sl);
|
|
free($2);
|
|
delete $5;
|
|
$$ = new VarDeclI(@$,vd);
|
|
}
|
|
| MZN_ENUM MZN_IDENTIFIER MZN_EQ MZN_IDENTIFIER '(' expr ')'
|
|
{
|
|
TypeInst* ti = new TypeInst(@$,Type::parsetint());
|
|
ti->setIsEnum(true);
|
|
vector<Expression*> args;
|
|
args.push_back($6);
|
|
Call* sl = new Call(@$, ASTString($4), args);
|
|
VarDecl* vd = new VarDecl(@$,ti,$2,sl);
|
|
free($2);
|
|
free($4);
|
|
$$ = new VarDeclI(@$,vd);
|
|
}
|
|
|
|
string_lit_list :
|
|
// empty
|
|
{ $$ = new std::vector<Expression*>(); }
|
|
| MZN_STRING_LITERAL
|
|
{ $$ = new std::vector<Expression*>();
|
|
$$->push_back(new StringLit(@$, $1)); free($1);
|
|
}
|
|
| string_lit_list ',' MZN_STRING_LITERAL
|
|
{ $$ = $1;
|
|
if ($$) $$->push_back(new StringLit(@$, $3));
|
|
free($3);
|
|
}
|
|
|
|
enum_id_list :
|
|
// empty
|
|
{ $$ = new std::vector<Expression*>(); }
|
|
| MZN_IDENTIFIER
|
|
{ $$ = new std::vector<Expression*>();
|
|
$$->push_back(new Id(@$,$1,NULL)); free($1);
|
|
}
|
|
| enum_id_list ',' MZN_IDENTIFIER
|
|
{ $$ = $1; if ($$) $$->push_back(new Id(@$,$3,NULL)); free($3); }
|
|
|
|
assign_item :
|
|
MZN_IDENTIFIER MZN_EQ expr
|
|
{ $$ = new AssignI(@$,$1,$3);
|
|
free($1);
|
|
}
|
|
|
|
constraint_item :
|
|
MZN_CONSTRAINT expr
|
|
{ $$ = new ConstraintI(@$,$2);}
|
|
| MZN_CONSTRAINT MZN_COLONCOLON string_expr expr
|
|
{ $$ = new ConstraintI(@$,$4);
|
|
if ($4 && $3)
|
|
$$->cast<ConstraintI>()->e()->ann().add(new Call(@2, ASTString("mzn_constraint_name"), {$3}));
|
|
}
|
|
|
|
solve_item :
|
|
MZN_SOLVE annotations MZN_SATISFY
|
|
{ $$ = SolveI::sat(@$);
|
|
if ($$ && $2) $$->cast<SolveI>()->ann().add(*$2);
|
|
delete $2;
|
|
}
|
|
| MZN_SOLVE annotations MZN_MINIMIZE expr
|
|
{ $$ = SolveI::min(@$,$4);
|
|
if ($$ && $2) $$->cast<SolveI>()->ann().add(*$2);
|
|
delete $2;
|
|
}
|
|
| MZN_SOLVE annotations MZN_MAXIMIZE expr
|
|
{ $$ = SolveI::max(@$,$4);
|
|
if ($$ && $2) $$->cast<SolveI>()->ann().add(*$2);
|
|
delete $2;
|
|
}
|
|
|
|
output_item :
|
|
MZN_OUTPUT expr
|
|
{ $$ = new OutputI(@$,$2);}
|
|
|
|
predicate_item :
|
|
MZN_PREDICATE MZN_IDENTIFIER params annotations operation_item_tail
|
|
{ if ($3) $$ = new FunctionI(@$,$2,new TypeInst(@$,
|
|
Type::varbool()),*$3,$5);
|
|
if ($$ && $4) $$->cast<FunctionI>()->ann().add(*$4);
|
|
free($2);
|
|
delete $3;
|
|
delete $4;
|
|
}
|
|
| MZN_TEST MZN_IDENTIFIER params annotations operation_item_tail
|
|
{ if ($3) $$ = new FunctionI(@$,$2,new TypeInst(@$,
|
|
Type::parbool()),*$3,$5);
|
|
if ($$ && $4) $$->cast<FunctionI>()->ann().add(*$4);
|
|
free($2);
|
|
delete $3;
|
|
delete $4;
|
|
}
|
|
|
|
function_item :
|
|
MZN_FUNCTION ti_expr ':' id_or_quoted_op params annotations operation_item_tail
|
|
{ if ($5) $$ = new FunctionI(@$,$4,$2,*$5,$7);
|
|
if ($$ && $6) $$->cast<FunctionI>()->ann().add(*$6);
|
|
free($4);
|
|
delete $5;
|
|
delete $6;
|
|
}
|
|
| ti_expr ':' MZN_IDENTIFIER '(' params_list ')' annotations operation_item_tail
|
|
{ if ($5) $$ = new FunctionI(@$,$3,$1,*$5,$8);
|
|
if ($$ && $7) $$->cast<FunctionI>()->ann().add(*$7);
|
|
free($3);
|
|
delete $5;
|
|
delete $7;
|
|
}
|
|
|
|
annotation_item :
|
|
MZN_ANNOTATION MZN_IDENTIFIER params
|
|
{
|
|
TypeInst* ti=new TypeInst(@1,Type::ann());
|
|
if ($3==NULL || $3->empty()) {
|
|
VarDecl* vd = new VarDecl(@$,ti,$2);
|
|
$$ = new VarDeclI(@$,vd);
|
|
} else {
|
|
$$ = new FunctionI(@$,$2,ti,*$3,NULL);
|
|
}
|
|
free($2);
|
|
delete $3;
|
|
}
|
|
| MZN_ANNOTATION MZN_IDENTIFIER params MZN_EQ expr
|
|
{ TypeInst* ti=new TypeInst(@1,Type::ann());
|
|
if ($3) $$ = new FunctionI(@$,$2,ti,*$3,$5);
|
|
delete $3;
|
|
}
|
|
|
|
operation_item_tail :
|
|
/*empty*/
|
|
{ $$=NULL; }
|
|
| MZN_EQ expr
|
|
{ $$=$2; }
|
|
|
|
params :
|
|
/* empty */
|
|
{ $$=new vector<VarDecl*>(); }
|
|
| '(' params_list ')'
|
|
{ $$=$2; }
|
|
| '(' error ')'
|
|
{ $$=new vector<VarDecl*>(); }
|
|
|
|
params_list :
|
|
/* empty */
|
|
{ $$=new vector<VarDecl*>(); }
|
|
| params_list_head comma_or_none
|
|
{ $$=$1; }
|
|
|
|
params_list_head :
|
|
ti_expr_and_id_or_anon
|
|
{ $$=new vector<VarDecl*>();
|
|
if ($1) $1->toplevel(false);
|
|
if ($1) $$->push_back($1); }
|
|
| params_list_head ',' ti_expr_and_id_or_anon
|
|
{ $$=$1;
|
|
if ($3) $3->toplevel(false);
|
|
if ($1 && $3) $1->push_back($3); }
|
|
|
|
comma_or_none : | ','
|
|
|
|
ti_expr_and_id_or_anon :
|
|
ti_expr_and_id
|
|
{ $$=$1; }
|
|
| ti_expr
|
|
{ if ($1) $$=new VarDecl(@$, $1, ""); }
|
|
|
|
ti_expr_and_id :
|
|
ti_expr ':' MZN_IDENTIFIER
|
|
{ if ($1 && $3) $$ = new VarDecl(@$, $1, $3);
|
|
free($3);
|
|
}
|
|
|
|
ti_expr_list : ti_expr_list_head comma_or_none
|
|
{ $$=$1; }
|
|
|
|
ti_expr_list_head :
|
|
ti_expr
|
|
{ $$=new vector<TypeInst*>(); $$->push_back($1); }
|
|
| ti_expr_list_head ',' ti_expr
|
|
{ $$=$1; if ($1 && $3) $1->push_back($3); }
|
|
|
|
ti_expr :
|
|
base_ti_expr
|
|
| MZN_ARRAY MZN_LEFT_BRACKET ti_expr_list MZN_RIGHT_BRACKET MZN_OF base_ti_expr
|
|
{
|
|
$$ = $6;
|
|
if ($$ && $3) $$->setRanges(*$3);
|
|
delete $3;
|
|
}
|
|
| MZN_LIST MZN_OF base_ti_expr
|
|
{
|
|
$$ = $3;
|
|
std::vector<TypeInst*> ti(1);
|
|
ti[0] = new TypeInst(@$,Type::parint());
|
|
if ($$) $$->setRanges(ti);
|
|
}
|
|
|
|
base_ti_expr :
|
|
base_ti_expr_tail
|
|
{ $$ = $1;
|
|
}
|
|
| MZN_OPT base_ti_expr_tail
|
|
{ $$ = $2;
|
|
if ($$) {
|
|
Type tt = $$->type();
|
|
tt.ot(Type::OT_OPTIONAL);
|
|
$$->type(tt);
|
|
}
|
|
}
|
|
| MZN_PAR opt_opt base_ti_expr_tail
|
|
{ $$ = $3;
|
|
if ($$ && $2) {
|
|
Type tt = $$->type();
|
|
tt.ot(Type::OT_OPTIONAL);
|
|
$$->type(tt);
|
|
}
|
|
}
|
|
| MZN_VAR opt_opt base_ti_expr_tail
|
|
{ $$ = $3;
|
|
if ($$) {
|
|
Type tt = $$->type();
|
|
tt.ti(Type::TI_VAR);
|
|
if ($2) tt.ot(Type::OT_OPTIONAL);
|
|
$$->type(tt);
|
|
}
|
|
}
|
|
| opt_opt MZN_SET MZN_OF base_ti_expr_tail
|
|
{ $$ = $4;
|
|
if ($$) {
|
|
Type tt = $$->type();
|
|
tt.st(Type::ST_SET);
|
|
if ($1) tt.ot(Type::OT_OPTIONAL);
|
|
$$->type(tt);
|
|
}
|
|
}
|
|
| MZN_PAR opt_opt MZN_SET MZN_OF base_ti_expr_tail
|
|
{ $$ = $5;
|
|
if ($$) {
|
|
Type tt = $$->type();
|
|
tt.st(Type::ST_SET);
|
|
if ($2) tt.ot(Type::OT_OPTIONAL);
|
|
$$->type(tt);
|
|
}
|
|
}
|
|
| MZN_VAR opt_opt MZN_SET MZN_OF base_ti_expr_tail
|
|
{ $$ = $5;
|
|
if ($$) {
|
|
Type tt = $$->type();
|
|
tt.ti(Type::TI_VAR);
|
|
tt.st(Type::ST_SET);
|
|
if ($2) tt.ot(Type::OT_OPTIONAL);
|
|
$$->type(tt);
|
|
}
|
|
}
|
|
|
|
opt_opt:
|
|
/* nothing */
|
|
{ $$ = false; }
|
|
| MZN_OPT
|
|
{ $$ = true; }
|
|
|
|
base_ti_expr_tail :
|
|
MZN_INT
|
|
{ $$ = new TypeInst(@$,Type::parint()); }
|
|
| MZN_BOOL
|
|
{ $$ = new TypeInst(@$,Type::parbool()); }
|
|
| MZN_FLOAT
|
|
{ $$ = new TypeInst(@$,Type::parfloat()); }
|
|
| MZN_STRING
|
|
{ $$ = new TypeInst(@$,Type::parstring()); }
|
|
| MZN_ANN
|
|
{ $$ = new TypeInst(@$,Type::ann()); }
|
|
| set_expr
|
|
{ if ($1) $$ = new TypeInst(@$,Type(),$1); }
|
|
| MZN_TI_IDENTIFIER
|
|
{ $$ = new TypeInst(@$,Type::top(),
|
|
new TIId(@$, $1));
|
|
free($1);
|
|
}
|
|
| MZN_TI_ENUM_IDENTIFIER
|
|
{ $$ = new TypeInst(@$,Type::parint(),
|
|
new TIId(@$, $1));
|
|
free($1);
|
|
}
|
|
|
|
array_access_expr_list : array_access_expr_list_head comma_or_none
|
|
|
|
array_access_expr_list_head :
|
|
array_access_expr
|
|
{ $$=new std::vector<MiniZinc::Expression*>; $$->push_back($1); }
|
|
| array_access_expr_list_head ',' array_access_expr
|
|
{ $$=$1; if ($$ && $3) $$->push_back($3); }
|
|
|
|
array_access_expr :
|
|
expr
|
|
{ $$ = $1; }
|
|
| MZN_DOTDOT
|
|
{ $$=new SetLit(@$, IntSetVal::a(-IntVal::infinity(),IntVal::infinity())); }
|
|
| MZN_DOTDOT expr
|
|
{ if ($2==NULL) {
|
|
$$ = NULL;
|
|
} else if ($2->isa<IntLit>()) {
|
|
$$=new SetLit(@$, IntSetVal::a(-IntVal::infinity(),$2->cast<IntLit>()->v()));
|
|
} else {
|
|
$$=new BinOp(@$, IntLit::a(-IntVal::infinity()), BOT_DOTDOT, $2);
|
|
}
|
|
}
|
|
| expr MZN_DOTDOT
|
|
{ if ($1==NULL) {
|
|
$$ = NULL;
|
|
} else if ($1->isa<IntLit>()) {
|
|
$$=new SetLit(@$, IntSetVal::a($1->cast<IntLit>()->v(),IntVal::infinity()));
|
|
} else {
|
|
$$=new BinOp(@$, $1, BOT_DOTDOT, IntLit::a(IntVal::infinity()));
|
|
}
|
|
}
|
|
|
|
|
|
expr_list : expr_list_head comma_or_none
|
|
|
|
expr_list_head :
|
|
expr
|
|
{ $$=new std::vector<MiniZinc::Expression*>; $$->push_back($1); }
|
|
| expr_list_head ',' expr
|
|
{ $$=$1; if ($$ && $3) $$->push_back($3); }
|
|
|
|
///
|
|
|
|
set_expr :
|
|
expr_atom_head
|
|
| set_expr MZN_COLONCOLON annotation_expr
|
|
{ if ($1 && $3) $1->addAnnotation($3); $$=$1; }
|
|
| set_expr MZN_UNION set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_UNION, $3); }
|
|
| set_expr MZN_DIFF set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_DIFF, $3); }
|
|
| set_expr MZN_SYMDIFF set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_SYMDIFF, $3); }
|
|
| set_expr MZN_DOTDOT set_expr
|
|
{ if ($1==NULL || $3==NULL) {
|
|
$$ = NULL;
|
|
} else if ($1->isa<IntLit>() && $3->isa<IntLit>()) {
|
|
$$=new SetLit(@$, IntSetVal::a($1->cast<IntLit>()->v(),$3->cast<IntLit>()->v()));
|
|
} else {
|
|
$$=new BinOp(@$, $1, BOT_DOTDOT, $3);
|
|
}
|
|
}
|
|
| MZN_DOTDOT_QUOTED '(' expr ',' expr ')'
|
|
{ if ($3==NULL || $5==NULL) {
|
|
$$ = NULL;
|
|
} else if ($3->isa<IntLit>() && $5->isa<IntLit>()) {
|
|
$$=new SetLit(@$, IntSetVal::a($3->cast<IntLit>()->v(),$5->cast<IntLit>()->v()));
|
|
} else {
|
|
$$=new BinOp(@$, $3, BOT_DOTDOT, $5);
|
|
}
|
|
}
|
|
| set_expr MZN_INTERSECT set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_INTERSECT, $3); }
|
|
| set_expr MZN_PLUSPLUS set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_PLUSPLUS, $3); }
|
|
| set_expr MZN_PLUS set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_PLUS, $3); }
|
|
| set_expr MZN_MINUS set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_MINUS, $3); }
|
|
| set_expr MZN_MULT set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_MULT, $3); }
|
|
| set_expr MZN_DIV set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_DIV, $3); }
|
|
| set_expr MZN_IDIV set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_IDIV, $3); }
|
|
| set_expr MZN_MOD set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_MOD, $3); }
|
|
| set_expr MZN_POW set_expr
|
|
{ $$=new BinOp(@$, $1, BOT_POW, $3); }
|
|
| set_expr MZN_WEAK_PLUS set_expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, ASTString("~+"), args);
|
|
}
|
|
| set_expr MZN_WEAK_MINUS set_expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, ASTString("~-"), args);
|
|
}
|
|
| set_expr MZN_WEAK_MULT set_expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, ASTString("~*"), args);
|
|
}
|
|
| set_expr MZN_WEAK_EQ set_expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, ASTString("~="), args);
|
|
}
|
|
| set_expr MZN_QUOTED_IDENTIFIER set_expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, $2, args);
|
|
free($2);
|
|
}
|
|
| MZN_PLUS set_expr %prec MZN_NOT
|
|
{ $$=new UnOp(@$, UOT_PLUS, $2); }
|
|
| MZN_MINUS set_expr %prec MZN_NOT
|
|
{ if ($2 && $2->isa<IntLit>()) {
|
|
$$ = IntLit::a(-$2->cast<IntLit>()->v());
|
|
} else if ($2 && $2->isa<FloatLit>()) {
|
|
$$ = FloatLit::a(-$2->cast<FloatLit>()->v());
|
|
} else {
|
|
$$=new UnOp(@$, UOT_MINUS, $2);
|
|
}
|
|
}
|
|
|
|
///
|
|
|
|
expr :
|
|
expr_atom_head
|
|
| expr MZN_COLONCOLON annotation_expr
|
|
{ if ($1 && $3) $1->addAnnotation($3); $$=$1; }
|
|
| expr MZN_EQUIV expr
|
|
{ $$=new BinOp(@$, $1, BOT_EQUIV, $3); }
|
|
| expr MZN_IMPL expr
|
|
{ $$=new BinOp(@$, $1, BOT_IMPL, $3); }
|
|
| expr MZN_RIMPL expr
|
|
{ $$=new BinOp(@$, $1, BOT_RIMPL, $3); }
|
|
| expr MZN_OR expr
|
|
{ $$=new BinOp(@$, $1, BOT_OR, $3); }
|
|
| expr MZN_XOR expr
|
|
{ $$=new BinOp(@$, $1, BOT_XOR, $3); }
|
|
| expr MZN_AND expr
|
|
{ $$=new BinOp(@$, $1, BOT_AND, $3); }
|
|
| expr MZN_LE expr
|
|
{ $$=new BinOp(@$, $1, BOT_LE, $3); }
|
|
| expr MZN_GR expr
|
|
{ $$=new BinOp(@$, $1, BOT_GR, $3); }
|
|
| expr MZN_LQ expr
|
|
{ $$=new BinOp(@$, $1, BOT_LQ, $3); }
|
|
| expr MZN_GQ expr
|
|
{ $$=new BinOp(@$, $1, BOT_GQ, $3); }
|
|
| expr MZN_EQ expr
|
|
{ $$=new BinOp(@$, $1, BOT_EQ, $3); }
|
|
| expr MZN_NQ expr
|
|
{ $$=new BinOp(@$, $1, BOT_NQ, $3); }
|
|
| expr MZN_IN expr
|
|
{ $$=new BinOp(@$, $1, BOT_IN, $3); }
|
|
| expr MZN_SUBSET expr
|
|
{ $$=new BinOp(@$, $1, BOT_SUBSET, $3); }
|
|
| expr MZN_SUPERSET expr
|
|
{ $$=new BinOp(@$, $1, BOT_SUPERSET, $3); }
|
|
| expr MZN_UNION expr
|
|
{ $$=new BinOp(@$, $1, BOT_UNION, $3); }
|
|
| expr MZN_DIFF expr
|
|
{ $$=new BinOp(@$, $1, BOT_DIFF, $3); }
|
|
| expr MZN_SYMDIFF expr
|
|
{ $$=new BinOp(@$, $1, BOT_SYMDIFF, $3); }
|
|
| expr MZN_DOTDOT expr
|
|
{ if ($1==NULL || $3==NULL) {
|
|
$$ = NULL;
|
|
} else if ($1->isa<IntLit>() && $3->isa<IntLit>()) {
|
|
$$=new SetLit(@$, IntSetVal::a($1->cast<IntLit>()->v(),$3->cast<IntLit>()->v()));
|
|
} else {
|
|
$$=new BinOp(@$, $1, BOT_DOTDOT, $3);
|
|
}
|
|
}
|
|
| MZN_DOTDOT_QUOTED '(' expr ',' expr ')'
|
|
{ if ($3==NULL || $5==NULL) {
|
|
$$ = NULL;
|
|
} else if ($3->isa<IntLit>() && $5->isa<IntLit>()) {
|
|
$$=new SetLit(@$, IntSetVal::a($3->cast<IntLit>()->v(),$5->cast<IntLit>()->v()));
|
|
} else {
|
|
$$=new BinOp(@$, $3, BOT_DOTDOT, $5);
|
|
}
|
|
}
|
|
| expr MZN_INTERSECT expr
|
|
{ $$=new BinOp(@$, $1, BOT_INTERSECT, $3); }
|
|
| expr MZN_PLUSPLUS expr
|
|
{ $$=new BinOp(@$, $1, BOT_PLUSPLUS, $3); }
|
|
| expr MZN_PLUS expr
|
|
{ $$=new BinOp(@$, $1, BOT_PLUS, $3); }
|
|
| expr MZN_MINUS expr
|
|
{ $$=new BinOp(@$, $1, BOT_MINUS, $3); }
|
|
| expr MZN_MULT expr
|
|
{ $$=new BinOp(@$, $1, BOT_MULT, $3); }
|
|
| expr MZN_DIV expr
|
|
{ $$=new BinOp(@$, $1, BOT_DIV, $3); }
|
|
| expr MZN_IDIV expr
|
|
{ $$=new BinOp(@$, $1, BOT_IDIV, $3); }
|
|
| expr MZN_MOD expr
|
|
{ $$=new BinOp(@$, $1, BOT_MOD, $3); }
|
|
| expr MZN_POW expr
|
|
{ $$=new BinOp(@$, $1, BOT_POW, $3); }
|
|
| expr MZN_WEAK_PLUS expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, ASTString("~+"), args);
|
|
}
|
|
| expr MZN_WEAK_MINUS expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, ASTString("~-"), args);
|
|
}
|
|
| expr MZN_WEAK_MULT expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, ASTString("~*"), args);
|
|
}
|
|
| expr MZN_WEAK_EQ expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, ASTString("~="), args);
|
|
}
|
|
| expr MZN_QUOTED_IDENTIFIER expr
|
|
{ vector<Expression*> args;
|
|
args.push_back($1); args.push_back($3);
|
|
$$=new Call(@$, $2, args);
|
|
free($2);
|
|
}
|
|
| MZN_NOT expr %prec MZN_NOT
|
|
{ $$=new UnOp(@$, UOT_NOT, $2); }
|
|
| MZN_PLUS expr %prec MZN_NOT
|
|
{ if (($2 && $2->isa<IntLit>()) || ($2 && $2->isa<FloatLit>())) {
|
|
$$ = $2;
|
|
} else {
|
|
$$=new UnOp(@$, UOT_PLUS, $2);
|
|
}
|
|
}
|
|
| MZN_MINUS expr %prec MZN_NOT
|
|
{ if ($2 && $2->isa<IntLit>()) {
|
|
$$ = IntLit::a(-$2->cast<IntLit>()->v());
|
|
} else if ($2 && $2->isa<FloatLit>()) {
|
|
$$ = FloatLit::a(-$2->cast<FloatLit>()->v());
|
|
} else {
|
|
$$=new UnOp(@$, UOT_MINUS, $2);
|
|
}
|
|
}
|
|
|
|
|
|
expr_atom_head :
|
|
expr_atom_head_nonstring
|
|
{ $$=$1; }
|
|
| string_expr
|
|
{ $$=$1; }
|
|
|
|
expr_atom_head_nonstring :
|
|
'(' expr ')'
|
|
{ $$=$2; }
|
|
| '(' expr ')' array_access_tail
|
|
{ if ($4) $$=createArrayAccess(@$, $2, *$4); delete $4; }
|
|
| MZN_IDENTIFIER
|
|
{ $$=new Id(@$, $1, NULL); free($1); }
|
|
| MZN_IDENTIFIER array_access_tail
|
|
{ if ($2) $$=createArrayAccess(@$, new Id(@1,$1,NULL), *$2);
|
|
free($1); delete $2; }
|
|
| MZN_UNDERSCORE
|
|
{ $$=new AnonVar(@$); }
|
|
| MZN_UNDERSCORE array_access_tail
|
|
{ if ($2) $$=createArrayAccess(@$, new AnonVar(@$), *$2);
|
|
delete $2; }
|
|
| MZN_BOOL_LITERAL
|
|
{ $$=constants().boollit(($1!=0)); }
|
|
| MZN_INTEGER_LITERAL
|
|
{ $$=IntLit::a($1); }
|
|
| MZN_INFINITY
|
|
{ $$=IntLit::a(IntVal::infinity()); }
|
|
| MZN_FLOAT_LITERAL
|
|
{ $$=FloatLit::a($1); }
|
|
| MZN_ABSENT
|
|
{ $$=constants().absent; }
|
|
| set_literal
|
|
| set_literal array_access_tail
|
|
{ if ($2) $$=createArrayAccess(@$, $1, *$2);
|
|
delete $2; }
|
|
| set_comp
|
|
| set_comp array_access_tail
|
|
{ if ($2) $$=createArrayAccess(@$, $1, *$2);
|
|
delete $2; }
|
|
| simple_array_literal
|
|
| simple_array_literal array_access_tail
|
|
{ if ($2) $$=createArrayAccess(@$, $1, *$2);
|
|
delete $2; }
|
|
| simple_array_literal_2d
|
|
| simple_array_literal_2d array_access_tail
|
|
{ if ($2) $$=createArrayAccess(@$, $1, *$2);
|
|
delete $2; }
|
|
| simple_array_comp
|
|
| simple_array_comp array_access_tail
|
|
{ if ($2) $$=createArrayAccess(@$, $1, *$2);
|
|
delete $2; }
|
|
| if_then_else_expr
|
|
| if_then_else_expr array_access_tail
|
|
{ if ($2) $$=createArrayAccess(@$, $1, *$2);
|
|
delete $2; }
|
|
| let_expr
|
|
| call_expr
|
|
| call_expr array_access_tail
|
|
{ if ($2) $$=createArrayAccess(@$, $1, *$2);
|
|
delete $2; }
|
|
|
|
string_expr:
|
|
MZN_STRING_LITERAL
|
|
{ $$=new StringLit(@$, $1); free($1); }
|
|
| MZN_STRING_QUOTE_START string_quote_rest
|
|
{ $$=new BinOp(@$, new StringLit(@$, $1), BOT_PLUSPLUS, $2);
|
|
free($1);
|
|
}
|
|
|
|
string_quote_rest:
|
|
expr_list_head MZN_STRING_QUOTE_END
|
|
{ if ($1) $$=new BinOp(@$, new Call(@$, ASTString("format"), *$1), BOT_PLUSPLUS, new StringLit(@$,$2));
|
|
free($2);
|
|
delete $1;
|
|
}
|
|
| expr_list_head MZN_STRING_QUOTE_MID string_quote_rest
|
|
{ if ($1) $$=new BinOp(@$, new Call(@$, ASTString("format"), *$1), BOT_PLUSPLUS,
|
|
new BinOp(@$, new StringLit(@$,$2), BOT_PLUSPLUS, $3));
|
|
free($2);
|
|
delete $1;
|
|
}
|
|
|
|
array_access_tail :
|
|
MZN_LEFT_BRACKET array_access_expr_list MZN_RIGHT_BRACKET
|
|
{ $$=new std::vector<std::vector<Expression*> >();
|
|
if ($2) {
|
|
$$->push_back(*$2);
|
|
delete $2;
|
|
}
|
|
}
|
|
| array_access_tail MZN_LEFT_BRACKET array_access_expr_list MZN_RIGHT_BRACKET
|
|
{ $$=$1;
|
|
if ($$ && $3) {
|
|
$$->push_back(*$3);
|
|
delete $3;
|
|
}
|
|
}
|
|
|
|
set_literal :
|
|
'{' '}'
|
|
{ $$ = new SetLit(@$, std::vector<Expression*>()); }
|
|
| '{' expr_list '}'
|
|
{ if ($2) $$ = new SetLit(@$, *$2);
|
|
delete $2; }
|
|
|
|
set_comp :
|
|
'{' expr '|' comp_tail '}'
|
|
{ if ($4) $$ = new Comprehension(@$, $2, *$4, true);
|
|
delete $4;
|
|
}
|
|
|
|
comp_tail :
|
|
generator_list
|
|
{ if ($1) $$=new Generators; $$->_g = *$1; delete $1; }
|
|
|
|
generator_list : generator_list_head comma_or_none
|
|
|
|
generator_list_head :
|
|
generator
|
|
{ $$=new std::vector<Generator>; if ($1) $$->push_back(*$1); delete $1; }
|
|
| generator_eq
|
|
{ $$=new std::vector<Generator>; if ($1) $$->push_back(*$1); delete $1; }
|
|
| generator_eq MZN_WHERE expr
|
|
{ $$=new std::vector<Generator>;
|
|
if ($1) $$->push_back(*$1);
|
|
if ($1 && $3) $$->push_back(Generator($$->size(),$3));
|
|
delete $1;
|
|
}
|
|
| generator_list_head ',' generator
|
|
{ $$=$1; if ($$ && $3) $$->push_back(*$3); delete $3; }
|
|
| generator_list_head ',' generator_eq
|
|
{ $$=$1; if ($$ && $3) $$->push_back(*$3); delete $3; }
|
|
| generator_list_head ',' generator_eq MZN_WHERE expr
|
|
{ $$=$1;
|
|
if ($$ && $3) $$->push_back(*$3);
|
|
if ($$ && $3 && $5) $$->push_back(Generator($$->size(),$5));
|
|
delete $3;
|
|
}
|
|
|
|
generator :
|
|
id_list MZN_IN expr
|
|
{ if ($1 && $3) $$=new Generator(*$1,$3,NULL); else $$=NULL; delete $1; }
|
|
| id_list MZN_IN expr MZN_WHERE expr
|
|
{ if ($1 && $3) $$=new Generator(*$1,$3,$5); else $$=NULL; delete $1; }
|
|
generator_eq :
|
|
MZN_IDENTIFIER MZN_EQ expr
|
|
{ if ($3) $$=new Generator({$1},NULL,$3); else $$=NULL; free($1); }
|
|
|
|
id_list : id_list_head comma_or_none
|
|
|
|
id_list_head :
|
|
MZN_IDENTIFIER
|
|
{ $$=new std::vector<std::string>; $$->push_back($1); free($1); }
|
|
| id_list_head ',' MZN_IDENTIFIER
|
|
{ $$=$1; if ($$ && $3) $$->push_back($3); free($3); }
|
|
|
|
simple_array_literal :
|
|
MZN_LEFT_BRACKET MZN_RIGHT_BRACKET
|
|
{ $$=new ArrayLit(@$, std::vector<MiniZinc::Expression*>()); }
|
|
| MZN_LEFT_BRACKET expr_list MZN_RIGHT_BRACKET
|
|
{ if ($2) $$=new ArrayLit(@$, *$2); delete $2; }
|
|
|
|
simple_array_literal_2d :
|
|
MZN_LEFT_2D_BRACKET MZN_RIGHT_2D_BRACKET
|
|
{ $$=new ArrayLit(@$, std::vector<std::vector<Expression*> >()); }
|
|
| MZN_LEFT_2D_BRACKET simple_array_literal_2d_list MZN_RIGHT_2D_BRACKET
|
|
{ if ($2) {
|
|
$$=new ArrayLit(@$, *$2);
|
|
for (unsigned int i=1; i<$2->size(); i++)
|
|
if ((*$2)[i].size() != (*$2)[i-1].size())
|
|
yyerror(&@2, parm, "syntax error, all sub-arrays of 2d array literal must have the same length");
|
|
delete $2;
|
|
} else {
|
|
$$ = NULL;
|
|
}
|
|
}
|
|
| MZN_LEFT_2D_BRACKET simple_array_literal_2d_list '|' MZN_RIGHT_2D_BRACKET
|
|
{ if ($2) {
|
|
$$=new ArrayLit(@$, *$2);
|
|
for (unsigned int i=1; i<$2->size(); i++)
|
|
if ((*$2)[i].size() != (*$2)[i-1].size())
|
|
yyerror(&@2, parm, "syntax error, all sub-arrays of 2d array literal must have the same length");
|
|
delete $2;
|
|
} else {
|
|
$$ = NULL;
|
|
}
|
|
}
|
|
| MZN_LEFT_2D_BRACKET simple_array_literal_3d_list MZN_RIGHT_2D_BRACKET
|
|
{
|
|
if ($2) {
|
|
std::vector<std::pair<int,int> > dims(3);
|
|
dims[0] = std::pair<int,int>(1,static_cast<int>($2->size()));
|
|
if ($2->size()==0) {
|
|
dims[1] = std::pair<int,int>(1,0);
|
|
dims[2] = std::pair<int,int>(1,0);
|
|
} else {
|
|
dims[1] = std::pair<int,int>(1,static_cast<int>((*$2)[0].size()));
|
|
if ((*$2)[0].size()==0) {
|
|
dims[2] = std::pair<int,int>(1,0);
|
|
} else {
|
|
dims[2] = std::pair<int,int>(1,static_cast<int>((*$2)[0][0].size()));
|
|
}
|
|
}
|
|
std::vector<Expression*> a;
|
|
for (int i=0; i<dims[0].second; i++) {
|
|
if ((*$2)[i].size() != dims[1].second) {
|
|
yyerror(&@2, parm, "syntax error, all sub-arrays of 3d array literal must have the same length");
|
|
} else {
|
|
for (int j=0; j<dims[1].second; j++) {
|
|
if ((*$2)[i][j].size() != dims[2].second) {
|
|
yyerror(&@2, parm, "syntax error, all sub-arrays of 3d array literal must have the same length");
|
|
} else {
|
|
for (int k=0; k<dims[2].second; k++) {
|
|
a.push_back((*$2)[i][j][k]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$$ = new ArrayLit(@$,a,dims);
|
|
delete $2;
|
|
} else {
|
|
$$ = NULL;
|
|
}
|
|
}
|
|
|
|
simple_array_literal_3d_list :
|
|
'|' '|'
|
|
{ $$=new std::vector<std::vector<std::vector<MiniZinc::Expression*> > >;
|
|
}
|
|
| '|' simple_array_literal_2d_list '|'
|
|
{ $$=new std::vector<std::vector<std::vector<MiniZinc::Expression*> > >;
|
|
if ($2) $$->push_back(*$2);
|
|
delete $2;
|
|
}
|
|
| simple_array_literal_3d_list ',' '|' simple_array_literal_2d_list '|'
|
|
{ $$=$1;
|
|
if ($$ && $4) $$->push_back(*$4);
|
|
delete $4;
|
|
}
|
|
|
|
simple_array_literal_2d_list :
|
|
expr_list
|
|
{ $$=new std::vector<std::vector<MiniZinc::Expression*> >;
|
|
if ($1) $$->push_back(*$1);
|
|
delete $1;
|
|
}
|
|
| simple_array_literal_2d_list '|' expr_list
|
|
{ $$=$1; if ($$ && $3) $$->push_back(*$3); delete $3; }
|
|
|
|
simple_array_comp :
|
|
MZN_LEFT_BRACKET expr '|' comp_tail MZN_RIGHT_BRACKET
|
|
{ if ($4) $$=new Comprehension(@$, $2, *$4, false);
|
|
delete $4;
|
|
}
|
|
|
|
if_then_else_expr :
|
|
MZN_IF expr MZN_THEN expr MZN_ENDIF
|
|
{
|
|
std::vector<Expression*> iexps;
|
|
iexps.push_back($2);
|
|
iexps.push_back($4);
|
|
$$=new ITE(@$, iexps, NULL);
|
|
}
|
|
| MZN_IF expr MZN_THEN expr elseif_list MZN_ELSE expr MZN_ENDIF
|
|
{
|
|
std::vector<Expression*> iexps;
|
|
iexps.push_back($2);
|
|
iexps.push_back($4);
|
|
if ($5) {
|
|
for (unsigned int i=0; i<$5->size(); i+=2) {
|
|
iexps.push_back((*$5)[i]);
|
|
iexps.push_back((*$5)[i+1]);
|
|
}
|
|
}
|
|
$$=new ITE(@$, iexps,$7);
|
|
delete $5;
|
|
}
|
|
|
|
elseif_list :
|
|
{ $$=new std::vector<MiniZinc::Expression*>; }
|
|
| elseif_list MZN_ELSEIF expr MZN_THEN expr
|
|
{ $$=$1; if ($$ && $3 && $5) { $$->push_back($3); $$->push_back($5); } }
|
|
|
|
quoted_op :
|
|
MZN_EQUIV_QUOTED
|
|
{ $$=BOT_EQUIV; }
|
|
| MZN_IMPL_QUOTED
|
|
{ $$=BOT_IMPL; }
|
|
| MZN_RIMPL_QUOTED
|
|
{ $$=BOT_RIMPL; }
|
|
| MZN_OR_QUOTED
|
|
{ $$=BOT_OR; }
|
|
| MZN_XOR_QUOTED
|
|
{ $$=BOT_XOR; }
|
|
| MZN_AND_QUOTED
|
|
{ $$=BOT_AND; }
|
|
| MZN_LE_QUOTED
|
|
{ $$=BOT_LE; }
|
|
| MZN_GR_QUOTED
|
|
{ $$=BOT_GR; }
|
|
| MZN_LQ_QUOTED
|
|
{ $$=BOT_LQ; }
|
|
| MZN_GQ_QUOTED
|
|
{ $$=BOT_GQ; }
|
|
| MZN_EQ_QUOTED
|
|
{ $$=BOT_EQ; }
|
|
| MZN_NQ_QUOTED
|
|
{ $$=BOT_NQ; }
|
|
| MZN_IN_QUOTED
|
|
{ $$=BOT_IN; }
|
|
| MZN_SUBSET_QUOTED
|
|
{ $$=BOT_SUBSET; }
|
|
| MZN_SUPERSET_QUOTED
|
|
{ $$=BOT_SUPERSET; }
|
|
| MZN_UNION_QUOTED
|
|
{ $$=BOT_UNION; }
|
|
| MZN_DIFF_QUOTED
|
|
{ $$=BOT_DIFF; }
|
|
| MZN_SYMDIFF_QUOTED
|
|
{ $$=BOT_SYMDIFF; }
|
|
| MZN_PLUS_QUOTED
|
|
{ $$=BOT_PLUS; }
|
|
| MZN_MINUS_QUOTED
|
|
{ $$=BOT_MINUS; }
|
|
| MZN_MULT_QUOTED
|
|
{ $$=BOT_MULT; }
|
|
| MZN_POW_QUOTED
|
|
{ $$=BOT_POW; }
|
|
| MZN_DIV_QUOTED
|
|
{ $$=BOT_DIV; }
|
|
| MZN_IDIV_QUOTED
|
|
{ $$=BOT_IDIV; }
|
|
| MZN_MOD_QUOTED
|
|
{ $$=BOT_MOD; }
|
|
| MZN_INTERSECT_QUOTED
|
|
{ $$=BOT_INTERSECT; }
|
|
| MZN_PLUSPLUS_QUOTED
|
|
{ $$=BOT_PLUSPLUS; }
|
|
| MZN_NOT_QUOTED
|
|
{ $$=-1; }
|
|
|
|
quoted_op_call :
|
|
quoted_op '(' expr ',' expr ')'
|
|
{ if ($1==-1) {
|
|
$$=NULL;
|
|
yyerror(&@3, parm, "syntax error, unary operator with two arguments");
|
|
} else {
|
|
$$=new BinOp(@$, $3,static_cast<BinOpType>($1),$5);
|
|
}
|
|
}
|
|
| quoted_op '(' expr ')'
|
|
{ int uot=-1;
|
|
switch ($1) {
|
|
case -1:
|
|
uot = UOT_NOT;
|
|
break;
|
|
case BOT_MINUS:
|
|
uot = UOT_MINUS;
|
|
break;
|
|
case BOT_PLUS:
|
|
uot = UOT_PLUS;
|
|
break;
|
|
default:
|
|
yyerror(&@3, parm, "syntax error, binary operator with unary argument list");
|
|
break;
|
|
}
|
|
if (uot==-1)
|
|
$$=NULL;
|
|
else {
|
|
if (uot==UOT_PLUS && $3 && ($3->isa<IntLit>() || $3->isa<FloatLit>())) {
|
|
$$ = $3;
|
|
} else if (uot==UOT_MINUS && $3 && $3->isa<IntLit>()) {
|
|
$$ = IntLit::a(-$3->cast<IntLit>()->v());
|
|
} else if (uot==UOT_MINUS && $3 && $3->isa<FloatLit>()) {
|
|
$$ = FloatLit::a(-$3->cast<FloatLit>()->v());
|
|
} else {
|
|
$$=new UnOp(@$, static_cast<UnOpType>(uot),$3);
|
|
}
|
|
}
|
|
}
|
|
|
|
call_expr :
|
|
MZN_IDENTIFIER '(' ')'
|
|
{ $$=new Call(@$, $1, std::vector<Expression*>()); free($1); }
|
|
| quoted_op_call
|
|
| MZN_IDENTIFIER '(' comp_or_expr ')'
|
|
{
|
|
if ($3!=NULL) {
|
|
bool hadWhere = false;
|
|
std::vector<Expression*> args;
|
|
for (unsigned int i=0; i<$3->size(); i++) {
|
|
if ((*$3)[i].second) {
|
|
yyerror(&@3, parm, "syntax error, 'where' expression outside generator call");
|
|
hadWhere = true;
|
|
$$=NULL;
|
|
}
|
|
args.push_back((*$3)[i].first);
|
|
}
|
|
if (!hadWhere) {
|
|
$$=new Call(@$, $1, args);
|
|
}
|
|
}
|
|
free($1);
|
|
delete $3;
|
|
}
|
|
| MZN_IDENTIFIER '(' comp_or_expr ')' '(' expr ')'
|
|
{
|
|
vector<Generator> gens;
|
|
vector<Id*> ids;
|
|
if ($3) {
|
|
for (unsigned int i=0; i<$3->size(); i++) {
|
|
if (Id* id = Expression::dyn_cast<Id>((*$3)[i].first)) {
|
|
if ((*$3)[i].second) {
|
|
ParserLocation loc = (*$3)[i].second->loc().parserLocation();
|
|
yyerror(&loc, parm, "illegal where expression in generator call");
|
|
}
|
|
ids.push_back(id);
|
|
} else {
|
|
if (BinOp* boe = Expression::dyn_cast<BinOp>((*$3)[i].first)) {
|
|
if (boe->lhs() && boe->rhs()) {
|
|
Id* id = Expression::dyn_cast<Id>(boe->lhs());
|
|
if (id && boe->op() == BOT_IN) {
|
|
ids.push_back(id);
|
|
gens.push_back(Generator(ids,boe->rhs(),(*$3)[i].second));
|
|
ids = vector<Id*>();
|
|
} else if (id && boe->op() == BOT_EQ && ids.empty()) {
|
|
ids.push_back(id);
|
|
gens.push_back(Generator(ids,NULL,boe->rhs()));
|
|
if ((*$3)[i].second) {
|
|
gens.push_back(Generator(gens.size(),(*$3)[i].second));
|
|
}
|
|
ids = vector<Id*>();
|
|
} else {
|
|
ParserLocation loc = (*$3)[i].first->loc().parserLocation();
|
|
yyerror(&loc, parm, "illegal expression in generator call");
|
|
}
|
|
}
|
|
} else {
|
|
ParserLocation loc = (*$3)[i].first->loc().parserLocation();
|
|
yyerror(&loc, parm, "illegal expression in generator call");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (ids.size() != 0) {
|
|
yyerror(&@3, parm, "illegal expression in generator call");
|
|
}
|
|
ParserState* pp = static_cast<ParserState*>(parm);
|
|
if (pp->hadError) {
|
|
$$=NULL;
|
|
} else {
|
|
Generators g; g._g = gens;
|
|
Comprehension* ac = new Comprehension(@$, $6,g,false);
|
|
vector<Expression*> args; args.push_back(ac);
|
|
$$=new Call(@$, $1, args);
|
|
}
|
|
free($1);
|
|
delete $3;
|
|
}
|
|
|
|
comp_or_expr : comp_or_expr_head comma_or_none
|
|
|
|
comp_or_expr_head :
|
|
expr
|
|
{ $$=new vector<pair<Expression*,Expression*> >;
|
|
if ($1) {
|
|
$$->push_back(pair<Expression*,Expression*>($1,NULL));
|
|
}
|
|
}
|
|
| expr MZN_WHERE expr
|
|
{ $$=new vector<pair<Expression*,Expression*> >;
|
|
if ($1 && $3) {
|
|
$$->push_back(pair<Expression*,Expression*>($1,$3));
|
|
}
|
|
}
|
|
| comp_or_expr_head ',' expr
|
|
{ $$=$1; if ($$ && $3) $$->push_back(pair<Expression*,Expression*>($3,NULL)); }
|
|
| comp_or_expr_head ',' expr MZN_WHERE expr
|
|
{ $$=$1; if ($$ && $3 && $5) $$->push_back(pair<Expression*,Expression*>($3,$5)); }
|
|
|
|
let_expr :
|
|
MZN_LET '{' let_vardecl_item_list '}' MZN_IN expr %prec PREC_ANNO
|
|
{ if ($3 && $6) {
|
|
$$=new Let(@$, *$3, $6); delete $3;
|
|
} else {
|
|
$$=NULL;
|
|
}
|
|
}
|
|
| MZN_LET '{' let_vardecl_item_list comma_or_semi '}' MZN_IN expr %prec PREC_ANNO
|
|
{ if ($3 && $7) {
|
|
$$=new Let(@$, *$3, $7); delete $3;
|
|
} else {
|
|
$$=NULL;
|
|
}
|
|
}
|
|
|
|
let_vardecl_item_list :
|
|
let_vardecl_item
|
|
{ $$=new vector<Expression*>; $$->push_back($1); }
|
|
| constraint_item
|
|
{ $$=new vector<Expression*>;
|
|
if ($1) {
|
|
ConstraintI* ce = $1->cast<ConstraintI>();
|
|
$$->push_back(ce->e());
|
|
ce->e(NULL);
|
|
}
|
|
}
|
|
| let_vardecl_item_list comma_or_semi let_vardecl_item
|
|
{ $$=$1; if ($$ && $3) $$->push_back($3); }
|
|
| let_vardecl_item_list comma_or_semi constraint_item
|
|
{ $$=$1;
|
|
if ($$ && $3) {
|
|
ConstraintI* ce = $3->cast<ConstraintI>();
|
|
$$->push_back(ce->e());
|
|
ce->e(NULL);
|
|
}
|
|
}
|
|
|
|
comma_or_semi : ',' | ';'
|
|
|
|
let_vardecl_item :
|
|
ti_expr_and_id annotations
|
|
{ $$ = $1;
|
|
if ($$) $$->toplevel(false);
|
|
if ($$ && $2) $$->addAnnotations(*$2);
|
|
delete $2;
|
|
}
|
|
| ti_expr_and_id annotations MZN_EQ expr
|
|
{ if ($1) $1->e($4);
|
|
$$ = $1;
|
|
if ($$) $$->loc(@$);
|
|
if ($$) $$->toplevel(false);
|
|
if ($$ && $2) $$->addAnnotations(*$2);
|
|
delete $2;
|
|
}
|
|
|
|
annotations :
|
|
/* empty */
|
|
{ $$=NULL; }
|
|
| ne_annotations
|
|
|
|
annotation_expr :
|
|
expr_atom_head_nonstring
|
|
{ $$ = $1; }
|
|
| string_expr
|
|
{ $$ = new Call(@1, ASTString("mzn_expression_name"), {$1}); }
|
|
|
|
ne_annotations :
|
|
MZN_COLONCOLON annotation_expr
|
|
{ $$=new std::vector<Expression*>(1);
|
|
(*$$)[0] = $2;
|
|
}
|
|
| ne_annotations MZN_COLONCOLON annotation_expr
|
|
{ $$=$1; if ($$) $$->push_back($3); }
|
|
|
|
id_or_quoted_op :
|
|
MZN_IDENTIFIER
|
|
{ $$=$1; }
|
|
| MZN_EQUIV_QUOTED
|
|
{ $$=strdup("'<->'"); }
|
|
| MZN_IMPL_QUOTED
|
|
{ $$=strdup("'->'"); }
|
|
| MZN_RIMPL_QUOTED
|
|
{ $$=strdup("'<-'"); }
|
|
| MZN_OR_QUOTED
|
|
{ $$=strdup("'\\/'"); }
|
|
| MZN_XOR_QUOTED
|
|
{ $$=strdup("'xor'"); }
|
|
| MZN_AND_QUOTED
|
|
{ $$=strdup("'/\\'"); }
|
|
| MZN_LE_QUOTED
|
|
{ $$=strdup("'<'"); }
|
|
| MZN_GR_QUOTED
|
|
{ $$=strdup("'>'"); }
|
|
| MZN_LQ_QUOTED
|
|
{ $$=strdup("'<='"); }
|
|
| MZN_GQ_QUOTED
|
|
{ $$=strdup("'>='"); }
|
|
| MZN_EQ_QUOTED
|
|
{ $$=strdup("'='"); }
|
|
| MZN_NQ_QUOTED
|
|
{ $$=strdup("'!='"); }
|
|
| MZN_IN_QUOTED
|
|
{ $$=strdup("'in'"); }
|
|
| MZN_SUBSET_QUOTED
|
|
{ $$=strdup("'subset'"); }
|
|
| MZN_SUPERSET_QUOTED
|
|
{ $$=strdup("'superset'"); }
|
|
| MZN_UNION_QUOTED
|
|
{ $$=strdup("'union'"); }
|
|
| MZN_DIFF_QUOTED
|
|
{ $$=strdup("'diff'"); }
|
|
| MZN_SYMDIFF_QUOTED
|
|
{ $$=strdup("'symdiff'"); }
|
|
| MZN_DOTDOT_QUOTED
|
|
{ $$=strdup("'..'"); }
|
|
| MZN_PLUS_QUOTED
|
|
{ $$=strdup("'+'"); }
|
|
| MZN_MINUS_QUOTED
|
|
{ $$=strdup("'-'"); }
|
|
| MZN_MULT_QUOTED
|
|
{ $$=strdup("'*'"); }
|
|
| MZN_POW_QUOTED
|
|
{ $$=strdup("'^'"); }
|
|
| MZN_DIV_QUOTED
|
|
{ $$=strdup("'/'"); }
|
|
| MZN_IDIV_QUOTED
|
|
{ $$=strdup("'div'"); }
|
|
| MZN_MOD_QUOTED
|
|
{ $$=strdup("'mod'"); }
|
|
| MZN_INTERSECT_QUOTED
|
|
{ $$=strdup("'intersect'"); }
|
|
| MZN_NOT_QUOTED
|
|
{ $$=strdup("'not'"); }
|
|
| MZN_PLUSPLUS_QUOTED
|
|
{ $$=strdup("'++'"); }
|