2

I am completely new to boost:spirit and guess this question is trivial for an advanced users. The following grammar doesn't do what I expect:

    #pragma once

    #include <string>
    #include <vector>

    #define BOOST_SPIRIT_UNICODE
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix_core.hpp>
    #include <boost/spirit/include/qi_alternative.hpp>


    namespace overmath
    {
        using namespace std;
        namespace qi = boost::spirit::qi;
        using namespace boost::spirit::unicode;

        struct identifier
        {
            wstring name;
        };

        struct function
        {
            identifier name;
        };

        struct program
        {
            vector<function> functions;
        };
    }

    BOOST_FUSION_ADAPT_STRUCT(
        overmath::identifier,
        (std::wstring, name)
    )

    BOOST_FUSION_ADAPT_STRUCT(
        overmath::function,
        (overmath::identifier, name)
    )

    BOOST_FUSION_ADAPT_STRUCT(
        overmath::program,
        (std::vector<overmath::function>, functions)
    )


    namespace overmath
    {
        using namespace boost::spirit::unicode;
        namespace qi = boost::spirit::qi;
        using boost::spirit::lit;

        template<typename Iterator> struct function_parser : qi::grammar<Iterator, program(), space_type>
        {
            function_parser() : function_parser::base_type(program)
            {
                identifier %=
                    qi::eps
                    >> +alnum;

                function %=
                    lit("def ")
                    >> identifier
                    >> '('
                    >> ')'
                    >> lit(" enddef");

                program %=
                    qi::eps
                    >> +function;
            }

            qi::rule<Iterator, identifier(), space_type> identifier;
            qi::rule<Iterator, function(), space_type> function;
            qi::rule<Iterator, program(), space_type> program;
        };

        template<typename Iterator> wstring parse(Iterator first, Iterator last)
        {
            using boost::spirit::qi::phrase_parse;

            program f;
            function_parser<Iterator> fp;

            auto b = phrase_parse(first, last, fp, space, f);
            if(b)
            {
                return wstring(L"OK");
            }
            return wstring(L"FAIL");
        }

    }

When I test it with the string "def abc() enddef" parsing fails. I have no idea why. What did I do incorrectly? Thanks a lot in advance.

sehe
  • 374,641
  • 47
  • 450
  • 633
Sakuragaoka
  • 177
  • 1
  • 8

1 Answers1

3

Your skipper eats spaces, so "def " and " enddef" will never match.

See also Boost spirit skipper issues

Live On Coliru

#include <string>
#include <vector>

#define BOOST_SPIRIT_UNICODE
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/qi_alternative.hpp>

namespace overmath {
    using namespace std;
    namespace qi = boost::spirit::qi;
    using namespace boost::spirit::unicode;

    struct identifier { wstring name;               } ;
    struct function   { identifier name;            } ;
    struct program    { vector<function> functions; } ;
}

BOOST_FUSION_ADAPT_STRUCT(overmath::identifier, (std::wstring,                    name))
BOOST_FUSION_ADAPT_STRUCT(overmath::function,   (overmath::identifier,            name))
BOOST_FUSION_ADAPT_STRUCT(overmath::program,    (std::vector<overmath::function>, functions))

namespace overmath {
    using namespace boost::spirit::unicode;
    namespace qi = boost::spirit::qi;
    using boost::spirit::lit;

    template <typename Iterator> struct function_parser : qi::grammar<Iterator, program(), space_type> {
        function_parser() : function_parser::base_type(program) {

            identifier = qi::eps >> +alnum;
            function   = "def" >> identifier >> '(' >> ')' >> "enddef";
            program    = qi::eps >> +function;
        }

        qi::rule<Iterator, identifier()> identifier;
        qi::rule<Iterator, function(),   space_type> function;
        qi::rule<Iterator, program(),    space_type> program;
    };

    template <typename Iterator> wstring parse(Iterator first, Iterator last) {
        using boost::spirit::qi::phrase_parse;

        program f;
        function_parser<Iterator> fp;

        auto b = phrase_parse(first, last, fp, space, f);
        if (b) {
            return wstring(L"OK");
        }
        return wstring(L"FAIL");
    }
}

int main() {
    std::wstring const s = L"def abc() enddef";
    std::wcout << overmath::parse(s.begin(), s.end());
}
Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Added a simplified working example. Not there are some very error-prone name clashes. I'd suggest to stop using `using namespace` so liberally. – sehe Dec 06 '15 at 22:26