增强精神带走关键字并忽略队长 [英] Boost spirit take away keyword and ignore skipper
问题描述
这是使用表达式的语法的一小部分.
This is a small part of a grammer using expressions.
prefix =
(lit(L"not") >> prefix)
|(lit('-') >> prefix)
| postfix
;
在后缀内的某种方式,我有 name_pure 来使用标识符..
Some way inside postfix I have name_pure to take an identifier ..
name_pure = lexeme[+(boost::spirit::standard_wide::alpha | '_') >> *(boost::spirit::standard_wide::alnum | '_')];
到目前为止,一切都很好.可以写类似
So far all is fine. Can write something like
a=not b
但是如果我开始使用 not 作为这样的名称前缀
But if I start to use not as a name prefix like this one
a=not notvarname
我从AST得到一个解析器输出,看起来像这样
I get a parser Output from the AST which look like this
a=not not varname
这意味着 not 用作前缀规则,而不与 Name_pure 规则一起用作Name
.
Which means the not is used as prefix rule and not as Name
with the rule Name_pure.
从我的角度来看,似乎船长未正确介入.
From my point of view it looks like the Skipper is not involved correctly.
这是我的船长
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;
};
推荐答案
就像上次一样,我认为船长不是您的问题.
Like last time, I don't think the skipper is your problem.
关于船长所做的假设.
-
space - eol
就是blank
. - 词汇无法跳过(这就是定义):提升精神队长问题
- PEG语法是贪婪的,并且是从左到右的.因此,如果您想避免在纯名称内匹配
"not"
,则需要确保您在单词边界上:如何正确地解析保留字
space - eol
is justblank
.- lexemes do not skip (that's the definition): Boost spirit skipper issues
- PEG grammars are greedy and left-to-right. So, you need to make sure you're on a word boundary if you want to avoid matching
"not"
inside a purename: Prevent the Boost Spirit Symbol parser from accepting a keyword too early or How to parse reserved words correctly in boost spirit
我会写出更具描述性的规则(例如eol_skipper
建议它跳过eol
,但这正是它不跳过的内容吗?)
I'd write the rules a lot more self-descriptive (e.g. eol_skipper
suggests it skips eol
, but that's exactly what it DOESN'T skip?).
using Skipper = qi::blank_type;
然后,只需从声明中删除船长,即可将identifier
规则(pure_name?)隐含为lexeme
:
Then, make your identifier
rule (pure_name?) an implicit lexeme
by just dropping the skipper from the declaration:
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
解析器指令断言not
在关键字/标识符边界上匹配:
Finally, use !p
parser directive to assert that not
matched on a keyword/identifier boundary:
negation
= lexeme [(lit("not") | '0') >> !(alnum|'_')] >> expr
;
演示时间
#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]
注意,下次定义
BOOST_SPIRIT_DEBUG
时如何为您提供调试输出,以防万一您想对规则进行故障排除:
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]
这篇关于增强精神带走关键字并忽略队长的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!