3

필자가 찾은 파서 결합 자의 자료는 구성을 통해 복잡한 파서를 구성하는 것을 다루지 만, 라이브러리의 작성된 파서를 조정하여 파서를 정의하는 좋은 방법이 있는지 알고 싶습니다. 원래 라이브러리의 논리를 완전히 복제합니다.파서 라이브러리를 깊이 확장하기위한 접근법

예를 들어, 여기 Real world Haskell

import Text.ParserCombinators.Parsec 

csvFile = endBy line eol 
line = sepBy cell (char ',') 
cell = many (noneOf ",\n") 
eol = char '\n' 

한 라이브러리에 정의 csvFile 가정 정의 간략화 CSV 파서 다른 라이브러리가 cell 파서 맞춤 버전을 사용하여 자신의 CSV 파서를 생성 할 필요없이 linecsvFile 파서도 다시 작성 하시겠습니까? 소스 라이브러리를 다시 작성하여이를 가능하게 할 수 있습니까? 이것은 CSV 파서에게는 충분히 간단하지만 광범위하게 적용 할 수있는 솔루션에 관심이 있습니다.

답변

9

일반적으로 바꾸려는 구성 요소의 서명을 추상화해야합니다. 예를 들어, CSV 예에서 csvFile 유형을 확장하여 사용자 정의 cell에 슬롯을 허용 할 수 있습니다.

line cell = sepBy cell (char ',') 
csvFile cell = endBy (line cell) eol 

명백하게 이것은 다루기가 쉽지 않습니다. 우리는이 정확히 취한 접근 방식 그리고 우리는이 LanguageDefinition

data Parsers = Parsers { line :: Parser Line, csvFile :: Parser [Line], ... } 

mkParsers :: LanguageDefinition -> Parsers 

을 통해 전체 파서 콤비 라이브러리를 파라미터 그러나 사전에까지 원하는 확장 점의 모든 패키지 주위

data LanguageDefinition = 
    LanguageDefinition { cell :: Parser Cell 
        , ... 
        } 

를 전달할 수 Parsec의 일반화 된 토큰 구문 분석 모듈 : Text.Parsec.TokenText.Parsec.Language을 참조하십시오.


전달되는 점점 더 많은 것들을 사전에 점점 더 추상화하는 훨씬 더 일반적인 접근법을 사용할 수 있습니다. 효과적으로 이것은 코드를 구성하는 객체 지향 또는 OCaml 모듈 지향 방법이되어 매우 효과적 일 수 있습니다.

민속 표현 문제에는 더 많은 기능을 도입하고 다양한 변형을 도입 할 때 긴장감이 있다고합니다. 이 경우 새 변종을 요구하므로 기능을 수정하고 사전에 모두 나열해야합니다. 새로운 변종을 소개하는 경로가 열릴 것입니다.

관련 문제