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/format.hpp>
9 #include <boost/filesystem.hpp>
10 // ============================================================================
11 #include "Parser.h"
12 #include "Messages.h"
13 #include "Node.h"
14 #include "Grammar.h"
15 #include "Iterator.h"
16 #include "IncludedFiles.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,
46  const std::string& stream_name, gp::Messages* messages,
47  gp::Node* root) {
48 
49  int last_line, last_column;
50 
51  GetLastLineAndColumn(stream, last_line, last_column);
52 
55 
56  BaseIterator in_begin(input.begin());
57  // convert input iterator to forward iterator, usable by spirit parser
58  ForwardIterator fwd_begin =
59  boost::spirit::make_default_multi_pass(in_begin);
60  ForwardIterator fwd_end;
61 
62  // wrap forward iterator with position iterator, to record the position
63 
64  Iterator position_begin(fwd_begin, fwd_end, stream_name);
65  Iterator position_end;
66 
67  Grammar gr;
68  gp::SkipperGrammar<Iterator> skipper;
69 
70  root->value = stream_name;
71  bool result = qi::phrase_parse(position_begin,
72  position_end, gr, skipper, *root);
73 
74  const IteratorPosition& pos = position_begin.get_position();
75  if (result && (pos.line == last_line) && (pos.column == last_column)) {
76  return true;
77  }
78 
79  messages->AddError(gp::Position(stream_name, pos.line,
80  pos.column),"parse error");
81  return false;
82 }
83 
84 // ============================================================================
85 template<typename Grammar>
86 bool ParseFile(const gp::Position& from, const std::string& filename,
87  const std::string& search_path,
88  gp::IncludedFiles* included, gp::Messages* messages,gp::Node* root) {
89  std::string search_path_with_current_dir =
90  gpu::replaceEnvironments(search_path);
91  if (!from.filename().empty()) { // Add current file directory to search_path
92  bf::path file_path(from.filename());
93  search_path_with_current_dir = file_path.parent_path().string()
94  + (search_path_with_current_dir.empty()?""
95  :("," + search_path_with_current_dir));
96  }
98  gpu::replaceEnvironments(filename), search_path_with_current_dir);
99 
100  if (absolute_path.empty()) {
101  messages->AddError(from, "Couldn't find a file " + filename+
102  " in search path '"+ search_path_with_current_dir+"'");
103  return false;
104  }
105  const gp::Position* included_from;
106  if (!included->GetPosition(absolute_path, &included_from)){
107  included->AddFile(absolute_path, from);
108  std::ifstream file{absolute_path};
109  if (!file.is_open()) {
110  messages->AddError(from, "Couldn't open a file "+filename);
111  return false;
112  }
113  return ParseStream<Grammar>(file, absolute_path, messages, root);
114  } else {
115  assert(included_from != NULL);
116  messages->AddWarning(from,
117  str(boost::format("File %1% already included from %2%")
118  % absolute_path % included_from->ToString()));
119  return true;
120  }
121 }
122 // ============================================================================
123 }
124 // ============================================================================
125 bool gp::Parse(const std::string& filename,
126  const std::string& search_path, IncludedFiles* included,
127  Messages* messages, Node* root){
128  return Parse(Position(), filename, search_path, included, messages,
129  root);
130 }
131 // ============================================================================
132 bool gp::Parse(const Position& from,
133  const std::string& filename,
134  const std::string& search_path, IncludedFiles* included,
135  Messages* messages, Node* root) {
137  return ParseFile<Grammar>(from, filename, search_path, included,
138  messages, root);
139 }
140 
141 // ============================================================================
142 bool gp::ParseUnits(const Position& from,
143  const std::string& filename,
144  const std::string& search_path, IncludedFiles* included,
145  Messages* messages, Node* root) {
147  return ParseFile<Grammar>(from, filename, search_path, included,
148  messages, root);
149 }
150 // ============================================================================
T empty(T...args)
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
bool ParseUnits(const Position &from, const std::string &filename, const std::string &search_path, IncludedFiles *included, Messages *messages, Node *root)
Definition: Parser.cpp:142
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:125
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:20
STL class.