【问题标题】:How can i implement const in Boost Spirit?如何在 Boost Spirit 中实现 const?
【发布时间】:2012-10-28 23:21:46
【问题描述】:

我现在对 Boost Spirit 很感兴趣,并尝试构建一些东西。我们可以使用 Spirit 在 C++ 中实现类似 const 的东西吗?例如,用户将定义一个类似的项目;

constant var PROG_LANG="Java"; 

"constant var" 看起来很奇怪,我接受,但你明白了。我搜索了互联网,但找不到任何相关信息。

【问题讨论】:

  • 知道在 C++ 中有一个 const 关键字,对吧?
  • 我当然知道,这与这个问题有什么关系?如何用我的小语言实现常量?
  • @userXXX 啊,所以你问的是你自己的语言!在这种情况下,只需在编译器中执行一个检查,禁止分配给const 值。

标签: c++ compiler-construction grammar boost-spirit


【解决方案1】:

BigBoss 说了什么:)

只有我会不使用语义操作 - 让它少得多……冗长(另见 Boost Spirit: "Semantic actions are evil"?):

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

就是这样。这使用qi::attr 来说明默认值(缺少constant 关键字)。

这是一个带有输出的完整演示:

http://liveworkspace.org/code/c9e4bef100d2249eb4d4b88205f85c4b

输出:

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;

代码:

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

【讨论】:

  • 感谢您的回复,呵呵。我会在我到家后应用这个,然后接受你的回答。你在精神上回答我的第二个问题。 (因为每天都有作业,我看不到精神)我希望我能投票 5 次。再次感谢。
  • 你是如何成为精神专家的?我阅读了所有 qi 文档并且正在查看示例,但我很难理解示例?你有什么建议吗?
  • @user1662800 我基本上是通过当我需要它阅读文档来学习的。然后我做了很多练习(基本上,使用 Spirit 来满足我的每一个解析需求,即使它不是最合适的)。我应该承认我从来没有关注过这些例子,所以我不知道它们有多“难”。
  • @sehe,如果我可以的话,有几个问题...... 1) identifier_value 的解析器会在开始(和结束之前)引用之后吃掉空格吗?如果这是不可取的,那么我们只是扩大词位[]? 2)那个波浪号'〜'字符有什么作用?我在 Spirit 文档中找不到它的文档。
  • @PeteUK 将正确包含空格。如果有的话,lexeme 在这里是多余的,因为规则(identifieridentifier_value)被声明为没有船长。很好的收获,在这方面。 ~ 的文档在这里 Expression Semantics
【解决方案2】:

我没有正确理解您的问题,spirit 是一个解析器,它与 constant 的含义无关,它只能解析它,但如果您的意思是解析一个像 constant 这样的可选变量,那么可以是一行:

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_(';');

当然还有其他方式,例如:

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

最简单的是:

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

【讨论】:

  • 您的 vdef 规则有问题:char_ 表达式都应该是文字,和/或正常的规则分配(operator= 而不是 auto-rule应该使用operator%=)。 (请参阅我的答案以获得更简洁的方式来编写此代码,而无需使用 phoenix 进行所有手动绑定)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多