00001
00002
00003
00004
00005 #include <fstream>
00006
00007
00008
00009 #include <boost/format.hpp>
00010 #include <boost/filesystem.hpp>
00011
00012 #include "Parser.h"
00013 #include "Messages.h"
00014 #include "Node.h"
00015 #include "Grammar.h"
00016 #include "Iterator.h"
00017 #include "IncludedFiles.h"
00018 #include "Utils.h"
00019
00020
00021
00022 #include "GaudiKernel/PathResolver.h"
00023
00024 namespace classic = boost::spirit::classic;
00025 namespace bf = boost::filesystem;
00026 namespace gp= Gaudi::Parsers;
00027 namespace gpu= Gaudi::Parsers::Utils;
00028 namespace qi = boost::spirit::qi;
00029
00030 namespace {
00031
00032 template<typename Grammar>
00033 bool ParseStream(std::ifstream& stream,
00034 const std::string& stream_name, gp::Messages* messages,
00035 gp::Node* root) {
00036
00037 BaseIterator in_begin(stream);
00038
00039 ForwardIterator fwd_begin =
00040 boost::spirit::make_default_multi_pass(in_begin);
00041 ForwardIterator fwd_end;
00042
00043
00044
00045 Iterator position_begin(fwd_begin, fwd_end, stream_name);
00046 Iterator position_end;
00047
00048 Grammar gr;
00049 gp::SkipperGrammar<Iterator> skipper;
00050
00051 root->value = stream_name;
00052 bool result = qi::phrase_parse(position_begin,
00053 position_end, gr, skipper, *root);
00054 if (result && (position_begin==position_end)) {
00055 return true;
00056 }
00057 const IteratorPosition& pos = position_begin.get_position();
00058 messages->AddError(gp::Position(stream_name, pos.line,
00059 pos.column),"parse error");
00060 return false;
00061 }
00062
00063
00064 template<typename Grammar>
00065 bool ParseFile(const gp::Position& from, const std::string& filename,
00066 const std::string& search_path,
00067 gp::IncludedFiles* included, gp::Messages* messages,gp::Node* root) {
00068 std::string search_path_with_current_dir =
00069 gpu::replaceEnvironments(search_path);
00070 if (!from.filename().empty()) {
00071 bf::path file_path(from.filename());
00072 search_path_with_current_dir = file_path.parent_path().string()
00073 + (search_path_with_current_dir.empty()?""
00074 :("," + search_path_with_current_dir));
00075 }
00076 std::string absolute_path = System::PathResolver::find_file_from_list(
00077 gpu::replaceEnvironments(filename), search_path_with_current_dir);
00078
00079 if (absolute_path.empty()) {
00080 messages->AddError(from, "Couldn't find a file " + filename+
00081 " in search path '"+ search_path_with_current_dir+"'");
00082 return false;
00083 }
00084 const gp::Position* included_from;
00085 if (!included->GetPosition(absolute_path, &included_from)){
00086 included->AddFile(absolute_path, from);
00087 std::ifstream file(absolute_path.c_str());
00088 if (!file.is_open()) {
00089 messages->AddError(from, "Couldn't open a file "+filename);
00090 return false;
00091 }
00092 return ParseStream<Grammar>(file, absolute_path, messages, root);
00093 } else {
00094 assert(included_from != NULL);
00095 messages->AddWarning(from,
00096 str(boost::format("File %1% already included from %2%")
00097 % absolute_path % included_from->ToString()));
00098 return true;
00099 }
00100 }
00101
00102 }
00103
00104 bool gp::Parse(const std::string& filename,
00105 const std::string& search_path, IncludedFiles* included,
00106 Messages* messages, Node* root){
00107 return Parse(Position(), filename, search_path, included, messages,
00108 root);
00109 }
00110
00111 bool gp::Parse(const Position& from,
00112 const std::string& filename,
00113 const std::string& search_path, IncludedFiles* included,
00114 Messages* messages, Node* root) {
00115 typedef FileGrammar<Iterator,SkipperGrammar<Iterator> > Grammar;
00116 return ParseFile<Grammar>(from, filename, search_path, included,
00117 messages, root);
00118 }
00119
00120
00121 bool gp::ParseUnits(const Position& from,
00122 const std::string& filename,
00123 const std::string& search_path, IncludedFiles* included,
00124 Messages* messages, Node* root) {
00125 typedef UnitsGrammar<Iterator,SkipperGrammar<Iterator> > Grammar;
00126 return ParseFile<Grammar>(from, filename, search_path, included,
00127 messages, root);
00128 }
00129