Разбор SQL INSERT с помощью Boost Spirit Classic - PullRequest
2 голосов
/ 25 мая 2011

Я пытаюсь изучить Boost Spirit и в качестве упражнения я попытался разобрать SQL INSERT statement с помощью Boost Spirit Classic.

Это строка, которую я пытаюсь разобрать:

INSERT INTO example_tab (cola, colb, colc, cold) VALUES (vala, valb, valc, vald);

Из этого примера SELECT Я создал эту маленькую грамматику:

struct microsql_grammar : public grammar<microsql_grammar>
{
    template <typename ScannerT>
    struct definition
    {
        definition(microsql_grammar const& self)
        {
            keywords = "insert", "into", "values";

            chlit<>     LPAREN('(');
            chlit<>     RPAREN(')');
            chlit<>     SEMI(';');
            chlit<>     COMMA(',');

            typedef inhibit_case<strlit<> > token_t;

            token_t INSERT      = as_lower_d["insert"];
            token_t INTO        = as_lower_d["into"];
            token_t VALUES      = as_lower_d["values"];

            identifier =
                nocase_d
                [
                    lexeme_d
                    [
                        (alpha_p >> *(alnum_p | '_'))
                    ]
                ];

             string_literal =
                lexeme_d
                [
                    ch_p('\'') >>  +( anychar_p - ch_p('\'') )
                    >> ch_p('\'')
                ];

            program =               +(query);

            query =                 insert_into_clause >> SEMI;

            insert_into_clause =    insert_clause >> into_clause;

            insert_clause =         INSERT >> INTO >> identifier >> LPAREN >> var_list_clause >> RPAREN;

            into_clause =           VALUES >> LPAREN >> var_list_clause >> RPAREN;

            var_list_clause =       list_p( identifier, COMMA );
        }

        rule<ScannerT> const& start() const { return program; }

        symbols<> keywords;

        rule<ScannerT> identifier, string_literal, program, query, insert_into_clause, insert_clause,
            into_clause, var_list_clause;
    };
};

Использование минимума для проверки:

void test_it(const string& my_example)
{
    microsql_grammar g;

    if (!parse(example.c_str(), g, space_p).full)
    {
                // point a - FAIL
        throw new exception();
    }

    // point b - OK
}

К сожалению, он всегда входит в точку А и выдает исключение. Поскольку я новичок в этом, я понятия не имею, где лежит моя ошибка. У меня два вопроса:

  1. Как правильно отлаживать ошибки синтаксического анализа при использовании Boost Spirit?
  2. Почему в этом примере происходит сбой?

1 Ответ

3 голосов
/ 25 мая 2011

Чтобы получить представление о том, что не удалось проанализировать, присвойте результат анализа parse_info <>, затем зарегистрируйте / проверьте поле parse_info <> :: stop, которое в этом случае должно быть const char *, указывающим напоследний байт вашей входной строки, которая соответствует вашей грамматике.

microsql_grammar g;

parse_info<std::string::const_iterator> result = parse(example.begin(), example.end(), g, space_p)
if (!result.full)
{
    std::string parsed(example.begin(), result.stop);
    std::cout << parsed << std::endl;

            // point a - FAIL
}

// point b - OK

Извинения, если это не компилируется, но должно быть отправной точкой.

...