语法意外地失败了boost :: spirit语法定义

时间:2015-12-06 21:44:28

标签: c++ boost grammar boost-spirit

我是全新的提升:精神和猜测这个问题对于高级用户来说是微不足道的。以下语法没有达到我的预期:

    #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");
        }

    }

当我使用字符串“def abc()enddef”进行测试时,解析失败。我不知道为什么。我做错了什么?非常感谢。

1 个答案:

答案 0 :(得分:3)

您的船长会占用空格,因此"def "" enddef"永远不会匹配。

另见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());
}