I\'m looking for the simplest way to implement variadic function which takes list of boost::spirit::qi rules and expands the list into expression of format: rule1 | rule2 |
You accidentally returned the TStruct type from the expandBitwise
helper. Fix it like so:
template
auto expandBitwise(T const& t) -> decltype(t.rule_)
{
return t.rule_;
}
template
auto expandBitwise(T const& t,Tail const&... tail) -> decltype(t.rule_)
{
return t.rule_ | expandBitwise(tail...);
}
If you want to expose attributes, the return type deduction rules become more involved. Basically, what you're doing is replicating the EDSL part of Spirit.
Let's swap stories...
Clippy:
It looks like you are trying to write a commandline argument parser. Would you like help with that?
Implementing the DSL mechanics for your option parser could be done more systematically by creating a new Proto Domain and actually creating the terminals. This would somehow appeal to me now.
Alternatively you could take this from another angle completely, using the Nabialek Trick. This happens to be an approach I played with just a few weeks ago, and I'll share with you the design I had come up with: https://gist.github.com/sehe/2a556a8231606406fe36#file-test-cpp
The important part is, where the grammar is "fixed":
start = -argument % '\0';
unparsed = as_string [ +~nul ] [ std::cerr << phx::val("ignoring unparsed argument: '") << _1 << "'\n" ];
argument = ('-' >> +shortopt) | ("--" >> longopt) >> -unparsed | unparsed;
The trick being in:
shortopt = shortNames [_a = _1] >> lazy(_a);
longopt = longNames [_a = _1] >> lazy(_a);
Where shortNames
and longNames
are qi::symbols
tables of parsers, built dynamically, based on a variadic list of CliOptions
and CliFlags
(I pass them as a tuple, because I wanted to store the result inside the CliOption
struct as well).
The qi::lazy(_a)
invokes the parser that was stored in the symbol table.
As a bonus, my CliOptions parser has a feature to generate "Usage" information as well. The builders for parse expressions as well as usage informations are extensible.
int main(int argc, char* argv[])
{
using CliParsing::make_option;
typedef std::string::const_iterator It;
auto config = std::make_tuple(
make_option('a', "absolutely", "absolutely"),
make_option('b', "borked" , "borked") ,
make_option('c', "completion", "completion"),
make_option('d', "debug", "turn on debugging"),
make_option('e', "", "no long name") ,
//make_option('f', "flungeons" , "flungeons") ,
//make_option('g', "goofing" , "") ,
//make_option('m', "monitor", "monitoring level"),
make_option('t', "testing" , "testing flags"),
make_option('\0',"file" , "with a filename (no short name)"),
make_option('y', "assume-yes", "always assume yes"),
make_option('v', "verbose", "increase verbosity level"),
make_option('i', "increment", "stepsize to increment with", 5)
);
CliParsing::OptionGrammar parser(config);
using namespace phx::arg_names;
const auto cmdline = std::accumulate(argv+1, argv+argc, std::string(), arg1 + arg2 + '\0');
bool ok = qi::parse(begin(cmdline), end(cmdline), parser);
std::cout << "Parse success " << std::boolalpha << ok << "\n";
std::cout << parser.getUsage();
return ok? 0 : 255;
}
When invoked with some random arguments -i 3 --completion -t --file=SOME.TXT -b huh?
, prints:
short form option --increment parsed
ignoring unparsed argument: '3'
long form switch --completion parsed
short form switch --testing parsed
long form switch --file parsed
ignoring unparsed argument: '=SOME.TXT'
short form switch --borked parsed
ignoring unparsed argument: 'huh?'
Parse success true
--absolutely (-a)
absolutely (flag)
--borked (-b)
borked (flag)
--completion (-c)
completion (flag)
--debug (-d)
turn on debugging (flag)
-e
no long name (flag)
--testing (-t)
testing flags (flag)
--file
with a filename (no short name) (flag)
--assume-yes (-y)
always assume yes (flag)
--verbose (-v)
increase verbosity level (flag)
--increment (-i)
stepsize to increment with (option with value; default '5')
As you can see, not all options have been implemented yet (notably, --
to mark the end of the option list).