2016-10-09 9 views
10

나는 현재 boost spirit x3을 사용하여 구문 분석하려고하는 규칙을 고수하고있다.정신 분석 규칙에서 왼쪽 재귀 탐색 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 부스트 정신 X3를 : 여기 은 내가 구문 분석하려고에 대한 테 EBNF (목록의 정신에서 % 연산자를 사용)입니다

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_; 
    }; 

저는 현재 작동하지 않는 here을 사용하고 있습니다. 변형 파서의 순서를 변경하려고했는데 도움이되지 않습니다. 끝내는 재귀를 얻거나 기대했던 동작을 얻지 못했습니다. (또는 소원). 아무도이 파서를 디버깅 할 수 있습니까? 파서에 왼쪽 재귀 유형이 있다고 생각합니다.이 문제를 피할 수있는 기회가 있습니까? 아니면 문법을 다시 작성할 기회가 없습니까? 이 문법은 부스트 ​​스피릿 x3에서도 파싱 가능합니까?

편집 :

나는이 문법에서 왼쪽 재귀를 eleminate 수 있었다. 이제 테 문법은 다음

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 

하지만 지금은 그 다음 문제가, 내가 주어진 구조체에이 규칙을 구문 분석하는 부스트 정신 X3를 만들 수있는 방법? A 또는 one_arg_lambda 파서가 지금 반환하는 것을 상상할 수 없습니다. one_arg_lambda 파서는 LambdaType 구조체로 구문 분석해야하지만, A이 파싱해야하는 내용이 지금은 필요하지 않습니다. 그래서 질문은 지금, 부울 - 스피릿 -x3을 사용하여 위의 문법을 내 구조체로 구문 분석하는 비 왼쪽 재귀 파서를 어떻게 얻을 수 있습니까?

편집 II는 :

그래서 foo => bar => baz => baham
내가이 문제를 해결하고, 솔루션은 매우 쉬웠다 foo => (bar => (baz => bahama))

+0

구조의 예를 들려 줄 수 있습니까? 그러면 문법을 올바르게 이해하는 것이 더 쉬울 것입니다. – Arunmu

+1

'foo => bar => baz'는 무엇을 의미합니까? '(foo => bar) => baz' 또는'foo => (bar => baz)'? – llonesmiz

+0

나는'foo => (bar => baz)'를 의미한다. – Exagon

답변

0

의미 => 잘 연관 싶습니다. 트릭은 문법을 변경하는 것입니다. 그래서 왼쪽 재귀가 없으며, 구조체를 멋지게 파싱합니다.

는 그래서

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%",", ">"] 

이 제 문법은 exaclty 같은 언어를 descripes에

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%",", ">"] 

변경되었지만 왼쪽 재귀없이, 상기 문법의 구조를 변경하지 않고. 이것은 실제로 운이 좋았고 분명히 모든 문법에 효과가 없었습니다.