2016-10-09 19 views
10

Obecnie utknąłem z zasadą próbuję parsować używając doładowania ducha x3. Oto EBNF te (za pomocą operatora% z duchem na listach) za to, co staram się analizować:Eleminating lewa rekurencja w parserze reguły ducha x3

type ::= class_type | lambda_type 

lambda_type ::= more_arg_lambda | one_arg_lambda 

more_arg_lambda ::= "(", type%",", ")", "=>", type 

one_arg_lambda ::= type, "=>", type <- here is the left recursion 

class_type ::= identifier%"::", ["<", type%",", ">"] 

usng ducha doładowania X3, staram się analizować w następujący struct/Wariant:

typedef x3::variant< 
     nil, 
     x3::forward_ast<LambdaType>, 
     x3::forward_ast<ClassType> 
    > Type; 

struct LambdaType { 
     std::vector<Type> parameters_; 
     Type return_type_; 
    }; 
struct ClassType{ 
     std::vector<std::string> name_; 
     std::vector<Type> template_args_; 
    }; 

Mam na żywo przykład tego, co aktualnie próbuję here, który nie działa, Próbowałem również zmienić kolejność parsera, co nie pomoże, dostaję nieskończoną recesję, lub nie zachowanie, którego oczekiwałbym (lub życzenie). Czy ktoś może mi pomóc w debugowaniu tego parsera? Myślę, że mam jakiś lewostronną rekursję w parserze, czy jest szansa, aby tego uniknąć, czy nie ma szansy na przepisanie gramatyki? Czy to gramar jest jeszcze parsable z doładowaniem ducha x3?

EDIT:

udało mi się eleminate lewej rekursji w tej gramatyki. Teraz te gramatyka jest następujący:

type ::= class_type | lambda_type 

    lambda_type ::= more_arg_lambda | one_arg_lambda 

    more_arg_lambda ::= "(", type%",", ")", "=>", type 

    one_arg_lambda ::= class_type, "=>" type, A 
         | "(", type%",", ")", "=>", type, "=>", type, A 

    class_type ::= identifier%"::", ["<", type%",", ">"] 

    A::= "=>", type, A | eps 

ale teraz jest kolejnym problemem, w jaki sposób mogę dokonać doładowania ducha x3 do analizowania tych przepisów do podanych elemencie? Nie mogę sobie wyobrazić, co teraz zwrócą parsery A lub one_arg_lambda, analizator składni one_arg_lambda powinien zostać sparsowany do struktury LambdaType, ale w zależności od tego, co A parsuje, nie jest to konieczne teraz. Pytanie brzmi teraz: w jaki sposób mogę uzyskać parser rekursywny, który nie jest lewy, który analizuje gramatykę powyżej w moich strukturach za pomocą funkcji boost-spirit-x3?

EDIT II:

chciałbym => mieć rację asocjacyjne tak foo => bar => baz => baham
oznacza foo => (bar => (baz => bahama))

+0

Czy możesz podać przykład struktury? Ułatwiłoby to prawidłowe zrozumienie gramatyki. – Arunmu

+1

Co chcesz "foo => bar => baz' oznaczać? '(foo => bar) => baz' lub' foo => (bar => baz) '? – llonesmiz

+0

Chcę, żeby to znaczyło 'foo => (bar => baz)' – Exagon

Odpowiedz

0

I rozwiązać ten problem, a rozwiązanie było bardzo proste. Sztuką jest zmiana gramatyki, więc nie mam lewej rekurencji, i parsuje ładne do moich struktur.

więc zmieniłem

type ::= class_type | lambda_type 

lambda_type ::= more_arg_lambda | one_arg_lambda 

more_arg_lambda ::= "(", type%",", ")", "=>", type 

one_arg_lambda ::= type, "=>", type <- here is the left recursion 

class_type ::= identifier%"::", ["<", type%",", ">"] 

do

type ::= class_type | lambda_type 

lambda_type ::= more_arg_lambda | one_arg_lambda 

more_arg_lambda ::= "(", type%",", ")", "=>", type 

one_arg_lambda ::= class_type, "=>", type <- here is the magic trick 

class_type ::= identifier%"::", ["<", type%",", ">"] 

ten drugi gramatyki descripes się exaclty samym językiem, ale bez lewej rekursji i bez zmiany struktury gramatyczne. To było prawdziwe szczęście i nie działa oczywiście dla każdej gramatyki.