如何解析后跟分号或换行符的条目(boost::spirit)
How to parse entries followed by semicolon or newline (boost::spirit)?
在 Boost::Spirit 中,如何解析后跟分号或带有可选分号的换行符的条目?
示例输入,其中每个条目都是 int 和双精度
:12 1.4;
63 13.2
2423 56.4 ; 5 8.1
下面是仅解析条目后跟空格的示例代码:
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;
typedef std::pair<int, double> Entry;
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, std::vector<Entry>(), Skipper> {
MyGrammar() : MyGrammar::base_type(entries) {
entry = qi::int_ >> qi::double_;
entries = +entry;
}
qi::rule<Iterator, Entry(), Skipper> entry;
qi::rule<Iterator, std::vector<Entry>(), Skipper> entries;
};
int main() {
typedef boost::spirit::istream_iterator It;
std::cin.unsetf(std::ios::skipws);
It it(std::cin), end;
MyGrammar<It, qi::space_type> entry_grammar;
std::vector<Entry> entries;
if (qi::phrase_parse(it, end, entry_grammar, qi::space, entries)
&& it == end) {
BOOST_FOREACH(Entry const& entry, entries) {
std::cout << entry.first << " and " << entry.second << std::endl;
}
}
else {
std::cerr << "FAIL" << std::endl;
exit(1);
}
return 0;
}
现在,为了解析我想要的方式(每个条目后跟分号或带有可选分号的换行符(,我替换了这个:
entries = +entry;
通过这个:
entries = +(entry >> (qi::no_skip[qi::eol] || ';'));
其中boost::spirit
运算符||
表示:(a 后跟可选的 b(或 b。但是,如果此示例输入中的1.4
后有一个空格,则会给出错误:
12 1.4
63 13.2
由于no_skip
,空间不匹配是有道理的,但我无法找到解决方案。
这是我
的看法。
- 您可能想知道
qi::blank
(除qi::eol
外,qi::space
(。这将消除对no_skip
的需求。 核心语法变为:
entry = qi::int_ >> qi::double_; entries = entry % +qi::char_("n;") >> qi::omit[*qi::space];
使用 BOOST_SPIRIT_DEBUG 了解解析失败的位置和原因(例如回溯(
输出:
12 and 1.4
63 and 13.2
2423 and 56.4
5 and 8.1
完整代码:
//#define BOOST_SPIRIT_DEBUG
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;
typedef std::pair<int, double> Entry;
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, std::vector<Entry>(), Skipper> {
MyGrammar() : MyGrammar::base_type(entries) {
entry = qi::int_ >> qi::double_;
entries =
entry % +qi::char_("n;") // the data
>> qi::omit[*qi::space] > qi::eoi; // trailing whitespace
BOOST_SPIRIT_DEBUG_NODE(entry);
BOOST_SPIRIT_DEBUG_NODE(entries);
}
qi::rule<Iterator, Entry(), Skipper> entry;
qi::rule<Iterator, std::vector<Entry>(), Skipper> entries;
};
int main() {
typedef boost::spirit::istream_iterator It;
std::cin.unsetf(std::ios::skipws);
It it(std::cin), end;
MyGrammar<It, qi::blank_type> entry_grammar;
std::vector<Entry> entries;
if (qi::phrase_parse(it, end, entry_grammar, qi::blank, entries)
&& it == end) {
BOOST_FOREACH(Entry const& entry, entries) {
std::cout << entry.first << " and " << entry.second << std::endl;
}
}
else {
std::cerr << "FAIL" << std::endl;
exit(1);
}
return 0;
}
好的,我发现这工作正常:
entries = +(entry >> (qi::no_skip[*qi::lit(' ') >> qi::eol] || ';'));
所以眼前的问题解决了。
但是,如果选项卡出现在1.4
中,它仍然会失败
12 1.4
63 13.2
这会更好,但它不会编译:
entries = +(entry >> (qi::no_skip[*qi::space >> qi::eol] || ';'));
错误:
error: invalid static_cast from type ‘const std::pair<int, double
>’ to type ‘int’
相关文章:
- Boost Spirit,获取迭代器内部语义动作
- boost::spirit::karma 替代生成器,带有 boost::variant 由字符串和字符串别名组成
- boost::spirit::x3 中的通用解析器生成器
- Boost.Spirit将表达转换为AST
- 使用 Boost.Spirit 解析具有混合数据类型的 OBJ 文件?
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- Boost Spirit X3:将(一些)空格解析为枚举
- Boost Spirit x3 条件(三元)运算符解析器
- 你如何从 Boost Spirit X3 词法解析器中获取字符串?
- 将 Boost.Spirit.X3 解析器拆分为多个 TU
- boost::spirit::x3 中的简单字符串解析器不起作用
- boost::spirit指针属性是用nullptr初始化的吗?
- Boost.Spirit Alternative Parser parallelization
- 如何在 boost::spirit::qi 中将某些语义操作排除在 AST 之外
- 自定义预期失败的完整错误消息(boost::spirit::x3)
- boost::spirit--试图编译大多数简单代码的编译器错误
- Boost.Spirit.Qi 语法,用于 Boost.Fusion 自适应结构中的默认值
- 使用 Boost.Spirit 解析嵌套列表
- (如何)我可以在不安装完整的提升库的情况下使用 boost::spirit X3 吗?
- n-ary布尔语法从中缀到前缀的Boost::Spirit转换?