gpt4 book ai didi

c++ - Spirit X3,指的是之前匹配的值

转载 作者:行者123 更新时间:2023-12-02 10:01:58 27 4
gpt4 key购买 nike

为了熟悉它,我在 Spirit X3 中编写了一个解析器,尽管我非常熟悉 Qi,但我仍然在 X3 中遇到了一些绊脚石。

例如,Qi 示例包括一个基本的 XML 解析器,您应该如何使用 Phoenix 占位符匹配先前匹配的值。但是,我只能在 X3 中弄明白:

#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

namespace x3 = boost::spirit::x3;

namespace mytest
{

struct SimpleElement
{
std::string tag;
std::string content;
};

} // namespace bbspirit

BOOST_FUSION_ADAPT_STRUCT
(
mytest::SimpleElement, tag, content
)

namespace mytest
{

namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;

using x3::lit;
using x3::lexeme;
using ascii::char_;

const x3::rule<class SimpleElementID, SimpleElement> simpleTag = "simpleTag";

auto assignTag = [](auto& ctx)
{
x3::_val(ctx).tag = x3::_attr(ctx);
};

auto testTag = [](auto& ctx)
{
x3::_pass(ctx) =
(x3::_val(ctx).tag == x3::_attr(ctx));
};

auto assignContent = [](auto& ctx)
{
x3::_val(ctx).content = x3::_attr(ctx);
};

auto const simpleTag_def
= '['
>> x3::lexeme[+(char_ - ']')][assignTag]
>> ']'
>> x3::lexeme[
+(char_ - x3::lit("[/"))]
[assignContent]
>> "[/"
>> x3::lexeme[+(char_ - ']')][testTag]
>> ']'
;

BOOST_SPIRIT_DEFINE(simpleTag);

} // namespace bbspirit


int main()
{

const std::string text = "[test]Hello World![/test]";
std::string::const_iterator start = std::begin(text);
const std::string::const_iterator stop = std::end(text);

mytest::SimpleElement element{};

bool result =
phrase_parse(start, stop, mytest::simpleTag, x3::ascii::space, element);

if (!result)
{
std::cout << "failed to parse!\n";
}
else
{
std::cout << "tag : " << element.tag << '\n';
std::cout << "content: " << element.content << '\n';
}

}

(链接: https://wandbox.org/permlink/xLZN9plcOwkSKCrD)

这可行,但是如果我尝试解析 [test]Hello [/World[/test] 之类的内容它不起作用,因为我没有在这里指定正确的省略:
    >> x3::lexeme[
+(char_ - x3::lit("[/"))]
[assignContent]

本质上,我想告诉解析器:
    >> x3::lexeme[
+(char_ - (x3::lit("[/") << *the start tag* << ']') )]
[assignContent]

我怎么能这样做呢?另外,我引用开始标签并稍后匹配它的方式是在 X3 中执行此操作的“最佳”方式,还是有更好/更首选的方式?

谢谢!

最佳答案

好问题。

最好的答案是完全按照 XML 所做的那样做:outlaw [/标签数据内。事实上,XML 是非法的 < (因为它可能会打开一个嵌套标签,并且您不想潜在地预读整个流以查找它是否是有效的子标签)。

XML uses character entities ("escapes" like &lt; and &gt;) or unparsed character data (CDATA[]) to encode contents that requires these characters.



接下来,您当然可以使用 !closeTag 进行否定的前瞻断言( -closeTagtag )像你已经做过的属性成员。

重新改写规则拼写litte,它甚至没有那么糟糕

Note I removed the need for manual propagation of the tag/contents using the , true> template argument on simpleTag rule. See Boost Spirit: "Semantic actions are evil"?


const x3::rule<class SimpleElementID, SimpleElement, true> simpleTag = "simpleTag";
auto testTag = [](auto& ctx) { _pass(ctx) = (_val(ctx).tag == _attr(ctx)); };

auto openTag = '[' >> x3::lexeme[+(char_ - ']')] >> ']';
auto closeTag = "[/" >> x3::lexeme[+(char_ - ']')] [testTag] >> ']';
auto tagContents = x3::lexeme[ +(char_ - closeTag) ];

auto const simpleTag_def
= openTag
>> tagContents
>> x3::omit [ closeTag ]
;

看到它 Live On Coliru

背景

这行得通,但最终变得相当笨拙,因为这意味着到处使用语义操作,并且还违背了属性引用的自然绑定(bind)。

稍微跳出框框思考:

在 Qi 你会使用 qi::locals inherited attributes为此(请参阅文档中非常相似的示例: MiniXML)。

这两者都会产生使用您的信息扩展解析器上下文的净效果。

X3 没有这样的“高级”功能。但它确实具有扩展您的上下文的构建 block : x3::witt<>(data) [ p ] .

x3::与

在这个简单的示例中,这似乎有点过头了,但在某些时候,您会欣赏如何在规则中使用额外的上下文而不将属性类型作为人质:
struct TagName{};
auto openTag
= x3::rule<struct openTagID, std::string, true> {"openTag"}
= ('[' >> x3::lexeme[+(char_ - ']')] >> ']')
[([](auto& ctx) { x3::get<TagName>(ctx) = _attr(ctx); })]
;
auto closeTag
= x3::rule<struct closeTagID, std::string, true> {"closeTag"}
= ("[/" >> x3::lexeme[+(char_ - ']')] >> ']')
[([](auto& ctx) { _pass(ctx) = (x3::get<TagName>(ctx) == _attr(ctx)); })]
;
auto tagContents
= x3::rule<struct openTagID, std::string> {"tagContents"}
= x3::lexeme[ +(char_ - closeTag) ];

auto const simpleTag
= x3::rule<class SimpleElementID, SimpleElement, true> {"simpleTag"}
= x3::with<TagName>(std::string()) [
openTag
>> tagContents
>> x3::omit [ closeTag ]
];

看到它 Live On Coliru

关于c++ - Spirit X3,指的是之前匹配的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62143841/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com