2011-12-16 2 views
3

나는이 양식 문자열에 대한 FParsec 파서를 쓰고 있어요와 선택적 멀티 라인 표현 구문 분석이가이 옵션 시간 정량에 문을 "할"입니다 즉FParsec

do[ n times]([ action] | \n([action]\n)*endDo) 

을하고, 끝에 "end do"가 붙은 단일 "action"문 또는 "action"의 목록 (간단히하기 위해 들여 쓰기/후미 공백 처리 생략).

유효 입력의 예는 다음과 같습니다

do action 

do 3 times action 

do 
endDo 

do 3 times 
endDo 

do 
action 
action 
endDo 

do 3 times 
action 
action 
endDo 

이 매우 복잡 보이지 않는,하지만 :

왜이 작동하지 않는 이유는 무엇입니까? 이 표현을위한 올바른 파서

let statement = pstring "action" 
let beginDo = pstring "do" 
       >>. opt (spaces1 >>. pint32 .>> spaces1 .>> pstring "times") 
let inlineDo = tuple2 beginDo (spaces >>. statement |>> fun w -> [w]) 
let expandedDo = (tuple2 (beginDo .>> newline) 
        (many (statement .>> newline))) 
       .>> pstring "endDo" 
let doExpression = (expandedDo <|> inlineDo) 

무엇입니까?

답변

5

attempt 기능을 사용해야합니다. 방금 ​​beginDodoExpression 기능을 수정했습니다.

코드입니다 :

let statement o=o|> pstring "action" 

let beginDo o= 
    attempt (pstring "do" 
     >>. opt (spaces1 >>. pint32 .>> spaces1 .>> pstring "times")) <|> 
     (pstring "do" >>% None)          <|o 

let inlineDo o= tuple2 beginDo (spaces >>. statement |>> fun w -> [w]) <|o 
let expandedDo o= (tuple2 (beginDo .>> newline) (many (statement .>> newline))) 
       .>> pstring "endDo" <|o 

let doExpression o= ((attempt expandedDo) <|> inlineDo) .>> eof <|o 

내가 끝에 eof을 추가했다. 이렇게하면 테스트하기가 더 쉬워집니다.

또한 값 제한을 피하기 위해 더미 o 매개 변수를 추가했습니다.

+0

작품! 그래서 기본적으로 나는 두 번의 시도를 놓치고 있었습니까? 나는 그들이 왜 필요한지 여전히 이해하지 못한다. –

+0

예, 첫 번째 구문 분석기 (p1 <|> p2 표현식에서)가 실패하고 입력을 사용하면 역 추적 할 방법이 필요하기 때문입니다. 기본적으로 시도 기능이하는 것입니다. – Gustavo

+0

오케이, 알겠습니다. 그렇다면 언제 시도없이 <|>을 사용할 수 있습니까? <|> b를 할 때마다 b를 선택하기 위해 실패해야합니다. 그렇지 않습니까? –