Page MenuHomec4science

libmultiscale_doc_parser.cc
No OneTemporary

File Metadata

Created
Fri, Nov 8, 12:47

libmultiscale_doc_parser.cc

/**
* @file libmultiscale_doc_parser.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Fri Oct 10 16:40:09 2014
*
* @brief Manual parser
*
* @section LICENSE
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* LibMultiScale is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* LibMultiScale is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "libmultiscale_doc_parser.hh"
/* -------------------------------------------------------------------------- */
#include <boost/version.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#if (BOOST_VERSION/100)%1000 <= 55
#include <boost/spirit/home/phoenix/bind/bind_member_function.hpp>
#include <boost/spirit/home/phoenix/bind/bind_function.hpp>
#else
#include <boost/phoenix/bind/bind_member_function.hpp>
#include <boost/phoenix/bind/bind_function.hpp>
#endif
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
#include <fstream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
/* -------------------------------------------------------------------------- */
using namespace boost::spirit;
/* -------------------------------------------------------------------------- */
typedef unsigned int UInt;
/* -------------------------------------------------------------------------- */
#define _call(x) boost::phoenix::bind(&LibMultiScaleDocParser::x,this)
#define _call1(x,p1) boost::phoenix::bind(&LibMultiScaleDocParser::x,this,p1)
#define _call2(x,p1,p2) boost::phoenix::bind(&LibMultiScaleDocParser::x,this,p1,p2)
#define _call3(x,p1,p2,p3) boost::phoenix::bind(&LibMultiScaleDocParser::x,this,p1,p2,p3)
#define _call4(x,p1,p2,p3,p4) boost::phoenix::bind(&LibMultiScaleDocParser::x,this,p1,p2,p3,p4)
/* -------------------------------------------------------------------------- */
std::string debug(const std::string & v){
std::cerr << "AAAAAAAAAA " << v << " AAAAAAAAAAAAA" << std::endl;
return v;
}
#define _dbg(x,p1) boost::phoenix::bind(&debug,p1)
/* -------------------------------------------------------------------------- */
template <typename Iterator,typename Skipper>
LibMultiScaleDocParser<Iterator,Skipper>::LibMultiScaleDocParser() :
LibMultiScaleDocParser::base_type(start,"start") {
std::string stag_desc = "/* LMDESC";
std::string etag_desc = "*/";
std::string stag_keyword = "/* LMKEYWORD";
std::string etag_keyword = "*/";
std::string stag_heritance = "/* LMHERITANCE";
std::string etag_heritance = "*/";
std::string stag_example = "/* LMEXAMPLE";
std::string etag_example = "*/";
using qi::char_;
using qi::print;
using qi::space;
using qi::alnum;
using qi::alpha;
using qi::string;
using qi::lexeme;
using qi::on_error;
using qi::fail;
using boost::phoenix::ref;
using boost::phoenix::val;
using boost::phoenix::construct;
using boost::phoenix::at_c;
using boost::phoenix::push_back;
start = text(stag_desc)
> description[_val = _1]
>> *(*(char_ - string(stag_keyword) - string(stag_heritance) - string(stag_example))
>> (heritance[at_c<7>(_val) = _1] |
keyword[push_back(at_c<3>(_val),_1)] |
example[at_c<8>(_val) = _1]
)
);
lookup_todo = *(char_ - string("TODO")) > eoi;
lookup_type = *(string("return") | (char_ - declaration(_r1)))
> declaration(_r1)[_val = _1];
lookup_syntax = *(char_ - string("LMSYNTAX")) > eoi;
// quantity_type = string("Quantity<") > name > string(">");
vec_quantity_type = string("Quantity<") > name
> - string(",") > *(char_ - '>') > string(">");
c_type =
+(char_ - "return" - eol - space - "{" - "}"
- "<<" - ">>" );
declaration = ( vec_quantity_type // | quantity_type
| c_type)[_val = _1]
>> +space >> string(_r1)
>> brackets[_val += _1] >> ';';
brackets = -(string("[") > *(char_ -string("]")) > string("]"));
description = lit(stag_desc)
> (*space) > name[at_c<0>(_val) = _1]
> *(space-eol) > eol[at_c<1>(_val) = val("class")]
> innertext(etag_desc)[at_c<2>(_val) = _1]
> lit(etag_desc);
defaults = *(char_-')');
keyword = lit(stag_keyword)
> name[at_c<0>(_val) = _1] > eol
> innertext(etag_desc)[at_c<2>(_val) = _1]
> lit(etag_keyword) > *eol
> (((
string("this->parseTag")[at_c<1>(_val) = "Tag"]
|string("this->parseKeyword")[at_c<1>(_val) = "Keyword"]
) > "(\"" > string(at_c<0>(_val)) > "\","
> *string("this->") > name[at_c<4>(_val) = _1] > *(char_-")"-",")
> -(string(",") > defaults[at_c<9>(_val) = _1]))
|(string("this->parseVectorKeyword")[at_c<1>(_val) = "Keyword ["]
> "(\"" > string(at_c<0>(_val)) > "\","
> expr[at_c<1>(_val) += _1 + val(std::string("]"))]
> "," > *string("this->") > name[at_c<4>(_val) = _1]
> -(
string(",") > string("VEC_DEFAULTS(")
> defaults[at_c<9>(_val) = _1] > string(")")))
) > string(");");
expr = *(char_ - string(",") - space);
heritance = lit(stag_heritance)
> (*space) >
*(name[push_back(_val,_1)] > *(space-eol))
> lit(etag_heritance) > eol;
example = lit(stag_example)
> (*space) >
*(char_ - string(etag_example))
> lit(etag_example) > eol;
// parse everything but a starting tag
text = *(char_ - string(_r1));
// // parse a single name
name = +(alnum|string("_"));
// // parse everything but the end tag
innertext = *(char_ - string(_r1));
description.name("description");
lookup_type.name("lookup_type");
lookup_todo.name("lookup_todo");
heritance.name("heritance");
start.name("start");
c_type.name("c_type");
declaration.name("declaration");
name.name("name");
text.name("text");
innertext.name("innertext");
keyword.name("keyword");
expr.name("expr");
example.name("example");
on_error<fail>(start,_call4(errorHandlerMain,_1,_2,_3,_4));
on_error<fail>(lookup_type,_call4(errorHandlerMain,_1,_2,_3,_4));
on_error<fail>(lookup_todo,_call4(errorHandlerTodo,_1,_2,_3,_4));
on_error<fail>(lookup_syntax,_call4(errorHandlerSyntax,_1,_2,_3,_4));
}
/* -------------------------------------------------------------------------- */
template <typename Iterator,typename Skipper>
bool LibMultiScaleDocParser<Iterator,Skipper>::parse(LMDocData & result,
std::set<std::string> & internal_key_list){
fname = result.filename.native();
std::ifstream file(result.filename.c_str());
if (!file.good()) std::cerr << "could not open file: " << result.filename << std::endl;
std::string str((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
iter = str.begin();
end = str.end();
bool parsed = qi::phrase_parse(iter, end, start,
boost::spirit::ascii::blank,result);
result.filename = fname;
if (result.example == "" && internal_key_list.count(result.name) == 0){
std::cerr << fname << ":0:Warning: no LMEXAMPLE found in that class" << std::endl;
}
else if (result.example != "" && internal_key_list.count(result.name) != 0){
std::cerr << fname << ":0:Warning: an example was provided for an internal class" << std::endl;
}
if (!parsed) return parsed;
iter = str.begin();
std::string todo;
qi::parse(iter, end, lookup_todo,todo);
if (!parsed) return parsed;
iter = str.begin();
std::string syntax;
qi::parse(iter, end, lookup_syntax,syntax);
for (UInt i = 0; i < result.children.size(); ++i) {
LMDocData & child = result.children[i];
// if (child.type == "Tag" ||
// child.type == "Keyword" ||
// child.type == "Keyword []"){
path cc_file = result.filename;
path hh_file = cc_file.replace_extension(path(".hh"));
std::string h_fname = hh_file.native();
std::ifstream hfile(h_fname.c_str());
if (hfile.is_open() == false){
std::cerr << "fname:0:Error: cannot find header file " << h_fname << std::endl;
return false;
}
std::string hstr((std::istreambuf_iterator<char>(hfile)),
std::istreambuf_iterator<char>());
iter = hstr.begin();
end = hstr.end();
std::string c_type;
// std::cerr << "look for parameter " << child.name << " " << child.var_name << " " << child.type << std::endl;
parsed &= qi::parse(iter, end, lookup_type(child.var_name),c_type);
if (!parsed){
std::cerr << h_fname << ":" << 0 << ":Error could not parse variable "
<< child.name << " " << child.var_name << " " << child.type << std::endl;
return parsed;
}
// std::cerr << "found parameter " << child.name << " " << child.var_name << " " << c_type << std::endl;
child.c_type = c_type;
// }
iter = hstr.begin();
std::string todo;
qi::parse(iter, end, lookup_todo,todo);
if (!parsed) return parsed;
iter = hstr.begin();
std::string syntax;
qi::parse(iter, end, lookup_syntax,syntax);
}
return parsed;
}
/* -------------------------------------------------------------------------- */
template <typename Iterator,typename Skipper>
int LibMultiScaleDocParser<Iterator,Skipper>::getLineNumber(const std::string & text,
std::string & now_parsing){
int last_index = 0;
UInt count_lines = 0;
size_t index = text.find_first_of("\n", 0);
while (index != text.npos){
count_lines++;
last_index = index;
index = text.find_first_of("\n", last_index + 1);
// std::cerr << last_index << " " << index << std::endl;
}
// std::cerr << last_index << " " << index << std::endl;
now_parsing = text.substr(last_index+1,index);
return count_lines;
}
/* -------------------------------------------------------------------------- */
template <typename Iterator,typename Skipper>
void LibMultiScaleDocParser<Iterator,Skipper>::errorHandlerMain(const std::string::const_iterator & a,
const std::string::const_iterator& b,
const std::string::const_iterator & c,
const info & what){
std::string already_parsed(a,c);
std::string now_parsing;
UInt count_lines = getLineNumber(already_parsed,now_parsing);
std::string not_parsed = std::string(c,b);
int index = not_parsed.find_first_of("\n",0);
std::string mess = now_parsing + " ^^^^ " + not_parsed.substr(0,index);
std::cerr << fname << ":" << count_lines+1 << ":Error Expecting " << what << " here: \"" <<
mess << "\"" << std::endl;
}
/* -------------------------------------------------------------------------- */
template <typename Iterator,typename Skipper>
void LibMultiScaleDocParser<Iterator,Skipper>::errorHandlerTodo(const std::string::const_iterator & a,
const std::string::const_iterator& b,
const std::string::const_iterator & c,
const info & what){
std::string already_parsed(a,c);
// std::cerr << "already parsed " << already_parsed << std::endl;
std::string now_parsing;
UInt count_lines = getLineNumber(already_parsed,now_parsing);
std::cerr << fname << ":" << count_lines+1 << ":Warning TODO remaining: "
<< what << ": " << now_parsing <<std::endl;
}
/* -------------------------------------------------------------------------- */
template <typename Iterator,typename Skipper>
void LibMultiScaleDocParser<Iterator,Skipper>::errorHandlerSyntax(const std::string::const_iterator & a,
const std::string::const_iterator& b,
const std::string::const_iterator & c,
const info & what){
std::string already_parsed(a,c);
// std::cerr << "already parsed " << already_parsed << std::endl;
std::string now_parsing;
UInt count_lines = getLineNumber(already_parsed,now_parsing);
std::cerr << fname << ":" << count_lines+1 << ":Warning old Syntax remaining: "
<< what << ": " << now_parsing <<std::endl;
}
/* -------------------------------------------------------------------------- */
template class LibMultiScaleDocParser<std::string::const_iterator>;

Event Timeline