灵气:完全无视一些规则的输出

Spirit Qi: Completely ignoring output of some rules

本文关键字:规则 输出 灵气      更新时间:2023-10-16

我正在解析一些结构模糊的输入,比如C-ish代码。像这样:

Name0
{
Name1
{
//A COMMENT!!
Param0 *= 2
Param2 = "lol"
}
}

其中一部分是评论,我想完全忽略它(它不起作用)。我认为有两件事是node,像Name0 {}这样的命名作用域(category规则)和像Param0 *= 2这样的值(param规则)。。。则存在CCD_ 6。我试过这样设置:

typedef boost::variant<boost::recursive_wrapper<Category>, Param> Node;
qi::rule<Iterator, Node(), ascii::space_type> node;

因此node规则将CategoryParam放入variant中。以下是其他规则(我省略了一些对此并不重要的规则):

qi::rule<Iterator> comment; //comment has no return type
qi::rule<Iterator, Category(), ascii::space_type> category;
qi::rule<Iterator, Param(), ascii::space_type> param;

他们的实际代码:

comment = "//" >> *(char_ - eol);
param %=
tagstring
>> operators
>> value;
category %=
tagstring
>> '{'
>> *node
> '}';
node %= comment | category | param;

comment被设置为使用=而不是%=,并且它没有返回类型。然而,无论注释出现在哪里,它们最终都会在我的输出Nodes中创建空的Categorys。我已经尝试过将commentnode规则中移出并进入category,如下所示:

category %=
tagstring
>> '{'
>> *(comment | node)
> '}';

还有其他各种各样的东西,但那些空条目不断出现。我不得不让comment输出一个字符串,并将std::string放在我的Nodevariant中,只是为了对它们进行排序和捕获,但这扰乱了我在规则的其他部分进行注释的能力(除非我真的在每个位置都获取了字符串)。

我怎么能完全忽略comment,让它不以任何方式出现在任何输出中?

编辑:你可能认为omit会做到,但似乎没有改变任何事情。。。

编辑2:参考这个SO的答案,我有一个不可靠的解决方案:

node %= category | param;
category %=
tagstring
>> '{'
>> *comment >> *(node >> *comment)
> '}';

然而,我想尝试将注释粘贴到各种位置(在tagstring{之间,在我未显示的root规则中,在根category之间,等等)。还有比这更简单的方法吗?我希望只要把一个简单的>> commentwrapper插到我想插的地方就可以完成。。。

好吧,让自己成为队长也不算太糟。正如Mike M所说,它优雅地解决了这个评论问题。我在一个名为Parser的结构中定义我的规则,该结构是用Iterator模板化的。必须做一些调整才能使用队长。首先,这里是在Parser中定义的队长,以及我的所有其他规则:

typedef qi::rule<Iterator> Skipper;
Skipper skipper;

所以CCD_ 33是CCD_。以下是我的Parser结构最初的样子,它使用ascii::space_type类型的ascii::space规则作为其队长,这与skipper所基于的qi::rule<Iterator>类型不同!

struct Parser : qi::grammar<Iterator, std::vector<Category>(), ascii::space_type>
{
qi::rule<Iterator, std::vector<Category>(), ascii::space_type> root;
...

因此,规则模板中ascii::space_type的每个实例都必须替换为Skipper!这包括除了这里显示的root之外的其他规则,例如我的问题中的paramcategory。留下旧ascii::space_type的任何残余都会产生神秘的编译器错误。

struct Parser : qi::grammar<Iterator, std::vector<Category>(), qi::rule<Iterator>>
{
typedef qi::rule<Iterator> Skipper;
Skipper skipper;
qi::rule<Iterator, std::vector<Category>(), Skipper> root;
...

最初的船长只是space,我的现在是spacecomment的替代品。没有丢失旧功能(空间跳过)。

skipper = space | comment;

然后需要从使用ascii::space:的旧版本调整phrase_parse调用

bool r = phrase_parse(iter, end, parser, ascii::space, result);

bool r = phrase_parse(iter, end, parser, parser.skipper, result);

现在评论就像空白一样容易消失。令人惊叹的