2014-12-06 4 views
1

저는 하스켈을 매우 신중하게 생각합니다. 연습을 위해지도 파일을 구문 분석하려고합니다. 내 코드가 컴파일되지만 잘못된 결과가 나옵니다. 내가 알기로는 "옳은 것"입니다.기본 Attoparsec 구문 분석은 "Right []"만 반환합니다.

내 코드는 here 튜토리얼과 매우 비슷하지만 필자는 필자의 필요에 맞게 작성했습니다. 이 (내가 여기에 공간을 절약하기 위해 라인의 대부분을 제거)처럼

내 파일은 같습니다

#test map 2 
0,0:1; 
1,0:1; 
2,0:1; 
3,0:1; 

내 코드 : 도움을

import Data.Word 
import Data.Time 
import Data.Attoparsec.Char8 
import Control.Applicative 
import qualified Data.ByteString as B 

-- Types -- 

data Tile = Tile Int Int Int deriving Show 

data MapLine = 
    MapLine { tile :: Tile } deriving Show 

-- Parsing -- 

parseTile :: Parser Tile 
parseTile = do 
    x <- decimal 
    char ',' 
    y <- decimal 
    char ':' 
    t <- decimal 
    char ';' 
    return $ Tile x y t 

mapLineParser :: Parser MapLine 
mapLineParser = do 
    t <- parseTile 
    return $ MapLine t 

fileParser :: Parser [MapLine] 
fileParser = many $ mapLineParser <* endOfLine 

-- Main -- 
main :: IO() 
--main = B.readFile "map.hexmap" >>= print . parseOnly fileParser 
main = do 
    print "Parsing map..." 
    let x = B.readFile "map.hexmap" 
    x >>= print . parseOnly fileParser 
    print "Done." 

감사합니다.

답변

1

파서는 첫 번째 줄에서 실패하기 전에 길이가 0 인 MapLines 목록을 "성공적으로 구문 분석"합니다. 해당 행을 제거하십시오 (파일에 BOM과 같이 시작 부분에 해석 할 수없는 바이트가 포함되어 있지 않은지 확인하십시오). 또는 결과를 무시하고 결합하는 #으로 시작하는 행에 대한 파서를 작성하십시오.

+0

저는 #을 무시할 파서를 만들려고 노력했지만 제대로 작동하지 않습니다. 내 파서가 보이는 같은 : 'skipComment :: 파서 B.ByteString skipComment = 할 문자 '#' takeTill (\ X -> X == '\ R'|| X == '\ n')' 이것을 mapLineParser에 추가하면 "Right []"가 다시 나타납니다. 조언 있니? – user3638162

+0

'takeTill'는 True를 리턴하는 입력을 소비하지 않으므로 파서가 실패 할 빈 줄이 남습니다. '<* endOfLine' 같은 것을 다시 사용하십시오 (또는 do 표기법에서 동등한 것). 작동해야합니다 (적어도 파서를 올바른 방법으로 mapLineParser에서 사용한다면). –

+0

또 다른 질문을하는 것은 유감이지만 어떻게''= print ''를 할 수 있습니까? parseOnly fileParser'는 목록을 줍니까? – user3638162