增强精神夺走关键字,而忽略船长



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

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

postfix i有 name_pure 以获取标识符。

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

到目前为止一切都很好。可以写

之类的东西
a=not b

但是,如果我开始使用而不是作为这样的名称前缀

a=not notvarname 

我从AST中获得一个解析器,看起来像这样

a=not not varname

这意味着不是用作前缀规则,而不是用规则 name_pure 作为Name

从我的角度来看,船长看来没有正确涉及。

这是我的船长

 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只是blank
  2. Lexemes不跳过(这是定义):增强精神船长问题
  3. 钉语法是贪婪和从左到右的。因此,如果要避免在Purename内部匹配"not",则需要确保您处于一个单词边界:防止Boost Spirit Symber Parser过早接受关键字,或者如何以Boost Spirit正确解析保留的单词

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

using Skipper = qi::blank_type;

然后,通过从声明中删除船长来制作您的 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解析器指令断言not在关键字/标识符边界上匹配:

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

演示时间

活在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 failedn";
        if (f!=l)
            std::cout << "Remaining unparsed input: '" << std::string(f,l) << "'n";
    }
}

打印

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

NOTE 定义BOOST_SPIRIT_DEBUG还为您提供调试输出,以防您要对规则进行故障排除,下次:

<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]

最新更新