2017-02-09 1 views
0

따라서 간단한 언어에 대한 구문 분석기를 정의하려면 PegJS을 사용하려고합니다.pegJS에 대한 재귀 규칙을 정의하는 방법

언어는 순수 같은 쉼표로 구분 무한히 깊은 함수 호출의 구성 : 재귀하지

call = 
    func"("arg")" 

func = 
    [a-zA-Z]+ 

arg = 
    [0-9a-z,A-Z]+/call 


_ "whitespace" 
    = [ \t\n\r]* 

그러나 그것의 :

f(4, g()) => [f, [4, g, []]] 

g() 
f(5) => [g, [], f, [5]] 

이 내가 가지고있는 문법이다

입력 : b (r (6))

오류 : Line 1, column 4: Expected ")" or [0-9a-z,A-Z] but "(" found.

왼쪽 재귀와 오른쪽 재귀의 개념이 있지만 전화 규칙을 무한정 반복하는 방법을 알지 못합니다.

답변

1

문제는 문법의 모호성에 있다고 생각합니다. "("

ARG = 0-9A-Z, AZ] + ARG = 통화를 = FUNC 펼치기 # 전화 ARG : GNF (선행 단자)를 향해 약간 확대, 우리는 알파벳 심볼 두 규칙 체인을 얻을 ")"# 1 확장 FUNC = [A-ZA-Z] + "("인수 ")"

따라서 알파벳 식별자는 중 ARG 또는 FUNC를 해결할 수 . 결과 구문 분석기는 ffunc의 첫 번째 부분이 아닌 g을 다른 arg으로 줄이기로 선택했습니다.

저는 PegJS에 익숙하지 않아서 파서를 제출할 방법을 강요하는 방법을 제안 할 수 없습니다. 이 문제를 해결하려면 을 수행하십시오.에 1 토큰 미리보기가 필요합니다.

그러나 일반적으로 파서에 대해 알고 있습니다. 많은 정규 표현 엔진은 "탐욕스러운"것입니다 : 그들은 가장 긴 매칭 문자열을 잡을 것입니다. 당신이 이들 중 하나가있는 경우, 중요한 문제는 다른 처리에 반환하기 전에

arg = [0-9a-z,A-Z]+ 

따라서 A와 "g()"를 발견 할 가능성을 절단, "g을 4"스팬을 소비하는 것입니다 두 번째 인수. 이 경우, 당신이 필요로하는 것은 각각의 논증을 찾는 문법이며, 에 대해 각각에 대한 욕심이 있습니다. 세퍼레이터로서 콤마를 사용하고 arg_list (새로운 비 토큰)에 함께 넣어 :

arg_list = arg \ 
      arg "," arg_list 

call = func "(" arg_list ")" \ 
     func "()" 

이 함수 호출을 파싱 한 표준 방법이다.

+0

감사합니다. 필자는 실제로이 함수를 일반적인 인자 앞에 함수 호출을 확인함으로써 해결했습니다. –

관련 문제