本文介绍了试图用Boost-Spirit解析SQL like语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是boost ::精神的新手。我写了程序来解析一个SQL语句,比如select * from table where条件。它编译失败。报告大量模板错误。那么,有人会帮助我吗?

I'm a newbie in boost::spirit. I wrote the program to parse a SQL statement, like "select * from table where conditions". It compile failed. A large of template errors reported. So, would somebody help me?

#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

struct db_select {
    void exec() {}

    std::string filed;
    std::string table;
    std::string condition;
};

std::ostream& operator<<(std::ostream& os, const db_select& se) {
    return os << "filed: " << se.filed << " table: " << se.table << " condition: " << se.condition;
}

template <class Iterator>
struct selecter : qi::grammar<Iterator, db_select (), ascii::space_type> {
    selecter() : selecter::base_type(se) {
            se %= "select" >> +qi::char_ << "from" << +qi::char_ << "where" << +qi::char_;
    }

    qi::rule<Iterator, db_select (), ascii::space_type> se;
};

int main(int argc, char* argv[]) {
    if (argc < 2)
            return -1;

    std::string str(argv[1]);
    const char* first = str.c_str();
    const char* last = &str[str.size()];
    selecter<const char*> se;
    db_select rst;

    bool r = qi::phrase_parse(first, last, se, ascii::space, rst);
    if (!r || first != last) {
            std::cout << "parse failed, at: " << std::string(first, last) << std::endl;
            return -1;
    } else
            std::cout << "success, " << rst << std::endl;

    return 0;
}


推荐答案

有三件事要注意:

解析器表达式包含错误(<< ,而不是 > )。这占很大的编译错误。注意编译器错误中出现 *******

The parser expression contained errors (<< instead of >> as intended). This accounts for a lot of compile errors. Note the appearance of ******* in the compiler error:

/.../qi/nonterminal/rule.hpp|176 col 13| error: no matching function for call to ‘assertion_failed(mpl_::failed************

这是为了引导您到源代码中的相应注释:

which is designed to lead you to the corresponding comment in the source code:

// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit qi expression.
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);

轻松修复一个,两个去!

Easily fixed. One down, two to go!

为了将你的数据类型指定为规则属性,你需要使它融合最方便的方法:

In order to assign to your datatype as an rule attribute, you need to make it fusion compatible. The most convenient way:

 BOOST_FUSION_ADAPT_STRUCT(db_select,
    (std::string,filed)(std::string,table)(std::string,condition));

编译,但解析失败了:

此外,您还需要采取措施,避免使用+ qi :: char_表达式搜索您的查询关键字。

Further more you will need to take measures to avoid 'eating' your query keywords with the +qi::char_ expressions.

作为基础,考虑写它例如

As a basis, consider writing it something like

   lexeme [  (!lit("where")  >> +qi::graph) % +qi::space ]




  • code> lexeme 禁止包含表达式的队长

  • 必须匹配

    • lexeme inhibits the skipper for the enclosed expression
    • ! Asserts that the specified keyword must not match
    • 最后,查看 qi :: no_case

      Lastly, look at the docs for qi::no_case to do case-insensitive matching.

      #include <iostream>
      #include <string>
      #include <boost/fusion/adapted.hpp>
      #include <boost/spirit/include/qi.hpp>
      
      namespace qi = boost::spirit::qi;
      
      struct db_select {
          void exec() {}
      
          std::string field;
          std::string table;
          std::string condition;
      };
      
      BOOST_FUSION_ADAPT_STRUCT(db_select,(std::string,field)(std::string,table)(std::string,condition));
      
      std::ostream& operator<<(std::ostream& os, const db_select& se) {
          return os << "field: " << se.field << " table: " << se.table << " condition: " << se.condition;
      }
      
      template <class Iterator>
      struct selecter : qi::grammar<Iterator, db_select (), qi::space_type> {
          selecter() : selecter::base_type(se) {
              using namespace qi;
              se %= "select"
                  >> lexeme [ (!lit("from")  >> +graph) % +space ] >> "from"
                  >> lexeme [ (!lit("where") >> +graph) % +space ] >> "where"
                  >> +qi::char_;
          }
      
          qi::rule<Iterator, db_select (), qi::space_type> se;
      };
      
      int main(int argc, char* argv[]) {
          if (argc < 2)
                  return -1;
      
          std::string str(argv[1]);
          const char* first = str.c_str();
          const char* last = &str[str.size()];
          selecter<const char*> se;
          db_select rst;
      
          bool r = qi::phrase_parse(first, last, se, qi::space, rst);
          if (!r || first != last) {
                  std::cout << "parse failed, at: " << std::string(first, last) << std::endl;
                  return -1;
          } else
                  std::cout << "success, " << rst << std::endl;
      
          return 0;
      }
      



      测试:



      Test:

      g++ test.cpp -o test
      ./test "select aap, noot, mies from table where field = 'value'"
      

      输出:

      success, field: aap,noot,mies table: table condition: field='value'
      

      这篇关于试图用Boost-Spirit解析SQL like语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 16:21