Karma alternatives and the & predicate
<richard.smart <at> nomura.com>
2012-01-24 10:29:59 GMT
Hi All,
I have a newbie Karma question. I've used Qi a few times before but I'm struggling to get my head around
alternatives and the & predicate in Karma. I've been through the docs and the samples and I can't figure it out.
Below is a (slightly contrived) sample program which should give an idea of what I'm trying to achieve. It
compiles for me with MSVC8.0. I'm afraid I haven't tried it on anything else yet.
The problem, essentially, is that the input data struct contains a 'table_type' member and depending on
the value of that member the output SQL needs to be slightly different.
The alternative is posed on l.70 of the program. As the program is presented the generate step fails for the
given input.
However if you change l. 104 to be
input.table_type = "SingleFixedRow";
then the generation succeeds.
It's clear that I am not quite saying what I want to say here but I am baffled as to how to say "If SingleFixedRow
then output some stuff else if MultipleFixedRow output something different". I've tried all manner of
combinations of moving brackets and the & around. Almost none of which compiled (and none worked)
A interesting (possibly related) problem is that when the generation succeeds (i.e. when you pass in
"SingleFixedRow") the trailing lit(')') from l.76 does not appear in the output. I'd also love to know why
that is.
All help most gratefully received.
Thanks
Richard
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <string>
#include <vector>
namespace accumulator {
namespace karma = boost::spirit::karma;
namespace phoenix = boost::phoenix;
struct column_t
{
std::string column_name;
std::string column_type;
};
struct data_defn_t
{
std::string table_name;
std::string table_type;
int num_header_rows;
std::vector<column_t> columns;
};
}
BOOST_FUSION_ADAPT_STRUCT(
accumulator::column_t,
(std::string, column_name)
(std::string, column_type)
)
BOOST_FUSION_ADAPT_STRUCT(
accumulator::data_defn_t,
(std::string, table_name)
(std::string, table_type)
(int, num_header_rows)
(std::vector<accumulator::column_t>, columns)
)
namespace accumulator {
template <typename OutputIterator>
struct create_table_sql_generator
: karma::grammar<OutputIterator, data_defn_t()>
{
create_table_sql_generator() : create_table_sql_generator::base_type(create_table_sql)
{
using boost::spirit::ascii::string;
using karma::skip;
using karma::lit;
using karma::int_;
using phoenix::val;
column = string
<< lit(' ')
<< string
;
columns = column % lit(',');
create_table_sql = lit("CREATE TABLE ")
<< string
<< lit(" ( ")
<< lit("id INTEGER PRIMARY KEY NOT NULL")
<< lit(", info_type TEXT")
<< lit(", qualifier TEXT")
<< lit(", ")
<<
( &string("SingleFixedRow") << skip[int_] << columns )
| ( &string("MultipleFixedRow") << skip[int_] << lit("row_id INTEGER, ") << columns )
<< lit(')')
;
}
karma::rule<OutputIterator, data_defn_t()> create_table_sql;
karma::rule<OutputIterator, column_t()> column;
karma::rule<OutputIterator, std::vector<column_t>()> columns;
};
template <typename OutputIterator>
bool generate_create_table_sql(OutputIterator sink, data_defn_t const& acc_defn)
{
using karma::generate;
using karma::lit;
create_table_sql_generator<OutputIterator> the_grammar;
return generate(sink,
the_grammar
, acc_defn // Data to output
);
}
}
int main(void)
{
std::string the_sql;
std::back_insert_iterator<std::string> sink(the_sql);
accumulator::data_defn_t input;
input.table_name = "FakeDataDefn";
input.table_type = "MultipleFixedRow";
input.num_header_rows = 0;
std::vector<accumulator::column_t> the_columns;
accumulator::column_t c1;
c1.column_name = "a_text_column";
c1.column_type = "TEXT";
the_columns.push_back(c1);
accumulator::column_t c2;
c2.column_name = "a_double_column";
c2.column_type = "REAL";
the_columns.push_back(c2);
input.columns = the_columns;
bool res = accumulator::generate_create_table_sql(sink, input);
std::cout << "Res is " << res << std::endl;
std::cout << the_sql << std::endl;
return 0;
}
This e-mail (including any attachments) is confidential, may contain
proprietary or privileged information and is intended for the named
recipient(s) only. Unintended recipients are prohibited from taking action
on the basis of information in this e-mail and must delete all copies.
Nomura will not accept responsibility or liability for the accuracy or
completeness of, or the presence of any virus or disabling code in, this
e-mail. If verification is sought please request a hard copy. Any reference
to the terms of executed transactions should be treated as preliminary only
and subject to formal written confirmation by Nomura. Nomura reserves the
right to monitor e-mail communications through its networks (in accordance
with applicable laws). No confidentiality or privilege is waived or lost by
Nomura by any mistransmission of this e-mail. Any reference to "Nomura" is
a reference to any entity in the Nomura Holdings, Inc. group. Please read
our Electronic Communications Legal Notice which forms part of this e-mail:
http://www.Nomura.com/email_disclaimer.htm
------------------------------------------------------------------------------
Keep Your Developer Skills Current with LearnDevNow!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-d2d