Boost.Spirit X3解析器“无类型命名为type in(...)" [英] Boost.Spirit X3 parser "no type named type in(...)"

查看:70
本文介绍了Boost.Spirit X3解析器“无类型命名为type in(...)"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


当我遇到错误时,我一直在玩Boost.Spirit X3计算器示例,我无法理解.
我将程序最小化以降低复杂度,但仍会引发相同的错误. 说我想将输入解析为语句(字符串)列表,后跟定界符(;").


I was toying with Boost.Spirit X3 calculator example when I encountered an error I couldn't get my head around.
I minimized the program to reduce complexity still throwing the same error. Say I want to parse an input as a list of statements (strings) followed by a delimiter (';').


namespace client { namespace ast
 {    
     struct program
    {
        std::list<std::string> stmts;
    };
 }}

BOOST_FUSION_ADAPT_STRUCT(client::ast::program,
            (std::list<std::string>, stmts)
)

语法如下:

namespace client
{ 
    namespace grammar
    {

   x3::rule<class program, ast::program> const program("program");

    auto const program_def =
            *((*char_) > ';')
            ;

   BOOST_SPIRIT_DEFINE(
       program
    );
    auto calculator = program;
}

using grammar::calculator;

}


    int
    main()
    {
    std::cout <<"///////////////////////////////////////////\n\n";
    std::cout << "Expression parser...\n\n";
    std::cout << //////////////////////////////////////////////////\n\n";
    std::cout << "Type an expression...or [q or Q] to quit\n\n";

    typedef std::string::const_iterator iterator_type;
    typedef client::ast::program ast_program;

    std::string str;
    while (std::getline(std::cin, str))
    {
        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
            break;

        auto& calc = client::calculator;    // Our grammar
        ast_program program;                // Our program (AST)

        iterator_type iter = str.begin();
        iterator_type end = str.end();
        boost::spirit::x3::ascii::space_type space;
        bool r = phrase_parse(iter, end, calc, space, program);

        if (r && iter == end)
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing succeeded\n";
            std::cout<< '\n';
            std::cout << "-------------------------\n";
        }
        else
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing failed\n";
            std::cout << "-------------------------\n";
        }
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}

我遇到的错误是

/opt/boost_1_66_0/boost/spirit/home/x3/support/traits/container_traits.hpp: In instantiation of ‘struct boost::spirit::x3::traits::container_value<client::ast::program, void>’:
.
.
.

/opt/boost_1_66_0/boost/spirit/home/x3/support/traits/container_traits.hpp:76:12: error: no type named ‘value_type’ in ‘struct client::ast::program’
         struct container_value
/opt/boost_1_66_0/boost/spirit/home/x3/operator/detail/sequence.hpp:497:72: error: no type named ‘type’ in ‘struct boost::spirit::x3::traits::container_value<client::ast::program, void>’
          , typename traits::is_substitute<attribute_type, value_type>::type());
                                                                        ^~~~~~

我尝试过的事情:


遵循>使用boost :: spirit :: qi来使用stl容器
即使使用了Qi,我还是尝试过:

Things I tried:


Following Getting boost::spirit::qi to use stl containers
Even though it uses Qi I nonetheless tried:

namespace boost{namespace spirit{ namespace traits{
template<>
struct container_value<client::ast::program> 
//also with struct container<client::ast::program, void>
{
      typedef std::list<std::string> type;
};
}}}

您看到我有点在黑暗中,所以无济于事.

You see I'm kinda in the dark, so expectably to no avail.

parser2.cpp:41:8: error: ‘container_value’ is not a class template
 struct container_value<client::ast::program>
        ^~~~~~~~~~~~~~~

在同一个SO问题中,我作者说
但是,有一个已知的限制,当您尝试使用具有单个元素的结构时,除非添加qi :,否则容器编译也会失败: eps >> ...按您的规则进行."

In the same SO question I author says
"There is one known limitation though, when you try to use a struct that has a single element that is also a container compilation fails unless you add qi::eps >> ... to your rule."

我确实尝试添加虚拟eps也没有成功.

I did try adding a dummy eps also without success.

请帮我弄清楚该错误的含义.

Please, help me decipher what that error means.

推荐答案

是的.当涉及到单元素序列时,这似乎是属性自动传播的另一个限制.

Yup. This looks like another limitation with automatic propagation of attributes when single-element sequences are involved.

我可能会硬着头皮,将规则定义从它的定义(以及您期望的工作)更改为:

I'd probably bite the bullet and change the rule definition from what it is (and what you'd expect to work) to:

x3::rule<class program_, std::vector<std::string> >

这消除了混乱的根源.

其他说明:

  • 您有char_,它也吃了';',因此语法永远不会成功,因为没有';'会遵循声明".

  • you had char_ which also eats ';' so the grammar would never succeed because no ';' would follow a "statement".

您的语句不是lexeme,因此空格被丢弃(这是您的意思吗?请参见

your statements aren't lexeme, so whitespace is discarded (is this what you meant? See Boost spirit skipper issues)

您的语句可能为空,这意味着解析总是会在输入结束时失败(在此情况下,它总是会读取空状态,然后发现预期的';'是丢失的).通过接受至少1个字符来修正该错误.

your statement could be empty, which meant parsing would ALWAYS fail at the end of input (where it would always read an empty state, and then discover that the expected ';' was missing). Fix it by requiring at least 1 character before accepting a statement.

进行一些简化/样式更改:

With some simplifications/style changes:

在Coliru上直播

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>
#include <list>

namespace x3 = boost::spirit::x3;

namespace ast {
    using statement = std::string;

    struct program {
        std::list<statement> stmts;
    };
} 

BOOST_FUSION_ADAPT_STRUCT(ast::program, stmts)

namespace grammar {
    auto statement 
        = x3::rule<class statement_, ast::statement> {"statement"}
        = +~x3::char_(';');
    auto program 
        = x3::rule<class program_, std::list<ast::statement> > {"program"}
        = *(statement >> ';');
} 

#include <iostream>
#include <iomanip>

int main() {
    std::cout << "Type an expression...or [q or Q] to quit\n\n";

    using It = std::string::const_iterator;

    for (std::string str; std::getline(std::cin, str);) {
        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
            break;

        auto &parser = grammar::program;
        ast::program program; // Our program (AST)

        It iter = str.begin(), end = str.end();
        if (phrase_parse(iter, end, parser, x3::space, program)) {
            std::cout << "Parsing succeeded\n";
            for (auto& s : program.stmts) {
                std::cout << "Statement: " << std::quoted(s, '\'') << "\n";
            }
        }
        else
            std::cout << "Parsing failed\n";

        if (iter != end)
            std::cout << "Remaining unparsed: " << std::quoted(std::string(iter, end), '\'') << "\n";
    }
}

输入"a; b; c; d;"打印:

Which for input "a;b;c;d;" prints:

Parsing succeeded
Statement: 'a'
Statement: 'b'
Statement: 'c'
Statement: 'd'

这篇关于Boost.Spirit X3解析器“无类型命名为type in(...)"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆