使用提升精神解析为结构

时间:2014-05-19 21:10:50

标签: c++ boost boost-spirit

这是我第一次使用嘘声,我想将这样的输入解析为结构:

  

fanout_n#(2,0,0)FANOUT_2(c7552_wire_2,{c7552_wire_2_0,c7552_wire_2_1});

  

fanout_n#(2,0,0)FANOUT_2({wire1,wire2},{c7552_wire_2_0,c7552_wire_2_1});

我的结构是这样的:

struct GateStruct
{
    int numberOfInputs;
    std::string gateName;
    std::vector<std::string> wireNames_first;
    std::vector<std::string> wireNames_second;
};

例如在解析之后,gate必须包含以下值:

struct GateStruct
{
    int numberOfInputs = 2;
    std::string gateName = FANOUT_2;
    std::vector<std::string> wireNames_first = {wire1 , wire2};
    std::vector<std::string> wireNames_second = {c7552_wire_2_0, c7552_wire_2_1};
};gate

我的语法是这样的:

template <typename Iterator>
struct gate_parser : qi::grammar<Iterator, GateStruct(), ascii::space_type>
{
    gate_parser() : gate_parser::base_type(start)
    {
        using qi::int_;
        using qi::lit;
        using qi::double_;
        using qi::lexeme;
        using ascii::char_;
        using qi::_1;
        //using phoenix::ref;

        wirenameString %= lexeme[+(char_)];
          numberString = lit("(") >> int_ >> *(lit(",") >> lit("0")) >> lit(")");
        wireList    = -(lit("{")) >> wirenameString >> *(lit(",") >> wirenameString) >> -(lit("}")); //will parse this: {wire1 , wire2 , ...,wiren}

        start %= lit("fanout_n")
                 >> lit("#")
                 >> numberString
                 >> wirenameString
                 >> lit("(")
                 >> wireList
                 >> lit(",")
                 >> wireList
                 >> lit(");")
                 ;

    }


    qi::rule<Iterator , int() , ascii::space_type > numberString;
    qi::rule<Iterator , std::string(), ascii::space_type > wirenameString;
    qi::rule<Iterator , std::vector<std::string >() , ascii::space_type> wireList;
    qi::rule<Iterator , GateStruct(), ascii::space_type > start;
};

并使用此代码将输入解析为struct:

int main(){

using boost::spirit::ascii::space;
typedef std::string::const_iterator iterator_type;
typedef client::gate_parser<iterator_type> gate_parser;

gate_parser g;
std::string str;
while (getline(std::cin, str))
{
    if (str.empty() || str[0] == 'q' || str[0] == 'Q')
        break;

    client::GateStruct gate;
    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();
    bool r = phrase_parse(iter, end, g, space, gate);

    if (r && iter == end)
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing succeeded\n";
        std::cout << "\n-------------------------\n";
    }
    else
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing failed\n";
        std::cout << "Remaining unparsed: '" << std::string(iter,end) << "'\n";
        std::cout << "-------------------------\n";
    }
}

std::cout << "Bye... :-) \n\n";
return 0;

}

它编译时没有任何错误或警告,但不幸的是它根本没有解析我的输入。

1 个答案:

答案 0 :(得分:2)

+qi::char_消耗所有输入,因为一切都匹配。

修正语法: Live On Coliru

注意:

  1. 启用BOOST_SPIRIT_DEBUG
  2. 打印输入的未解析部分
  3. 限制可构成wirenameString的字符,以便它不会&#34;吃掉#34;所有输入:

    wirenameString = +char_("a-zA-Z_0-9"); // lexeme implicit because no skipper
    
  4. 写下wireList,以便 期望平衡{ ... },或者无。

    wireList    = ('{' >> wirenameString % ',' >> '}')
                | wirenameString;
    

    注意使用 the list parser operator (%)

  5. 现在开始规则变为

    start %= qi::lexeme[ "fanout_n" ]
             >> '#' >> numberString
             >> wirenameString >> '(' >> wireList >> ',' >> wireList >> ");"
           ;
    

    所有这一切都有效,因为没有空格,(){},是有效的线号字符串字符。

  6. #define BOOST_SPIRIT_DEBUG
    #include <boost/fusion/include/adapt_struct.hpp>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    
    namespace client {
        namespace qi    = boost::spirit::qi;
        namespace ascii = boost::spirit::ascii;
    
        struct GateStruct {
            int numberOfInputs;
            std::string gateName;
            std::vector<std::string> wireNames_first;
            std::vector<std::string> wireNames_second;
        };
    }
    
    BOOST_FUSION_ADAPT_STRUCT(client::GateStruct ,
                              (int ,numberOfInputs)
                              (std::string, gateName)
                              (std::vector<std::string>, wireNames_first)
                              (std::vector<std::string>, wireNames_second)
                             )
    
    namespace client 
    {
        template <typename Iterator>
        struct gate_parser : qi::grammar<Iterator, GateStruct(), ascii::space_type> {
            gate_parser() : gate_parser::base_type(start) {
                using qi::int_;
                using qi::lit;
                using ascii::char_;
    
                wirenameString = +char_("a-zA-Z_0-9"); // lexeme implicit because no skipper
                numberString   = "(" >> int_ >> *(',' >> lit('0')) >> ')';
                wireList       = ('{' >> wirenameString % ',' >> '}')
                            | wirenameString;
    
                start %= qi::lexeme[ "fanout_n" ]
                         >> '#' >> numberString
                         >> wirenameString >> '(' >> wireList >> ',' >> wireList >> ");"
                       ;
    
                BOOST_SPIRIT_DEBUG_NODES( (start)(numberString)(wirenameString)(wireList) )
            }
          private:
    
            qi::rule<Iterator , int(),                      ascii::space_type>  numberString;
            qi::rule<Iterator , std::string()               /* lexeme */>       wirenameString;
            qi::rule<Iterator , std::vector<std::string>(), ascii::space_type>  wireList;
            qi::rule<Iterator , GateStruct(),               ascii::space_type>  start;
        };
    
    }
    
    int main() 
    {
        using boost::spirit::ascii::space;
        typedef std::string::const_iterator iterator_type;
        typedef client::gate_parser<iterator_type> gate_parser;
    
        gate_parser g;
        std::string str;
        while(getline(std::cin, str)) {
            if(str.empty() || str[0] == 'q' || str[0] == 'Q') {
                break;
            }
    
            client::GateStruct gate;
            std::string::const_iterator iter = str.begin();
            std::string::const_iterator end = str.end();
            bool r = phrase_parse(iter, end, g, space, gate);
    
            if(r) {
                std::cout << "-------------------------\n";
                std::cout << "Parsing succeeded\n";
                std::cout << "\n-------------------------\n";
            } else {
                std::cout << "-------------------------\n";
                std::cout << "Parsing failed\n";
                std::cout << "-------------------------\n";
            }
            if (iter != end)
                std::cout << "Remaining unparsed: '" << std::string(iter,end) << "'\n";
        }
    
        std::cout << "Bye...\n";
    }