Boost.Spirit解析可选前缀
Boost.Spirit Parsing Optional Prefix
我正在尝试解析一串以空格分隔的可选标记关键字。例如
descr:expense type:receivable customer 27.3
其中冒号前面的表达式是标签,它是可选的(即假定默认标签(。
我无法让解析器做我想做的事。我从一个规范的例子做了一些小的改编,其目的是解析键/值对(很像HTTP查询字符串(。
typedef std::pair<boost::optional<std::string>, std::string> pair_type;
typedef std::vector<pair_type> pairs_type;
template <typename Iterator>
struct field_value_sequence_default_field
: qi::grammar<Iterator, pairs_type()>
{
field_value_sequence_default_field()
: field_value_sequence_default_field::base_type(query)
{
query = pair >> *(qi::lit(' ') >> pair);
pair = -(field >> ':') >> value;
field = +qi::char_("a-zA-Z0-9");
value = +qi::char_("a-zA-Z0-9+-\.");
}
qi::rule<Iterator, pairs_type()> query;
qi::rule<Iterator, pair_type()> pair;
qi::rule<Iterator, std::string()> field, value;
};
但是,当我解析它时,当标签被省略时,optional<string>
不是空/假的。相反,它有该值的副本。货币对的第二部分也有价值。
如果未标记的关键字不能是标签(语法规则,例如具有小数点(,那么事情就像我期望的那样工作。
我做错了什么?这是PEG的概念错误吗?
相反,它有该值的副本。货币对的第二部分也有价值。
这是容器属性和回溯的常见陷阱:使用qi::hold
,例如理解Boost.spirit的字符串解析器
pair = -qi::hold[field >> ':'] >> value;
完整的样品在科里鲁直播
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/optional/optional_io.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
typedef std::pair<boost::optional<std::string>, std::string> pair_type;
typedef std::vector<pair_type> pairs_type;
template <typename Iterator>
struct Grammar : qi::grammar<Iterator, pairs_type()>
{
Grammar() : Grammar::base_type(query) {
query = pair % ' ';
pair = -qi::hold[field >> ':'] >> value;
field = +qi::char_("a-zA-Z0-9");
value = +qi::char_("a-zA-Z0-9+-\.");
}
private:
qi::rule<Iterator, pairs_type()> query;
qi::rule<Iterator, pair_type()> pair;
qi::rule<Iterator, std::string()> field, value;
};
int main()
{
using It = std::string::const_iterator;
for (std::string const input : {
"descr:expense type:receivable customer 27.3",
"expense type:receivable customer 27.3",
"descr:expense receivable customer 27.3",
"expense receivable customer 27.3",
}) {
It f = input.begin(), l = input.end();
std::cout << "==== '" << input << "' =============n";
pairs_type data;
if (qi::parse(f, l, Grammar<It>(), data)) {
std::cout << "Parsed: n";
for (auto& p : data) {
std::cout << p.first << "t->'" << p.second << "'n";
}
} else {
std::cout << "Parse failedn";
}
if (f != l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'n";
}
}
印刷
==== 'descr:expense type:receivable customer 27.3' =============
Parsed:
descr ->'expense'
type ->'receivable'
-- ->'customer'
-- ->'27.3'
==== 'expense type:receivable customer 27.3' =============
Parsed:
-- ->'expense'
type ->'receivable'
-- ->'customer'
-- ->'27.3'
==== 'descr:expense receivable customer 27.3' =============
Parsed:
descr ->'expense'
-- ->'receivable'
-- ->'customer'
-- ->'27.3'
==== 'expense receivable customer 27.3' =============
Parsed:
-- ->'expense'
-- ->'receivable'
-- ->'customer'
-- ->'27.3'
相关文章:
- Boost Spirit,获取迭代器内部语义动作
- boost::spirit::karma 替代生成器,带有 boost::variant 由字符串和字符串别名组成
- 编译器如何在前缀和 postix 运算符之间进行区分?
- boost::spirit::x3 中的通用解析器生成器
- 查找带有 Anaconda cmake 前缀的 boost-python3
- Boost.Spirit将表达转换为AST
- 迭代器类的重载前缀增量运算符会引发分段错误
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- 生成前缀位掩码
- 使用 Boost.Spirit 解析具有混合数据类型的 OBJ 文件?
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- Boost Spirit X3:将(一些)空格解析为枚举
- 定义宏以将前缀 0x 添加到十六进制字符串文本
- CMake 错误 - 目标 foo INTERFACE_SOURCES属性包含在源目录中以前缀为前缀的路径
- Boost Spirit x3 条件(三元)运算符解析器
- 你如何从 Boost Spirit X3 词法解析器中获取字符串?
- 如何在自定义对象的<<运算符中添加自定义前缀
- 将 Boost.Spirit.X3 解析器拆分为多个 TU
- n-ary布尔语法从中缀到前缀的Boost::Spirit转换?
- Boost.Spirit解析可选前缀