开发者

Parsing a SQL INSERT with Boost Spirit Classic

I'm trying to learn Boost Spirit and as an exercise, I've tried to parse a SQL INSERT statement using Boost Spirit Classic.

This is the string I'm trying to parse:

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

From this SELECT example I've created this little grammar:

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
                [
       开发者_JAVA百科             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;
    };
};

Using a minimal to test it:

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
}

Unfortunately it always enters the point A and throws the exception. Since I'm new to this, I have no idea where my error lies. I have two questions:

  1. What's the proper way to debug parsing errors when using Boost Spirit?
  2. Why parsing fails in this example?


To get visibility into what is failing to parse, assign the result of parse to a parse_info<>, then log/examine the parse_info<>::stop field, which in this case should be a const char * pointing at the last byte of you input string that matched your grammar.

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

Apologies if this doesn't compile, but should be a starting point.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜