I'm trying to write an INI file parser/generator with spirit
as found in boost repo at r57337 (2009-11-03 18:35:33 +0100).
The grammar uses no skip parser, but I want to skip horizontal
space in part of it. What I have so far:
The else branch parses input just ok, it is the code I started
with. The other branches fail to parse my test input:
optname %= bareword;
optval %= bareword;
bareword %= lexeme[+alpha]
optionline
#if SKIP
%= skip[optname > '=' > optval]
#elif SKIP_S
%= skip(blank)[optname > '=' > optval]
#else
%= optname
> omit[*space]
> '='
> omit[*space]
> optval
#endif
> '\n'
;
the SKIP branch gives me:
Error! Expecting "=" here: " =two
third= three
fourth = four
...
the SKIP_S branch:
Error! Expecting <optval> here: " three
fourth = four
[bar]
...
[phini.cpp]
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
namespace phini
{
using boost::optional;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;
using ascii::alnum;
using ascii::alpha;
using ascii::blank;
using ascii::char_;
using ascii::digit;
using ascii::no_case;
using ascii::space;
using ascii::string;
using qi::int_;
using qi::lit;
using qi::lexeme;
using qi::skip;
using qi::eoi;
using qi::omit;
using phx::val;
using phx::construct;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::on_error;
using qi::fail;
namespace metagram
{
//typedef std::string bareword;
struct bareword : std::string {};
typedef bareword optname;
typedef bareword optval;
typedef bareword sectionname;
typedef std::pair<optname, optval> assignment;
typedef std::pair<sectionname, std::vector<assignment> > section;
typedef std::vector<section> config;
} // namespace metagram
template<class Iter>
struct
grammar
: qi::grammar<Iter, metagram::config()>
{
template<class T>
struct my
{
typedef qi::rule<Iter, T> rule;
};
grammar() : grammar::base_type(start)
{
start
%= *section
>> eoi
;
optionline
#if SKIP
%= skip[optname > '=' > optval]
#elif SKIP_S
%= skip(blank)[optname > '=' > optval]
#else
%= optname
> omit[*space]
> '='
> omit[*space]
> optval
#endif
> '\n'
;
section
%= headerline
> *optionline
;
headerline
%= lexeme['[' > sectionname > ']']
> '\n'
;
sectionname %= bareword;
optname %= bareword;
optval %= bareword;
bareword %= lexeme[+alpha];
on_error<fail>
(
start
, std::cout
<< val("Error! Expecting ")
<< _4
<< val(" here: \"")
<< construct<std::string>(_3, _2)
<< val("\"")
<< std::endl
);
}
typename my<metagram::config()>::rule start;
typename my<void()>::rule commentline;
typename my<metagram::assignment()>::rule optionline;
typename my<metagram::section()>::rule section;
typename my<metagram::sectionname()>::rule headerline;
typename my<metagram::sectionname()>::rule sectionname;
typename my<metagram::optname()>::rule optname;
typename my<metagram::optval()>::rule optval;
typename my<metagram::bareword()>::rule bareword;
typename my<void()>::rule comment;
};
template<class Iter>
optional<metagram::config>
parse(Iter & first, Iter last)
{
grammar<Iter> g;
metagram::config rv;
optional<metagram::config> oct;
bool ok = qi::parse(
first
, last
, g
, rv
);
if (ok && first == last)
oct = rv;
return oct;
}
} // namespace phini
int
main(int argc, char **argv)
{
std::string const s(argc > 1 ? argv[1] : "/dev/stdin");
std::ifstream input(s, std::ios_base::binary);
input.unsetf(std::ios::skipws);
std::istreambuf_iterator<char> b(input), e;
auto cfg = phini::parse(b, e);
if (!cfg) {
return 1;
}
BOOST_FOREACH(auto sec, *cfg) {
std::cout
<< "[" << sec.first << "]"
<< std::endl
;
BOOST_FOREACH(auto ass, sec.second) {
std::cout
<< ass.first
<< " = "
<< ass.second
<< std::endl
;
}
std::cout << std::endl;
}
return 0;
}
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.
http://p.sf.net/sfu/bobj-july_______________________________________________
Spirit-general mailing list
Spirit-general@...
https://lists.sourceforge.net/lists/listinfo/spirit-general