2013-03-13 1 views
0

파섹 (Parsec)을 사용하여 파싱 문자열을 배우기 시작 했으므로 마음을 감쌀 수없는 다음 문제에 직면했습니다.파섹 파서 : 특정 상황에서 사용자 정의 오류가 평가되지 않습니다.

다음 코드는 세 가지 파서 실행을 포함하며 두 개는 분명히 실패합니다. 이상한 점은 내 사용자 지정 실패 메시지는 두 번째 실행에서만 발생하며 세 번째 실행에서는 발생하지 않는다는 것입니다.

import Text.Parsec 
import Text.Parsec.String 

ps :: Parser String 
ps = (string "123") <|> (string "456") <|> fail "my-failure" 

main = do 
    putStrLn $ "A: " ++ show (parse ps "" "123") 
    putStrLn $ "\nB: " ++ show (parse ps "" "789") 
    putStrLn $ "\nC: " ++ show (parse ps "" "45x") 

출력 : 항상 두 번째 <|>의 부품 왼쪽에 장애가 발생 내 실패 메시지를 가지고

A: Right "123" 

B: Left (line 1, column 1): 
unexpected "7" 
expecting "123" or "456" 
my-failure 

C: Left (line 1, column 1): 
unexpected "x" 
expecting "456" 

어떤 것이 올바른 방법? 이전에 발생한 오류를 무시할 수 있습니까?

답변

8

Parsec의 <|> 조합자는 파서가 입력을 소비하지 않을 때 다음 옵션 만 시도합니다. 귀하의 경우 파서 string "456""45x"의 시작과 일치하므로 더 이상의 대안을 시도하지 않습니다. 임의의 미리보기가 필요한 경우 try 기능을 사용해야합니다. <|>의 파섹의 문서에서

ps :: Parser String 
ps = string "123" <|> try (string "456") <|> fail "my-failure" 

는 :

이 콤비는 선택을 구현합니다. 파서 p < |> q 먼저 p를 적용합니다. 성공하면 p 값이 리턴됩니다. p가 입력을 소비하지 않고 실패하면, 파서 q가 시도됩니다. 이 결합자는 MonadPlus 클래스의 mplus 멤버 및 Alternative의 (< |>) 멤버와 동일하게 정의됩니다.

파서 p 이 파서 p 이 소비하지 않을 때 (즉, 미리보기가 1)에만 시도되기 때문에 파서는 predictive라고합니다. 이 비 역 추적 동작은 파서 결합 자의 효율적인 구현과 좋은 오류 메시지의 생성을 모두 허용합니다. 대신

+2

'당신이 사용하는 것을 선호 수도' "내 고장을"실패 <|> [''] (http://hackage.haskell.org/packages/archive/parsec/latest/doc/html/Text -parsec-Prim.html # v : -60--63--62-) ' "구문 요소"와 같이 사용하면'my-failure' 대신'expecting syntax element'라는 오류 메시지가 나타납니다. 하지만 여전히'try'를 사용해야합니다. – Beetle

관련 문제