使用 Boost.Spirit.Qi 捕获字符串直到行尾
Capturing string until end of line with Boost.Spirit.Qi
我正在尝试编写一个自定义结构来捕获字符串,直到 EOL 或 EOS 作为更大语法的一部分,但我无法编译它。我关注了 tutorial code,但我无法找出以下代码段中的错误。
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <cassert>
namespace qi = boost::spirit::qi;
namespace project {
struct RawValue {
std::string str;
};
}
BOOST_FUSION_ADAPT_STRUCT(project::RawValue, str)
namespace project::parser {
struct RawValueParser : qi::grammar<std::string::const_iterator, RawValue(), qi::space_type> {
RawValueParser() : RawValueParser::base_type(expr) {
using qi::blank;
using qi::char_;
using qi::eol;
using qi::lexeme;
expr %= lexeme[*(char_ - eol) >> (char_ - blank)];
}
qi::rule<iterator_type, RawValue(), skipper_type> expr;
};
}
int main() {
project::parser::RawValueParser expr;
project::RawValue result;
std::string s1 = "test1";
auto iter = s1.cbegin();
auto end = s1.cend();
assert(qi::phrase_parse(iter, end, expr, qi::space, result));
return 0;
}
https://wandbox.org/permlink/PjaaYwO0Qz18998y
这应该是一个相当简单的示例。我做错了什么?
编译错误来源:
test.cpp|21 col 58| required from here
/home/sehe/custom/spirit/include/boost/spirit/home/qi/nonterminal/grammar.hpp|77 col 13| error: static assertion failed: incompatible_start_rule
|| 77 | BOOST_SPIRIT_ASSERT_MSG(
|| | ^~~~~~~~~~~~~~~~~~~~~~~
如果您到达指定位置(另请参阅 How do I grok boost spirit compiler errors):
// If you see the assertion below failing then the start rule
// passed to the constructor of the grammar is not compatible with
// the grammar (i.e. it uses different template parameters).
BOOST_SPIRIT_ASSERT_MSG(
(is_same<start_type, rule<Iterator_, T1_, T2_, T3_, T4_> >::value)
, incompatible_start_rule, (rule<Iterator_, T1_, T2_, T3_, T4_>));
那是你的问题。语法是 <It, RawValue(), qi::space_type>
但起始规则是 <iterator_type, RawValue(), skipper_type>
,其中
static_assert(std::is_same_v<It, iterator_type>);
static_assert(std::is_same_v<qi::space_type, skipper_type>);
qi::space_type _y = skipper_type{};
显示第二个断言失败。第三行导致更详细的诊断:Live
test.cpp|33 col 29| error: could not convert ‘boost::spirit::qi::grammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, project::RawValue(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0> >::skipper_type{}’ from ‘boost::spirit::qi::grammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, project::RawValue(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0> >::skipper_type’ {aka ‘boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >’} to ‘boost::spirit::standard::space_type’ {aka ‘boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::te
|| 33 | qi::space_type _y = skipper_type{};
|| | ^~~~~~~~~~~~~~
|| | |
|| | boost::spirit::qi::grammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, project::RawValue(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0> >::skipper_type {aka boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >}
您可以将整个事情分开,但足以说明您认为 skipper_type
等于第三个模板参数的假设是错误的。
只需拼出您期望的类型:Live
qi::rule<It, RawValue(), qi::space_type> expr;
旁注
lexeme
禁用船长。考虑到这一点,考虑简化整个事情:Live (see also Boost spirit skipper issues)
operator %=
在没有语义操作的情况下没有意义
expr
好像用词不当
否定字符 类 比减法解析器更有效;您的意思是 (char_ - blank)
比 eol
更重要吗?
现在不接受输入结束而不是 eol。也许你应该允许它。我会这样写
start = *~qi::char_("\n\r") >> (eol | eoi);
简化列表
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
using It = std::string::const_iterator;
struct RawValue { std::string str; };
BOOST_FUSION_ADAPT_STRUCT(RawValue, str)
struct RawValueParser : qi::grammar<It, RawValue()> {
RawValueParser() : RawValueParser::base_type(start)
{
using namespace qi;
start = *~qi::char_("\n\r") >> (eol | eoi);
}
private:
qi::rule<It, RawValue()> start;
};
int main() {
RawValueParser expr;
for (std::string const s : {
"test1",
" test2\tbla \n",
}) {
RawValue result;
std::cout
<< std::boolalpha
//<< qi::phrase_parse(begin(s), end(s), expr, qi::space, result)
<< qi::parse(begin(s), end(s), expr, result) << " -> "
<< std::quoted(result.str) << "\n";
}
}
版画
true -> "test1"
true -> " test2 bla "
我正在尝试编写一个自定义结构来捕获字符串,直到 EOL 或 EOS 作为更大语法的一部分,但我无法编译它。我关注了 tutorial code,但我无法找出以下代码段中的错误。
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <cassert>
namespace qi = boost::spirit::qi;
namespace project {
struct RawValue {
std::string str;
};
}
BOOST_FUSION_ADAPT_STRUCT(project::RawValue, str)
namespace project::parser {
struct RawValueParser : qi::grammar<std::string::const_iterator, RawValue(), qi::space_type> {
RawValueParser() : RawValueParser::base_type(expr) {
using qi::blank;
using qi::char_;
using qi::eol;
using qi::lexeme;
expr %= lexeme[*(char_ - eol) >> (char_ - blank)];
}
qi::rule<iterator_type, RawValue(), skipper_type> expr;
};
}
int main() {
project::parser::RawValueParser expr;
project::RawValue result;
std::string s1 = "test1";
auto iter = s1.cbegin();
auto end = s1.cend();
assert(qi::phrase_parse(iter, end, expr, qi::space, result));
return 0;
}
https://wandbox.org/permlink/PjaaYwO0Qz18998y
这应该是一个相当简单的示例。我做错了什么?
编译错误来源:
test.cpp|21 col 58| required from here
/home/sehe/custom/spirit/include/boost/spirit/home/qi/nonterminal/grammar.hpp|77 col 13| error: static assertion failed: incompatible_start_rule
|| 77 | BOOST_SPIRIT_ASSERT_MSG(
|| | ^~~~~~~~~~~~~~~~~~~~~~~
如果您到达指定位置(另请参阅 How do I grok boost spirit compiler errors):
// If you see the assertion below failing then the start rule
// passed to the constructor of the grammar is not compatible with
// the grammar (i.e. it uses different template parameters).
BOOST_SPIRIT_ASSERT_MSG(
(is_same<start_type, rule<Iterator_, T1_, T2_, T3_, T4_> >::value)
, incompatible_start_rule, (rule<Iterator_, T1_, T2_, T3_, T4_>));
那是你的问题。语法是 <It, RawValue(), qi::space_type>
但起始规则是 <iterator_type, RawValue(), skipper_type>
,其中
static_assert(std::is_same_v<It, iterator_type>);
static_assert(std::is_same_v<qi::space_type, skipper_type>);
qi::space_type _y = skipper_type{};
显示第二个断言失败。第三行导致更详细的诊断:Live
test.cpp|33 col 29| error: could not convert ‘boost::spirit::qi::grammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, project::RawValue(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0> >::skipper_type{}’ from ‘boost::spirit::qi::grammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, project::RawValue(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0> >::skipper_type’ {aka ‘boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >’} to ‘boost::spirit::standard::space_type’ {aka ‘boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::te
|| 33 | qi::space_type _y = skipper_type{};
|| | ^~~~~~~~~~~~~~
|| | |
|| | boost::spirit::qi::grammar<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, project::RawValue(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0> >::skipper_type {aka boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >}
您可以将整个事情分开,但足以说明您认为 skipper_type
等于第三个模板参数的假设是错误的。
只需拼出您期望的类型:Live
qi::rule<It, RawValue(), qi::space_type> expr;
旁注
lexeme
禁用船长。考虑到这一点,考虑简化整个事情:Live (see also Boost spirit skipper issues)operator %=
在没有语义操作的情况下没有意义expr
好像用词不当否定字符 类 比减法解析器更有效;您的意思是
(char_ - blank)
比eol
更重要吗?现在不接受输入结束而不是 eol。也许你应该允许它。我会这样写
start = *~qi::char_("\n\r") >> (eol | eoi);
简化列表
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
using It = std::string::const_iterator;
struct RawValue { std::string str; };
BOOST_FUSION_ADAPT_STRUCT(RawValue, str)
struct RawValueParser : qi::grammar<It, RawValue()> {
RawValueParser() : RawValueParser::base_type(start)
{
using namespace qi;
start = *~qi::char_("\n\r") >> (eol | eoi);
}
private:
qi::rule<It, RawValue()> start;
};
int main() {
RawValueParser expr;
for (std::string const s : {
"test1",
" test2\tbla \n",
}) {
RawValue result;
std::cout
<< std::boolalpha
//<< qi::phrase_parse(begin(s), end(s), expr, qi::space, result)
<< qi::parse(begin(s), end(s), expr, result) << " -> "
<< std::quoted(result.str) << "\n";
}
}
版画
true -> "test1"
true -> " test2 bla "