|
#pragma once
#include <boost/spirit/core.hpp>
#include <boost/spirit/utility/escape_char.hpp>
#include <boost/spirit/utility/confix.hpp>
#include <iostream>
#include <vector>
#include <map>
namespace myparser
{
using namespace std;
using namespace boost::spirit;
struct assign_string
{
assign_string(std::string& str_)
: str(str_) {};
template<typename IteratorT >
void operator()(IteratorT first, IteratorT last) const
{
str.assign(first, last);
}
std::string& str;
};
struct keyvalue_grammar : public grammar<keyvalue_grammar>
{
keyvalue_grammar(std::string& str_key_, std::string& str_val_)
: str_key(str_key_), str_val(str_val_){};
static const int key_start_tag = 1;
static const int key_tag = 2;
static const int equal_tag = 3;
static const int value_tag = 4;
static const int key_value_tag = 5;
static const int filechar_p_tag = 6;
template <typename ScannerT>
struct definition
{
definition(keyvalue_grammar const& self)
{
equal = ch_p('=');
filechar_p = ch_p('.') | ch_p('/') | ch_p('\\') | ch_p(':') | ch_p('_');
key_value = key >> equal >> value;
key_start = ch_p('-') | ch_p('/');
key = key_start >>
(+alnum_p)[ assign_string(self.str_key) ];
//value = (
// confix_p(
// '"',
// (+ c_escape_ch_p )[assign_string(self.str_val)] ,
// '"'
// )
// | (+ alnum_p )[assign_string(self.str_val)] );
value = confix_p('"', (+(alnum_p | blank_p | filechar_p ))[assign_string(self.str_val)], '"') | (+(alnum_p | filechar_p))[assign_string(self.str_val)];
}
rule<ScannerT, parser_context<>, parser_tag<key_start_tag> > key_start;
rule<ScannerT, parser_context<>, parser_tag<key_tag> > key;
rule<ScannerT, parser_context<>, parser_tag<equal_tag> > equal;
rule<ScannerT, parser_context<>, parser_tag<value_tag> > value;
rule<ScannerT, parser_context<>, parser_tag<key_value_tag> > key_value;
rule<ScannerT, parser_context<>, parser_tag<filechar_p_tag> > filechar_p;
rule<ScannerT, parser_context<>, parser_tag<key_value_tag> > const& start() const { return key_value; };
};
std::string& str_key;
std::string& str_val;
};
template<typename keyvalue_container>
class add_keyvalue_pair
{
public:
add_keyvalue_pair( keyvalue_container& kvc_, std::string& key_, std::string& val_)
: kvc( kvc_ ), key(key_), val(val_)
{
}
template <typename IteratorT>
void operator()(IteratorT first, IteratorT last) const
{
kvc.insert( keyvalue_container::value_type(key, val) );
}
private:
std::string& key;
std::string& val;
keyvalue_container& kvc;
};
template<typename keyvalue_container>
struct cmdline_grammar : public grammar< cmdline_grammar >
{
cmdline_grammar( keyvalue_container& kvc_, std::string& str_command_)
: kvc(kvc_), str_command(str_command_)
{};
template <typename ScannerT>
struct definition
{
definition( cmdline_grammar<keyvalue_container> const& self )
: key_value( key, value )
{
command = *ch_p('"') >>
*((+alnum_p) | ch_p('\\') | ch_p(':') | ch_p('.') | ch_p('_')) >>
*ch_p('"');
line = command >> *( key_value[ add_keyvalue_pair<keyvalue_container>( self.kvc, key, value ) ] );
}
rule<ScannerT> command, line;
keyvalue_grammar key_value;
std::string key;
std::string value;
rule<ScannerT> const& start() const { return line; }
};
keyvalue_container& kvc;
std::string& str_command;
};
};
class command_line_parser
{
public:
typedef std::map< std::string, std::string> keyvalue_container;
command_line_parser(){};
~command_line_parser(){};
bool parse(const std::string& str)
{
kvc.clear();
myparser::cmdline_grammar<keyvalue_container> parser(kvc, command);
info = boost::spirit::parse(str.c_str(), parser, boost::spirit::space_p);
return info.full;
};
const char* stop() const { return info.stop;};
const string& get_command() const { return command;};
const keyvalue_container& get_keyvalues()const { return kvc;};
const string& get_value( const string& key ) { return kvc[ key ]; }
protected:
std::string command;
keyvalue_container kvc;
parse_info<> info;
};
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Jay Kint has been a software engineer/hacker for most of his life, starting with 8 bit Ataris. After a lengthy stint in the game industry, he now works at Microsoft in SQL Server.