用Boost Spirit Classic解析SQL INSERT

问题描述:

我正在努力学习Boost Spirit并作为练习,我试着用Boost Spirit Classic解析SQL INSERT statement用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. 为什么解析在这个例子中失败?
+0

我试过你的语法,它解析上面的输入。如果您提供的输入具有任何尾随空格或换行符,它们将阻止parse_info :: full标志被设置,但parse_info :: hit标志将被设置。 – equackenbush 2011-05-24 20:45:49

为了得到知名度到什么是无法解析,解析的结果赋值给一个parse_info <>,然后登录/检查parse_info <> ::停止字段,在这种情况下应该是一个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 

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

+0

谢谢!我从文件中读取字符串,但没有注意到字符串上附加了一个换行符,因此它没有完全匹配字符串。 – 2011-05-26 14:29:58