Created
October 9, 2015 14:34
-
-
Save cviebig/bdefedcf2c5ece8eeb86 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*============================================================================= | |
Copyright (c) 2001-2015 Joel de Guzman | |
Distributed under the Boost Software License, Version 1.0. (See accompanying | |
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
=============================================================================*/ | |
#include <boost/config/warning_disable.hpp> | |
#include <boost/spirit/home/x3.hpp> | |
#include <boost/spirit/home/x3/support/ast/position_tagged.hpp> | |
#include <boost/spirit/home/x3/support/ast/variant.hpp> | |
#include <boost/fusion/include/adapt_struct.hpp> | |
#include <boost/fusion/include/std_pair.hpp> | |
#include <boost/fusion/include/io.hpp> | |
#include <iostream> | |
#include <fstream> | |
#include <string> | |
#include <map> | |
namespace sql { namespace ast | |
{ | |
struct explain_clause : boost::spirit::x3::position_tagged { | |
bool explain; | |
bool query_plan; | |
char a; | |
}; | |
}} | |
BOOST_FUSION_ADAPT_STRUCT(sql::ast::explain_clause, | |
(bool, explain) | |
(bool, query_plan) | |
(char, a) | |
) | |
namespace sql { namespace ast | |
{ | |
struct sql_printer | |
{ | |
sql_printer(std::ostream& out) | |
: out(out) {} | |
void operator()(ast::explain_clause const& ast) const | |
{ | |
if(ast.explain) { | |
out << "EXPLAIN "; | |
if(ast.query_plan) { | |
out << "QUERY PLAN "; | |
} | |
} | |
out << ast.a; | |
} | |
std::ostream& out; | |
}; | |
}} | |
namespace sql { namespace parser | |
{ | |
namespace x3 = boost::spirit::x3; | |
namespace ascii = boost::spirit::x3::ascii; | |
using x3::attr; | |
using x3::lit; | |
using x3::matches; | |
using x3::omit; | |
using x3::char_; | |
struct explain_clause_class; | |
x3::rule<explain_clause_class, ast::explain_clause> const | |
explain_clause = "explain_clause"; | |
// proof that the ast is configured correctly: | |
// auto const explain_clause_def = (attr(true) >> attr(false)) >> char_; | |
// auto const explain_clause_def = attr(true) >> attr(false) >> char_; | |
// this one is the problem: | |
// auto const explain_clause_def = ((omit[lit("EXPLAIN")] >> attr(true) >> matches[lit("QUERY") >> lit("PLAN")]) | |
// | (attr(false) >> attr(false))) >> char_; | |
// I would expect that it is able to parse char, EXPLAIN char or EXPLAIN QUERY char. but it fails to compile | |
// in turn __duplicating__ the char_ parser makes it work: | |
auto const explain_clause_def = ((omit[lit("EXPLAIN")] >> attr(true) >> matches[lit("QUERY") >> lit("PLAN")]) >> char_) | |
| ((attr(false) >> attr(false)) >> char_); | |
// but shouldn't the first case be valid too, because of the encapsulation in braces? | |
BOOST_SPIRIT_DEFINE(explain_clause); | |
}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Main program | |
/////////////////////////////////////////////////////////////////////////////// | |
int main(int argc, char **argv) | |
{ | |
std::cout << "Give input to parse or type [q or Q] to quit\n\n"; | |
std::string str; | |
while (getline(std::cin, str)) | |
{ | |
if (str.empty() || str[0] == 'q' || str[0] == 'Q') | |
break; | |
using sql::parser::explain_clause; // Our grammar | |
sql::ast::explain_clause ast; // Our tree | |
using boost::spirit::x3::ascii::space; | |
auto iter(str.begin()); | |
auto const end(str.end()); | |
if (phrase_parse(iter, end, explain_clause, space, ast)) { | |
if(iter == end) { | |
std::cout << "Parsing succeeded and the whole string was consumed\n"; | |
} else { | |
std::cout << "Parsing succeeded but only a part of the string was consumed\n"; | |
} | |
sql::ast::sql_printer printer(std::cout); | |
printer(ast); | |
std::cout << "\n"; | |
} else { | |
std::cout << "Parsing failed\n"; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment