How can i implement const in Boost Spirit?

亡梦爱人 提交于 2019-12-06 05:58:30
sehe

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\";");
}

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