diff --git a/toml/parser.hpp b/toml/parser.hpp
index ab309fb..07a23d5 100644
--- a/toml/parser.hpp
+++ b/toml/parser.hpp
@@ -1331,7 +1331,7 @@ result
parse_ml_table(location& loc)
return err(std::string("toml::parse_ml_table: input is empty"));
}
- // XXX at lest one newline is needed
+ // XXX at lest one newline is needed.
using skip_line = repeat<
sequence, maybe, lex_newline>, at_least<1>>;
skip_line::invoke(loc);
@@ -1367,6 +1367,17 @@ result parse_ml_table(location& loc)
return err(kv.unwrap_err());
}
+ // comment lines are skipped by the above function call.
+ // However, since the `skip_line` requires at least 1 newline, it fails
+ // if the file ends with ws and/or comment without newline.
+ // `skip_line` matches `ws? + comment? + newline`, not `ws` or `comment`
+ // itself. To skip the last ws and/or comment, call lexers.
+ // It does not matter if these fails, so the return value is discarded.
+ lex_ws::invoke(loc);
+ lex_comment::invoke(loc);
+
+ // skip_line is (whitespace? comment? newline)_{1,}. multiple empty lines
+ // and comments after the last key-value pairs are allowed.
const auto newline = skip_line::invoke(loc);
if(!newline && loc.iter() != loc.end())
{
@@ -1379,11 +1390,10 @@ result parse_ml_table(location& loc)
return err(msg);
}
- // comment lines are skipped by the above function call.
- // However, if the file ends with comment without newline,
- // it might cause parsing error because skip_line matches
- // `comment + newline`, not `comment` itself. to skip the
- // last comment, call lex_comment one more time.
+ // the skip_lines only matches with lines that includes newline.
+ // to skip the last line that includes comment and/or whitespace
+ // but no newline, call them one more time.
+ lex_ws::invoke(loc);
lex_comment::invoke(loc);
}
return ok(tab);