Created
October 13, 2012 20:34
-
-
Save sehe/3886058 to your computer and use it in GitHub Desktop.
Parsing a number of named sets of other named sets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
test | |
*.o | |
*~ | |
*.sw? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# comment | |
# other comment | |
set "Myset A" | |
{ | |
figure "AF 1" | |
{ | |
i 0 0 0 | |
i 1 2 5 | |
i 1 1 1 | |
f 3.1 45.11 5.3 | |
i 3 1 5 | |
f 1.1 2.33 5.166 | |
} | |
figure "AF 2" | |
{ | |
i 25 5 1 | |
i 3 1 3 | |
} | |
} | |
# comment | |
set "Myset B" | |
{ | |
figure "BF 1" | |
{ | |
f 23.1 4.3 5.11 | |
} | |
} | |
set "Myset C" | |
{ | |
include "Myset A" # includes all figures from Myset A | |
figure "CF" | |
{ | |
i 1 1 1 | |
f 3.11 5.33 3 | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all:test output.txt | |
CPPFLAGS+=-std=c++0x | |
CPPFLAGS+=-g -O0 | |
CPPFLAGS+=-I ~/custom/boost/ | |
CPPFLAGS+=-march=native | |
# CXX=/usr/lib/gcc-snapshot/bin/g++ | |
# CC=/usr/lib/gcc-snapshot/bin/gcc | |
# CXX=~/Projects/CLANG/build/Debug+Asserts/bin/clang++ | |
# CC=~/Projects/CLANG/build/Debug+Asserts/bin/clang | |
%:%.cpp | |
$(CXX) $(CPPFLAGS) $^ -o $@ $(LDFLAGS) | |
output.txt: test | |
./test > $@ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# figure sets exported automatically by karma | |
set "Myset A" | |
{ | |
figure "AF 1" | |
{ | |
i 0 0 0 | |
i 1 2 5 | |
i 1 1 1 | |
f 3.1 45.11 5.3 | |
i 3 1 5 | |
f 1.1 2.33 5.166 | |
} | |
figure "AF 2" | |
{ | |
i 25 5 1 | |
i 3 1 3 | |
} | |
} | |
set "Myset B" | |
{ | |
figure "BF 1" | |
{ | |
f 23.1 4.3 5.11 | |
} | |
} | |
set "Myset C" | |
{ | |
include "Myset A" | |
figure "CF" | |
{ | |
i 1 1 1 | |
f 3.11 5.33 3.0 | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#define BOOST_SPIRIT_DEBUG // before including Spirit | |
#define BOOST_SPIRIT_USE_PHOENIX_V3 | |
#include <boost/fusion/adapted.hpp> | |
#include <boost/spirit/include/qi.hpp> | |
#include <boost/spirit/include/karma.hpp> | |
#include <boost/spirit/include/phoenix.hpp> | |
#include <boost/spirit/include/phoenix_fusion.hpp> | |
#include <fstream> | |
namespace Format | |
{ | |
struct int_point { int x, y, z; }; | |
struct float_point { float x, y, z; }; | |
typedef boost::variant<int_point, float_point> if_point; | |
struct figure | |
{ | |
std::string name; | |
std::vector<if_point> if_points; | |
}; | |
struct figure_set | |
{ | |
std::string name; | |
std::set<std::string> includes; | |
std::vector<figure> figures; | |
}; | |
typedef std::vector<figure_set> file_data; | |
} | |
BOOST_FUSION_ADAPT_STRUCT(Format::int_point, | |
(int, x)(int, y)(int, z)) | |
BOOST_FUSION_ADAPT_STRUCT(Format::float_point, | |
(float, x)(float, y)(float, z)) | |
BOOST_FUSION_ADAPT_STRUCT(Format::figure, | |
(std::string, name) | |
(std::vector<Format::if_point>, if_points)) | |
BOOST_FUSION_ADAPT_STRUCT(Format::figure_set, | |
(std::string, name) | |
(std::set<std::string>, includes) | |
(std::vector<Format::figure>, figures)) | |
namespace /*anon*/ | |
{ | |
namespace phx = boost::phoenix; | |
namespace qi = boost::spirit::qi; | |
namespace karma = boost::spirit::karma; | |
template <typename Iterator> struct skipper | |
: public qi::grammar<Iterator> | |
{ | |
skipper() : skipper::base_type(start, "skipper") | |
{ | |
using namespace qi; | |
comment = '#' >> *(char_ - eol) >> (eol|eoi); | |
start = comment | qi::space; | |
BOOST_SPIRIT_DEBUG_NODE(start); | |
BOOST_SPIRIT_DEBUG_NODE(comment); | |
} | |
private: | |
qi::rule<Iterator> start, comment; | |
}; | |
template <typename Iterator> struct parser | |
: public qi::grammar<Iterator, Format::file_data(), skipper<Iterator> > | |
{ | |
parser() : parser::base_type(start, "parser") | |
{ | |
using namespace qi; | |
using phx::push_back; | |
using phx::at_c; | |
name = lexeme [ '"' >> *~char_('"') >> '"' ]; | |
include = "include" >> name; | |
ipoints = "i" >> int_ >> int_ >> int_; | |
fpoints = "f" >> float_ >> float_ >> float_; | |
figure = "figure" >> name >> '{' >> *(ipoints | fpoints) >> '}'; | |
set = "set" >> name >> '{' >> *include >> *figure >> '}'; | |
start = *set; | |
} | |
private: | |
qi::rule<Iterator, std::string() , skipper<Iterator> > name, include; | |
qi::rule<Iterator, Format::int_point() , skipper<Iterator> > ipoints; | |
qi::rule<Iterator, Format::float_point(), skipper<Iterator> > fpoints; | |
qi::rule<Iterator, Format::figure() , skipper<Iterator> > figure; | |
qi::rule<Iterator, Format::figure_set() , skipper<Iterator> > set; | |
qi::rule<Iterator, Format::file_data() , skipper<Iterator> > start; | |
}; | |
template <typename Iterator> struct generator | |
: public karma::grammar<Iterator, Format::file_data(), char> | |
{ | |
generator() : generator::base_type(start, "generator") | |
{ | |
using namespace karma; | |
name = no_delimit ['"' << string << '"']; | |
include = "include" << name; | |
ipoints = "\n i" << int_ << int_ << int_; | |
fpoints = "\n f" << float_ << float_ << float_; | |
figure = "figure" << name << "\n {" << *(ipoints | fpoints) << "\n }"; | |
set = "set" << name << "\n{" | |
<< *("\n " << include) | |
<< *("\n " << figure) << "\n}"; | |
start = "# figure sets exported automatically by karma\n\n" << set % eol; | |
} | |
private: | |
karma::rule<Iterator, std::string() , char> name, include; | |
karma::rule<Iterator, Format::int_point() , char> ipoints; | |
karma::rule<Iterator, Format::float_point(), char> fpoints; | |
karma::rule<Iterator, Format::figure() , char> figure; | |
karma::rule<Iterator, Format::figure_set() , char> set; | |
karma::rule<Iterator, Format::file_data() , char> start; | |
}; | |
} | |
namespace Parser { | |
bool parsefile(const std::string& spec, Format::file_data& data) | |
{ | |
std::ifstream in(spec.c_str()); | |
in.unsetf(std::ios::skipws); | |
std::string v; | |
v.reserve(4096); | |
v.insert(v.end(), std::istreambuf_iterator<char>(in.rdbuf()), std::istreambuf_iterator<char>()); | |
if (!in) | |
return false; | |
typedef char const * iterator_type; | |
iterator_type first = &v[0]; | |
iterator_type last = first+v.size(); | |
try | |
{ | |
parser<iterator_type> p; | |
skipper<iterator_type> s; | |
bool r = qi::phrase_parse(first, last, p, s, data); | |
r = r && (first == last); | |
if (!r) | |
std::cerr << spec << ": parsing failed at: \"" << std::string(first, last) << "\"\n"; | |
return r; | |
} | |
catch (const qi::expectation_failure<char const *>& e) | |
{ | |
std::cerr << "FIXME: expected " << e.what_ << ", got '" << std::string(e.first, e.last) << "'" << std::endl; | |
return false; | |
} | |
} | |
} | |
int main() | |
{ | |
Format::file_data data; | |
bool ok = Parser::parsefile("input.txt", data); | |
std::cerr << "Parse " << (ok?"success":"failed") << std::endl; | |
generator<boost::spirit::karma::ostream_iterator<char> > g; | |
std::cout << format_delimited(g, ' ', data); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment