2016-11-01 1 views
2

"YYYYMMDD"형식의 날짜 문자열 (예 : "20161030")을 구문 분석하여 Parsec을 배우려고합니다. 내 솔루션은 다음과 같습니다.Parsec을 사용하여 일부 범위에서만 정수 문자열을 구문 분석하는 방법은 무엇입니까?

date :: Parser (String, String, String) 
date = do 
    year <- replicateM 4 digit 
    month <- replicateM 2 digit 
    day <- replicateM 2 digit 
    return (year, month, day) 

그러나 문제는 "20161356"이 (가) 내 코드의 올바른 날짜이기 때문입니다.

"MM"의 유효성을 검사하는 방법은 1에서 12 사이입니다. "DD"는 1 ~ 31 사이입니까? 토마스 M. DuBuisson에 의해 제안

+2

'guard $ month> = 0 && month <= 12'입니까? –

+1

'> = 1' 어쩌면? : D – ThreeFx

+0

사이드 노트 20160229는 유효하지만, 20000229는 유효하지 않습니다. 또한 확인하기 위해 foget하지 마십시오 – epsilonhalbe

답변

2

당신은 guard를 추가 할 수 있습니다

그러나,이 나쁜 오류 메시지가 발생
date :: Parser (String, String, String) 
date = do 
    year <- replicateM 4 digit 
    month <- replicateM 2 digit 
    day <- replicateM 2 digit 
    guard $ read month > 0 && read month <= 12 && read day > 0 && read day <= 31 
    return (year, month, day) 

:

λ> parse date "" "20161356" 
Left (line 1, column 9):unknown parse error 

우리는이 문제를 해결할 수 <?>guard을 결합하여 더 나은 오류 메시지를 제공합니다.

date :: Parser (String, String, String) 
date = do 
    year <- replicateM 4 digit 
    month <- replicateM 2 digit 
    guard (read month > 0 && read month <= 12) <?> "valid month (1–12)" 
    day <- replicateM 2 digit 
    guard (read day > 0 && read day <= 31) <?> "valid day (1–31)" 
    return (year, month, day) 
이 방법으로

, 당신은보다 유용한 오류 메시지가 얻을 : 보조 노트로

λ> parse date "" "20161356" 
Left (line 1, column 7): 
expecting valid month (1–12) 

을, 나는-파서의 보장이 유효성을 검사 할 가치 (또는 적어도 전성 검사)는의 날짜라고 생각합니다 날짜 유효성 검사는 파서 및 오류 처리 코드의 나머지 부분으로 구성됩니다. 나중에 코드에서 날짜를 확인하는 것을 잊지 마세요. 오류가 현지화되어있어 많은 날짜의 문서를 구문 분석하는 경우 매우 유용합니다.

+2

물론 실제 코드에서는 (여기에 표시된 것과 같은 교육용 코드와는 달리) ['fromGregorianValid'] (http://hackage.haskell.org/package/time-1.6.0.1/docs/Data-Time)을 사용해야합니다. -Calendar.html # v : fromGregorianValid)를 작성하는 것이 좋습니다. –

+0

@DanielWagner : 그렇습니다. 좀 더 상세한 오류 메시지를 얻기 위해 자신의 온 전성 체크를 약간 할 수도 있습니다. –

관련 문제