带船长的Boost.Qi规则与“."不匹配特点 [英] Boost.Qi rule with skipper does not match '.' character

查看:58
本文介绍了带船长的Boost.Qi规则与“."不匹配特点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有以下qi队长:

So I have the following qi skipper:

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

verilog_skipper() : verilog_skipper::base_type(skip) {
    namespace phx = boost::phoenix;
    skip = qi::ascii::space | qi::eol | line_comment;
    line_comment = (qi::lit("//") >> *(qi::char_ - qi::eol) >> *(qi::eol));
}
qi::rule<Iterator> skip;
qi::rule<Iterator> line_comment;
};

和以下齐语法:

template <typename Iterator, 
typename Skipper = verilog_skipper<Iterator> struct verilog_grammer : 
qi::grammar<Iterator, Skipper> {
verilog_ast ckt_ast;

verilog_grammer()
: verilog_grammer::base_type(module) {

namespace phx = boost::phoenix;

module = (module_definition >> statements >> qi::lit("endmodule"));

statements = statement % ';';

statement = (input_wires | instance);

module_definition = (qi::lit("module") >> ident >> qi::char_('(')
                >> ident_list >>  qi::char_(')') >> ';' );

input_wires = (qi::lit("input") >> ident_list);

instance = (ident >> ident >> 
qi::char_('(') >> connection_pair_list >> qi::char_(')'));

connection_pair_list = connection_pair % ',';
connection_pair =  (qi::char_('.')[phx::bind(&found_smth)] 
>> ident >> qi::char_('(') >> ident >> qi::char_(')'));

ident_list = ident % ',';
ident = (qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9"));
}

qi::rule<Iterator, Skipper> module;
qi::rule<Iterator, Skipper> module_definition;
qi::rule<Iterator, Skipper> statements;
qi::rule<Iterator, Skipper> statement;
qi::rule<Iterator, Skipper> instance;
qi::rule<Iterator, Skipper> input_wires;
qi::rule<Iterator, std::vector<std::pair<std::string, std::string> >(), Skipper> connection_pair_list;
qi::rule<Iterator, std::pair<std::string, std::string>(), Skipper> connection_pair;
qi::rule<Iterator, std::vector<std::string>(), Skipper> ident_list;
qi::rule<Iterator, std::string(), Skipper> ident;
};

我已经将 found_smth 函数绑定到语法中的点字符.我认为规则正确,但是我无法匹配以下输入中的任何connection_pairs,并且由于迭代器彼此不可达,因此解析失败:

I have binded the found_smth function to the dot character in the grammar. I feel the rules are correct but I am unable to match any connection_pairs in the following input and the parse fails as the iterators do not reach one another:

module mymod (A, B);

input A, B;

XOR21 gatexor5 (.A(B) , .C(D));
endmodule

船长是否正在消耗点?我应该立刻在点上找到火柴,对吗?谁能帮我发现问题?

Is the skipper consuming the dot? I should get a match on the dot immediately right? Can anyone help me spot the issue?

这是我的主要代码:

typedef verilog_skipper<std::string::const_iterator> verilog_skipper;
typedef verilog_grammer<std::string::const_iterator, verilog_skipper> verilog_grammar;
verilog_grammar vg; // Our grammar
verilog_skipper vg_skip; // Our grammar

using boost::spirit::ascii::space;
std::string::const_iterator iter = storage.begin();
std::string::const_iterator end = storage.end();

bool r = qi::phrase_parse(iter, end, vg, vg_skip);

if (r && iter == end)
{
  std::cout << "-------------------------\n";
  std::cout << "Parsing succeeded\n";
  std::cout << "-------------------------\n";
  return 0;
}

推荐答案

一些事情.

  1. 您需要复习船长和词素:

  1. You need to brush up on skippers and lexemes:

具体来说, qi :: eol qi :: space 的一部分(不是 qi :: blank ).我可以简单地将船长指定为

Specifically, qi::eol is part of qi::space (not qi::blank). I'd specify the skipper simply as

skip = qi::ascii::space | line_comment;
line_comment = "//" >> *(qi::char_ - qi::eol) >> (qi::eol|qi::eoi);

  • 更具体地说,您将/需要/确保标识符是一个词素.最简单的方法是从规则的声明中删除船长.否则,"a b \ nc" 是标识符"abc" 的完全有效的拼写.

  • Even more specifically, you'll /need/ to make sure identifiers are a lexeme. The simplest way is to drop the skipper from the rule's declaration. Otherwise "a b\nc" is a perfectly valid spelling of the identifier "abc".

    // lexemes
    qi::rule<Iterator, std::string()> primitive_gate, ident;
    

  • 下一个示例显示每个语句以';'结尾.但是你的语法说:

  • Next up your sample shows every statement terminated with ';'. But your grammar says:

    statements = statement % ';';
    

    这将允许"S1" "S1; S2" ,...但不允许 "S1;" .有几种方法可以修复它.最简单的似乎是

    This will allow "S1", "S1;S2", ... but not "S1;". There are several ways to fix it. The simplest would appear to be

    statements = +(statement >> ';'); // require exactly one `;` always
    

    或者,如果"S1 ;;;;" 也可以接受,您可能会想说

    Alternatively, if "S1;;;;" is also acceptable, you might be tempted to say

    statements = +(statement >> +qi::lit(';')); // require at least one `;` always
    

    请注意,尽管这将接受您可能期望的";;; S1 ;;" " .我经常采用的模式是可选元素列表:

    Note though that this would not accept ";;;S1;;", nor "" as you might have expected. A pattern I often employ is the optional element list:

    statements = -statement % ';'; // simple and flexible
    

    哪种方法可以很好地接受" ;" ";;" "S1" ";; S1;" 等.请注意,它效率不如

    Which has a nice way of accepting "", ";", ";;", "S1", ";;S1;" etc. Note it's not as efficient as something more verbose like

    statements = *(*qi::lit(';') >> statement >> +qi::lit(';')); // require exactly one `;` always
    

  • 我注意到您使用了 qi :: char _('(')(及类似方法),它将在合成属性中公开匹配的字符. 高度 这不是您的意思,而是使用 qi :: lit('(')解析表达式¹

  • I note you use qi::char_('(') (and similar) that will expose the matched character in the synthesized attribute. It is highly unlikely this is what you mean. Use qi::lit('(') instead, or indeed, using bare character/string literals in your parser expression will promote them to parser expressions¹

    考虑使用BOOST_SPIRIT_DEBUG来了解您的语法在做什么

    Consider using BOOST_SPIRIT_DEBUG to gain insight into what your grammar is doing

    封装您的队长,因为不应打扰呼叫者,并且您可能不希望语法用户更改队长(这可能会破坏整个语法).

    Encapsulate your skipper, since the caller should not be bothered about it, and you likely do not want users of your grammar to be able to change the skipper (that might break the entire grammar).

    考虑使用符号而不是列出关键字,例如:

    Consider using symbols instead of listing keywords, like:

    primitive_gate       = qi::lit("nand") | "nor" | "and" | "or" | "xor" |
        "xnor" | "buf" | "not";
    

  • 请注意顺序和关键字匹配.如果您解析标识符,则将匹配诸如 nand 的关键字.但是,如果您有一个标识符,例如 xor21 ,则关键字 xor 将首先匹配.您可能需要/需要注意这一点(如何以激进的精神正确地解析保留字)

  • Pay attention to the ordering and keyword matching. If you parse an identifier, a keyword like nand would match. If you have an identifier like xor21 however, the keyword xor would match first. You may want/need to guard against this (How to parse reserved words correctly in boost spirit)

    请注意,除非您使用 operator%= found_smth )会抑制自动属性传播.code>将解析器表达式分配给规则.

    Note that the presence of a semantic action (like e.g. the found_smth) inhibits automatic attribute propagation, unless you use operator%= to assign the parser expression to the rule.

    演示时间

    应用以上...:

    DEMO TIME

    Applying the above...:

    在魔盒上直播 >

    #define BOOST_SPIRIT_DEBUG
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <boost/spirit/repository/include/qi_distinct.hpp>
    #include <boost/fusion/adapted.hpp>
    namespace qi = boost::spirit::qi;
    
    static void found_smth() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
    
    template <typename Iterator> struct verilog_skipper : qi::grammar<Iterator> {
    
        verilog_skipper() : verilog_skipper::base_type(skip) {
            skip = qi::ascii::space | line_comment;
            line_comment = "//" >> *(qi::char_ - qi::eol) >> (qi::eol|qi::eoi);
        }
      private:
        qi::rule<Iterator> skip;
        qi::rule<Iterator> line_comment;
    };
    
    template <typename Iterator>
    struct verilog_grammar : qi::grammar<Iterator> {
        //verilog_ast ckt_ast;
        typedef verilog_skipper<Iterator> Skipper;
    
        verilog_grammar() : verilog_grammar::base_type(start) {
    
            namespace phx = boost::phoenix;
            using boost::spirit::repository::qi::distinct;
            auto kw = distinct(qi::char_("a-zA-Z_0-9"));
    
            start                = qi::skip(qi::copy(skipper)) [module];
            module               = (module_definition >> statements >> kw["endmodule"]);
    
            module_definition    = (kw["module"] >> ident >> '(' >> ident_list >> ')' >> ';');
    
            statements           = -statement % ';';
    
            statement            = input_wires | output_wires | internal_wires | primitive | instance;
    
            input_wires          = kw["input"] >> ident_list;
    
            output_wires         = kw["output"] >> ident_list;
    
            internal_wires       = kw["wire"] >> ident_list;
    
            primitive            = primitive_gate >> ident >> '(' >> ident_list >> ')';
    
            instance             = ident >> ident >> '(' >> connection_pair_list >> ')';
    
            connection_pair_list = connection_pair % ',';
    
            // NOTE subtle use of `operator%=` in the presence of a semantic action
            connection_pair     %= (qi::lit('.')[phx::bind(&found_smth)] >> ident
                    >> '(' >> ident >> ')');
    
            ident_list           = ident % ',';
            ident                = (qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9"));
    
            primitive_gate       = qi::raw[kw[primitive_gate_]];
    
            BOOST_SPIRIT_DEBUG_NODES(
                    (module)(module_definition)(statements)(statement)
                    (primitive)(primitive_gate)(instance)
                    (output_wires)(input_wires)(input_wires)
                    (connection_pair_list)(connection_pair)(ident_list)(ident)
                )
        }
      private:
        qi::rule<Iterator> start;
        qi::rule<Iterator, Skipper> module;
        qi::rule<Iterator, Skipper> module_definition;
        qi::rule<Iterator, Skipper> statements;
        qi::rule<Iterator, Skipper> statement;
        qi::rule<Iterator, Skipper> primitive;
        qi::rule<Iterator, std::string()> primitive_gate;
        qi::rule<Iterator, Skipper> instance;
        qi::rule<Iterator, Skipper> output_wires;
        qi::rule<Iterator, Skipper> input_wires;
        qi::rule<Iterator, Skipper> internal_wires;
        qi::rule<Iterator, std::vector<std::pair<std::string, std::string> >(), Skipper> connection_pair_list;
        qi::rule<Iterator, std::pair<std::string, std::string>(), Skipper> connection_pair;
        qi::rule<Iterator, std::vector<std::string>(), Skipper> ident_list;
    
        // lexemes
        qi::rule<Iterator, std::string()> ident;
        struct primitive_gate_t : qi::symbols<char> {
            primitive_gate_t() { this->add("nand")("nor")("and")("or")("xor")("xnor")("buf")("not"); }
        } primitive_gate_;
    
        Skipper skipper;
    };
    
    #include <fstream>
    int main() {
        std::ifstream ifs("input.txt");
        using It = boost::spirit::istream_iterator;
        It f(ifs >> std::noskipws), l;
    
        bool ok = qi::parse(f, l, verilog_grammar<It>{});
        if (ok) 
            std::cout << "Parsed\n";
        else
            std::cout << "Parse failed\n";
    
        if (f!=l)
            std::cout << "Remaining unparsed '" << std::string(f,l) << "'\n";
    }
    

    打印:

    void found_smth()
    void found_smth()
    Parsed
    

    或启用了调试信息( BOOST_SPIRIT_DEBUG ):

    Or with debug information enabled (BOOST_SPIRIT_DEBUG):

    <module>
      <try>module mymod (A, B);</try>
      <module_definition>
        <try>module mymod (A, B);</try>
        <ident>
          <try>mymod (A, B);\n\ninput</try>
          <success> (A, B);\n\ninput A, B</success>
          <attributes>[[m, y, m, o, d]]</attributes>
        </ident>
        <ident_list>
          <try>A, B);\n\ninput A, B;\n</try>
          <ident>
            <try>A, B);\n\ninput A, B;\n</try>
            <success>, B);\n\ninput A, B;\n\n</success>
            <attributes>[[A]]</attributes>
          </ident>
          <ident>
            <try>B);\n\ninput A, B;\n\nXO</try>
            <success>);\n\ninput A, B;\n\nXOR</success>
            <attributes>[[B]]</attributes>
          </ident>
          <success>);\n\ninput A, B;\n\nXOR</success>
          <attributes>[[[A], [B]]]</attributes>
        </ident_list>
        <success>\n\ninput A, B;\n\nXOR21</success>
        <attributes>[]</attributes>
      </module_definition>
      <statements>
        <try>\n\ninput A, B;\n\nXOR21</try>
        <statement>
          <try>\n\ninput A, B;\n\nXOR21</try>
          <input_wires>
            <try>\n\ninput A, B;\n\nXOR21</try>
            <input_wires>
              <try>\n\ninput A, B;\n\nXOR21</try>
              <ident_list>
                <try> A, B;\n\nXOR21 gatexo</try>
                <ident>
                  <try>A, B;\n\nXOR21 gatexor</try>
                  <success>, B;\n\nXOR21 gatexor5</success>
                  <attributes>[[A]]</attributes>
                </ident>
                <ident>
                  <try>B;\n\nXOR21 gatexor5 (</try>
                  <success>;\n\nXOR21 gatexor5 (.</success>
                  <attributes>[[B]]</attributes>
                </ident>
                <success>;\n\nXOR21 gatexor5 (.</success>
                <attributes>[[[A], [B]]]</attributes>
              </ident_list>
              <success>;\n\nXOR21 gatexor5 (.</success>
              <attributes>[]</attributes>
            </input_wires>
            <success>;\n\nXOR21 gatexor5 (.</success>
            <attributes>[]</attributes>
          </input_wires>
          <success>;\n\nXOR21 gatexor5 (.</success>
          <attributes>[]</attributes>
        </statement>
        <statement>
          <try>\n\nXOR21 gatexor5 (.A</try>
          <input_wires>
            <try>\n\nXOR21 gatexor5 (.A</try>
            <input_wires>
              <try>\n\nXOR21 gatexor5 (.A</try>
              <fail/>
            </input_wires>
            <fail/>
          </input_wires>
          <output_wires>
            <try>\n\nXOR21 gatexor5 (.A</try>
            <fail/>
          </output_wires>
          <primitive>
            <try>\n\nXOR21 gatexor5 (.A</try>
            <primitive_gate>
              <try>XOR21 gatexor5 (.A(B</try>
              <fail/>
            </primitive_gate>
            <fail/>
          </primitive>
          <instance>
            <try>\n\nXOR21 gatexor5 (.A</try>
            <ident>
              <try>XOR21 gatexor5 (.A(B</try>
              <success> gatexor5 (.A(B) , .</success>
              <attributes>[[X, O, R, 2, 1]]</attributes>
            </ident>
            <ident>
              <try>gatexor5 (.A(B) , .C</try>
              <success> (.A(B) , .C(D));\nen</success>
              <attributes>[[g, a, t, e, x, o, r, 5]]</attributes>
            </ident>
            <connection_pair_list>
              <try>.A(B) , .C(D));\nendm</try>
              <connection_pair>
                <try>.A(B) , .C(D));\nendm</try>
                <ident>
                  <try>A(B) , .C(D));\nendmo</try>
                  <success>(B) , .C(D));\nendmod</success>
                  <attributes>[[A]]</attributes>
                </ident>
                <ident>
                  <try>B) , .C(D));\nendmodu</try>
                  <success>) , .C(D));\nendmodul</success>
                  <attributes>[[B]]</attributes>
                </ident>
                <success> , .C(D));\nendmodule</success>
                <attributes>[[[A], [B]]]</attributes>
              </connection_pair>
              <connection_pair>
                <try> .C(D));\nendmodule\n</try>
                <ident>
                  <try>C(D));\nendmodule\n</try>
                  <success>(D));\nendmodule\n</success>
                  <attributes>[[C]]</attributes>
                </ident>
                <ident>
                  <try>D));\nendmodule\n</try>
                  <success>));\nendmodule\n</success>
                  <attributes>[[D]]</attributes>
                </ident>
                <success>);\nendmodule\n</success>
                <attributes>[[[C], [D]]]</attributes>
              </connection_pair>
              <success>);\nendmodule\n</success>
              <attributes>[[[[A], [B]], [[C], [D]]]]</attributes>
            </connection_pair_list>
            <success>;\nendmodule\n</success>
            <attributes>[]</attributes>
          </instance>
          <success>;\nendmodule\n</success>
          <attributes>[]</attributes>
        </statement>
        <statement>
          <try>\nendmodule\n</try>
          <input_wires>
            <try>\nendmodule\n</try>
            <input_wires>
              <try>\nendmodule\n</try>
              <fail/>
            </input_wires>
            <fail/>
          </input_wires>
          <output_wires>
            <try>\nendmodule\n</try>
            <fail/>
          </output_wires>
          <primitive>
            <try>\nendmodule\n</try>
            <primitive_gate>
              <try>endmodule\n</try>
              <fail/>
            </primitive_gate>
            <fail/>
          </primitive>
          <instance>
            <try>\nendmodule\n</try>
            <ident>
              <try>endmodule\n</try>
              <success>\n</success>
              <attributes>[[e, n, d, m, o, d, u, l, e]]</attributes>
            </ident>
            <ident>
              <try></try>
              <fail/>
            </ident>
            <fail/>
          </instance>
          <fail/>
        </statement>
        <success>\nendmodule\n</success>
        <attributes>[]</attributes>
      </statements>
      <success>\n</success>
      <attributes>[]</attributes>
    </module>
    


    ¹,只要涉及表达的一个操作数来自Qi原型表达域


    ¹ as long as one operand involved in the expression is from the Qi proto-expression domain

    这篇关于带船长的Boost.Qi规则与“."不匹配特点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆