2012-09-28 4 views
3

왜 이것이 실패합니까?왜 마이너스가있는 문자열의 구문 분석이 실패합니까?

data Value = Num Integer 
      | Str String 

let numberOrString = (liftM Num (try int) <|> liftM Str (many1 (noneOf " ")) 
parse (numberOrString >> space) "" "123-4 " 

>> space이 필요합니다. 다른 파서 중지 할 123

예상 결과 후 :

parse numberOrString "" "1234" 
-> Num 1234 

parse numberOrString "" "12-34" 
-> Str "12-34" 

결과 :

parse numberOrString "" "1234-34 " 
-> Left (line 1, column 5): 
    unexpected "-" 
    expecting digit or space 

답변

4

당신은 int 파서 콤비에 대한 정의를 제공하지만,의는 본질적으로 하나를 기대하고 있다고 가정하지 않는다 선택적으로 앞부분에 "-"가 표시 될 수 있습니다 (단 앞에서 만!). 이제 numberOrString 파서를 살펴 보겠습니다.

정수 리터럴을 구문 분석하거나, 공백이 아닌 문자로 구성된 문자열을 분석합니다. 예제 문자열에서 파서의 첫 번째 분기는 숫자 열을보기 때문에 성공합니다. 그것은 "-"문자 바로 앞에 멈출 것입니다. 왜냐하면 그것은 숫자가 아니기 때문입니다. 자, numberOrString >> space은 숫자가 나오기 때문에 다음 문자가 "-"가 아닌 공백이기 때문에 실패합니다.

본질적으로 파서를 두 개의 문자열 (양수 및 음수) (또는 문법에 따라 두 개의 양수 리터럴을 "-"로 구분)로 적용했습니다. 이것은 구문 분석 할 수있는 최대 정수 리터럴이기 때문에 numberOfString 파서 만 적용하면 "1234"만 사용하는 이유이기도합니다.

편집 : 대부분 숫자의 문자열에 임의의 비 숫자 문자가있는 경우 try int이 실패하면 원하는 것으로 추측합니다. 다시 말하지만 이것은 실제로 여러분의 정의 인 int에 달려 있지만 아마도 알파벳 문자가 뒤 따르지 않는 적어도 하나의 숫자의 문자열에서 성공하는 파서로 정의 될 것입니다. int의 일반적인 정의는 두 자리 리터럴과 중위 연산자 사이의 공백을 선택적으로 만들기 때문에 중간에 공백 문자가없는 경우에도 "-"와 같은 영숫자가 아닌 문자 뒤에 오는 문자열에 성공합니다. 또한 "123"을 쓰지 않고 "123"을 성공적으로 구문 분석 할 수 있습니다.

+0

(문자열이 정수 리터럴이라는 사실은 부적합합니다. 정확하게''1234a34 ''와 똑같은 방식으로 실패합니다.) – huon

+0

정확하게 해결책은 아니지만 제가 준 것은 그것이 효과가 없었던 이유입니다. 그것으로 나는 올바른 길로 나를 잡았다. 감사! – fho

관련 문제