2014-11-09 2 views
1

싱크대가있어서 attoparsec을 사용하여 파싱을하고 싶습니다. Partial 결과가 발생합니다. 그래서 나는 단지 leftover을 사용하여 불충분 한 내용을 다시 업스트림에 넣을 수있을 것이라고 생각 했으므로 나중에 더 많이 추가 될 것입니다. 그러나 내가 바라던대로 새로운 내용이 추가되지 않습니다. 이 문제를 해결하는 방법에 대한 제안은 매우 감사하겠습니다. 감사!남은 부분이있는 도관 싱크

{-# LANGUAGE OverloadedStrings #-} 

import Control.Monad.IO.Class (liftIO) 
import Data.Conduit 
import qualified Data.Conduit.List as CL 
import qualified Data.ByteString.Char8 as BS 
import Data.Attoparsec.Char8 


main = (CL.sourceList [BS.pack "foo", BS.pack "bar"]) $$ sink -- endless loop 

-- this works: 
-- main = (CL.sourceList [BS.pack "foobar"]) $$ sink 

sink :: Sink BS.ByteString IO() 
sink = awaitForever $ \str -> do 
        liftIO $ putStrLn $ BS.unpack str -- debug, will print foo forever. 
        case (parse (string "foobar") str) of 
         Fail _ _ _ -> do 
            liftIO $ putStr $ "f: " ++ BS.unpack str 
            sink 
         Partial _ -> do 
            leftover str 
            sink 
         Done rest final -> do 
              liftIO $ putStr $ "d: " ++ show final ++ " // " ++ show rest 
              sink 
+1

['Data.Conduit.Attoparsec'] (https://hackage.haskell.org/package/conduit-extra-1.1.4.1/docs/Data-Conduit-Attoparsec.html)도 참조하십시오. –

+0

감사합니다. 이것은 적합 할 수도 있습니다! 하지만 내 솔루션이 왜 작동하지 않는지 설명 할 수 있습니까? 두 번 파싱하는 것을 신경 쓰지 않습니다. lewvers는 그런 식으로 작동 할 수도 있다고 생각했습니다. – Schoon

+0

코드를 테스트 케이스와 함께 [자체 포함] (http://sscce.org/) 예제로 만드실 수 있습니까? –

답변

0

Conduit에는 출력을 연결하는 개념이 없습니다. 결과는 다음과 같습니다.

  • 관거에 부분 입력이 있습니다.
  • 구문 분석하기에 충분하지 않습니다.
  • 남은 부분으로 다시 넣습니다.
  • 관로는 다시 넣은 것과 동일한 내용을 다시 읽습니다.
  • 그리고 이것은 영원히 계속됩니다.

반복적으로 파서를 시도하는 방향을 추구하려면 남은 값을 다시 넣을 때마다 이전 시간보다 커야합니다. 그래서 당신은 다음과 같이 할 것입니다 : 파서가 끝나지 않으면, 추가 입력을 읽고, 이미 가지고있는 입력과 연결하고, 나머지를 나머지로 푸시하고 다시 시도하십시오.

위 절차의 복잡성은 O (n^2)이며, 큰 데이터 블록을 소비 한 후에 파서가 성공할 경우 특히 문제가됩니다. 한 번에 한 문자 씩받을 수 있고 파서가 1000자를 소비해야하는 경우 500000 개의 처리 단계가 표시됩니다. 따라서 Conduit과 Attoparsec 사이에 제공된 바인딩을 사용하는 것이 좋습니다. 또는 직접 수행하려는 경우 Partial에서 제공하는 연속을 적절히 사용하십시오.

+0

감사합니다. – Schoon

2

"부분적"이라는 개념은 사용자에게 계속 기능을 반환한다는 것입니다. 즉, 입력이 많으면 해당 입력을 계속할 수 있습니다. 남은 행을 다시 입력 스트림으로 푸시하려고하면 첫 번째 입력 비트를 반복적으로 파싱하기 때문에 낭비가됩니다.

파서 기능을 매개 변수로 사용하려면 함수를 작성해야합니다. 그런 다음 부분의 경우 추가 입력 대기 한 후 중단 된 부분에서 새로운 입력을 구문 분석을 계속할 것 "C"함수에 손을 "싱크"가 발생합니다

Partial c -> sink c 

을 읽어야합니다.