Обработка правильного состояния с помощью грамматики pegtl - PullRequest
0 голосов
/ 20 декабря 2018

Я очень плохо знаком с 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) для первого символа и завершается неудачей, затем переходит к другому (A).Но даже если он «перематывает», он всегда вызывает test_action :: apply.Как правильно справиться с этой ситуацией?Я намерен вывести «AAB», возможно, без усложнения грамматики.

1 Ответ

0 голосов
/ 07 января 2019

Я попросил авторов библиотеки pegtl любезно дать мне правильный путь: лучше всего сделать так, чтобы ваш синтаксический анализатор создал дерево разбора, которое легко исправить, когда он возвращается с помощью простых операций push и pop.

Я разработал код ниже для тех, у кого были подобные сомнения.

  • избегайте возврата в правилах с прикрепленными действиями:

    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", ""));
    }
    
  • buildдерево разбора:

    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", ""));
    }
    
...