From e5b51a92dc78a0692efacc84d700a0258156a18a Mon Sep 17 00:00:00 2001 From: Fulvio Date: Wed, 1 Feb 2023 17:02:53 +0100 Subject: [PATCH] Let pgn_impl::parse_token determine when a game is terminated. The parser's functions can still return false to interrupt. --- src/pgn_lexer.h | 12 ++++++++---- src/pgnparse.h | 42 +++++++++++++++++++----------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/pgn_lexer.h b/src/pgn_lexer.h index b14cb5cc3..9e5aad286 100644 --- a/src/pgn_lexer.h +++ b/src/pgn_lexer.h @@ -152,7 +152,8 @@ template char is_PGNtermination(TView tok) { * @param input: the input to get data from. * @param parser: will receive the tokens via visitPGN_* functions. * @param section: -1 pregame, 0 for tag pair section, 1 for movetext section. - * @returns the result of the invoked parser's function. + * @return: false if it parsed the last token of the game, otherwise return the + * result of the parser's invoked function. */ template bool parse_token(char ch, TInput& input, TVisitor& parser, int& section) { @@ -176,7 +177,8 @@ bool parse_token(char ch, TInput& input, TVisitor& parser, int& section) { return true; case '*': // self terminating - return parser.visitPGN_ResultFinal('*'); + parser.visitPGN_ResultFinal('*'); + return false; case '(': // self terminating return parser.visitPGN_VariationStart(); @@ -277,8 +279,10 @@ bool parse_token(char ch, TInput& input, TVisitor& parser, int& section) { if (notdigit == tok.second) return parser.visitPGN_MoveNum(tok); - if (auto result = is_PGNtermination(tok)) - return parser.visitPGN_ResultFinal(result); + if (auto result = is_PGNtermination(tok)) { + parser.visitPGN_ResultFinal(result); + return false; + } return parser.visitPGN_Unknown(tok); } diff --git a/src/pgnparse.h b/src/pgnparse.h index b0838d360..d470bcad2 100644 --- a/src/pgnparse.h +++ b/src/pgnparse.h @@ -47,19 +47,15 @@ class PgnVisitor { public: explicit PgnVisitor(Game& g) : game(g) {} - bool visitPGN_inputEOF() { - if (nErrorsAllowed_ < 0) // Skip until the end of the game - return true; - - return logErr("Unexpected end of input (result missing ?)."); + void visitPGN_inputEOF() { + if (nErrorsAllowed_) + logErr("Unexpected end of input (result missing ?)."); } - bool visitPGN_inputUnexpectedPGNHeader() { - if (nErrorsAllowed_ < 0) // Skip until the end of the game - return true; - - return logErr("Unexpected end of game: PGN header '[' seen " - "inside game (result missing ?)."); + void visitPGN_inputUnexpectedPGNHeader() { + if (nErrorsAllowed_) + logErr("Unexpected end of game: PGN header '[' seen " + "inside game (result missing ?)."); } bool visitPGN_Comment(TView comment) { @@ -81,17 +77,18 @@ class PgnVisitor { return true; } - bool visitPGN_EPD(TView line) { + void visitPGN_EPD(TView line) { ASSERT(nErrorsAllowed_ >= 0); std::string tmp(line.first, line.second); - if (game.SetStartFen(tmp.c_str()) != OK) - return logErr("Failed to parse EPD record: ", line); - - int spaces = 0; - auto opcode = std::find_if(line.first, line.second, [&](char ch) { - return (ch == ' ') ? spaces++ == 4 : spaces == 4; - }); - return visitPGN_Comment(std::make_pair(opcode, line.second)); + if (game.SetStartFen(tmp.c_str()) == OK) { + auto opcode = std::find_if( + line.first, line.second, [spaces = 0](char ch) mutable { + return (ch == ' ') ? spaces++ == 4 : spaces == 4; + }); + visitPGN_Comment(std::make_pair(opcode, line.second)); + } else { + logFatalErr("Failed to parse EPD record: ", line); + } } bool visitPGN_Escape(TView) { return true; } @@ -109,7 +106,7 @@ class PgnVisitor { return true; } - bool visitPGN_ResultFinal(char resultCh) { + void visitPGN_ResultFinal(char resultCh) { auto result = RESULT_None; switch (resultCh) { case '0': @@ -132,7 +129,6 @@ class PgnVisitor { if (prev_result != RESULT_None && nErrorsAllowed_ >= 0) logErr("Final result did not match the header tag."); } - return false; } bool visitPGN_SANMove(TView tok) { @@ -371,7 +367,7 @@ inline bool pgnParseGame(const char* input, size_t inputLen, Game& game, PgnParseLog& log) { struct VisitorNoEOF : public PgnVisitor { explicit VisitorNoEOF(Game& g) : PgnVisitor(g) {} - bool visitPGN_inputEOF() { return true; } + void visitPGN_inputEOF() {} } visitor(game); auto parse = pgn::parse_game({input, input + inputLen}, visitor);