Created
October 9, 2015 14:35
-
-
Save cviebig/32510a8e57edd0b545c8 to your computer and use it in GitHub Desktop.
Encapsulating alternatives (2) separate AST nodes
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 select_stmt : boost::spirit::x3::position_tagged | |
{ | |
char a; | |
}; | |
struct explain_clause : boost::spirit::x3::position_tagged { | |
bool explain; | |
bool query_plan; | |
}; | |
struct sql_stmt : boost::spirit::x3::position_tagged | |
{ | |
explain_clause explain; | |
select_stmt stmt; | |
}; | |
}} | |
BOOST_FUSION_ADAPT_STRUCT(sql::ast::select_stmt, | |
a | |
) | |
BOOST_FUSION_ADAPT_STRUCT(sql::ast::explain_clause, | |
(bool, explain) | |
(bool, query_plan) | |
) | |
BOOST_FUSION_ADAPT_STRUCT(sql::ast::sql_stmt, | |
(sql::ast::explain_clause, explain) | |
(sql::ast::select_stmt, stmt) | |
) | |
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 "; | |
} | |
} | |
} | |
void operator()(ast::sql_stmt const& ast) const | |
{ | |
sql_printer{out}(ast.explain); | |
sql_printer{out}(ast.stmt); | |
} | |
void operator()(ast::select_stmt const& ast) const | |
{ | |
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 select_stmt_class; | |
struct explain_clause_class; | |
struct sql_stmt_class; | |
x3::rule<select_stmt_class, ast::select_stmt> const | |
select_stmt = "select_stmt"; | |
x3::rule<explain_clause_class, ast::explain_clause> const | |
explain_clause = "explain_clause"; | |
x3::rule<sql_stmt_class, ast::sql_stmt> const | |
sql_stmt = "sql_stmt"; | |
auto const select_stmt_def = char_; | |
auto const explain_clause_def = (omit[lit("EXPLAIN")] >> attr(true) >> matches[lit("QUERY") >> lit("PLAN")]) | |
| (attr(false) >> attr(false)); | |
auto const sql_stmt_def = explain_clause_def >> select_stmt_def; | |
BOOST_SPIRIT_DEFINE(select_stmt, explain_clause, sql_stmt); | |
}} | |
/////////////////////////////////////////////////////////////////////////////// | |
// 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::sql_stmt; // Our grammar | |
sql::ast::sql_stmt ast; // Our tree | |
using boost::spirit::x3::ascii::space; | |
auto iter(str.begin()); | |
auto const end(str.end()); | |
if (phrase_parse(iter, end, sql_stmt, 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