2017-09-12 14 views
4

: 내가 가지고있는생성 파서 조인 결과를 문자열로 CSV 필드의 필드를 구문 분석하는 의미는 다음 종류 및 기능, 주어진

type Parser resultType = ParsecT String() Identity resultType 
cell :: Parser String 

다음과 같은 기능을 구현 :

customCell :: String -> Parser res -> Parser res 
customCell typeName subparser = 
    cell 
    >>= either (const $ unexpected typeName) 
       return . parse (subparser <* eof) "" 

내가 원하는만큼 모나드 개념을 사용하고 있지 않다 그리고 결국 특별히 외부 파서 내부의 결과를 병합 할 수있는 더 좋은 방법이 있다는 생각을 멈출 수는 없지만 그 실패에 관해서.

아무도 내가 어떻게 그렇게 할 수 있는지 또는이 코드가 무엇을 의미합니까?

추신 : 이제는 내 형식 단순화가 적절하지 않을 수 있으며 내가 원했던 정체성 모나드를 모나드로 대체하겠다는 사실을 깨달았습니다 .... 불행히도 모나드 변압기에 대해 아직 충분히 알지 못합니다. .

PS2 - 근본적인 모나드는 어쨌든 좋습니다.

답변

1

슬프게도 나는 이런 식으로 수직 파서 컴포지션을 지원하는 Haskell을위한 파서 라이브러리 또는 파서 생성기를 안다. 당신이 쓴 것이 마치 그것이 얻는만큼 좋은 것입니다. 댕!

+1

수직 파서 구도가 무슨 뜻인지 잘 모르겠습니다. 조금 더 확장 해 주시겠습니까? – gallais

+1

@gallais "파서 푸 바 (Parser Foo Bar)"와 "파서 바 바즈 (Parser Bar Baz)"를 가져 와서 파서 푸 바즈 (Parser Foo Baz)로 바꾸는 방법을 말합니다. –

+1

아, 알겠습니다. 이러한 간단한 유형의 목표는 OP의 질문보다 훨씬 명확합니다. 설명 주셔서 감사합니다! – gallais

4

@Daniel Wagner의 대답에 정교하게 ... 파서가 일반적으로 Parsec으로 구축되는 방식은 특정 문자 (예 : 더하기 기호 또는 숫자)를 구문 분석하는 저급 파서로 시작하고 상단에 파서를 작성합니다 (하나의 숫자를 하나 이상의 숫자를 읽는 파서로 읽는 파서를 만드는 many1 조합 자나 "하나 이상의 숫자"를 파싱하는 모나드 구문 분석 "더하기 기호"와 " 하나 이상의 숫자 ").

그러나 각 파서는 하위 수준 디지타이저 파서 또는 상위 수준 "추가 식"파서이든 상관없이 동일한 입력 스트림에 직접 적용됩니다.

그렇지 는 일반적으로 음주, 말, 구문 분석 String 다른 파서를 생성하는 입력 스트림의 덩어리를 먹는다 파서를 쓰기 란 그 (대신 원래의 입력 스트림의) String 및 그들을 결합하려고합니다. 이것은 Parsec이 직접 지원하지 않는 부 자연스러운 비 모나드 식의 "수직 구성"입니다.

로가 수직 조성은 (당신이 하나 개의 언어가 구성 요소 또는 다른 언어의 표현에 내장 된 때 등) 깨끗한 전반적인 접근 방식이다 일부 상황이 있지만, 촬영 일반적인 접근 방법이 아니다, 의견에서 지적 Parsec 파서에 의해.

String 만 생성하는 파서는 cell 파서가 유용하기에 너무 전문화되어 있습니다.이제

import Text.Parsec 
import Text.Parsec.String 

-- | `csv cell` parses a CSV file each of whose elements is parsed by `cell` 
csv :: Parser a -> Parser [[a]] 
csv cell = many (row cell) 

-- | `row cell` parses a newline-terminated row of comma separated 
-- `cell`-expressions 
row :: Parser a -> Parser [a] 
row cell = sepBy cell (char ',') <* char '\n' 

, 당신은 양의 정수를 구문 분석 사용자 정의 셀 파서 쓸 수 있습니다 : CSV 파일에 대한 더 유용한 파섹 프레임 워크는 것

customCell :: Parser Int 
customCell = read <$> many1 digit 

및 CSV 파일을 구문 분석 :

> parse (csv customCell) "" "1,2,3\n4,5,6\n" 
Right [[1,2,3],[4,5,6]] 
> 

여기서 쉼표로 구분 된 셀을 다른 파서에 공급할 문자열로 명시 적으로 구문 분석하는 하위 파서를 cell 대신 사용하는 대신 "셀"은 suppl ia 셀 파서는, 입력 스트림의 중간의 행의 중간에 콤마로 단락 지어진 셀을 필요로하는 적절한 포인트에서 기본이되는 입력 스트림을 구문 분석하기 위해서 불려갑니다.