Skip to content

Commit

Permalink
Let pgn_impl::parse_token determine when a game is terminated.
Browse files Browse the repository at this point in the history
The parser's functions can still return false to interrupt.
  • Loading branch information
benini committed Feb 1, 2023
1 parent d2c8ca4 commit e5b51a9
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 27 deletions.
12 changes: 8 additions & 4 deletions src/pgn_lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ template <typename TView> 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 <typename TInput, typename TVisitor>
bool parse_token(char ch, TInput& input, TVisitor& parser, int& section) {
Expand All @@ -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();
Expand Down Expand Up @@ -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);
}
Expand Down
42 changes: 19 additions & 23 deletions src/pgnparse.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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; }
Expand All @@ -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':
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit e5b51a9

Please sign in to comment.