need help with the skip[] directive

View: New views
1 Messages — Rating Filter:   Alert me  

Parent Message unknown need help with the skip[] directive

by Roman Neuhauser-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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

lf.ini (122 bytes) Download Attachment