Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Parser.cpp
Go to the documentation of this file.
1 // ============================================================================
2 // STD:
3 // ============================================================================
4 #include <fstream>
5 // ============================================================================
6 // BOOST:
7 // ============================================================================
8 #include <boost/filesystem.hpp>
9 #include <boost/format.hpp>
10 // ============================================================================
11 #include "Grammar.h"
12 #include "IncludedFiles.h"
13 #include "Iterator.h"
14 #include "Messages.h"
15 #include "Node.h"
16 #include "Parser.h"
17 #include "Utils.h"
18 // ============================================================================
19 // Gaudi:
20 // ============================================================================
22 // ============================================================================
23 namespace classic = boost::spirit::classic;
24 namespace bf = boost::filesystem;
25 namespace gp = Gaudi::Parsers;
26 namespace gpu = Gaudi::Parsers::Utils;
27 namespace qi = boost::spirit::qi;
28 // ============================================================================
29 namespace {
30  // ============================================================================
31  void GetLastLineAndColumn( std::ifstream& ifs, int& line, int& column ) {
32  int n = 0;
33  std::string str;
34  while ( !ifs.eof() ) {
35  getline( ifs, str );
36  ++n;
37  }
38  line = n;
39  column = str.length() + 1;
40  ifs.clear();
41  ifs.seekg( 0, ifs.beg );
42  }
43 
44  template <typename Grammar>
45  bool ParseStream( std::ifstream& stream, const std::string& stream_name, gp::Messages* messages, gp::Node* root ) {
46 
47  int last_line, last_column;
48 
49  GetLastLineAndColumn( stream, last_line, last_column );
50 
52 
53  BaseIterator in_begin( input.begin() );
54  // convert input iterator to forward iterator, usable by spirit parser
55  ForwardIterator fwd_begin = boost::spirit::make_default_multi_pass( in_begin );
56  ForwardIterator fwd_end;
57 
58  // wrap forward iterator with position iterator, to record the position
59 
60  Iterator position_begin( fwd_begin, fwd_end, stream_name );
61  Iterator position_end;
62 
63  Grammar gr;
64  gp::SkipperGrammar<Iterator> skipper;
65 
66  root->value = stream_name;
67  bool result = qi::phrase_parse( position_begin, position_end, gr, skipper, *root );
68 
69  const IteratorPosition& pos = position_begin.get_position();
70  if ( result && ( pos.line == last_line ) && ( pos.column == last_column ) ) { return true; }
71 
72  messages->AddError( gp::Position( stream_name, pos.line, pos.column ), "parse error" );
73  return false;
74  }
75 
76  // ============================================================================
77  template <typename Grammar>
78  bool ParseFile( const gp::Position& from, const std::string& filename, const std::string& search_path,
79  gp::IncludedFiles* included, gp::Messages* messages, gp::Node* root ) {
80  std::string search_path_with_current_dir = gpu::replaceEnvironments( search_path );
81  if ( !from.filename().empty() ) { // Add current file directory to search_path
82  bf::path file_path( from.filename() );
83  search_path_with_current_dir =
84  file_path.parent_path().string() +
85  ( search_path_with_current_dir.empty() ? "" : ( "," + search_path_with_current_dir ) );
86  }
87  std::string absolute_path =
88  System::PathResolver::find_file_from_list( gpu::replaceEnvironments( filename ), search_path_with_current_dir );
89 
90  if ( absolute_path.empty() ) {
91  messages->AddError( from, "Couldn't find a file " + filename + " in search path '" +
92  search_path_with_current_dir + "'" );
93  return false;
94  }
95  const gp::Position* included_from;
96  if ( !included->GetPosition( absolute_path, &included_from ) ) {
97  included->AddFile( absolute_path, from );
98  std::ifstream file{absolute_path};
99  if ( !file.is_open() ) {
100  messages->AddError( from, "Couldn't open a file " + filename );
101  return false;
102  }
103  return ParseStream<Grammar>( file, absolute_path, messages, root );
104  } else {
105  assert( included_from != NULL );
106  messages->AddWarning( from, str( boost::format( "File %1% already included from %2%" ) % absolute_path %
107  included_from->ToString() ) );
108  return true;
109  }
110  }
111  // ============================================================================
112 } // namespace
113 // ============================================================================
114 bool gp::Parse( const std::string& filename, const std::string& search_path, IncludedFiles* included,
115  Messages* messages, Node* root ) {
116  return Parse( Position(), filename, search_path, included, messages, root );
117 }
118 // ============================================================================
119 bool gp::Parse( const Position& from, const std::string& filename, const std::string& search_path,
120  IncludedFiles* included, Messages* messages, Node* root ) {
122  return ParseFile<Grammar>( from, filename, search_path, included, messages, root );
123 }
124 
125 // ============================================================================
126 bool gp::ParseUnits( const Position& from, const std::string& filename, const std::string& search_path,
127  IncludedFiles* included, Messages* messages, Node* root ) {
129  return ParseFile<Grammar>( from, filename, search_path, included, messages, root );
130 }
131 // ============================================================================
T empty(T...args)
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:109
bool ParseUnits(const Position &from, const std::string &filename, const std::string &search_path, IncludedFiles *included, Messages *messages, Node *root)
Definition: Parser.cpp:126
static std::string find_file_from_list(const std::string &logical_file_name, const std::string &search_list, SearchType search_type=LocalSearch)
T getline(T...args)
std::string::const_iterator BaseIterator
Definition: Iterator.h:16
std::string replaceEnvironments(const std::string &input)
Definition: Utils.cpp:18
T seekg(T...args)
boost::spirit::multi_pass< BaseIterator > ForwardIterator
Definition: Iterator.h:17
STL class.
T eof(T...args)
bool Parse(const std::string &filename, const std::string &search_path, IncludedFiles *included, Messages *messages, Node *root)
Definition: Parser.cpp:114
T clear(T...args)
T length(T...args)
boost::spirit::classic::position_iterator2< ForwardIterator > Iterator
Definition: Iterator.h:18
boost::spirit::classic::file_position_base< std::string > IteratorPosition
Definition: Iterator.h:19
STL class.