2013-11-24 3 views
3

특정 필드가 대부분 구조화되어있는 텍스트를 파싱하고 싶습니다. (가끔 특별한 케이스, 오타 등으로 인해) 구조가 누락되었습니다.파서 타입의 파서 연결자 만들기 -> 파서 b -> 파서 (ab) 중 하나

예. 보통 경우는 Cost: 5이지만 가끔 Cost: 5m 또는 Cost: 3 + 1 per ally이나 기타 임의의 내용이 표시됩니다.

일반 파서 (p)가 작동하지 않는 경우 전체 줄을 문자열로 사용하는 파서로 대체하고 싶습니다.

이 목적을 위해 Parser a -> Parser b -> Either a b 유형의 결합자를 만들고 싶습니다. 그러나 case parse p "" txt of ...과 같은 작업을 수행하지 않고 첫 번째 파서가 성공했는지 여부를 확인하려고 시도한 결과를 검사하는 방법을 알아낼 수 없습니다.

내가 콤비의 빌드를 볼 수 없습니다,하지만 난이 시도

답변

6

난 당신이

eitherParse :: Parser a -> Parser b -> Parser (Either a b) 
eitherParse a b = fmap Left (try a) <|> fmap Right b 

T 뭔가를 원한다고 생각 그는 try입니다. a이 일부 입력을 소비하고 실패 할 경우 제대로 되돌아 가게됩니다. 그럼 그냥 그들은 콤비는 서로 다른 유형을 지원하려는 Either a b

case parse p "" str of 
    Right (Left a) -> useA a 
    Right (Right b) -> useB b 
    Left err  -> handleParserError err 
+0

이 덧글을 무시합니다 - 글을 올린 후 가볍게 생각했습니다. 그러나 GHC는 a와 b를 쉽게 결합 할 수 없습니다 (fmap 왼쪽 foo) :: ab 양쪽, (fmap 오른쪽 막대) :: ab ab – Squidly

+0

@MrBones 무슨 뜻인지 분명히 해? 이것은 나를 위해 잘 컴파일 – jozefg

+0

내가 틀렸어, 나는 매개 변수를 바꿀 때 형식 서명을 수정하지 않았을 및 b. – Squidly

-1

을 누락이 문제를 해결하기 위해 몇 가지 쉬운 방법이있을거야 : 당신이 그것을 사용할 수 원칙적으로 (<|>) :: ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a

가 이 방법 :

try p <|> q 
+1

로 변환하는 매우 쉽습니다 Either ParseError (Either a b)

을 산출하기 위해 파서를 실행하기위한 일반적인 방법을 사용할 수 있습니다. – ChaosPandion