19 #include <boost/filesystem.hpp>
20 #include <fmt/format.h>
24 namespace bf = boost::filesystem;
27 namespace qi = boost::spirit::qi;
31 std::pair<int, int> GetLastLineAndColumn( std::string_view
s,
const char delim =
'\n' ) {
33 for (
size_t p =
s.find( delim ); p !=
s.npos; p =
s.find( delim ) ) {
34 s.remove_prefix( p + 1 );
37 return {
line,
s.size() + 1 };
40 template <
typename Grammar>
43 const std::string input = ( std::ostringstream{} <<
stream.rdbuf() ).str();
45 auto [last_line, last_column] = GetLastLineAndColumn( input );
49 ForwardIterator fwd_begin = boost::spirit::make_default_multi_pass( in_begin );
53 Iterator position_begin( fwd_begin, fwd_end, stream_name );
59 root->value = stream_name;
60 bool result = qi::phrase_parse( position_begin, position_end,
gr, skipper, *
root );
63 if ( result && ( pos.line == last_line ) && ( pos.column == last_column ) ) {
return true; }
69 template <
typename Grammar>
70 bool ParseFile(
const gp::Position& from, std::string_view
filename, std::string_view search_path,
75 search_path_with_current_dir =
76 file_path.parent_path().string() +
77 ( search_path_with_current_dir.empty() ?
"" : (
"," + search_path_with_current_dir ) );
79 std::string absolute_path =
82 if ( absolute_path.empty() ) {
83 messages->
AddError( from,
"Couldn't find a file " + std::string{
filename } +
" in search path '" +
84 search_path_with_current_dir +
"'" );
88 if ( !included->
GetPosition( absolute_path, &included_from ) ) {
89 included->
AddFile( absolute_path, from );
90 std::ifstream file{ absolute_path };
91 if ( !file.is_open() ) {
92 messages->
AddError( from, std::string{
"Couldn't open a file " }.append(
filename ) );
95 return ParseStream<Grammar>( file, absolute_path, messages,
root );
97 assert( included_from !=
nullptr );
99 from,
fmt::format(
"File {} already included from {}", absolute_path, included_from->
ToString() ) );
113 return ParseFile<Grammar>( from,
filename, search_path, included, messages,
root );
119 return ParseFile<Grammar>( from,
filename, search_path, included, messages,
root );