fix the case of file w/o newline at the end

toml::parse failed with the file that contains whitespace or comment at
the end of file without newline. this commit fixes the error.
This commit is contained in:
ToruNiina
2018-12-24 16:00:33 +09:00
parent d24a188d4c
commit 11c7ee4501

View File

@@ -1331,7 +1331,7 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
return err(std::string("toml::parse_ml_table: input is empty")); 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< using skip_line = repeat<
sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>; sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>;
skip_line::invoke(loc); skip_line::invoke(loc);
@@ -1367,6 +1367,17 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
return err(kv.unwrap_err()); 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); const auto newline = skip_line::invoke(loc);
if(!newline && loc.iter() != loc.end()) if(!newline && loc.iter() != loc.end())
{ {
@@ -1379,11 +1390,10 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
return err(msg); return err(msg);
} }
// comment lines are skipped by the above function call. // the skip_lines only matches with lines that includes newline.
// However, if the file ends with comment without newline, // to skip the last line that includes comment and/or whitespace
// it might cause parsing error because skip_line matches // but no newline, call them one more time.
// `comment + newline`, not `comment` itself. to skip the lex_ws::invoke(loc);
// last comment, call lex_comment one more time.
lex_comment::invoke(loc); lex_comment::invoke(loc);
} }
return ok(tab); return ok(tab);