The Gaudi Framework  master (37c0b60a)
Parser.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #include "Parser.h"
12 #include "Grammar.h"
13 #include "IncludedFiles.h"
14 #include "Iterator.h"
15 #include "Messages.h"
16 #include "Node.h"
17 #include "Utils.h"
19 #include <boost/filesystem.hpp>
20 #include <fmt/format.h>
21 #include <fstream>
22 #include <sstream>
23 
24 // ============================================================================
25 namespace classic = boost::spirit::classic;
26 namespace bf = boost::filesystem;
27 namespace gp = Gaudi::Parsers;
28 namespace gpu = Gaudi::Parsers::Utils;
29 namespace qi = boost::spirit::qi;
30 // ============================================================================
31 namespace {
32 
33  // Return last line and column number of text in `s` with newline delimiter `delim`
34  std::pair<int, int> GetLastLineAndColumn( std::string_view s, const char delim = '\n' ) {
35  size_t line = 1;
36  for ( size_t p = s.find( delim ); p != s.npos; p = s.find( delim ) ) {
37  s.remove_prefix( p + 1 );
38  ++line;
39  }
40  return { line, s.size() + 1 };
41  }
42 
43  template <typename Grammar>
44  bool ParseStream( std::ifstream& stream, const std::string& stream_name, gp::Messages* messages, gp::Node* root ) {
45  // Load input stream
46  const std::string input = ( std::ostringstream{} << stream.rdbuf() ).str();
47 
48  auto [last_line, last_column] = GetLastLineAndColumn( input );
49 
50  BaseIterator in_begin( input.begin() );
51  // convert input iterator to forward iterator, usable by spirit parser
52  ForwardIterator fwd_begin = boost::spirit::make_default_multi_pass( in_begin );
53  ForwardIterator fwd_end;
54 
55  // wrap forward iterator with position iterator, to record the position
56  Iterator position_begin( fwd_begin, fwd_end, stream_name );
57  Iterator position_end;
58 
59  Grammar gr;
61 
62  root->value = stream_name;
63  bool result = qi::phrase_parse( position_begin, position_end, gr, skipper, *root );
64 
65  const IteratorPosition& pos = position_begin.get_position();
66  if ( result && ( pos.line == last_line ) && ( pos.column == last_column ) ) { return true; }
67 
68  messages->AddError( gp::Position( stream_name, pos.line, pos.column ), "parse error" );
69  return false;
70  }
71 
72  // ============================================================================
73  template <typename Grammar>
74  bool ParseFile( const gp::Position& from, std::string_view filename, std::string_view search_path,
75  gp::IncludedFiles* included, gp::Messages* messages, gp::Node* root ) {
76  std::string search_path_with_current_dir = gpu::replaceEnvironments( search_path );
77  if ( !from.filename().empty() ) { // Add current file directory to search_path
78  bf::path file_path( from.filename() );
79  search_path_with_current_dir =
80  file_path.parent_path().string() +
81  ( search_path_with_current_dir.empty() ? "" : ( "," + search_path_with_current_dir ) );
82  }
83  std::string absolute_path =
85 
86  if ( absolute_path.empty() ) {
87  messages->AddError( from, "Couldn't find a file " + std::string{ filename } + " in search path '" +
88  search_path_with_current_dir + "'" );
89  return false;
90  }
91  const gp::Position* included_from;
92  if ( !included->GetPosition( absolute_path, &included_from ) ) {
93  included->AddFile( absolute_path, from );
94  std::ifstream file{ absolute_path };
95  if ( !file.is_open() ) {
96  messages->AddError( from, std::string{ "Couldn't open a file " }.append( filename ) );
97  return false;
98  }
99  return ParseStream<Grammar>( file, absolute_path, messages, root );
100  } else {
101  assert( included_from != nullptr );
102  messages->AddWarning(
103  from, fmt::format( "File {} already included from {}", absolute_path, included_from->ToString() ) );
104  return true;
105  }
106  }
107  // ============================================================================
108 } // namespace
109 // ============================================================================
110 bool gp::Parse( std::string_view filename, std::string_view search_path, IncludedFiles* included, Messages* messages,
111  Node* root ) {
112  return Parse( Position(), filename, search_path, included, messages, root );
113 }
114 // ============================================================================
115 bool gp::Parse( const Position& from, std::string_view filename, std::string_view search_path, IncludedFiles* included,
116  Messages* messages, Node* root ) {
118  return ParseFile<Grammar>( from, filename, search_path, included, messages, root );
119 }
120 
121 // ============================================================================
122 bool gp::ParseUnits( const Position& from, std::string_view filename, std::string_view search_path,
123  IncludedFiles* included, Messages* messages, Node* root ) {
125  return ParseFile<Grammar>( from, filename, search_path, included, messages, root );
126 }
127 // ============================================================================
Write.stream
stream
Definition: Write.py:32
std::string
STL class.
graphanalysis.gr
gr
Definition: graphanalysis.py:131
Grammar.h
AtlasMCRecoFullPrecedenceDump.path
path
Definition: AtlasMCRecoFullPrecedenceDump.py:49
BaseIterator
std::string::const_iterator BaseIterator
Definition: Iterator.h:26
std::pair< int, int >
Gaudi::Parsers::Position::filename
const std::string & filename() const
Definition: Position.h:28
gaudirun.s
string s
Definition: gaudirun.py:346
IteratorPosition
boost::spirit::classic::file_position_base< std::string > IteratorPosition
Definition: Iterator.h:29
gaudiComponentHelp.root
root
Definition: gaudiComponentHelp.py:42
Gaudi::Parsers::FileGrammar
Definition: Grammar.h:144
Gaudi::Parsers::Node
Definition: Node.h:35
ForwardIterator
boost::spirit::multi_pass< BaseIterator > ForwardIterator
Definition: Iterator.h:27
Gaudi::Parsers::IncludedFiles::AddFile
bool AddFile(std::string filename, Position from)
Definition: IncludedFiles.cpp:25
Gaudi::Parsers::IncludedFiles::GetPosition
bool GetPosition(std::string_view filename, const Position **pos) const
Definition: IncludedFiles.cpp:29
Utils.h
IncludedFiles.h
Gaudi::Parsers::Utils
Definition: Utils.h:21
Gaudi::Parsers::Utils::replaceEnvironments
std::string replaceEnvironments(std::string_view input)
Definition: Utils.cpp:28
Gaudi::Parsers::Position
Definition: Position.h:23
Gaudi::Parsers::Messages
Definition: Messages.h:31
Gaudi::Parsers::Position::ToString
std::string ToString() const
Definition: Position.cpp:14
Gaudi::Parsers::Parse
bool Parse(std::string_view filename, std::string_view search_path, IncludedFiles *included, Messages *messages, Node *root)
Definition: Parser.cpp:110
Gaudi::Parsers::SkipperGrammar
Definition: Grammar.h:51
Iterator.h
format
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
Parser.h
Gaudi::Parsers::IncludedFiles
Definition: IncludedFiles.h:26
std::string::append
T append(T... args)
Messages.h
std::ostringstream
STL class.
Gaudi::Parsers::UnitsGrammar
Definition: Grammar.h:127
Gaudi::Parsers::Messages::AddError
void AddError(std::string_view error)
Definition: Messages.h:39
Gaudi::Parsers::Messages::AddWarning
void AddWarning(std::string_view warning)
Definition: Messages.h:37
Node.h
std::string::begin
T begin(T... args)
std::string::empty
T empty(T... args)
plotSpeedupsPyRoot.line
line
Definition: plotSpeedupsPyRoot.py:198
Gaudi::Parsers
Definition: DODBasicMapper.cpp:17
Gaudi::Parsers::ParseUnits
bool ParseUnits(const Position &from, std::string_view filename, std::string_view search_path, IncludedFiles *included, Messages *messages, Node *root)
Definition: Parser.cpp:122
PathResolver.h
graphanalysis.filename
filename
Definition: graphanalysis.py:130
System::PathResolver::find_file_from_list
static std::string find_file_from_list(const std::string &logical_file_name, const std::string &search_list, SearchType search_type=LocalSearch)
Definition: PathResolver.cpp:129
Iterator
boost::spirit::classic::position_iterator2< ForwardIterator > Iterator
Definition: Iterator.h:28
std::ifstream
STL class.