Boost.Spirit.Qi uygulamasının çalışma zamanında rasgele sayıdaki kuralları dinamik olarak birleştirip birleştirmediğini merak ediyordum. Boost.Spirit'in iç işleyişi hala benim için bir gizem. Ama kurallar objeler olarak uygulandığından uygulanabilir görünüyor. Benim motivasyonum, gramerimin bazı bölümlerini kolayca genişletilebilir yapmaktır.Çalışma zamanında Boost.Spirit.Qi kurallarını dinamik olarak birleştirin (isteğe bağlı seçenek sayısı)
error C2440: 'initializing' : cannot convert from 'boost::fusion::void_' to 'int &'
Benim şüphe bu grammar.copy()
için miras niteliği geçmediğine neden olmasıdır: Visual Studio 2010 tarafından verilen
namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;
typedef std::string::const_iterator iterator_t;
template<typename Expr>
inline bool parse_full(const std::string& input, const Expr& expr)
{
iterator_t first(input.begin()), last(input.end());
bool result = qi::phrase_parse(first, last, expr, boost::spirit::ascii::space);
return first == input.end() && result;
}
void no_op() {}
int main(int argc, char *argv[])
{
int attr = -1;
// "Static" version - Works fine!
/*
qi::rule<iterator_t, void(int&)> grammar;
qi::rule<iterator_t, void(int&)> ruleA = qi::char_('a')[qi::_r1 = px::val(0)];
qi::rule<iterator_t, void(int&)> ruleB = qi::char_('b')[qi::_r1 = px::val(1)];
qi::rule<iterator_t, void(int&)> ruleC = qi::char_('c')[qi::_r1 = px::val(2)];
grammar =
ruleA(qi::_r1) | //[no_op]
ruleB(qi::_r1) | //[no_op]
ruleC(qi::_r1); //[no_op]
*/
// "Dynamic" version - Does not compile! :(
std::vector<qi::rule<iterator_t, void(int&)>> rules;
rules.push_back(qi::char_('a')[qi::_r1 = px::val(0)]);
rules.push_back(qi::char_('b')[qi::_r1 = px::val(1)]);
rules.push_back(qi::char_('c')[qi::_r1 = px::val(2)]);
std::vector<qi::rule<iterator_t, void(int&)>>::iterator i(rules.begin()), last(rules.end());
qi::rule<iterator_t, void(int&)> grammar;
grammar = (*i)(qi::_r1);
for(++i; i!=last; ++i)
{
grammar = grammar.copy() | (*i)(qi::_r1);
}
// Tests
if(parse_full("a", grammar(px::ref(attr)))) std::cout << attr << std::endl;
if(parse_full("b", grammar(px::ref(attr)))) std::cout << attr << std::endl;
if(parse_full("c", grammar(px::ref(attr)))) std::cout << attr << std::endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return 0;
}
hatadır:
aşağıdaki yapmacık örneği ele alalım. Ne yazık ki, bunu yapmanın kolay bir yolunu bulamadım, bu yüzden bir geçici çözüm seçtim. Sonuç olarak, son bir versiyonum var (ve şimdiye kadar sıkışmış olan herkese şimdiden teşekkür etmek istiyorum!). davranış gerçekten garip olur,
// "Dynamic" version - Kind of works! :-/
std::vector<qi::rule<iterator_t, void(int&)>> rules;
rules.push_back(qi::char_('a')[qi::_r1 = px::val(0)]);
rules.push_back(qi::char_('b')[qi::_r1 = px::val(1)]);
rules.push_back(qi::char_('c')[qi::_r1 = px::val(2)]);
std::vector<qi::rule<iterator_t, void(int&)>>::iterator i(rules.begin()), last(rules.end());
qi::rule<iterator_t, int()> temp;
temp = (*i)(qi::_val); //[no_op]
for(++i; i!=last; ++i)
{
temp = temp.copy() | (*i)(qi::_val); //[no_op]
}
qi::rule<iterator_t, void(int&)> grammar;
grammar = temp[qi::_r1 = qi::_1];
Ancak, bir kez (örneğin, "[no_op]" gibi) basit bir semantik eylemi takmak: Bu aslında çalışıyor gibi görünüyor. Daha önce olduğu gibi 0,1,2 basmak yerine, 0,0,2 basıyor. Bu yüzden merak ediyorum, tanımlanamayan davranışlarla sonuçlanmaya çalıştığım şey nedir? Bu bir hata mı? Ya da büyük olasılıkla, sadece bir şey (örneğin, semantik eylemler?) Yanlış yol kullanıyor muyum?
teşekkür ederiz! Cevabınız çok umut verici görünüyor. Maalesef, şu anda test etme imkanım yok. Bunu denemek için bir şans elde eder etmez kabul edeceğim! – kloffy
Bu düzeltme çalışması mı? –
Neredeyse iki yıl geç kaldığım için samimi özür dilerim. Şimdi bu çözümü test etmek için geldim ve harika çalışıyor! – kloffy