/* ========================================================================= */ /* NAME : lp_rlp.y */ /* ========================================================================= */ %token VAR CONS INTCONS VARIABLECOLON INF SEC_INT SEC_SEC SEC_SOS SOSDESCR SEC_FREE SIGN AR_M_OP RE_OPLE RE_OPGE END_C COMMA COLON MINIMISE MAXIMISE UNDEFINED %{ #include #include #include "lpkit.h" #include "yacc_read.h" #ifdef FORTIFY # include "lp_fortify.h" #endif static int HadVar0, HadVar1, HadVar2, HasAR_M_OP, do_add_row, Had_lineair_sum0, HadSign; static char *Last_var = NULL, *Last_var0 = NULL; static REAL f, f0, f1; static int x; static int state, state0; static int Sign; static int isign, isign0; /* internal_sign variable to make sure nothing goes wrong */ /* with lookahead */ static int make_neg; /* is true after the relational operator is seen in order */ /* to remember if lin_term stands before or after re_op */ static int Within_int_decl = FALSE; /* TRUE when we are within an int declaration */ static int Within_sec_decl = FALSE; /* TRUE when we are within a sec declaration */ static int Within_sos_decl = FALSE; /* TRUE when we are within a sos declaration */ static int Within_sos_decl1; static int Within_free_decl = FALSE; /* TRUE when we are within a free declaration */ static short SOStype0; /* SOS type */ static short SOStype; /* SOS type */ static int SOSNr; static int SOSweight = 0; /* SOS weight */ static int HadConstraint; static int HadVar; static int Had_lineair_sum; extern FILE *yyin; #define YY_FATAL_ERROR lex_fatal_error /* let's please C++ users */ #ifdef __cplusplus extern "C" { #endif static int wrap(void) { return(1); } static int __WINAPI lp_input_yyin(void *fpin, char *buf, int max_size) { int result; if ( (result = fread( (char*)buf, sizeof(char), max_size, (FILE *) fpin)) < 0) YY_FATAL_ERROR( "read() in flex scanner failed"); return(result); } static read_modeldata_func *lp_input; #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result = lp_input((void *) yyin, buf, max_size); #ifdef __cplusplus }; #endif #define yywrap wrap #define yyerror read_error #include "lp_rlp.h" %} %start inputfile %% EMPTY: /* EMPTY */ ; inputfile : { isign = 0; make_neg = 0; Sign = 0; HadConstraint = FALSE; HadVar = HadVar0 = FALSE; } objective_function constraints int_sec_sos_free_declarations ; /* start objective_function */ /* objective_function: MAXIMISE real_of | MINIMISE real_of | real_of; real_of: lineair_sum END_C; lineair_sum: EMPTY | x_lineair_sum; */ objective_function: MAXIMISE real_of { set_obj_dir(TRUE); } | MINIMISE real_of { set_obj_dir(FALSE); } | real_of ; real_of: lineair_sum END_C { add_row(); HadConstraint = FALSE; HadVar = HadVar0 = FALSE; isign = 0; make_neg = 0; } ; lineair_sum: EMPTY | x_lineair_sum ; /* end objective_function */ /* start constraints */ /* constraints: EMPTY | x_constraints; x_constraints: constraint | x_constraints constraint; constraint: real_constraint | VARIABLECOLON real_constraint; real_constraint: x_lineair_sum2 RE_OP x_lineair_sum3 optionalrange END_C; optionalrange: EMPTY | RE_OP cons_term RHS_STORE; RE_OP: RE_OPLE | RE_OPGE; cons_term: x_SIGN REALCONS | INF; x_lineair_sum2: EMPTY | x_lineair_sum3; x_lineair_sum3: x_lineair_sum | INF RHS_STORE; x_lineair_sum: x_lineair_sum1; x_lineair_sum1: x_lineair_term | x_lineair_sum1 x_lineair_term; x_lineair_term: x_SIGN x_lineair_term1; x_lineair_term1: REALCONS | optional_AR_M_OP VAR; x_SIGN: EMPTY | SIGN; REALCONS: INTCONS | CONS; optional_AR_M_OP: EMPTY | AR_M_OP; */ constraints: EMPTY | x_constraints ; x_constraints : constraint | x_constraints constraint ; constraint : real_constraint | VARIABLECOLON { if(!add_constraint_name(Last_var)) YYABORT; HadConstraint = TRUE; } real_constraint ; real_constraint : x_lineair_sum2 { HadVar1 = HadVar0; HadVar0 = FALSE; } RE_OP { if(!store_re_op((char *) yytext, HadConstraint, HadVar, Had_lineair_sum)) YYABORT; make_neg = 1; f1 = 0; } x_lineair_sum3 { Had_lineair_sum0 = Had_lineair_sum; Had_lineair_sum = TRUE; HadVar2 = HadVar0; HadVar0 = FALSE; do_add_row = FALSE; if(HadConstraint && !HadVar ) { /* it is a range */ /* already handled */ } else if(!HadConstraint && HadVar) { /* it is a bound */ if(!store_bounds(TRUE)) YYABORT; } else { /* it is a row restriction */ if(HadConstraint && HadVar) store_re_op("", HadConstraint, HadVar, Had_lineair_sum); /* makes sure that data stored in temporary buffers is treated correctly */ do_add_row = TRUE; } } optionalrange END_C { if((!HadVar) && (!HadConstraint)) { yyerror("parse error"); YYABORT; } if(do_add_row) add_row(); HadConstraint = FALSE; HadVar = HadVar0 = FALSE; isign = 0; make_neg = 0; null_tmp_store(TRUE); } ; optionalrange: EMPTY { if((!HadVar1) && (Had_lineair_sum0)) if(!negate_constraint()) YYABORT; } | RE_OP { make_neg = 0; isign = 0; if(HadConstraint) HadVar = Had_lineair_sum = FALSE; HadVar0 = FALSE; if(!store_re_op((char *) ((*yytext == '<') ? ">" : (*yytext == '>') ? "<" : yytext), HadConstraint, HadVar, Had_lineair_sum)) YYABORT; } cons_term { f -= f1; } RHS_STORE { if((HadVar1) || (!HadVar2) || (HadVar0)) { yyerror("parse error"); YYABORT; } if(HadConstraint && !HadVar ) { /* it is a range */ /* already handled */ if(!negate_constraint()) YYABORT; } else if(!HadConstraint && HadVar) { /* it is a bound */ if(!store_bounds(TRUE)) YYABORT; } } ; x_lineair_sum2: EMPTY { /* to allow a range */ /* constraint: < max */ if(!HadConstraint) { yyerror("parse error"); YYABORT; } Had_lineair_sum = FALSE; } | x_lineair_sum3 { Had_lineair_sum = TRUE; } ; x_lineair_sum3 : x_lineair_sum | INF { isign = Sign; } RHS_STORE ; x_lineair_sum: { state = state0 = 0; } x_lineair_sum1 { if (state == 1) { /* RHS_STORE */ if ( (isign0 || !make_neg) && !(isign0 && !make_neg)) /* but not both! */ f0 = -f0; if(make_neg) f1 += f0; if(!rhs_store(f0, HadConstraint, HadVar, Had_lineair_sum)) YYABORT; } } ; x_lineair_sum1 : x_lineair_term | x_lineair_sum1 x_lineair_term ; x_lineair_term : x_SIGN x_lineair_term1 { if ((HadSign || state == 1) && (state0 == 1)) { /* RHS_STORE */ if ( (isign0 || !make_neg) && !(isign0 && !make_neg)) /* but not both! */ f0 = -f0; if(make_neg) f1 += f0; if(!rhs_store(f0, HadConstraint, HadVar, Had_lineair_sum)) YYABORT; } if (state == 1) { f0 = f; isign0 = isign; } if (state == 2) { if((HadSign) || (state0 != 1)) { isign0 = isign; f0 = 1.0; } if ( (isign0 || make_neg) && !(isign0 && make_neg)) /* but not both! */ f0 = -f0; if(!var_store(Last_var, f0, HadConstraint, HadVar, Had_lineair_sum)) { yyerror("var_store failed"); YYABORT; } HadConstraint |= HadVar; HadVar = HadVar0 = TRUE; } state0 = state; } ; x_lineair_term1 : REALCONS { state = 1; } | optional_AR_M_OP { if ((HasAR_M_OP) && (state != 1)) { yyerror("parse error"); YYABORT; } } VAR { state = 2; } ; RE_OP: RE_OPLE | RE_OPGE ; cons_term: x_SIGN REALCONS | INF { isign = Sign; } ; /* end constraints */ /* start common for objective & constraints */ REALCONS: INTCONS | CONS ; x_SIGN: EMPTY { isign = 0; HadSign = FALSE; } | SIGN { isign = Sign; HadSign = TRUE; } ; optional_AR_M_OP: EMPTY { HasAR_M_OP = FALSE; } | AR_M_OP { HasAR_M_OP = TRUE; } ; RHS_STORE: EMPTY { if ( (isign || !make_neg) && !(isign && !make_neg)) /* but not both! */ f = -f; if(!rhs_store(f, HadConstraint, HadVar, Had_lineair_sum)) YYABORT; isign = 0; } ; /* end common for objective & constraints */ /* start int_sec_sos_free_declarations */ int_sec_sos_free_declarations: EMPTY | real_int_sec_sos_free_decls ; real_int_sec_sos_free_decls: int_sec_sos_free_declaration | real_int_sec_sos_free_decls int_sec_sos_free_declaration ; SEC_INT_SEC_SOS_FREE: SEC_INT | SEC_SEC | SEC_SOS | SEC_FREE ; int_sec_sos_free_declaration: SEC_INT_SEC_SOS_FREE { Within_sos_decl1 = Within_sos_decl; } x_int_sec_sos_free_declaration ; xx_int_sec_sos_free_declaration: { if((!Within_int_decl) && (!Within_sec_decl) && (!Within_sos_decl1) && (!Within_free_decl)) { yyerror("parse error"); YYABORT; } SOStype = SOStype0; check_int_sec_sos_free_decl(Within_int_decl, Within_sec_decl, Within_sos_decl1 = (Within_sos_decl1 ? 1 : 0), Within_free_decl); } optionalsos vars optionalsostype END_C { if((Within_sos_decl1) && (SOStype == 0)) { yyerror("Unsupported SOS type (0)"); YYABORT; } } ; x_int_sec_sos_free_declaration: xx_int_sec_sos_free_declaration | x_int_sec_sos_free_declaration xx_int_sec_sos_free_declaration ; optionalsos: EMPTY | SOSDESCR { FREE(Last_var0); Last_var0 = strdup(Last_var); } sosdescr ; optionalsostype: EMPTY { if(Within_sos_decl1) { set_sos_type(SOStype); set_sos_weight((double) SOSweight, 1); } } | RE_OPLE INTCONS { if((Within_sos_decl1) && (!SOStype)) { set_sos_type(SOStype = (short) (f + .1)); } else { yyerror("SOS type not expected"); YYABORT; } } optionalSOSweight ; optionalSOSweight:EMPTY { set_sos_weight((double) SOSweight, 1); } | COLON INTCONS { set_sos_weight(f, 1); } ; vars: EMPTY | x_vars ; x_vars : onevarwithoptionalweight | x_vars optionalcomma onevarwithoptionalweight ; optionalcomma: EMPTY | COMMA ; variable: EMPTY { if(Within_sos_decl1 == 1) { char buf[16]; SOSweight++; sprintf(buf, "SOS%d", SOSweight); storevarandweight(buf); check_int_sec_sos_free_decl(Within_int_decl, Within_sec_decl, 2, Within_free_decl); Within_sos_decl1 = 2; SOSNr = 0; } storevarandweight(Last_var); if(Within_sos_decl1 == 2) { SOSNr++; set_sos_weight((double) SOSNr, 2); } } ; variablecolon: { if(!Within_sos_decl1) { yyerror("parse error"); YYABORT; } if(Within_sos_decl1 == 1) { FREE(Last_var0); Last_var0 = strdup(Last_var); } if(Within_sos_decl1 == 2) { storevarandweight(Last_var); SOSNr++; set_sos_weight((double) SOSNr, 2); } } ; sosweight: EMPTY { if(Within_sos_decl1 == 1) { char buf[16]; SOSweight++; sprintf(buf, "SOS%d", SOSweight); storevarandweight(buf); check_int_sec_sos_free_decl(Within_int_decl, Within_sec_decl, 2, Within_free_decl); Within_sos_decl1 = 2; SOSNr = 0; storevarandweight(Last_var0); SOSNr++; } set_sos_weight(f, 2); } ; sosdescr: EMPTY { /* SOS name */ if(Within_sos_decl1 == 1) { storevarandweight(Last_var0); set_sos_type(SOStype); check_int_sec_sos_free_decl(Within_int_decl, Within_sec_decl, 2, Within_free_decl); Within_sos_decl1 = 2; SOSNr = 0; SOSweight++; } } ; onevarwithoptionalweight: VAR variable | VARIABLECOLON variablecolon INTCONSorVARIABLE ; INTCONSorVARIABLE:REALCONS /* INTCONS */ sosweight | sosdescr x_onevarwithoptionalweight ; x_onevarwithoptionalweight: VAR variable | VARIABLECOLON variablecolon REALCONS /* INTCONS */ sosweight ; /* end int_sec_sos_free_declarations */ %% static void yy_delete_allocated_memory(void) { /* free memory allocated by flex. Otherwise some memory is not freed. This is a bit tricky. There is not much documentation about this, but a lot of reports of memory that keeps allocated */ /* If you get errors on this function call, just comment it. This will only result in some memory that is not being freed. */ # if defined YY_CURRENT_BUFFER /* flex defines the macro YY_CURRENT_BUFFER, so you should only get here if lp_rlp.h is generated by flex */ /* lex doesn't define this macro and thus should not come here, but lex doesn't has this memory leak also ...*/ yy_delete_buffer(YY_CURRENT_BUFFER); /* comment this line if you have problems with it */ yy_init = 1; /* make sure that the next time memory is allocated again */ yy_start = 0; # endif FREE(Last_var); FREE(Last_var0); } static int parse(void) { return(yyparse()); } lprec *read_lp1(lprec *lp, void *userhandle, read_modeldata_func read_modeldata, int verbose, char *lp_name) { yyin = (FILE *) userhandle; yyout = NULL; yylineno = 1; lp_input = read_modeldata; return(yacc_read(lp, verbose, lp_name, &yylineno, parse, yy_delete_allocated_memory)); } lprec * __WINAPI read_lp(FILE *filename, int verbose, char *lp_name) { return(read_lp1(NULL, filename, lp_input_yyin, verbose, lp_name)); } lprec * __WINAPI read_lpex(void *userhandle, read_modeldata_func read_modeldata, int verbose, char *lp_name) { return(read_lp1(NULL, userhandle, read_modeldata, verbose, lp_name)); } lprec *read_LP1(lprec *lp, char *filename, int verbose, char *lp_name) { FILE *fpin; if((fpin = fopen(filename, "r")) != NULL) { lp = read_lp1(lp, fpin, lp_input_yyin, verbose, lp_name); fclose(fpin); } else lp = NULL; return(lp); } lprec * __WINAPI read_LP(char *filename, int verbose, char *lp_name) { return(read_LP1(NULL, filename, verbose, lp_name)); } MYBOOL __WINAPI LP_readhandle(lprec **lp, FILE *filename, int verbose, char *lp_name) { if(lp != NULL) *lp = read_lp1(*lp, filename, lp_input_yyin, verbose, lp_name); return((lp != NULL) && (*lp != NULL)); }