我是boost :: spirit的新手.我编写了程序来解析一个SQL语句,比如"select*from table where conditions".它编译失败.报告了大量模板错误.那么,有人会帮助我吗?
#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;
}
Run Code Online (Sandbox Code Playgroud)
编辑最后在电脑后面修改答案:
有三件事需要注意
解析器表达式包含错误(<<而不是>>预期的错误).这导致了很多编译错误.注意*******编译器错误的外观:
/.../qi/nonterminal/rule.hpp|176 col 13| error: no matching function for call to ‘assertion_failed(mpl_::failed************
Run Code Online (Sandbox Code Playgroud)
它旨在引导您到源代码中的相应注释:
// 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);
Run Code Online (Sandbox Code Playgroud)
轻松修复.一个下来,两个去!
要将数据类型指定为规则属性,需要使其与Fusion兼容.最方便的方式:
BOOST_FUSION_ADAPT_STRUCT(db_select,
(std::string,field)(std::string,table)(std::string,condition));
Run Code Online (Sandbox Code Playgroud)
现在代码编译.但是解析失败了.还有一个:
您还需要采取措施避免使用+ qi :: char_表达式"吃掉"查询关键字.
作为基础,考虑写一些类似的东西
lexeme [ (!lit("where") >> +qi::graph) % +qi::space ]
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
g++ test.cpp -o test
./test "select aap, noot, mies from table where field = 'value'"
Run Code Online (Sandbox Code Playgroud)
输出:
success, field: aap,noot,mies table: table condition: field='value'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
925 次 |
| 最近记录: |