У меня есть следующий MWE:
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
namespace spirit = boost::spirit;
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
int main() {
std::string input("1 2");
qi::rule<std::string::iterator, void(), qi::space_type> parser;
qi::rule<std::string::iterator, void(), qi::space_type> parser2;
qi::rule<std::string::iterator, void(), qi::space_type> parser3;
parser = qi::int_[
std::cerr << phoenix::val("First int: ") << qi::_1 << std::endl
];
parser2 = qi::int_[
std::cerr << phoenix::val("Second int: ") << qi::_1 << std::endl
];
try {
// Comment out these two lines, (finished below ...)
parser3 = parser >> parser2;
phrase_parse(input.begin(), input.end(), parser3, qi::space);
// ... then un-comment these lines, and the program will crash (and no
// exception is caught below).
// parser = parser >> parser2;
// phrase_parse(input.begin(), input.end(), parser, qi::space);
}
catch (...) {
std::cerr << "Exception caught." << std::endl;
}
}
Как отмечено в закомментированных строках, если я назначу третье правило qi::rule последовательности из еще двух правил и проанализирую его, используя это третье правило, моя программа будет работать так, как ожидалось. Однако, если я назначу ту же последовательность первому правилу в последовательности, а затем проанализирую это первое правило, программа рухнет, когда я ее запущу, по-видимому, даже не выдав исключения, поскольку блок catch (...) { . . . }
не выполняется.
Итак, мой вопрос: есть ли какое-то правило о «qi::rule
», которое я должен знать, которое запрещает назначать последовательность, содержащую правило, тому же самому правилу, или это сбой из-за ошибки в Boost.Spirit.Qi?
Намерение
Чтобы пояснить, в свете комментария cv_and_he, моя цель, стоящая за этим маленьким игрушечным примером, состоит в том, чтобы выяснить, как выполнить динамическую генерацию синтаксического анализатора во время выполнения; в частности, как сгенерировать правило из последовательности правил, количество которых известно только во время выполнения, например parser = A1 >> A2 >> ... >> AN;
, где N
неизвестно во время компиляции, поэтому я не могу просто жестко закодировать одно правило с фиксированным числом ' >>
' таким образом. Это было бы похоже на построение списка во время выполнения путем добавления элементов в конец по одному.
int i = 0; i = i + 1
, поскольку правила в последовательности RHS семантически не похожи на переменные C++, но на самом деле являются нетерминалами в грамматике. Так это я создал грамматику с бесконечной рекурсией? Так является ли сбой, который я вижу, результатом нехватки места в стеке? - person Anthony Hall   schedule 23.11.2013parser
так же, как в вашем примере с int? Если это последнее, вы можете использоватьparser = parser.copy() >> parser2;
- person llonesmiz   schedule 23.11.2013qi::repeat
сqi::lazy
? - person Mike M   schedule 23.11.2013vector<variant<...>>
в качестве целевого типа. Также может прийти на ум трюк Набалика, вы можете добавлять различные правила в анализатор символов во время выполнения... - person Mike M   schedule 23.11.2013parser.copy()
помогает. - person Anthony Hall   schedule 24.11.2013