> prefix) |(lit('-') >> prefix) | postfix -6ren">
gpt4 book ai didi

c++ - 提升精神带走关键字并忽略船长

转载 作者:行者123 更新时间:2023-11-30 03:27:24 25 4
gpt4 key购买 nike

这是使用表达式的语法的一小部分。

 prefix =
(lit(L"not") >> prefix)
|(lit('-') >> prefix)
| postfix
;

在 postfix 中的某种方式,我有 name_pure 来获取标识符..

name_pure = lexeme[+(boost::spirit::standard_wide::alpha | '_') >> *(boost::spirit::standard_wide::alnum | '_')];

目前一切正常。可以这样写

a=not b

但是如果我像这样开始使用not作为名称前缀

a=not notvarname 

我从 AST 得到一个解析器输出,看起来像这样

a=not not varname

这意味着 not 用作前缀规则,而不是 Name 规则 Name_pure

在我看来,Skipper 似乎没有正确参与。

这是我的船长

 template<typename Iterator>
struct eol_skipper : public qi::grammar<Iterator> {

eol_skipper() : eol_skipper::base_type(skip)
{

using qi::eol;
using qi::lit;
using qi::char_;
skip = ascii::space -eol;
}
qi::rule<Iterator> skip;
};

最佳答案

和上次一样,我不认为船长是你的问题。

也许是关于船长做什么的假设。

  1. space - eol 只是空白
  2. 词位不跳过(这是定义):Boost spirit skipper issues
  3. PEG 语法是贪婪的并且是从左到右的。因此,如果要避免在纯名称内匹配 "not",则需要确保处于单词边界:Prevent the Boost Spirit Symbol parser from accepting a keyword too earlyHow to parse reserved words correctly in boost spirit

我会编写更多 self 描述的规则(例如 eol_skipper 建议它跳过 eol,但这正是它不会跳过的内容?)。

using Skipper = qi::blank_type;

然后,通过从声明中删除 skipper,使您的 identifier 规则(pure_name?)成为一个隐式的 lexeme:

  private:
qi::rule<Iterator, Ast::AssignmentStatement()> start;
qi::rule<Iterator, Ast::AssignmentStatement(), Skipper> assignment;
qi::rule<Iterator, Ast::Expr(), Skipper> expr;
qi::rule<Iterator, Ast::Negated(), Skipper> negation;
// implicit lexemes
qi::rule<Iterator, Ast::Identifier()> identifier;

最后,使用 !p 解析器指令断言匹配关键字/标识符边界:

    negation
= lexeme [(lit("not") | '0') >> !(alnum|'_')] >> expr
;

演示时间

Live On Coliru

#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;

namespace Ast {
using Identifier = std::string;
struct Negated;

using Expr = boost::variant<Identifier, boost::recursive_wrapper<Negated> >;

struct Negated {
Expr expr;
};

struct AssignmentStatement {
Identifier lhs;
Expr rhs;
};
}

BOOST_FUSION_ADAPT_STRUCT(Ast::Negated, expr)
BOOST_FUSION_ADAPT_STRUCT(Ast::AssignmentStatement, lhs, rhs)

template <typename Iterator> struct parser : qi::grammar<Iterator, Ast::AssignmentStatement()> {
using Skipper = qi::blank_type;

parser() : parser::base_type(start) {
using namespace qi;

start = skip(blank) [ assignment ];

assignment = identifier >> '=' >> expr;

expr = negation | identifier;

negation
= lexeme [(lit("not") | '0') >> !(alnum|'_')] >> expr
;

identifier = char_("a-zA-Z_") >> *char_("a-zA-Z0-9_");
// or:
identifier = raw [ +(alpha | '_') >> *(alnum | '_') ];

BOOST_SPIRIT_DEBUG_NODES((start)(expr)(assignment)(identifier)(negation))
}

private:
qi::rule<Iterator, Ast::AssignmentStatement()> start;
qi::rule<Iterator, Ast::AssignmentStatement(), Skipper> assignment;
qi::rule<Iterator, Ast::Expr(), Skipper> expr;
qi::rule<Iterator, Ast::Negated(), Skipper> negation;
// implicit lexemes
qi::rule<Iterator, Ast::Identifier()> identifier;
};

namespace Ast {
std::ostream& operator<<(std::ostream& os, Negated const& o) { return os << "NOT[" << o.expr << "]"; }
std::ostream& operator<<(std::ostream& os, AssignmentStatement const& a) { return os << a.lhs << " = " << a.rhs; }
}

int main() {
using It = std::string::const_iterator;
for (std::string const input : {
"a=not _b",
"a=not not_var_name",
})
{
It f = input.begin(), l = input.end();

Ast::AssignmentStatement assignment;
if (parse(f, l, parser<It>{}, assignment))
std::cout << "Parsed " << assignment << "\n";
else
std::cout << "Parse failed\n";

if (f!=l)
std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'\n";
}
}

打印

Parsed a = NOT[_b]
Parsed a = NOT[not_var_name]

NOTE how defining BOOST_SPIRIT_DEBUG also gives you debug output in case you wanted to troubleshoot your rules, next time:

<start>
<try>a=not b</try>
<assignment>
<try>a=not b</try>
<identifier>
<try>a=not b</try>
<success>=not b</success>
<attributes>[[a]]</attributes>
</identifier>
<expr>
<try>not b</try>
<negation>
<try>not b</try>
<expr>
<try> b</try>
<negation>
<try> b</try>
<fail/>
</negation>
<identifier>
<try>b</try>
<success></success>
<attributes>[[b]]</attributes>
</identifier>
<success></success>
<attributes>[[b]]</attributes>
</expr>
<success></success>
<attributes>[[[b]]]</attributes>
</negation>
<success></success>
<attributes>[[[b]]]</attributes>
</expr>
<success></success>
<attributes>[[[a], [[b]]]]</attributes>
</assignment>
<success></success>
<attributes>[[[a], [[b]]]]</attributes>
</start>
Parsed a = NOT[b]
<start>
<try>a=not notvarname</try>
<assignment>
<try>a=not notvarname</try>
<identifier>
<try>a=not notvarname</try>
<success>=not notvarname</success>
<attributes>[[a]]</attributes>
</identifier>
<expr>
<try>not notvarname</try>
<negation>
<try>not notvarname</try>
<expr>
<try> notvarname</try>
<negation>
<try> notvarname</try>
<fail/>
</negation>
<identifier>
<try>notvarname</try>
<success></success>
<attributes>[[n, o, t, v, a, r, n, a, m, e]]</attributes>
</identifier>
<success></success>
<attributes>[[n, o, t, v, a, r, n, a, m, e]]</attributes>
</expr>
<success></success>
<attributes>[[[n, o, t, v, a, r, n, a, m, e]]]</attributes>
</negation>
<success></success>
<attributes>[[[n, o, t, v, a, r, n, a, m, e]]]</attributes>
</expr>
<success></success>
<attributes>[[[a], [[n, o, t, v, a, r, n, a, m, e]]]]</attributes>
</assignment>
<success></success>
<attributes>[[[a], [[n, o, t, v, a, r, n, a, m, e]]]]</attributes>
</start>
Parsed a = NOT[notvarname]

关于c++ - 提升精神带走关键字并忽略船长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47427893/

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