- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在我的语义操作中,我不只是试图打印出已解析的内容。但是语义 Action 函数应该创建一些新对象,而这些新对象又应该是解析器创建的值。
让我们假设以下任务:解析器应该将地址/引用传递给对象
typedef std::pair<
std::map<std::string, std::size_t>,
std::map<std::size_t, std::string>
> mapping;
并且解析器应该将所有非空白字符串转换为 std::size_t
返回 std::vector<std::size_t>
在代表所有字符串的 EOI 上。当然,这意味着在上面的映射中创建/查找条目。
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <vector>
#include <map>
#include <string>
#include <iostream>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef std::pair<
std::map<std::string, std::size_t>,
std::map<std::size_t, std::string>
> mapping;
struct convert
{ mapping &m_r;
convert(mapping &_r)
:m_r(_r)
{
}
std::size_t operator()(const std::string &_r, const boost::fusion::unused_type&, const boost::fusion::unused_type&) const
{ const auto pFind = m_r.first.find(_r);
if (pFind != m_r.first.end())
return pFind->second;
else
{ const auto iID = m_r.first.size();
m_r.second.insert(std::make_pair(iID, _r));
m_r.first.insert(std::make_pair(_r, iID));
return iID;
}
}
};
template<typename Iterator>
struct parser:qi::grammar<Iterator, std::vector<std::size_t>(), ascii::space_type>
{ qi::rule<Iterator, std::vector<std::size_t>(), ascii::space_type> start;
qi::rule<Iterator, std::size_t(), ascii::space_type> name;
parser(mapping &_r)
:parser::base_type(start)
{ name = (+qi::char_)[convert(_r)];
start %= *name;
}
};
int main(int, char**)
{ const auto sVector = std::vector<char>(std::istream_iterator<char>(std::cin), std::istream_iterator<char>());
mapping sMapping;
parser<std::vector<char>::const_iterator> sParser(sMapping);
qi::phrase_parse(sVector.begin(), sVector.end(), sParser, ascii::space_type());
}
最佳答案
您希望解析器生成的只是“单词 ID”的序列(我们称它们为原子)。
只有为您的语义 Action 提供动力的仿函数才需要“了解”映射。
我将在这里简化您的数据结构:
using AtomId = size_t;
using Atom = std::string_view; // or boost::string_view
struct mapping {
std::map<Atom, AtomId> by_word;
std::map<AtomId, Atom> by_id;
};
您可以阅读有关 Anatomy Of Spirit Semantic Actions 的信息.
如果你想使用 synthesized 、local、exposed 或 inherited 属性,你需要解码 context 参数。最好的治疗方法仍然是这个答案:boost spirit semantic action parameters
但是,如果你看过它,你会发现它不是很方便。相反,我建议留在 Phoenix 域中(像 _1
、 _val
、 _pass
、 _r1
和 _a
之类的东西神奇地具有预期的含义,而不必知道如何在上下文)。
在这种情况下,您将希望您的函数如下所示:
struct convert_f {
mapping &m_ref;
using Range = boost::iterator_range<It>;
AtomId operator()(Range const& text) const {
Atom atom{&*text.begin(), text.size()};
auto& left = m_ref.by_word;
auto& right = m_ref.by_id;
auto it = left.find(atom);
if (it != left.end())
return it->second;
else {
const auto iID = left.size();
left.emplace (atom, iID);
right.emplace(iID, atom);
return iID;
}
}
};
boost::phoenix::function<convert_f> convert;
你本可以制作 Range
只是 std::string
, 但我在想,既然你把整个文件读入一个 vector ,你就可以使用 string_view
基于原始源迭代器范围,以避免复制任何内容。这也消除了存储相同的令人毛骨悚然的冗余 std::string
在两张 map 中¹。
¹ 但请参阅新的“奖金”部分
+char_
要仅匹配连续的字符,请确保将其包装在 lexeme[]
中(所以它不能静默地跳过空格)或者当然使规则隐式 lexeme(见 Boost spirit skipper issues )。+char_
除非你打算解析/anything/在你的情况下,你想要连续的非空间延伸,所以至少让它成为 +qi::graph
std::cin
读取数据时你已经跳过了空格,所以所有的输入都会再次变成大字。使用 std::noskipws
首先或使用 std::istreambuf_iterator
相反 std::istream_iterator
.微妙的,我知道。我可能忘记了更多的步骤,但现在,让我们忘记这些,只放一个演示:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string_view> // or <boost/utility/string_view.hpp>
#include <iostream>
#include <map>
using AtomId = size_t;
using Atom = std::string_view; // or boost::string_view
using Atoms = std::vector<AtomId>;
struct mapping {
std::map<Atom, AtomId> by_word;
std::map<AtomId, Atom> by_id;
};
namespace qi = boost::spirit::qi;
template <typename It>
struct parser : qi::grammar<It, Atoms()> {
parser(mapping &r) : parser::base_type(start), convert({r}) {
using namespace qi;
// we don't expose the skipper anymore, so we specify it at toplevel
start = skip(ascii::space)[ *name ];
name = raw[ +graph ] [_val = convert(_1)];
}
private:
qi::rule<It, Atoms()> start;
qi::rule<It, AtomId()> name;
struct convert_f {
mapping &m_ref;
using Range = boost::iterator_range<It>;
AtomId operator()(Range const& text) const {
Atom atom{&*text.begin(), text.size()};
auto& left = m_ref.by_word;
auto& right = m_ref.by_id;
auto it = left.find(atom);
if (it != left.end())
return it->second;
else {
const auto iID = left.size();
left.emplace (atom, iID);
right.emplace(iID, atom);
return iID;
}
}
};
boost::phoenix::function<convert_f> convert;
};
int main() {
using It = std::string::const_iterator;
std::string const input { std::istreambuf_iterator<char>(std::cin), {} };
mapping sMapping;
parser<It> const sParser(sMapping);
if (qi::parse(input.begin(), input.end(), sParser)) {
std::cout << "Parsed " << sMapping.by_id.size() << " unique atoms\n";
for (auto& [atom, id] : sMapping.by_word) {
std::cout << atom << "(" << id << ")\n";
}
std::cout << "\n";
} else {
std::cout << "Parse failed\n";
return 1;
}
}
打印(对于 current post text ):
Parsed 282 unique atoms
!=(153)
"know(34)
"word(19)
##(63)
&m_ref;(135)
(atom,(161)
(it(152)
(let's(21)
(see(230)
(so(220)
(where(111)
**<kbd>[Live(279)
,(78)
//(50)
/anything/(236)
0.(208)
=(46)
About(64)
Action(67)
Actions](http://boost-spirit.com/home/2010/03/03/the-anatomy-of-semantic-actions-in-qi/).(75)
Atom(48)
Atom>(60)
AtomId(45)
AtomId>(57)
BUG:(209)
Coliru]()</kbd>**(281)
DEMO(278)
However,(92)
I(174)
I'd(105)
I'm(37)
If(76)
In(129)
Instead,(104)
OR(225)
Of(73)
On(280)
Only(25)
Phoenix(109)
Points(207)
Problem(206)
Range(136)
Semantic(66)
Some(204)
Spirit(74)
Still(86)
Subtle,(261)
That(65)
There(0)
This(193)
Use(255)
Varied(205)
What(11)
You(68)
[Anatomy(72)
`+char_`(211)
`+qi::graph`(241)
`Range`(171)
`_1`,(114)
`_a`(119)
`_pass`,(116)
`_r1`(117)
`_val`,(115)
`lexeme[]`(219)
`std::cin`(246)
`std::istream_iterator`.(260)
`std::istreambuf_iterator`(258)
`std::noskipws`(256)
`std::string`(200)
`std::string`,(172)
`string_view`(183)
a(40)
about(71)
about"(35)
action(32)
address(127)
again.(254)
ahead,(177)
all(249)
already(247)
also(194)
and(118)
answer:(90)
anything.(192)
at(96)
atom);(164)
atoms).(24)
atom{&*text.begin(),(142)
attribute(9)
attributes,(81)
auto(149)
auto&(144)
avoid(190)
based(184)
be(132)
become(251)
best(87)
big(252)
binding(4)
bit(41)
boost::iterator_range<It>;(137)
boost::phoenix::function<convert_f>(167)
boost::string_view(52)
but(173)
by_id;(61)
by_word;(58)
call(22)
caller(266)
can(69)
cannot(221)
case,(130)
change(267)
chars,(215)
complexity(42)
const(141)
const&(139)
context(84)
context).(128)
contiguous(214)
convenient.(103)
convert;(168)
convert_f(134)
copying(191)
could(169)
course(226)
creepy(196)
data(244)
decode(83)
demo:(277)
domain(110)
don't(232)
drop(276)
else(157)
expect(210)
expose(263)
exposed(8)
file(180)
find(99)
first(257)
for(265)
forget(275)
forgot(269)
from(245)
fuel(29)
full(179)
function(131)
functor(26)
going(38)
have(82)
having(124)
here:(43)
how(126)
https://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#17073965).(231)
https://stackoverflow.com/questions/3066701/boost-spirit-semantic-action-parameters/3067881#3067881(91)
iID(158)
iID);(162)
iID;(165)
ids"(20)
if(93)
implicitly(228)
in(108)
inherited(80)
input(250)
inside(201)
instead(259)
intended(121)
into(181)
is(1)
it(150)
it's(100)
it,(97)
it->second;(156)
iterator(188)
just(16)
know(125)
know.(262)
least(240)
left(145)
left.emplace(160)
left.end())(154)
left.find(atom);(151)
left.size();(159)
let's(274)
lexeme(229)
like(113)
like:(133)
little(2)
local,(79)
looked(95)
m_ref.by_id;(148)
m_ref.by_word;(146)
made(170)
magically(120)
make(216)
map(6)
mapping(54)
mappings.(36)
maps.(203)
match(212)
mean(234)
meanings,(122)
more(271)
needs(33)
non-space,(238)
not(101)
now,(273)
of(18)
on(185)
only(213)
operator()(Range(138)
or(51)
parameter.(85)
parse(235)
parser(14)
probably(268)
produce(15)
range,(189)
raw(186)
read(70)
reading(243)
redundancy(197)
removes(195)
return(155)
right(147)
right.emplace(iID,(163)
rule(227)
same(199)
semantic(31)
sequence(17)
sidestep(39)
silently)(224)
since(178)
size_t;(47)
skip(222)
skipper(264)
so(239)
some(270)
source(187)
stay(107)
std::map<Atom,(56)
std::map<AtomId,(59)
std::string_view;(49)
steps,(272)
storing(198)
stretches(237)
struct(53)
suggest(106)
sure(217)
synthesized(77)
text)(140)
text.size()};(143)
that(27)
the(5)
them(23)
things(112)
thinking(176)
this(89)
to(7)
treatment(88)
two(202)
type.(10)
unless(233)
use(3)
using(44)
vector,(182)
very(102)
want(13)
was(175)
when(242)
whitespace,(248)
whitespaces(223)
will(28)
without(123)
word(253)
wrap(218)
you(12)
you'll(98)
you've(94)
your(30)
{(55)
}(166)
};(62)
哦,我忘了实际存储 Atoms
:
Atoms idlist;
if (qi::parse(input.begin(), input.end(), sParser, idlist)) {
std::cout << "Parsed " << sMapping.by_id.size() << " unique atoms\n";
for (AtomId id : idlist) {
std::cout << "'" << sMapping.by_id.at(id) << "' ";
}
std::cout << "\n";
} else {
// ...
打印一些开始的东西:
Parsed 282 unique atoms
'There' 'is' 'little' 'use' 'binding' 'the' 'map' 'to' 'the' 'exposed' 'attribute' 'type.' 'What' 'you' 'want' 'the' ...
using mapping = boost::bimap<Atom, AtomId>;
// ...
AtomId convert_f::operator()(Range const& text) const {
Atom atom{&*text.begin(), text.size()};
return m_ref.left.insert({atom, m_ref.size()}).first->second;
}
然后在用法上:
std::cout << "Parsed " << sMapping.size() << " unique atoms\n";
for (AtomId id : idlist) {
std::cout << "'" << sMapping.right.at(id) << "' ";
}
关于c++ - 使用非空函数对象提升精神语义 Action ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47082565/
我正在尝试提升我的 javascript 编程技能(或者说我的编程技能时期 :)) 所以我试图理解一些语义: 第一行的“?”是什么意思?均值和“-distance”中的减号 第二行中的“+=”或“-=
我正在尝试在语义 UI 中执行复选框,但它不起作用,我无法弄清楚我做错了什么。 我包括jquery、semantic.min.js、checkbox.js 和semantic.min.css,然后我添
我正在构建一个 Spring 后端。我有一个 Controller ,它获取一个“搜索对象” - 一个具有 10 个字段的对象,其中只有一个应该被填充,所以搜索功能(我没有编写,但需要对其进行更改和重
我面临着编写更智能/高级的“相关内容”算法的挑战,并且不知道从哪里开始,所以我决定提出一个问题,是否有人会指出我正确的方向。 我们的数据库包含很多文章,到目前为止,我们使用关键字/标签查询了相关文章,
我正在尝试将通用字符串写入Rust中的数字函数,其中支持的类型为i16,i32,i64,u32,u64,f32和f64。 最初我有这个: fn str_to_num(s: &str, default_
假设我们在 hpp 文件中有一个带有唯一指针的简单结构: struct SomeType { SomeType() = default; ~SomeType(); st
这是同一预处理指令的多个问题。 1 - <> 还是 ""? 除了在 MSDN 中找到的信息: #include Directive (C-C++) 1.a:这两种符号有什么区别? 1.b:所有编译器都
所以基本上我有一个带有列表的简单系统,当我选择一个项目时,它会显示描述和绑定(bind)到该项目的图像。 项目:https://jsfiddle.net/jhnjcddh/2/ 问题是我需要在 JS
很抱歉问了一个愚蠢的问题,但有人能告诉我以下是什么意思吗 for ctype, (codename, name) in searched_perms: 我不明白括号里是怎么回事。 for ctype
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Why do all these crazy function pointer definitions al
我正在学习 HTML5,并获得了一个将 CSS Zen Gardens 转换为 HTML5 语义版本的项目。我已经能够轻松地转换其中的大部分内容,但是底部的链接/导航给我带来了一些问题。 转换此/处理
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improv
我一直在我的 emacs c/c++ 开发设置中试验 cedet 和语义,除了一个小细节外,我对它非常满意。 我使用 ede-cpp-root-project 创建一个项目,并给出我的项目的根目录以及
引用问题自http://www.garfieldtech.com/blog/put-up-with-put (这是针对 Drupal 开源项目的,有点元,因为这里没有代码): GET、HEAD 和 P
我有以下代码。 let v_blue = UIView() v_blue.backgroundColor = UIColor.blueColor() l
我目前正在 objc.io 上阅读优秀的 Advanced Swift 书籍,但遇到了一些我不明白的问题。 如果您在操场上运行以下代码,您会注意到在修改字典中包含的结构时,下标访问会生成一个副本,但随
谁能给我一个关于 Flutter 上下文中语义概念的清晰解释(或链接)(它实际上是什么,何时使用,更新...)? 我在谷歌上搜索了很多,但到目前为止还没有找到任何好的解释。 非常感谢, 最佳答案 Di
这是我的代码 Was this what you wanted? It's good to see you again.
我有一个侧边栏,其中包含应用程序的主导航。它还包含一个 button 触发侧边栏的打开/关闭。在语义方面,标记应该是什么样的? 我应该把侧边栏放在一边,然后只在周围设置导航吗主导航,不包括打开/关闭触
考虑下面这行 Lisp 代码: (some-function 7 8 | 9) ;; some comment. note the extra indentation 该点位于“8”和
我是一名优秀的程序员,十分优秀!