如何延长提振精神的语法 [英] How can I extend a boost spirit grammar

查看:114
本文介绍了如何延长提振精神的语法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

的事情是,我做了相当有用的任务的语法,但现在
任务发生了变化,我需要定义新的规则。

The thing is that I made a grammar that has been useful for a task, but now the task has changed and I need to define new rules.

不过,我不希望修改语法我已经有那不是我愿意
想创建一个使用现有的语法我有没有code一个新的语法
重复,所以我只需要定义,我需要新的规则。我试过的东西
这样,但不工作:

But I wouldn't like to modify the grammar I already have instead of that I'd like to create a new grammar that uses the existing grammar I have without code duplication, so I just need to define the new rules I need. I tried something like this, but is not working :

struct New_grammar : Old_grammar<Iterator, Skipper>    
{
    New_grammar() : New_grammar::base_type(Command_list)
    {
        Command_list %= qi::eps >> + Commands;
        Comandos %= oneoldCommand | NewCommand;
        NewCommand = ("NewCommand" >> stmt)[qi::_val = phoenix::new_<NewCom>(qi::_1)];
    }
    // this is a new rule I need:
    qi::rule<Iterator, Commands*(), qi::locals<std::string>, Skipper> NewCommand; 
};

基本上 Old_grammar 是语法我已经有了,我只想补充
新的规则,我需要在 New_grammar ,也可以使用的规则和
语法我已经在 Old_gramar

basically Old_grammar is the grammar I already have and I just want to add the new rule I need in the New_grammar and also be able to use the rules and grammars I already have in the Old_gramar.

推荐答案

我不继承问题复杂化。成分往往是绰绰有余,而且它不会混淆齐解析器接口。

I'd not complicate matters by inheriting. Composition is often more than enough, and it won't confuse the qi parser interface.

我画了一个版本的语法如何做一个小的草图。假设旧的语法:

I've drawn up a small sketch of how a versioning grammar could be done. Assume the old grammar:

template <typename It, typename Skipper>
struct OldGrammar : qi::grammar<It, Skipper, std::string()>
{
    OldGrammar() : OldGrammar::base_type(mainrule)
    {
        using namespace qi;
        rule1 = int_(1); // expect version 1
        rule2 = *char_;  // hopefully some interesting grammar
        mainrule = omit [ "version" > rule1 ] >> rule2;
    }
  private:
    qi::rule<It, Skipper, std::string()> mainrule;
    qi::rule<It, Skipper, int()>         rule1;
    qi::rule<It, Skipper, std::string()> rule2;
};

正如你所看到的,这是相当严格的,要求的版本是完全1。然而,未来发生的事情,和语法的新版本被发明。现在,我想补充

As you can see, this was quite restrictive, requiring the version to be exactly 1. However, the future happened, and a new version of the grammar was invented. Now, I'd add

friend struct NewGrammar<It, Skipper>;

旧语法和去实现新的语法,它慷慨地回退到旧的语法如有需要:

to the old grammar and go about implementing the new grammar, which graciously falls back to the old grammar if so required:

template <typename It, typename Skipper>
struct NewGrammar : qi::grammar<It, Skipper, std::string()>
{
    NewGrammar() : NewGrammar::base_type(mainrule)
    {
        using namespace qi;
        new_rule1 = int_(2); // support version 2 now
        new_start = omit [ "version" >> new_rule1 ] >> old.rule2; // note, no expectation point

        mainrule = new_start 
                 | old.mainrule;  // or fall back to version 1 grammar
    }
  private:
    OldGrammar<It, Skipper> old;
    qi::rule<It, Skipper, std::string()> new_start, mainrule;
    qi::rule<It, Skipper, int()>         new_rule1;
};

(我没有试过,使其与传承工作,虽然在所有的可能性,也应该工作。)

(I haven't tried to make it work with inheritance, though in all likelihood it should also work.)

让我们来测试这个婴儿:

Let's test this baby:

template <template <typename It,typename Skipper> class Grammar>
bool test(std::string const& input)
{
    auto f(input.begin()), l(input.end());
    static const Grammar<std::string::const_iterator, qi::space_type> p;
    try {
        return qi::phrase_parse(f,l,p,qi::space) && (f == l); // require full input consumed
    } 
    catch(...) { return false; } // qi::expectation_failure<>
}

int main()
{
    assert(true  == test<OldGrammar>("version 1 woot"));
    assert(false == test<OldGrammar>("version 2 nope"));

    assert(true  == test<NewGrammar>("version 1 woot"));
    assert(true  == test<NewGrammar>("version 2 woot as well"));
}

所有的测试都通过了,很明显: <一个href=\"http://coliru.stacked-crooked.com/view?id=255cbc1b0785e267e1fad6159a20bc73-542192d2d8aca3c820c7acc656fa0c68\">see它生活在Coliru 1 希望这有助于!

1 好了,织补。 Coliru太慢今天这个编译。因此,这里是完整的测试程序:

1 Well, darn. Coliru is too slow to compile this today. So here is the full test program:

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

template <typename It, typename Skipper>
struct NewGrammar; // forward declare for friend declaration

template <typename It, typename Skipper>
struct OldGrammar : qi::grammar<It, Skipper, std::string()>
{
    friend struct NewGrammar<It, Skipper>; // NOTE

    OldGrammar() : OldGrammar::base_type(mainrule)
    {
        using namespace qi;
        rule1 = int_(1); // expect version 1
        rule2 = *char_;  // hopefully some interesting grammar
        mainrule = omit [ "version" > rule1 ] >> rule2;

        BOOST_SPIRIT_DEBUG_NODE(mainrule);
        BOOST_SPIRIT_DEBUG_NODE(rule1);
        BOOST_SPIRIT_DEBUG_NODE(rule2);
    }
  private:
    qi::rule<It, Skipper, std::string()> mainrule;
    qi::rule<It, Skipper, int()>         rule1;
    qi::rule<It, Skipper, std::string()> rule2;
};

template <typename It, typename Skipper>
struct NewGrammar : qi::grammar<It, Skipper, std::string()>
{
    NewGrammar() : NewGrammar::base_type(mainrule)
    {
        using namespace qi;
        new_rule1 = int_(2); // support version 2 now
        new_start = omit [ "version" >> new_rule1 ] >> old.rule2; // note, no expectation point

        mainrule = new_start 
                 | old.mainrule;  // or fall back to version 1 grammar

        BOOST_SPIRIT_DEBUG_NODE(new_start);
        BOOST_SPIRIT_DEBUG_NODE(mainrule);
        BOOST_SPIRIT_DEBUG_NODE(new_rule1);
    }
  private:
    OldGrammar<It, Skipper> old;
    qi::rule<It, Skipper, std::string()> new_start, mainrule;
    qi::rule<It, Skipper, int()>         new_rule1;
};

template <template <typename It,typename Skipper> class Grammar>
bool test(std::string const& input)
{
    auto f(input.begin()), l(input.end());
    static const Grammar<std::string::const_iterator, qi::space_type> p;
    try {
        return qi::phrase_parse(f,l,p,qi::space) && (f == l); // require full input consumed
    } 
    catch(...) { return false; } // qi::expectation_failure<>
}

int main()
{
    assert(true  == test<OldGrammar>("version 1 woot"));
    assert(false == test<OldGrammar>("version 2 nope"));

    assert(true  == test<NewGrammar>("version 1 woot"));
    assert(true  == test<NewGrammar>("version 2 woot as well"));
}

这篇关于如何延长提振精神的语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆