2012-10-04 4 views
2

저는 하스켈과 파섹을 처음 접했습니다.이 질문이 사소한 경우 사과드립니다.Parsec을 사용하여 텍스트를 특수 문자로 내림

나는 다음과 같이 구성되어 텍스트 줄 구문 분석 할 : 시작 부분과 끝 부분에

<Text to be dropped> <special character (say "#")> <field 1> <comma> <field 2> 
<comma> <field 3> <special character 2 (say "%")> <Text to be dropped> 

내가 버리고 내 파서 "텍스트가 감소 할"원하는, 그리고 로 유지 들판의 내용. 필자의 가장 큰 문제는 모든 특수 문자를 버리는 파서를 작성하는 방법을 이해하는 것입니다.

라이브러리에서 도움이되는 파서는 anyChar, manyTill 및 oneOf이지만 그 (것)들을 결합하는 방법을 이해하지 못합니다. 간단한 예를 들어 주시면 감사하겠습니다.

답변

3

파섹 코드를 작성할 때 BNF 형식으로 먼저 구문 분석 할 문법을 먼저 작성하는 것이 좋습니다. 파섹에서 작성된 파서는 결국 문법처럼 보입니다.

이의 그 해보자 : 위의 생산에서

line ::= garbage '#' field ',' field ',' field '%' garbage 

을, 우리는 실제의 정의 당신이 실제로 떨어 원하는 텍스트에 따라 달라집니다 garbage라는 이름의 생산을 가정합니다. 마찬가지로 우리는 field이라는 프로덕션을 가정합니다. 이제이 프로덕션을 parsec 코드로 작성해 봅시다.

line = do 
    garbage 
    char '#' 
    field1 <- field 
    char ',' 
    field2 <- field 
    char ',' 
    field3 <- field 
    char '%' 
    garbage 
    return (field1, field2, field3) 

이 코드는 BNF와 정확하게 같습니다. 근본적인 차이점은 일부 결과물의 이름이 지정되므로이 결과 (이 경우 튜플)로 작성된 값을 반환 할 수 있다는 것입니다.

이제 쓰레기 개념에 대해 모르겠지만 예를 들어 공백을 의미한다고 가정 해 보겠습니다. 다음과 같이 그럼 당신은 garbage을 정의 할 수 있습니다 :

garbage = many space 

(또는, 대안 그렇게 파섹 이미 spaces라고 0 개 이상의 공백을 구문 분석 연결자를 가지고 발생). 쓰레기가 # 구분 문자를 제외하고 아무것도 할 수 있다면, 당신은

garbage = many (noneOf "#") 

이 라인에 첫 번째 '#'을 제외한까지 모든 입력을 뭉크 것입니다 말할 수 있습니다. 어쨌든, 어떤 값 garbage이 결과로 생성 되더라도 값에 이름을 바인딩하지 않으므로 버려 질 것입니다.

+0

을 나는 전혀 뒤 따르지 않는 단 하나 개의 문자를 구문 분석 생각, 그래서 당신은 많은 같은과 결합해야합니다. 또한 skipMany가 있습니다. 여러분이 방금 결과를 버리면 더 효율적이라고 생각합니다. –

+0

@ Ørjan Johansen, 아, 잘 발견되었습니다. 감사합니다. – macron

+0

시간 내 주셔서 감사합니다. 매우 유용했습니다! – user1720555

1

다른 방법으로는 실용적 파서를 사용할 수 있습니다

import Control.Applicative 
import Text.Parsec 
import Text.Parsec.String 

type Field =()     --your type here 

field = string "()" *> pure() --your parser here 

parser :: Parser (Field, Field, Field) 
parser = manyTill anyChar (char '#') *> 
     ((,,) <$> (field <* char ',') 
       <*> (field <* char ',') 
       <*> (field <* char '%')) 
관련 문제