2

私はboost::spiritの初心者です。「select*fromtablewhereconditions」のようなSQLステートメントを解析するプログラムを作成しました。コンパイルに失敗しました。多数のテンプレートエラーが報告されました。それで、誰かが私を助けてくれますか?

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

1 に答える 1

5

最後にコンピューターの背後で編集し、答えを修正しました:

注意すべきことが3つありました

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

簡単に修正できます。1つダウン、残り2つ!

2.構造体を適応させる

データ型をルール属性として割り当てるには、フュージョン互換にする必要があります。最も便利な方法:

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

これで、コードがコンパイルされます。しかし、解析は失敗します。もう1つ:

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'
于 2012-04-26T19:02:02.973 に答える