/***************************************************************************** Copyright (C) 1994-2000 the Omega Project Team Copyright (C) 2005-2011 Chun Chen All Rights Reserved. Purpose: yacc parser for calculator. Notes: History: 02/04/11 work with flex c++ mode, Chun Chen *****************************************************************************/ %{ //#define YYDEBUG 1 #include #include #include #include #include #include #include #include #include #include "parser.tab.hh" #include //#include #if defined __USE_POSIX #include #elif defined __WIN32 #include #endif #ifndef WIN32 #include #include #endif #if !defined(OMIT_GETRUSAGE) #include #include #include #endif #if !defined(OMIT_GETRUSAGE) #ifdef __sparc__ extern "C" int getrusage (int, struct rusage*); #endif struct rusage start_time; bool anyTimingDone = false; void start_clock( void ) { getrusage(RUSAGE_SELF, &start_time); } int clock_diff( void ) { struct rusage current_time; getrusage(RUSAGE_SELF, ¤t_time); return (current_time.ru_utime.tv_sec -start_time.ru_utime.tv_sec)*1000000 + (current_time.ru_utime.tv_usec-start_time.ru_utime.tv_usec); } #endif #ifdef BUILD_CODEGEN #include #endif extern myFlexLexer mylexer; #define yylex mylexer.yylex int omega_calc_debug = 0; extern bool is_interactive; extern const char *PROMPT_STRING; bool simplify = true; using namespace omega; extern std::string err_msg; bool need_coef; namespace { int redundant_conj_level = 2; // default maximum 2 int redundant_constr_level = 4; // default maximum 4 } std::map relationMap; int argCount = 0; int tuplePos = 0; Argument_Tuple currentTuple = Input_Tuple; Relation LexForward(int n); reachable_information *reachable_info; void yyerror(const std::string &s); void flushScanBuffer(); %} %union { int INT_VALUE; omega::coef_t COEF_VALUE; Rel_Op REL_OPERATOR; char *VAR_NAME; std::set *VAR_LIST; Exp *EXP; std::set *EXP_LIST; AST *ASTP; omega::Argument_Tuple ARGUMENT_TUPLE; AST_constraints *ASTCP; Declaration_Site *DECLARATION_SITE; omega::Relation *RELATION; tupleDescriptor *TUPLE_DESCRIPTOR; std::pair, std::vector > *REL_TUPLE_PAIR; omega::Dynamic_Array1 * RELATION_ARRAY_1D; std::string *STRING_VALUE; } %token VAR %token INT %token COEF %token STRING %token OPEN_BRACE CLOSE_BRACE %token SYMBOLIC NO_SIMPLIFY %token OR AND NOT %token ST APPROX %token IS_ASSIGNED %token FORALL EXISTS %token DOMAIN RANGE %token DIFFERENCE DIFFERENCE_TO_RELATION %token GIST GIVEN HULL WITHIN MAXIMIZE MINIMIZE %token AFFINE_HULL VENN CONVEX_COMBINATION POSITIVE_COMBINATION LINEAR_COMBINATION AFFINE_COMBINATION CONVEX_HULL CONIC_HULL LINEAR_HULL QUICK_HULL PAIRWISE_CHECK CONVEX_CHECK CONVEX_REPRESENTATION RECT_HULL SIMPLE_HULL DECOUPLED_CONVEX_HULL %token MAXIMIZE_RANGE MINIMIZE_RANGE %token MAXIMIZE_DOMAIN MINIMIZE_DOMAIN %token LEQ GEQ NEQ %token GOES_TO %token COMPOSE JOIN INVERSE COMPLEMENT IN CARRIED_BY TIME TIMECLOSURE %token UNION INTERSECTION %token VERTICAL_BAR SUCH_THAT %token SUBSET CODEGEN DECOUPLED_FARKAS FARKAS %token MAKE_UPPER_BOUND MAKE_LOWER_BOUND %token REL_OP %token RESTRICT_DOMAIN RESTRICT_RANGE %token SUPERSETOF SUBSETOF SAMPLE SYM_SAMPLE %token PROJECT_AWAY_SYMBOLS PROJECT_ON_SYMBOLS REACHABLE_FROM REACHABLE_OF %token ASSERT_UNSAT %token PARSE_EXPRESSION PARSE_FORMULA PARSE_RELATION %type exp simpleExp %type expList %type varList %type argumentList %type formula optionalFormula %type constraintChain %type tupleDeclaration %type varDecl varDeclOptBrackets %type relation builtRelation context %type reachable_of %type relPairList %type reachable %destructor {delete []$$;} VAR %destructor {delete $$;} STRING %destructor {delete $$;} relation builtRelation tupleDeclaration formula optionalFormula context reachable_of constraintChain varDecl varDeclOptBrackets relPairList reachable %destructor {delete $$;} exp simpleExp %destructor { for (std::set::iterator i = $$->begin(); i != $$->end(); i++) delete *i; delete $$; } expList; %destructor { for (std::set::iterator i = $$->begin(); i != $$->end(); i++) delete []*i; delete $$; } varList; %nonassoc ASSERT_UNSAT %left UNION p1 '+' '-' %nonassoc SUPERSETOF SUBSETOF %left p2 RESTRICT_DOMAIN RESTRICT_RANGE %left INTERSECTION p3 '*' '@' %left p4 %left OR p5 %left AND p6 %left COMPOSE JOIN CARRIED_BY %right NOT APPROX DOMAIN RANGE HULL PROJECT_AWAY_SYMBOLS PROJECT_ON_SYMBOLS DIFFERENCE DIFFERENCE_TO_RELATION INVERSE COMPLEMENT FARKAS SAMPLE SYM_SAMPLE MAKE_UPPER_BOUND MAKE_LOWER_BOUND p7 %left p8 %nonassoc GIVEN %left p9 %left '(' p10 %% inputSequence : /*empty*/ | inputSequence { assert( current_Declaration_Site == globalDecls);} inputItem; ; inputItem : ';' /*empty*/ | NO_SIMPLIFY ';'{ simplify = false; } | error ';' { flushScanBuffer(); std::cout << err_msg; err_msg.clear(); current_Declaration_Site = globalDecls; need_coef = false; std::cout << "...skipping to statement end..." << std::endl; delete relationDecl; relationDecl = NULL; } | SYMBOLIC globVarList ';' {flushScanBuffer();} | VAR IS_ASSIGNED relation ';' { flushScanBuffer(); try { if(simplify) $3->simplify(redundant_conj_level, redundant_constr_level); else $3->simplify(); Relation *r = relationMap[std::string($1)]; if (r != NULL) delete r; relationMap[std::string($1)] = $3; } catch(const std::exception &e){ std::cout << e.what() << std::endl; } delete []$1; } | relation ';' { flushScanBuffer(); if(simplify) $1->simplify(redundant_conj_level, redundant_constr_level); else $1->simplify(); $1->print_with_subs(stdout); delete $1; } | TIME relation ';' { #if defined(OMIT_GETRUSAGE) printf("'time' requires getrusage, but the omega calclator was compiled with OMIT_GETRUSAGE set!\n"); #else flushScanBuffer(); printf("\n"); int t; Relation R; bool SKIP_FULL_CHECK = getenv("OC_TIMING_SKIP_FULL_CHECK"); ($2)->and_with_GEQ(); start_clock(); for (t=1;t<=100;t++) { R = *$2; R.finalize(); } int copyTime = clock_diff(); start_clock(); for (t=1;t<=100;t++) { R = *$2; R.finalize(); R.simplify(); /* default simplification effort */ } int simplifyTime = clock_diff() -copyTime; Relation R2; if (!SKIP_FULL_CHECK) { start_clock(); for (t=1;t<=100;t++) { R2 = *$2; R2.finalize(); R2.simplify(2,4); /* maximal simplification effort */ } } int excessiveTime = clock_diff() - copyTime; printf("Times (in microseconds): \n"); printf("%5d us to copy original set of constraints\n",copyTime/100); printf("%5d us to do the default amount of simplification, obtaining: \n\t", simplifyTime/100); R.print_with_subs(stdout); printf("\n"); if (!SKIP_FULL_CHECK) { printf("%5d us to do the maximum (i.e., excessive) amount of simplification, obtaining: \n\t", excessiveTime/100); R2.print_with_subs(stdout); printf("\n"); } if (!anyTimingDone) { bool warn = false; #ifndef SPEED warn =true; #endif #ifndef NDEBUG warn = true; #endif if (warn) { printf("WARNING: The Omega calculator was compiled with options that force\n"); printf("it to perform additional consistency and error checks\n"); printf("that may slow it down substantially\n"); printf("\n"); } printf("NOTE: These times relect the time of the current _implementation_\n"); printf("of our algorithms. Performance bugs do exist. If you intend to publish or \n"); printf("report on the performance on the Omega test, we respectfully but strongly \n"); printf("request that send your test cases to us to allow us to determine if the \n"); printf("times are appropriate, and if the way you are using the Omega library to \n"); printf("solve your problem is the most effective way.\n"); printf("\n"); printf("Also, please be aware that over the past two years, we have focused our \n"); printf("efforts on the expressive power of the Omega library, sometimes at the\n"); printf("expensive of raw speed. Our original implementation of the Omega test\n"); printf("was substantially faster on the limited domain it handled.\n"); printf("\n"); printf(" Thanks, \n"); printf(" the Omega Team \n"); } anyTimingDone = true; delete $2; #endif } | TIMECLOSURE relation ';' { #if defined(OMIT_GETRUSAGE) printf("'timeclosure' requires getrusage, but the omega calclator was compiled with OMIT_GETRUSAGE set!\n"); #else flushScanBuffer(); try { int t; Relation R; ($2)->and_with_GEQ(); start_clock(); for (t=1;t<=100;t++) { R = *$2; R.finalize(); } int copyTime = clock_diff(); start_clock(); for (t=1;t<=100;t++) { R = *$2; R.finalize(); R.simplify(); } int simplifyTime = clock_diff() -copyTime; Relation Rclosed; start_clock(); for (t=1;t<=100;t++) { Rclosed = *$2; Rclosed.finalize(); Rclosed = TransitiveClosure(Rclosed, 1,Relation::Null()); } int closureTime = clock_diff() - copyTime; Relation R2; start_clock(); for (t=1;t<=100;t++) { R2 = *$2; R2.finalize(); R2.simplify(2,4); } int excessiveTime = clock_diff() - copyTime; printf("Times (in microseconds): \n"); printf("%5d us to copy original set of constraints\n",copyTime/100); printf("%5d us to do the default amount of simplification, obtaining: \n\t", simplifyTime/100); R.print_with_subs(stdout); printf("\n"); printf("%5d us to do the maximum (i.e., excessive) amount of simplification, obtaining: \n\t", excessiveTime/100); R2.print_with_subs(stdout); printf("%5d us to do the transitive closure, obtaining: \n\t", closureTime/100); Rclosed.print_with_subs(stdout); printf("\n"); if (!anyTimingDone) { bool warn = false; #ifndef SPEED warn =true; #endif #ifndef NDEBUG warn = true; #endif if (warn) { printf("WARNING: The Omega calculator was compiled with options that force\n"); printf("it to perform additional consistency and error checks\n"); printf("that may slow it down substantially\n"); printf("\n"); } printf("NOTE: These times relect the time of the current _implementation_\n"); printf("of our algorithms. Performance bugs do exist. If you intend to publish or \n"); printf("report on the performance on the Omega test, we respectfully but strongly \n"); printf("request that send your test cases to us to allow us to determine if the \n"); printf("times are appropriate, and if the way you are using the Omega library to \n"); printf("solve your problem is the most effective way.\n"); printf("\n"); printf("Also, please be aware that over the past two years, we have focused our \n"); printf("efforts on the expressive power of the Omega library, sometimes at the\n"); printf("expensive of raw speed. Our original implementation of the Omega test\n"); printf("was substantially faster on the limited domain it handled.\n"); printf("\n"); printf(" Thanks, \n"); printf(" the Omega Team \n"); } anyTimingDone = true; } catch (const std::exception &e) { std::cout << e.what() << std::endl; } delete $2; #endif } | relation SUBSET relation ';' { flushScanBuffer(); try { if (Must_Be_Subset(copy(*$1), copy(*$3))) std::cout << "True" << std::endl; else if (Might_Be_Subset(copy(*$1), copy(*$3))) std::cout << "Possible" << std::endl; else std::cout << "False" << std::endl; } catch (const std::exception &e) { std::cout << e.what() << std::endl; } delete $1; delete $3; } | CODEGEN relPairList context';' { flushScanBuffer(); #ifdef BUILD_CODEGEN try { CodeGen cg($2->first, $2->second, *$3); CG_result *cgr = cg.buildAST(); if (cgr != NULL) { std::string s = cgr->printString(); std::cout << s << std::endl; delete cgr; } else std::cout << "/* empty */" << std::endl; } catch (const std::exception &e) { std::cout << e.what() << std::endl; } #else std::cout << "CodeGen package not built" << std::endl; #endif delete $3; delete $2; } | CODEGEN INT relPairList context';' { flushScanBuffer(); #ifdef BUILD_CODEGEN try { CodeGen cg($3->first, $3->second, *$4); CG_result *cgr = cg.buildAST($2); if (cgr != NULL) { std::string s = cgr->printString(); std::cout << s << std::endl; delete cgr; } else std::cout << "/* empty */" << std::endl; } catch (const std::exception &e) { std::cout << e.what() << std::endl; } #else std::cout << "CodeGen package not built" << std::endl; #endif delete $4; delete $3; } | reachable ';' { flushScanBuffer(); Dynamic_Array1 &final = *$1; bool any_sat = false; int i,n_nodes = reachable_info->node_names.size(); for(i = 1; i <= n_nodes; i++) if(final[i].is_upper_bound_satisfiable()) { any_sat = true; std::cout << "Node " << reachable_info->node_names[i] << ": "; final[i].print_with_subs(stdout); } if(!any_sat) std::cout << "No nodes reachable.\n"; delete $1; delete reachable_info; } ; context : {$$ = new Relation(); *$$ = Relation::Null();} | GIVEN relation {$$ = $2; } ; relPairList : relPairList ',' relation ':' relation { try { $1->first.push_back(*$3); $1->second.push_back(*$5); } catch (const std::exception &e) { delete $1; delete $3; delete $5; yyerror(e.what()); YYERROR; } delete $3; delete $5; $$ = $1; } | relPairList ',' relation { try { $1->first.push_back(Identity($3->n_set())); $1->second.push_back(*$3); } catch (const std::exception &e) { delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $3; $$ = $1; } | relation ':' relation { std::pair, std::vector > *rtp = new std::pair, std::vector >(); try { rtp->first.push_back(*$1); rtp->second.push_back(*$3); } catch (const std::exception &e) { delete rtp; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; $$ = rtp; } | relation { std::pair, std::vector > *rtp = new std::pair, std::vector >(); try { rtp->first.push_back(Identity($1->n_set())); rtp->second.push_back(*$1); } catch (const std::exception &e) { delete rtp; delete $1; yyerror(e.what()); YYERROR; } delete $1; $$ = rtp; } ; relation : OPEN_BRACE {need_coef = true; relationDecl = new Declaration_Site();} builtRelation CLOSE_BRACE { need_coef = false; $$ = $3; current_Declaration_Site = globalDecls; delete relationDecl; relationDecl = NULL; } | VAR { Relation *r = relationMap[std::string($1)]; if (r == NULL) { yyerror(std::string("relation ") + to_string($1) + std::string(" not declared")); delete []$1; YYERROR; } $$ = new Relation(*r); delete []$1; } | '(' relation ')' {$$ = $2;} | relation '+' %prec p9 { $$ = new Relation(); try { *$$ = TransitiveClosure(*$1, 1, Relation::Null()); } catch (const std::exception &e) { delete $$; delete $1; yyerror(e.what()); YYERROR; } delete $1; } | relation '*' %prec p9 { $$ = new Relation(); try { int vars = $1->n_inp(); *$$ = Union(Identity(vars), TransitiveClosure(*$1, 1, Relation::Null())); } catch (const std::exception &e) { delete $$; delete $1; yyerror(e.what()); YYERROR; } delete $1; } | relation '+' WITHIN relation %prec p9 { $$ = new Relation(); try { *$$= TransitiveClosure(*$1, 1, *$4); } catch (const std::exception &e) { delete $$; delete $1; delete $4; yyerror(e.what()); YYERROR; } delete $1; delete $4; } | relation '^' '@' %prec p8 { $$ = new Relation(); try { *$$ = ApproxClosure(*$1); } catch (const std::exception &e) { delete $$; delete $1; yyerror(e.what()); YYERROR; } delete $1; } | relation '^' '+' %prec p8 { $$ = new Relation(); try { *$$ = calculateTransitiveClosure(*$1); } catch (const std::exception &e) { delete $$; delete $1; yyerror(e.what()); YYERROR; } delete $1; } | MINIMIZE_RANGE relation %prec p8 { $$ = new Relation(); try { Relation o(*$2); Relation r(*$2); r = Join(r,LexForward($2->n_out())); *$$ = Difference(o,r); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | MAXIMIZE_RANGE relation %prec p8 { $$ = new Relation(); try { Relation o(*$2); Relation r(*$2); r = Join(r,Inverse(LexForward($2->n_out()))); *$$ = Difference(o,r); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | MINIMIZE_DOMAIN relation %prec p8 { $$ = new Relation(); try { Relation o(*$2); Relation r(*$2); r = Join(LexForward($2->n_inp()),r); *$$ = Difference(o,r); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | MAXIMIZE_DOMAIN relation %prec p8 { $$ = new Relation(); try { Relation o(*$2); Relation r(*$2); r = Join(Inverse(LexForward($2->n_inp())),r); *$$ = Difference(o,r); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | MAXIMIZE relation %prec p8 { $$ = new Relation(); try { Relation c(*$2); Relation r(*$2); *$$ = Cross_Product(Relation(*$2),c); *$$ = Difference(r,Domain(Intersection(*$$,LexForward($$->n_inp())))); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | MINIMIZE relation %prec p8 { $$ = new Relation(); try { Relation c(*$2); Relation r(*$2); *$$ = Cross_Product(Relation(*$2),c); *$$ = Difference(r,Range(Intersection(*$$,LexForward($$->n_inp())))); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | FARKAS relation %prec p8 { $$ = new Relation(); try { *$$ = Farkas(*$2, Basic_Farkas); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | DECOUPLED_FARKAS relation %prec p8 { $$ = new Relation(); try { *$$ = Farkas(*$2, Decoupled_Farkas); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | relation '@' %prec p9 { $$ = new Relation(); try { *$$ = ConicClosure(*$1); } catch (const std::exception &e) { delete $$; delete $1; yyerror(e.what()); YYERROR; } delete $1; } | PROJECT_AWAY_SYMBOLS relation %prec p8 { $$ = new Relation(); try { *$$ = Project_Sym(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | PROJECT_ON_SYMBOLS relation %prec p8 { $$ = new Relation(); try { *$$ = Project_On_Sym(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | DIFFERENCE relation %prec p8 { $$ = new Relation(); try { *$$ = Deltas(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | DIFFERENCE_TO_RELATION relation %prec p8 { $$ = new Relation(); try { *$$ = DeltasToRelation(*$2,$2->n_set(),$2->n_set()); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | DOMAIN relation %prec p8 { $$ = new Relation(); try { *$$ = Domain(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | VENN relation %prec p8 { $$ = new Relation(); try { *$$ = VennDiagramForm(*$2,Relation::True(*$2)); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | VENN relation GIVEN relation %prec p8 { $$ = new Relation(); try { *$$ = VennDiagramForm(*$2,*$4); } catch (const std::exception &e) { delete $$; delete $2; delete $4; yyerror(e.what()); YYERROR; } delete $2; delete $4; } | CONVEX_HULL relation %prec p8 { $$ = new Relation(); try { *$$ = ConvexHull(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | DECOUPLED_CONVEX_HULL relation %prec p8 { $$ = new Relation(); try { *$$ = DecoupledConvexHull(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | POSITIVE_COMBINATION relation %prec p8 { $$ = new Relation(); try { *$$ = Farkas(*$2,Positive_Combination_Farkas); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | LINEAR_COMBINATION relation %prec p8 { $$ = new Relation(); try { *$$ = Farkas(*$2,Linear_Combination_Farkas); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | AFFINE_COMBINATION relation %prec p8 { $$ = new Relation(); try { *$$ = Farkas(*$2,Affine_Combination_Farkas); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | CONVEX_COMBINATION relation %prec p8 { $$ = new Relation(); try { *$$ = Farkas(*$2,Convex_Combination_Farkas); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | PAIRWISE_CHECK relation %prec p8 { $$ = new Relation(); try { *$$ = CheckForConvexRepresentation(CheckForConvexPairs(*$2)); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | CONVEX_CHECK relation %prec p8 { $$ = new Relation(); try { *$$ = CheckForConvexRepresentation(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | CONVEX_REPRESENTATION relation %prec p8 { $$ = new Relation(); try { *$$ = ConvexRepresentation(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | AFFINE_HULL relation %prec p8 { $$ = new Relation(); try { *$$ = AffineHull(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | CONIC_HULL relation %prec p8 { $$ = new Relation(); try { *$$ = ConicHull(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | LINEAR_HULL relation %prec p8 { $$ = new Relation(); try { *$$ = LinearHull(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | QUICK_HULL relation %prec p8 { $$ = new Relation(); try { *$$ = QuickHull(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | RECT_HULL relation %prec p8 { $$ = new Relation(); try { *$$ = RectHull(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | SIMPLE_HULL relation %prec p8 { $$ = new Relation(); try { *$$ = SimpleHull(*$2, true, true); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | HULL relation %prec p8 { $$ = new Relation(); try { *$$ = Hull(*$2,true,1,Relation::Null()); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | HULL relation GIVEN relation %prec p8 { $$ = new Relation(); try { *$$ = Hull(*$2,true,1,*$4); } catch (const std::exception &e) { delete $$; delete $2; delete $4; yyerror(e.what()); YYERROR; } delete $2; delete $4; } | APPROX relation %prec p8 { $$ = new Relation(); try { *$$ = Approximate(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | RANGE relation %prec p8 { $$ = new Relation(); try { *$$ = Range(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | INVERSE relation %prec p8 { $$ = new Relation(); try { *$$ = Inverse(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | COMPLEMENT relation %prec p8 { $$ = new Relation(); try { *$$ = Complement(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | GIST relation GIVEN relation %prec p8 { $$ = new Relation(); try { *$$ = Gist(*$2,*$4,1); } catch (const std::exception &e) { delete $$; delete $2; delete $4; yyerror(e.what()); YYERROR; } delete $2; delete $4; } | relation '(' relation ')' { $$ = new Relation(); try { *$$ = Composition(*$1,*$3); } catch (const std::exception &e) { delete $$; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; } | relation COMPOSE relation { $$ = new Relation(); try { *$$ = Composition(*$1,*$3); } catch (const std::exception &e) { delete $$; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; } | relation CARRIED_BY INT { $$ = new Relation(); try { *$$ = After(*$1,$3,$3); (*$$).prefix_print(stdout); } catch (const std::exception &e) { delete $$; delete $1; yyerror(e.what()); YYERROR; } delete $1; } | relation JOIN relation { $$ = new Relation(); try { *$$ = Composition(*$3,*$1); } catch (const std::exception &e) { delete $$; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; } | relation RESTRICT_RANGE relation { $$ = new Relation(); try { *$$ = Restrict_Range(*$1,*$3); } catch (const std::exception &e) { delete $$; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; } | relation RESTRICT_DOMAIN relation { $$ = new Relation(); try { *$$ = Restrict_Domain(*$1,*$3); } catch (const std::exception &e) { delete $$; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; } | relation INTERSECTION relation { $$ = new Relation(); try { *$$ = Intersection(*$1,*$3); } catch (const std::exception &e) { delete $$; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; } | relation '-' relation %prec INTERSECTION { $$ = new Relation(); try { *$$ = Difference(*$1,*$3); } catch (const std::exception &e) { delete $$; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; } | relation UNION relation { $$ = new Relation(); try { *$$ = Union(*$1,*$3); } catch (const std::exception &e) { delete $$; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; } | relation '*' relation { $$ = new Relation(); try { *$$ = Cross_Product(*$1,*$3); } catch (const std::exception &e) { delete $$; delete $1; delete $3; yyerror(e.what()); YYERROR; } delete $1; delete $3; } | SUPERSETOF relation { $$ = new Relation(); try { *$$ = Union(*$2, Relation::Unknown(*$2)); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | SUBSETOF relation { $$ = new Relation(); try { *$$ = Intersection(*$2, Relation::Unknown(*$2)); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | MAKE_UPPER_BOUND relation %prec p8 { $$ = new Relation(); try { *$$ = Upper_Bound(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | MAKE_LOWER_BOUND relation %prec p8 { $$ = new Relation(); try { *$$ = Lower_Bound(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | SAMPLE relation { $$ = new Relation(); try { *$$ = Sample_Solution(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | SYM_SAMPLE relation { $$ = new Relation(); try { *$$ = Symbolic_Solution(*$2); } catch (const std::exception &e) { delete $$; delete $2; yyerror(e.what()); YYERROR; } delete $2; } | reachable_of { $$ = $1; } | ASSERT_UNSAT relation { if (($2)->is_satisfiable()) { fprintf(stderr,"assert_unsatisfiable failed on "); ($2)->print_with_subs(stderr); exit(1); } $$=$2; } ; builtRelation : tupleDeclaration GOES_TO {currentTuple = Output_Tuple;} tupleDeclaration {currentTuple = Input_Tuple;} optionalFormula { Relation * r = new Relation($1->size,$4->size); resetGlobals(); F_And *f = r->add_and(); for(int i = 1; i <= $1->size; i++) { $1->vars[i-1]->vid = r->input_var(i); if (!$1->vars[i-1]->anonymous) r->name_input_var(i, $1->vars[i-1]->stripped_name); } for(int i = 1; i <= $4->size; i++) { $4->vars[i-1]->vid = r->output_var(i); if (!$4->vars[i-1]->anonymous) r->name_output_var(i, $4->vars[i-1]->stripped_name); } r->setup_names(); for (std::set::iterator i = $1->eq_constraints.begin(); i != $1->eq_constraints.end(); i++) install_eq(f, *i, 0); for (std::set::iterator i = $1->geq_constraints.begin(); i != $1->geq_constraints.end(); i++) install_geq(f, *i, 0); for (std::set::iterator i = $1->stride_constraints.begin(); i != $1->stride_constraints.end(); i++) install_stride(f, *i); for (std::set::iterator i = $4->eq_constraints.begin(); i != $4->eq_constraints.end(); i++) install_eq(f, *i, 0); for (std::set::iterator i = $4->geq_constraints.begin(); i != $4->geq_constraints.end(); i++) install_geq(f, *i, 0); for (std::set::iterator i = $4->stride_constraints.begin(); i != $4->stride_constraints.end(); i++) install_stride(f, *i); if ($6) $6->install(f); delete $1; delete $4; delete $6; $$ = r; } | tupleDeclaration optionalFormula { Relation * r = new Relation($1->size); resetGlobals(); F_And *f = r->add_and(); for(int i = 1; i <= $1->size; i++) { $1->vars[i-1]->vid = r->set_var(i); if (!$1->vars[i-1]->anonymous) r->name_set_var(i, $1->vars[i-1]->stripped_name); } r->setup_names(); for (std::set::iterator i = $1->eq_constraints.begin(); i != $1->eq_constraints.end(); i++) install_eq(f, *i, 0); for (std::set::iterator i = $1->geq_constraints.begin(); i != $1->geq_constraints.end(); i++) install_geq(f, *i, 0); for (std::set::iterator i = $1->stride_constraints.begin(); i != $1->stride_constraints.end(); i++) install_stride(f, *i); if ($2) $2->install(f); delete $1; delete $2; $$ = r; } | formula { Relation * r = new Relation(0,0); F_And *f = r->add_and(); $1->install(f); delete $1; $$ = r; } ; optionalFormula : formula_sep formula {$$ = $2;} | {$$ = 0;} ; formula_sep : ':' | VERTICAL_BAR | SUCH_THAT ; tupleDeclaration : {currentTupleDescriptor = new tupleDescriptor; tuplePos = 1;} '[' optionalTupleVarList ']' {$$ = currentTupleDescriptor; tuplePos = 0;} ; optionalTupleVarList : /* empty */ | tupleVar | optionalTupleVarList ',' tupleVar ; tupleVar : VAR %prec p10 { Declaration_Site *ds = defined($1); if (!ds) currentTupleDescriptor->extend($1,currentTuple,tuplePos); else { Variable_Ref *v = lookupScalar($1); if (v == NULL) { yyerror(std::string("cannot find declaration for variable ") + to_string($1)); delete []$1; YYERROR; } if (ds != globalDecls) currentTupleDescriptor->extend($1, new Exp(v)); else currentTupleDescriptor->extend(new Exp(v)); } tuplePos++; delete []$1; } | '*' {currentTupleDescriptor->extend(); tuplePos++;} | exp %prec p1 { currentTupleDescriptor->extend($1); tuplePos++; } | exp ':' exp %prec p1 { currentTupleDescriptor->extend($1,$3); tuplePos++; } | exp ':' exp ':' COEF %prec p1 { currentTupleDescriptor->extend($1,$3,$5); tuplePos++; } ; varList : varList ',' VAR {$$ = $1; $$->insert($3); $3 = NULL;} | VAR {$$ = new std::set(); $$->insert($1); $1 = NULL;} ; varDecl : varList { $$ = current_Declaration_Site = new Declaration_Site($1); for (std::set::iterator i = $1->begin(); i != $1->end(); i++) delete [](*i); delete $1; } ; varDeclOptBrackets : varDecl {$$ = $1;} |'[' varDecl ']' {$$ = $2;} ; globVarList : globVarList ',' globVar | globVar ; globVar : VAR '(' INT ')' {globalDecls->extend_both_tuples($1, $3); delete []$1;} | VAR { globalDecls->extend($1); delete []$1; } ; formula : formula AND formula {$$ = new AST_And($1,$3);} | formula OR formula {$$ = new AST_Or($1,$3);} | constraintChain {$$ = $1;} | '(' formula ')' {$$ = $2;} | NOT formula {$$ = new AST_Not($2);} | start_exists varDeclOptBrackets exists_sep formula end_quant {$$ = new AST_exists($2,$4);} | start_forall varDeclOptBrackets forall_sep formula end_quant {$$ = new AST_forall($2,$4);} ; start_exists : '(' EXISTS | EXISTS '(' ; exists_sep : ':' | VERTICAL_BAR | SUCH_THAT ; start_forall : '(' FORALL | FORALL '(' ; forall_sep : ':' ; end_quant : ')' {popScope();} ; expList : exp ',' expList {$$ = $3; $$->insert($1);} | exp {$$ = new std::set(); $$->insert($1);} ; constraintChain : expList REL_OP expList {$$ = new AST_constraints($1,$2,$3);} | expList REL_OP constraintChain {$$ = new AST_constraints($1,$2,$3);} ; simpleExp : VAR %prec p9 { Variable_Ref *v = lookupScalar($1); if (v == NULL) { yyerror(std::string("cannot find declaration for variable ") + to_string($1)); delete []$1; YYERROR; } $$ = new Exp(v); delete []$1; } | VAR '(' {argCount = 1;} argumentList ')' %prec p9 { Variable_Ref *v; if ($4 == Input_Tuple) v = functionOfInput[$1]; else v = functionOfOutput[$1]; if (v == NULL) { yyerror(std::string("Function ") + to_string($1) + std::string(" not declared")); delete []$1; YYERROR; } $$ = new Exp(v); delete []$1; } | '(' exp ')' { $$ = $2; } ; argumentList : argumentList ',' VAR { Variable_Ref *v = lookupScalar($3); if (v == NULL) { yyerror(std::string("cannot find declaration for variable ") + to_string($1)); delete []$3; YYERROR; } if (v->pos != argCount || v->of != $1 || (v->of != Input_Tuple && v->of != Output_Tuple)) { yyerror("arguments to function must be prefix of input or output tuple"); delete []$3; YYERROR; } $$ = v->of; argCount++; delete []$3; } | VAR { Variable_Ref *v = lookupScalar($1); if (v == NULL) { yyerror(std::string("cannot find declaration for variable ") + to_string($1)); delete []$1; YYERROR; } if (v->pos != argCount || (v->of != Input_Tuple && v->of != Output_Tuple)) { yyerror("arguments to function must be prefix of input or output tuple"); delete []$1; YYERROR; } $$ = v->of; argCount++; delete []$1; } ; exp : COEF {$$ = new Exp($1);} | COEF simpleExp %prec '*' {$$ = multiply($1,$2);} | simpleExp {$$ = $1; } | '-' exp %prec '*' {$$ = negate($2);} | exp '+' exp {$$ = add($1,$3);} | exp '-' exp {$$ = subtract($1,$3);} | exp '*' exp { try { $$ = multiply($1,$3); } catch (const std::exception &e) { yyerror(e.what()); YYERROR; } } ; reachable : REACHABLE_FROM nodeNameList nodeSpecificationList { Dynamic_Array1 *final = Reachable_Nodes(reachable_info); $$ = final; } ; reachable_of : REACHABLE_OF VAR IN nodeNameList nodeSpecificationList { Dynamic_Array1 *final = Reachable_Nodes(reachable_info); int index = reachable_info->node_names.index(std::string($2)); if (index == 0) { yyerror(std::string("no such node ") + to_string($2)); delete []$2; delete final; delete reachable_info; YYERROR; } $$ = new Relation; *$$ = (*final)[index]; delete final; delete reachable_info; delete []$2; } ; nodeNameList : '(' realNodeNameList ')' { int sz = reachable_info->node_names.size(); reachable_info->node_arity.reallocate(sz); reachable_info->transitions.resize(sz+1,sz+1); reachable_info->start_nodes.resize(sz+1); } ; realNodeNameList : realNodeNameList ',' VAR { reachable_info->node_names.append(std::string($3)); delete []$3; } | VAR { reachable_info = new reachable_information; reachable_info->node_names.append(std::string($1)); delete []$1; } ; nodeSpecificationList : OPEN_BRACE realNodeSpecificationList CLOSE_BRACE { int i,j; int n_nodes = reachable_info->node_names.size(); Tuple &arity = reachable_info->node_arity; Dynamic_Array2 &transitions = reachable_info->transitions; /* fixup unspecified transitions to be false */ /* find arity */ for(i = 1; i <= n_nodes; i++) arity[i] = -1; for(i = 1; i <= n_nodes; i++) for(j = 1; j <= n_nodes; j++) if(! transitions[i][j].is_null()) { int in_arity = transitions[i][j].n_inp(); int out_arity = transitions[i][j].n_out(); if(arity[i] < 0) arity[i] = in_arity; if(arity[j] < 0) arity[j] = out_arity; if(in_arity != arity[i] || out_arity != arity[j]) { yyerror(std::string("arity mismatch in node transition: ") + to_string(reachable_info->node_names[i]) + std::string(" -> ") + to_string(reachable_info->node_names[j])); delete reachable_info; YYERROR; } } for(i = 1; i <= n_nodes; i++) if(arity[i] < 0) arity[i] = 0; /* Fill in false relations */ for(i = 1; i <= n_nodes; i++) for(j = 1; j <= n_nodes; j++) if(transitions[i][j].is_null()) transitions[i][j] = Relation::False(arity[i],arity[j]); /* fixup unused start node positions */ Dynamic_Array1 &nodes = reachable_info->start_nodes; for(i = 1; i <= n_nodes; i++) if(nodes[i].is_null()) nodes[i] = Relation::False(arity[i]); else if(nodes[i].n_set() != arity[i]){ yyerror(std::string("arity mismatch in start node ") + to_string(reachable_info->node_names[i])); delete reachable_info; YYERROR; } } ; realNodeSpecificationList : realNodeSpecificationList ',' VAR ':' relation { int n_nodes = reachable_info->node_names.size(); int index = reachable_info->node_names.index($3); if (!(index > 0 && index <= n_nodes)) { yyerror(std::string("no such node ")+to_string($3)); delete $5; delete []$3; delete reachable_info; YYERROR; } reachable_info->start_nodes[index] = *$5; delete $5; delete []$3; } | realNodeSpecificationList ',' VAR GOES_TO VAR ':' relation { int n_nodes = reachable_info->node_names.size(); int from_index = reachable_info->node_names.index($3); if (!(from_index > 0 && from_index <= n_nodes)) { yyerror(std::string("no such node ")+to_string($3)); delete $7; delete []$3; delete []$5; delete reachable_info; YYERROR; } int to_index = reachable_info->node_names.index($5); if (!(to_index > 0 && to_index <= n_nodes)) { yyerror(std::string("no such node ")+to_string($5)); delete $7; delete []$3; delete []$5; delete reachable_info; YYERROR; } reachable_info->transitions[from_index][to_index] = *$7; delete $7; delete []$3; delete []$5; } | VAR GOES_TO VAR ':' relation { int n_nodes = reachable_info->node_names.size(); int from_index = reachable_info->node_names.index($1); if (!(from_index > 0 && from_index <= n_nodes)) { yyerror(std::string("no such node ")+to_string($1)); delete $5; delete []$1; delete []$3; delete reachable_info; YYERROR; } int to_index = reachable_info->node_names.index($3); if (!(to_index > 0 && to_index <= n_nodes)) { yyerror(std::string("no such node ")+to_string($3)); delete $5; delete []$1; delete []$3; delete reachable_info; YYERROR; } reachable_info->transitions[from_index][to_index] = *$5; delete $5; delete []$1; delete []$3; } | VAR ':' relation { int n_nodes = reachable_info->node_names.size(); int index = reachable_info->node_names.index($1); if (!(index > 0 && index <= n_nodes)) { yyerror(std::string("no such node ")+to_string($1)); delete $3; delete []$1; delete reachable_info; YYERROR; } reachable_info->start_nodes[index] = *$3; delete $3; delete []$1; } ; %% void yyerror(const std::string &s) { std::stringstream ss; if (is_interactive) ss << s << "\n"; else ss << s << " at line " << mylexer.lineno() << "\n"; err_msg = ss.str(); } int main(int argc, char **argv) { if (argc > 2){ fprintf(stderr, "Usage: %s [script_file]\n", argv[0]); exit(1); } if (argc == 2) { std::ifstream *ifs = new std::ifstream; ifs->open(argv[1], std::ifstream::in); if (!ifs->is_open()) { fprintf(stderr, "can't open input file %s\n", argv[1]); exit(1); } yy_buffer_state *bs = mylexer.yy_create_buffer(ifs, 8092); mylexer.yypush_buffer_state(bs); } //yydebug = 1; is_interactive = false; if (argc == 1) { #if defined __USE_POSIX if (isatty((int)fileno(stdin))) is_interactive = true; #elif defined __WIN32 if (_isatty(_fileno(stdin))) is_interactive = true; #endif } if (is_interactive) { #ifdef BUILD_CODEGEN std::cout << "Omega+ and CodeGen+ "; #else std::cout << "Omega+ "; #endif std::cout << "v2.2.3 (built on " OMEGA_BUILD_DATE ")" << std::endl; std::cout << "Copyright (C) 1994-2000 the Omega Project Team" << std::endl; std::cout << "Copyright (C) 2005-2011 Chun Chen" << std::endl; std::cout << "Copyright (C) 2011-2012 University of Utah" << std::endl; std::cout << PROMPT_STRING << ' '; std::cout.flush(); } need_coef = false; current_Declaration_Site = globalDecls = new Global_Declaration_Site(); if (yyparse() != 0) { if (!is_interactive) std::cout << "syntax error at the end of the file, missing ';'" << std::endl; else std::cout << std::endl; delete relationDecl; relationDecl = NULL; } else { if (is_interactive) std::cout << std::endl; } for (std::map::iterator i = relationMap.begin(); i != relationMap.end(); i++) delete (*i).second; delete globalDecls; return 0; } Relation LexForward(int n) { Relation r(n,n); F_Or *f = r.add_or(); for (int i=1; i <= n; i++) { F_And *g = f->add_and(); for(int j=1;jadd_EQ(); e.update_coef(r.input_var(j),-1); e.update_coef(r.output_var(j),1); e.finalize(); } GEQ_Handle e = g->add_GEQ(); e.update_coef(r.input_var(i),-1); e.update_coef(r.output_var(i),1); e.update_const(-1); e.finalize(); } r.finalize(); return r; }