Я очень плохо знаком с peg и pegtl, так что, вероятно, я что-то упустил.
У меня есть грамматика, очень похожая на следующую:
using namespace tao::pegtl;
struct A : one<'A'> { };
struct B : one<'B'> { };
struct comp : seq<plus<sor<seq<A, B>, A>>,eof> { };
template< typename Rule >
struct test_action : nothing< Rule > {};
template<>
struct test_action<A>
{
template< typename Input >
static void apply(const Input& in)
{
std::cout << "A";
}
};
template<>
struct test_action<B>
{
template< typename Input >
static void apply(const Input& in)
{
std::cout << "B";
}
};
void test()
{
parse< comp, test_action >(memory_input("AAB", ""));
}
Разбор работает отлично, но слишком много активаций test_action :: apply.
Программа выводит «AAAB», потому что, если я хорошо понимаю, анализ разбирает первый вариант (AB) для первого символа и завершается неудачей, затем продолжается
с другой (А). Но даже если он «перематывает», он всегда вызывает test_action :: apply.
Как правильно справиться с этой ситуацией?
Мое намерение состоит в том, чтобы вывести «AAB», возможно, без осложнений грамматики.
Я попросил авторов библиотеки pegtl любезно дать мне правильный путь: лучше всего сделать так, чтобы ваш синтаксический анализатор создал дерево синтаксического анализа, которое легко исправить, когда он возвращается с помощью простых операций push и pop.
Я разработал код ниже для тех, у кого были подобные сомнения.
избегайте возврата в правилах с прикрепленными действиями:
namespace solution_a {
using namespace tao::pegtl;
struct A : one<'A'> { };
struct B : one<'B'> { };
struct real_A : A {};
struct real_AB : seq<A, B> {};
struct comp : seq<plus<sor<real_AB, real_A>>,eof> { };
template< typename Rule >
struct test_action : nothing< Rule > {};
template<>
struct test_action<real_A>
{
template< typename Input >
static void apply(const Input& in)
{
std::cout << "A";
}
};
template<>
struct test_action<real_AB>
{
template< typename Input >
static void apply(const Input& in)
{
std::cout << "AB";
}
};void test()
{
parse< comp, test_action >(memory_input("AAB", ""));
}
построить дерево разбора:
namespace solution_b {
using namespace tao::pegtl;
struct A : one<'A'> { };
struct B : one<'B'> { };struct comp : seq<plus<sor<seq<A, B>, A>>, eof> { };
template< typename Rule >
struct test_action : nothing< Rule > {};void test()
{
auto root = parse_tree::parse<comp>(memory_input("AAB", ""));
}
}
Других решений пока нет …