c++ - 尝试使用 Boost-Spirit 解析类似 SQL 的语句

标签 c++ boost-spirit

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

#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;
}

最佳答案

编辑终于在电脑后面,修改了答案:

需要注意三件事

1。语法错误

解析器表达式包含错误( << 而不是预期的 >> )。这导致了很多编译错误。注意 ******* 的外观在编译器中出现错误:

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

旨在引导您找到源代码中相应的注释:

// 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);

很容易修复。一关下来,还有两关!

2。调整结构

为了将您的数据类型分配为规则属性,您需要使其融合兼容。最方便的方法:

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

现在代码编译。但解析失败。还有一件事要做:

3。词位

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

作为基础,考虑将其写成类似

   lexeme [  (!lit("where")  >> +qi::graph) % +qi::space ]
  • lexeme抑制封闭表达式的船长
  • !断言指定的关键字必须匹配

最后,查看 qi::no_case 的文档进行不区分大小写的匹配。

完整代码

#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;
}

测试:

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'

关于c++ - 尝试使用 Boost-Spirit 解析类似 SQL 的语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10331264/

相关文章:

c++ - C++14 中 for 循环中的并行网络下载

html - 在 C++ 应用程序中嵌入 WebKit

c++ - 使用 boost Spirit 预处理自定义文本文件以删除注释

c++ - Boost.Spirit语法问题

c++ - 如果函数调用返回 true,则跳过 boost::spirit::qi 中的部分输入

c++ - 两个线程都阻塞调用 boost::mutex::lock()

c++ - 我可以在 C++ 中使用函数初始化类成员变量吗?如果是这样怎么办?

c++ - 是否可以使用 mpl::map 来初始化符号解析器?

c++ - 使用 spirit 解析器从字符串中提取值

c++ - 结构新手,我对如何从 void 函数返回值并将其放入另一个函数感到困惑