簡體   English   中英

帶船長的Boost.Qi規則與“。”不匹配 字符

[英]Boost.Qi rule with skipper does not match '.' character

所以我有以下qi隊長:

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,並且由於迭代器彼此不可達,因此解析失敗:

module mymod (A, B);

input A, B;

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

隊長是否在消耗點數? 我應該馬上在點上找到火柴,對嗎? 誰能幫我發現問題?

這是我的main代碼:

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. 您需要復習船長和詞素:

  2. 具體來說, qi::eolqi::space一部分(而不是qi::blank )。 我會簡單地指定船長為

     skip = qi::ascii::space | line_comment; line_comment = "//" >> *(qi::char_ - qi::eol) >> (qi::eol|qi::eoi); 
  3. 更具體地說,您將/需要/確保標識符是一個詞素。 最簡單的方法是從規則的聲明中刪除船長。 否則, "ab\\nc"是標識符"abc"的完全有效的拼寫。

     // lexemes qi::rule<Iterator, std::string()> primitive_gate, ident; 
  4. 接下來的示例顯示了每個';'結尾的語句 但是你的語法說:

     statements = statement % ';'; 

    這將允許"S1""S1;S2" ,...,但不允許 "S1;" 有幾種解決方法。 最簡單的似乎是

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

    或者,如果為"S1;;;;" 也可以接受,您可能會想說

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

    請注意,盡管這將接受";;;S1;;" ,也不像您預期​​的那樣是"" 我經常采用的模式是可選元素列表:

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

    可以很好地接受""";" ";;" "S1"";;S1;" 等。請注意,它不像更冗長的內容那樣有效

     statements = *(*qi::lit(';') >> statement >> +qi::lit(';')); // require exactly one `;` always 
  5. 我注意到您使用qi::char_('(') (和類似方法)將在綜合屬性中公開匹配的字符。這不太可能是您的意思。請改用qi::lit('(') ,或者的確,在解析器表達式中使用裸字符/字符串文字將其提升為解析器表達式¹

  6. 考慮使用BOOST_SPIRIT_DEBUG來了解您的語法在做什么

  7. 封裝您的隊長,因為調用者不必為此而煩惱,並且您可能不希望語法用戶更改隊長(這可能會破壞整個語法)。

  8. 考慮使用符號而不是列出關鍵字,例如:

     primitive_gate = qi::lit("nand") | "nor" | "and" | "or" | "xor" | "xnor" | "buf" | "not"; 
  9. 注意順序和關鍵字匹配。 如果您解析一個標識符,那么像nand這樣的關鍵字將匹配。 但是,如果您具有xor21類的標識符,則關鍵字xor將首先匹配。 您可能需要/需要注意這一點( 如何以增強的精神正確地解析保留字

  10. 請注意,除非您使用operator%=來將解析器表達式分配給規則,否則語義動作(例如found_smth )的存在會禁止自動屬性傳播。

演示時間

應用以上...:

魔盒直播

#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 ):

<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原型表達域

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM