// File : CommandLineGrammar.hpp // Author : Boris Kolpackov // $Id$ #ifndef COMMAND_LINE_GRAMMAR_H #define COMMAND_LINE_GRAMMAR_H #include "MSVC_Pragmas.hpp" #include #include #include #include "CCF/CodeGenerationKit/CommandLine.hpp" using namespace std; using namespace boost::spirit; template struct string_directive : public unary > > { typedef string_directive self_t; string_directive (S const& a) : unary > > (a) { } template typename parser_result::type parse(ScannerT const& scan) const { typedef typename ScannerT::iterator_t Iterator; typedef typename ScannerT::value_t Value; typedef typename Value::const_iterator ValueIterator; Iterator save = scan.first; int len = 0; if (!scan.at_end()) { // Now go one level deeper Value const& v = *scan; ValueIterator first = v.begin (); ValueIterator last = v.end (); scanner > sl_scan(first, last); match hit = this->subject ().parse(sl_scan); if (hit.length() == v.length ()) { ++scan; return scan.create_match(1, nil_t(), save, scan.first); } else { return scan.no_match(); } } else { return scan.no_match(); } } }; template string_directive string_d (parser const& a) { return string_directive(a.derived()); } struct CLineGrammar : public grammar { CommandLine& cl_; CLineGrammar (CommandLine& cl) throw () : cl_(cl) {} template struct SemanticAction { SemanticAction (CommandLine& cl) : cl_ (cl), code_ () {} void operator()(IteratorT first, IteratorT last) const { string str (first, last); code_.execute (cl_, str); } private: CommandLine& cl_; CodeT code_; }; struct SetCommandName { void execute (CommandLine& cl, string const& s) const throw () { cl.command = s; } }; template struct SetOptionName { SetOptionName (CommandLine& cl, CommandLine::Option::OptionType type) : cl_ (cl), type_ (type) { } void operator()(IteratorT first, IteratorT last) const { string s (first, last); cl_.options.push_back (CommandLine::Option(type_, s, "")); } private: CommandLine& cl_; CommandLine::Option::OptionType type_; }; struct SetOptionValue { void execute (CommandLine& cl, string const& s) const throw () { CommandLine::Options::reverse_iterator r = cl.options.rbegin (); if (r != cl.options.rend () && r->value_ == "") { r->value_ = s; } else { //@@ //throw } } }; struct SetArgument { void execute (CommandLine& cl, string const& s) const throw () { cl.arguments.push_back (s); } }; struct SetSeparator { void execute (CommandLine& cl, string const& s) const throw () { cl.separator = true; } }; template struct definition { typedef typename ScannerT::value_t::const_iterator SLIterator; typedef scanner > SLScanner; typedef rule Rule; typedef rule SLRule; Rule r_argument; Rule r_arg_list; Rule argument; Rule arg_list; SLRule option_prefix; SLRule e_name; // equational name, i.e. can meet '=' SLRule c_name; // composite name, i.e. failes if meets '=' SLRule e_value; // equational value, i.e. can contain leading '-' SLRule c_value; // composite value, i.e. cannot contain leading '-' Rule composite; Rule equational; Rule option_list; Rule option; SLRule command_name; Rule command_line; // Semantic actions typedef SemanticAction CommandNameHandler; typedef SetOptionName OptionNameHandler; typedef SemanticAction OptionValueHandler; typedef SemanticAction ArgumentHandler; typedef SemanticAction SeperatorHandler; /* As many people naively believe command line is not a space separated array of words. -- unknown author. NOTE: (1) This grammar is space-sensitive. (2) Anychar is assumend not to clash with . Instead is assumed to be a next-dimension entitiy. ::= [ [ ] [ [ ] | ] ] ::= anychar+ ::=