How can i implement const in Boost Spirit?

雨燕双飞 提交于 2019-12-08 02:03:35

问题


I am interested in Boost Spirit nowadays and trying to build something. Can we implement something like a const in C++ using Spirit? For instance, user will define an item like;

constant var PROG_LANG="Java"; 

"constant var" seems weird, I accept but you got the idea. I searched the internet but can't found anything about it.


回答1:


What the BigBoss said :)

Only I'd do without the semantic actions - making it far less... verbose (See also Boost Spirit: "Semantic actions are evil"?):

vdef = 
    ("constant" >> attr(true) | attr(false)) >>
    "var" >> identifier >> '=' >> identifier_value >> ';' ;

That's all. This uses qi::attr to account for the default (missing constant keyword).

Here's a full demo with output:

http://liveworkspace.org/code/c9e4bef100d2249eb4d4b88205f85c4b

Output:

parse success: 'var myvariable = "has some value";'
data: false;myvariable;has some value;
parse success: 'constant var myvariable = "has some value";'
data: true;myvariable;has some value;

Code:

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>

namespace qi    = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace phx   = boost::phoenix;

struct var_definition {
    bool is_constant;
    std::string name;
    std::string value;

    var_definition() : is_constant( false ) {}
};

BOOST_FUSION_ADAPT_STRUCT(var_definition, (bool, is_constant)(std::string, name)(std::string, value))


void doParse(const std::string& input)
{
    typedef std::string::const_iterator It;

    qi::rule<It, std::string()> identifier, identifier_value;
    qi::rule<It, var_definition(), qi::space_type> vdef;

    {
        using namespace qi;

        identifier_value = '"' >> lexeme [ +~char_('"') ] > '"';
        identifier       = lexeme [ +graph ];
        vdef             = 
            ("constant" >> attr(true) | attr(false)) >>
            "var" >> identifier >> '=' >> identifier_value >> ';' ;
    }

    var_definition data;

    It f(std::begin(input)), l(std::end(input));
    bool ok = qi::phrase_parse(f,l,vdef,qi::space,data);
    if (ok)   
    {
        std::cout << "parse success: '" << input << "'\n";
        std::cout << "data: " << karma::format_delimited(karma::auto_, ';', data) << "\n";
    }
}

int main()
{
    doParse("var myvariable = \"has some value\";");
    doParse("constant var myvariable = \"has some value\";");
}



回答2:


I don't get your question correctly, spirit is a parser and it has nothing to do with the meaning of constant it can only parse it, but if you mean parse an optional variable like constant then it can be something line:

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

typedef std::string::const_iterator it;
struct var_definition {
    bool is_constant;
    std::string name;
    std::string value;
    var_definition() : is_constant( false ) {}
};
qi::rule<it, std::string()> identifier;
qi::rule<it, std::string()> identifier_value;
qi::rule<it, var_definition(), boost::spirit::ascii::space_type> vdef;

void mark_var_as_constant(var_definition& vd) {vd.is_constant=true;}
void set_var_name(var_definition& vd, std::string const& val) {vd.name=val;}
void set_var_value(var_definition& vd, std::string const& val) {vd.value=val;}

vdef %=
    -qi::lit("constant")[phx::bind(mark_var_as_constant, qi::_val)] >>
    qi::lit("var") >>
    identifier[phx::bind(set_var_name, qi::_val, qi::_1)] >>
    qi::char_('=') >>
    identifier_value[phx::bind(set_var_value, qi::_val, qi::_1)] >>
    qi::char_(';');

Of course there are other ways, for example:

(qi::lit("constant")[phx::bind(mark_var_as_constant, qi::_val)] | qi::eps)

And the easiest is:

qi::hold[ qi::lit("constant")[phx::bind(mark_var_as_constant, qi::_val)] ]


来源:https://stackoverflow.com/questions/13114052/how-can-i-implement-const-in-boost-spirit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!