使用pegtl语法正确处理状态

时间:2018-12-20 08:58:08

标签: c++ peg

我对钉子和钉子很陌生,所以可能我缺少了一些东西。 我的语法非常类似于以下语法:

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 :(得分:1)

I asked to pegtl library authors and they kindly give me the correct way: the best thing to do is make your parser construct a parse tree, which is easy to fix when it backtracks using simple push and pop operations.

I developed the code below for who had similar doubts.

  • avoid backtracking in rules with attached actions:

    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 a parse tree:

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