diff --git a/check/TestFilereader.cpp b/check/TestFilereader.cpp index b77bb9585c..dfb00233a6 100644 --- a/check/TestFilereader.cpp +++ b/check/TestFilereader.cpp @@ -143,6 +143,8 @@ TEST_CASE("filereader-edge-cases", "[highs_filereader]") { REQUIRE(read_status == HighsStatus::kError); model = "1451"; + // Vanilla .lp file, but for constraint named "end" which tests code + // to permit keywords as constraint names if (dev_run) printf("\n%s.lp\n", model.c_str()); model_file = std::string(HIGHS_DIR) + "/check/instances/" + model + ".lp"; read_status = highs.readModel(model_file); diff --git a/check/instances/1451.lp b/check/instances/1451.lp index a3bb488697..c79595d24b 100644 --- a/check/instances/1451.lp +++ b/check/instances/1451.lp @@ -1,7 +1,8 @@ Minimize x Subject to - x - 1 >= 2 +\ Name this constraint end to test for keywords as constraint names + end: x - 1 >= 2 Integer x End diff --git a/highs/io/filereaderlp/reader.cpp b/highs/io/filereaderlp/reader.cpp index dd85d4179b..d54b885768 100644 --- a/highs/io/filereaderlp/reader.cpp +++ b/highs/io/filereaderlp/reader.cpp @@ -55,6 +55,48 @@ enum class RawTokenType { ASTERISK }; +/* + // Useful for debugging +static std::string tokenTypeToString(const RawTokenType& type) { + switch (type) { + case RawTokenType::NONE: + return "None"; + case RawTokenType::STR: + return "String"; + case RawTokenType::CONS: + return "Constraint "; + case RawTokenType::LESS: + return "<="; + case RawTokenType::GREATER: + return ">="; + case RawTokenType::EQUAL: + return "="; + case RawTokenType::COLON: + return ":"; + case RawTokenType::LNEND: + return "\\n"; + case RawTokenType::FLEND: + return "EOF"; + case RawTokenType::BRKOP: + return "("; + case RawTokenType::BRKCL: + return ")"; + case RawTokenType::PLUS: + return "+"; + case RawTokenType::MINUS: + return "-"; + case RawTokenType::HAT: + return "^"; + case RawTokenType::SLASH: + return "/"; + case RawTokenType::ASTERISK: + return "*"; + default: + return "Unknown"; + } +} +*/ + struct RawToken { RawTokenType type = RawTokenType::NONE; std::string svalue; @@ -244,6 +286,7 @@ class Reader { std::vector::iterator end, std::shared_ptr expr, bool isobj); + // void printRawTokens(); public: Reader(std::string filename) { #ifdef ZLIB_FOUND @@ -872,8 +915,13 @@ void Reader::splittokens() { void Reader::processtokens() { std::string svalue_lc; while (!rawtokens[0].istype(RawTokenType::FLEND)) { - fflush(stdout); - + if (rawtokens[0].type == RawTokenType::STR) { + if (parsesectionkeyword(rawtokens[0].svalue) != LpSectionKeyword::NONE) { + // Found an LP section keyword so check it's not a constraint name! + if (rawtokens[1].type == RawTokenType::COLON) + rawtokens[0].type = RawTokenType::CONS; + } + } // Slash + asterisk: comment, skip everything up to next asterisk + slash if (rawtokens[0].istype(RawTokenType::SLASH) && rawtokens[1].istype(RawTokenType::ASTERISK)) { @@ -1119,6 +1167,8 @@ void Reader::processtokens() { assert(!rawtokens[0].istype(RawTokenType::FLEND)); // catch all unknown symbols + // + // printRawTokens(); lpassert(false); break; } @@ -1309,3 +1359,17 @@ bool Reader::readnexttoken(RawToken& t) { lpassert(false); return false; } + +/* + // Useful for debugging +void Reader::printRawTokens() { + for(int iToken=0; iToken < NRAWTOKEN; iToken++) { + const RawToken& rawtoken = rawtokens[iToken]; + printf("rawtokens[%d]: ", int(iToken)); + printf("type = %-12s", tokenTypeToString(rawtoken.type).c_str()); + printf("; svalue = %8s: ", rawtoken.svalue.c_str()); + if (iToken < NRAWTOKEN-1) printf("; "); + } + printf("\n"); +} +*/