Boost.Spirit X3 解析器 "no type named type in(...)"
Boost.Spirit X3 parser "no type named type in(...)"
我在玩 Boost.Spirit X3 计算器示例时遇到了一个我无法理解的错误。
我最小化了程序以降低复杂性仍然抛出相同的错误。
假设我想将输入解析为语句列表(字符串),后跟定界符(';')。
这是我的结构:
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());
^~~~~~
我尝试过的事情:
正在关注 Getting boost::spirit::qi to use stl containers
尽管它使用 Qi 我仍然尝试过:
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;
};
}}}
你看我有点蒙在鼓里,所以预计无济于事。
parser2.cpp:41:8: error: ‘container_value’ is not a class template
struct container_value<client::ast::program>
^~~~~~~~~~~~~~~
在同一个问题中我作者说
"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,但也没有成功。
请帮我解读一下错误的含义。
是的。这看起来像是涉及单元素序列时属性自动传播的另一个限制。
我可能会硬着头皮将规则定义从原来的(以及您期望的工作方式)更改为:
x3::rule<class program_, std::vector<std::string> >
这消除了混乱的根源。
其他说明:
你有 char_
它也吃 ';'
所以语法 永远不会 成功因为没有 ';'
会跟随"statement".
你的语句不是词素,所以空格被丢弃(这是你的意思吗?见Boost spirit skipper issues)
你的语句可能是空的,这意味着解析总是会在输入结束时失败(它会总是读取一个空状态,然后发现预期的 ';'
丢失了)。通过在接受声明之前要求至少 1 个字符来修复它。
有一些 simplifications/style 更改:
#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;" 打印:
Parsing succeeded
Statement: 'a'
Statement: 'b'
Statement: 'c'
Statement: 'd'
我在玩 Boost.Spirit X3 计算器示例时遇到了一个我无法理解的错误。
我最小化了程序以降低复杂性仍然抛出相同的错误。
假设我想将输入解析为语句列表(字符串),后跟定界符(';')。
这是我的结构:
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());
^~~~~~
我尝试过的事情:
正在关注 Getting boost::spirit::qi to use stl containers
尽管它使用 Qi 我仍然尝试过:
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;
};
}}}
你看我有点蒙在鼓里,所以预计无济于事。
parser2.cpp:41:8: error: ‘container_value’ is not a class template
struct container_value<client::ast::program>
^~~~~~~~~~~~~~~
在同一个问题中我作者说
"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,但也没有成功。
请帮我解读一下错误的含义。
是的。这看起来像是涉及单元素序列时属性自动传播的另一个限制。
我可能会硬着头皮将规则定义从原来的(以及您期望的工作方式)更改为:
x3::rule<class program_, std::vector<std::string> >
这消除了混乱的根源。
其他说明:
你有
char_
它也吃';'
所以语法 永远不会 成功因为没有';'
会跟随"statement".你的语句不是词素,所以空格被丢弃(这是你的意思吗?见Boost spirit skipper issues)
你的语句可能是空的,这意味着解析总是会在输入结束时失败(它会总是读取一个空状态,然后发现预期的
';'
丢失了)。通过在接受声明之前要求至少 1 个字符来修复它。
有一些 simplifications/style 更改:
#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;" 打印:
Parsing succeeded
Statement: 'a'
Statement: 'b'
Statement: 'c'
Statement: 'd'