2012-02-14 4 views
2

parsec Haskell 라이브러리를 사용하고 있습니다.Haskell에서 특정 문자열 구문 분석

나는 다음과 같은 종류의 문자열을 구문 분석 할 :

[[v1]][[v2]] 

xyz[[v1]][[v2]] 

[[v1]]xyz[[v2]] 

난 단지 값 v1 및 V2를 수집하고 데이터 구조에이를 저장하는 재미 있어요.

나는 다음과 같은 코드로 시도 : 입력 프로그램이 잘 작동 "[[v1]][[v2]]" 경우, 이런 식으로

import Text.ParserCombinators.Parsec 

quantifiedVars = sepEndBy var (string "]]") 
var = between (string "[[") (string "") (many (noneOf "]]")) 

parseSL :: String -> Either ParseError [String] 
parseSL input = parse quantifiedVars "(unknown)" input 

main = do { 
    c <- getContents; 
    case parse quantifiedVars "(stdin)" c of { 
     Left e -> do { putStrLn "Error parsing input:"; print e; }; 
     Right r -> do{ putStrLn "ok"; mapM_ print r; }; 
    } 
} 

, 다음과 같은 출력 반환 :

"v1" 

"v2" 

하면 입력 "xyz[[v1]][[v2]]" 경우 프로그램이 작동하지 않습니다. 특히 [[...]]에 들어있는 내용 만 "xyz"을 무시하고 싶습니다.

또한 [[...]]의 내용을 데이터 구조에 저장하려고합니다.

이 문제를 어떻게 해결합니까?

+0

그래서'[['and']]'로 구분하지 않은 것을 건너 뛰고 싶습니까? xyz [[v1]] [[v2]] "'와 [[[v1]] xyz [[v2]]"는 모두 [[ "v1", "v2"]' –

+0

정규 표현식에서는 쉬운 작업입니다. '\\ [\\ [([^]] +) \\] \\]' – Yuras

답변

10

파서를 재구성해야합니다. 당신은 매우 이상한 장소에서 연결자를 사용하고 있으며, 물건을 엉망으로 만듭니다.

var은 "[["과 "]]"사이에 varName입니다. 그래서, 쓰기 :

var = between (string "[[") (string "]]") varName 

varName 당신이 파서를해야하므로, 형식의 일종 (I, 당신은 "%의 A¤ %의 &"을 수용 할 것인지 생각하지 않는다 당신을합니까?)해야 그에 대한; 그러나 경우에 정말 아무것도 할 수있다 다만이 작업을 수행 :

varName = many $ noneOf "]" 

그런 다음, 바르 포함 된 텍스트가 아닌 바르로 구분 바르 뭔가입니다. someText는 '['를 제외하고 아무것도입니다

varText = someText *> var `sepEndBy` someText 

... :

someText = many $ noneOf "[" 
이이 구문 분석되고 싶은 경우

상황이 더 복잡 :

다음
bla bla [ bla bla [[somevar]blabla]] 

당신이 필요합니다 varNamesomeText에 대한 더 나은 파서 :

varName = concat <$> many (try incompleteTerminator <|> many1 (noneOf "]")) 

-- Parses e.g. "]a" 
incompleteTerminator = (\ a b -> [a, b]) <$> char ']' <*> noneOf "]" 

someText = concat <$> many (try incompleteInitiator <|> many1 (noneOf "[")) 

-- Parses e.g. "[b" 
incompleteInitiator = (\ a b -> [a, b]) <$> char '[' <*> noneOf "[" 

. (<*>), (*>)(<$>)Control.Applicative이다.

+0

dflemstr 님, 매우 자세한 답변을 해주셔서 감사합니다.귀하의 솔루션을 구현하려하지만 "Text.ParserCombinators.Parsec"과 함께 "Control.Applicative"라이브러리를 가져 오는 애매한 문제가 있습니다. 특히, "모호한 출제'many '..." "모호한 출현'<|>'...". 그래서 "숨기기 ((<|>), 많은)"를 사용하려고했지만 ghc는 새로운 오류를 반환합니다. 이 문제를 어떻게 해결합니까? 감사! – kafka

+1

그게 내가하는 일이야. 당신은'import Control.Applicative ((<*>), (*>), (<$>))'대신에 시도해 볼 수 있습니다. – dflemstr