【问题标题】:Parsing a SQL INSERT with Boost Spirit Classic使用 Boost Spirit Classic 解析 SQL INSERT
【发布时间】:2011-05-24 20:02:47
【问题描述】:

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

这是我要解析的字符串:

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::full 标志,但是,将设置 parse_info::hit 标志。

标签: c++ parsing boost boost-spirit


【解决方案1】:

要了解无法解析的内容,请将解析结果分配给 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

抱歉,如果这不能编译,但应该是一个起点。

【讨论】:

  • 谢谢!我正在从文件中读取字符串,但我没有注意到字符串上附加了换行符,因此它与字符串不完全匹配。
猜你喜欢
  • 2011-03-05
  • 1970-01-01
  • 2013-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-13
  • 2019-07-16
相关资源
最近更新 更多