![](/img/trans.png)
[英]How can I stop my simple addition grammar terminating early in Boost Spirit?
[英]How can I extend a boost spirit grammar
問題是我創建了一個對任務有用的語法,但現在任務已經改變,我需要定義新規則。
但是我不想修改我已經擁有的語法而不是我想創建一個使用現有語法而沒有代碼重復的新語法,所以我只需要定義我需要的新規則。 我嘗試過類似的東西,但是沒有用:
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
已有的規則和語法。
我不會通過繼承來使問題復雜化。 組合通常綽綽有余,並且不會混淆qi解析器接口。
我已經制作了一個關於如何完成版本化語法的小草圖。 假設舊語法:
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.然而,未來發生了,並且發明了新版本的語法。 現在,我補充一下
friend struct NewGrammar<It, Skipper>;
對於舊語法並開始實現新語法,如果需要,它將慷慨地回歸到舊語法:
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;
};
(我沒有嘗試過使用繼承,盡管它很可能也可以工作。)
我們來試試這個寶貝:
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"));
}
顯然,所有的測試都通過了: 看到它在Coliru 1 上生活希望這有幫助!
1嗯,笨蛋。 Coliru今天編譯速度太慢了。 所以這是完整的測試程序:
#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"));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.