更新时间:2021-09-07 23:46:04
我怀疑您只需要 fusion/adapted/std_pair.hpp
让我尝试使其编译
好
您的开始规则不兼容
your start rule was incompatible
qi::rule<Iterator, std::multiset<dn_key_value_map>(), ascii::space_type> dn;
符号表应映射到字符串,而不是char
the symbol table should map to string, not char
struct dn_reserved_chars_ : public qi::symbols<char, std::string> {
或,您应该将映射值更改为char文字.
or you should change the mapped values to char literals.
为什么要使用它而不是
char _("\\ = +,;#<> \"%)
?
已经完成了对语法的审查(完全从实现的角度出发,因此我实际上没有阅读RFC来检查假设).
Have completed my review of the Grammar (purely from the implementation point-of-view, so I haven't actually read the RFC to check the assumptions).
我在此处创建了拉取请求: https://github.com/Rerito/pkistore/pull/1
一般说明
General Notes
map< string,string>
语法规则:
符号< char,char>
需要 char
值(不是."
,而是'.'
)许多简化
symbols<char,char>
requires char
values (not "."
but '.'
)Many simplifications
& char _(...)
实例(它们不匹配任何内容,它是只是一个断言) no_case []
lexeme []
指令;大多数已经实现通过从规则声明中删除船长 hex_string
制成的 key
至少需要一个字符(未检查规格).注意如何
&char_(...)
instances (they don't match anything, it's
just an assertion)no_case[]
lexeme[]
directives; most have been realized
by removing the skipper from the rule declarationshex_string
made key
require at least one character (not checked the specs).
Note how
key = ascii::no_case[qi::lexeme[(*qi::alnum) >> (*(qi::char_('-') >> qi::alnum))]];
成为
key = raw[ alnum >> *(alnum | '-') ];
原始
表示输入序列将逐字反映(而不是逐个字符地构建副本)
raw
means that the input sequence will be reflected verbatim
(instead of building a copy character by character)
对 value
上的分支进行了重新排序(未选中,但我下注未定)字符串基本上会吃掉其他所有东西)
reordered branches on value
(not checked, but I wager unqouted
strings would basically eat everything else)
测试
根据rfc中的示例"部分添加了一个测试程序test.cpp(3.).
Added a test program test.cpp, based on the Examples section in the rfc (3.).
添加了一些我自己设计的更复杂的示例.
Added some more complicated examples of my own devising.
尾端松动
要做的事情:查看规范中的实际规则和要求
To do: review the specs for actual rules and requirements on
在各种内部包含空格(包括换行符)串香:
inclusion of whitespace (incl. newline characters) inside the various string flavours:
还启用了可选的 BOOST_SPIRIT_DEBUG
还在语法内部设置了船长(安全!)
Also made the skipper internal to the grammar (security!)
还提供了一个方便使用的功能,该功能使解析器可用不会泄漏实施细节(Qi)
Also made a convenience free function that makes the parser usable without leaking implementation details (Qi)
//#include "dn_parser.hpp"
//#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <map>
#include <set>
namespace pkistore {
namespace parsing {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace ast {
typedef std::map<std::string, std::string> rdn;
typedef std::vector<rdn> dn;
}
template <typename Iterator>
struct dn_grammar_common : public qi::grammar<Iterator, ast::dn()> {
dn_grammar_common() : dn_grammar_common::base_type(start) {
using namespace qi;
// syntax as defined in rfc1779
key = raw[ alnum >> *(alnum | '-') ];
char_escape = '\\' >> (hexchar | dn_reserved_chars);
quote_string = '"' >> *(char_escape | (char_ - dn_reserved_chars)) >> '"' ;
value = quote_string
| '#' >> *hexchar
| *(char_escape | (char_ - dn_reserved_chars))
;
rdn_pair = key >> '=' >> value;
rdn = rdn_pair % qi::char_("+");
dn = rdn % qi::char_(",;");
start = skip(qi::ascii::space) [ dn ];
BOOST_SPIRIT_DEBUG_NODES((start)(dn)(rdn)(rdn_pair)(key)(value)(quote_string)(char_escape))
}
private:
qi::int_parser<char, 16, 2, 2> hexchar;
qi::rule<Iterator, ast::dn()> start;
qi::rule<Iterator, ast::dn(), ascii::space_type> dn;
qi::rule<Iterator, ast::rdn(), ascii::space_type> rdn;
qi::rule<Iterator, std::pair<std::string, std::string>(), ascii::space_type> rdn_pair;
qi::rule<Iterator, std::string()> key, value, quote_string;
qi::rule<Iterator, char()> char_escape;
struct dn_reserved_chars_ : public qi::symbols<char, char> {
dn_reserved_chars_() {
add ("\\", '\\') ("\"", '"')
("=" , '=') ("+" , '+')
("," , ',') (";" , ';')
("#" , '#') ("%" , '%')
("<" , '<') (">" , '>')
;
}
} dn_reserved_chars;
};
} // namespace parsing
static parsing::ast::dn parse(std::string const& input) {
using It = std::string::const_iterator;
pkistore::parsing::dn_grammar_common<It> const g;
It f = input.begin(), l = input.end();
pkistore::parsing::ast::dn parsed;
bool ok = boost::spirit::qi::parse(f, l, g, parsed);
if (!ok || (f!=l))
throw std::runtime_error("dn_parse failure");
return parsed;
}
} // namespace pkistore
int main() {
for (std::string const input : {
"OU=Sales + CN=J. Smith, O=Widget Inc., C=US",
"OU=#53616c6573",
"OU=Sa\\+les + CN=J. Smi\\%th, O=Wid\\,\\;get In\\3bc., C=US",
//"CN=Marshall T. Rose, O=Dover Beach Consulting, L=Santa Clara,\nST=California, C=US",
//"CN=FTAM Service, CN=Bells, OU=Computer Science,\nO=University College London, C=GB",
//"CN=Markus Kuhn, O=University of Erlangen, C=DE",
//"CN=Steve Kille,\nO=ISODE Consortium,\nC=GB",
//"CN=Steve Kille ,\n\nO = ISODE Consortium,\nC=GB",
//"CN=Steve Kille, O=ISODE Consortium, C=GB\n",
})
{
auto parsed = pkistore::parse(input);
std::cout << "===========\n" << input << "\n";
for(auto const& dn : parsed) {
std::cout << "-----------\n";
for (auto const& kv : dn) {
std::cout << "\t" << kv.first << "\t->\t" << kv.second << "\n";
}
}
}
}
打印:
===========
OU=Sales + CN=J. Smith, O=Widget Inc., C=US
-----------
CN -> J. Smith
OU -> Sales
-----------
O -> Widget Inc.
-----------
C -> US
===========
OU=#53616c6573
-----------
OU -> Sales
===========
OU=Sa\+les + CN=J. Smi\%th, O=Wid\,\;get In\3bc., C=US
-----------
CN -> J. Smi%th
OU -> Sa+les
-----------
O -> Wid,;get In;c.
-----------
C -> US