c++ - 使用 Boost Spirit Classic 解析 SQL INSERT

标签 c++ parsing boost boost-spirit

我正在尝试学习 Boost Spirit,作为练习,我尝试使用 Boost Spirit Classic 解析 SQL INSERT 语句

这是我要解析的字符串:

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

从此SELECT example我创建了这个小语法:

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
}

不幸的是它总是进入A点并抛出异常。由于我是新手,我不知道我的错误在哪里。我有两个问题:

  1. 使用 Boost Spirit 时调试解析错误的正确方法是什么?
  2. 为什么此示例中解析失败?

最佳答案

要了解解析失败的内容,请将解析结果分配给 parse_info<>,然后记录/检查 parse_info<>::stop 字段,在本例中该字段应该是指向您输入的字符串的最后一个字节与您的语法相匹配。

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

如果这不能编译,我们深表歉意,但这应该是一个起点。

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

相关文章:

c++ - 按 vector 中的对象属性合并排序

Java:解析 ffmpeg 的输出

c++ - Boost Beast 服务器响应延迟 1 秒

c++ - boost::multi_array View 和子数组之间有什么区别

c++ - 如何在 Visual Studio 2010 中使用 cpp-netlib?

c++ - (c++) 节点 header 的语法错误

c++ - `char _3 = ' c'` 在 C 和 C++ 中有效吗?

c++ - 在矩阵中查找邻居位置

javascript - 显示 JSON 数据中的图像?

javascript - 使用 PEG.js 忽略空格