2017-01-01 1 views
0

하스켈에서 Parser Combinators (a la parsec)를 구현할 때 this tutorial을 따르고 있습니다. 이 게시물을 통해 언급 한 NanoParsec의 모든 것을 구현했습니다. 이제 몇 시간 동안 파서 결합자를 사용하여 try (look-ahead) 및 untilStop 구현

, 나는 꽤 작업

-- try p. If p fails continue without consuming anything 
try :: Parser a -> Parser a 
try p = ... 

-- Parser for everything, until the character-sequence stop appears. 
-- If stop does not appear at all: fail 
untilStop :: String -> Parser String 
untilStop stop = ... 

에게 untilStop은 다음과 같이 다소처럼 보이는 않는 구현하기 위해 최선 시도를 구현하는 struggeling하고

untilStop :: String -> Parser String 
untilStop (c : cs) = do 
    s <- some $ satisfy (/= d) 
    string (c : cs) <|> do 
    i <- item 
    untilStop (d : ds) 
    -- maybe use msum from MonadPlus to combine? 

나는 방법을 알아낼 수 없었다 s, i과 재귀 호출을 결합하면 string이 모든 것을 함께 얻지 못하기 때문에 영원히 실패하지 않습니다.

한번 생각해 보면 try 일 때 untilStop은 간단해야합니다. 누군가 나를 올바른 방향으로 가르키거나 구현할 수 있습니까 (try)?

지금 당장은 모나드, 응용 프로그램 및 관련 자료에 대해 배우기 때문에 파섹의 소스 코드를 이해하려고 시도하는 것은 불가능했습니다.

+0

이 간단한 파서 라이브러리에'시도 '할 필요가 없습니다. 'p <|> q '는 이미'try p <|> q'처럼 행동합니다. 내가 맞습니까? – Euge

+0

음'<|> :: 파서 a -> 파서 a -> 파서 a'는 내 * 시도한 * 옵션에 대한 대안이 필요합니다. 나는 단지 시도 할 수있는 무엇인가를 원했고 실패하면 아무것도하지 않고 단지'do' 표기법으로 다음 문장으로 넘어갔습니다. – elfeck

+0

정확하게'<|>'이 이미 작동하는 방법입니다. – Euge

답변

1

나는 의견에서 말했듯이, 당신은 Parsec-like try을 가질 필요가 없다고 생각합니다. untilStop를 들어

,이를 확인 : 정지 문자열이 비어있는 경우

untilStop :: String -> Parser String 
untilStop [] = everything 
untilStop (c:cs) = item >>= fun 
    where fun i = do { s <- untilStop cs; 
        if i == c && s == "" then return "" else failure } <|> do 
        s <- untilStop (c : cs) 
        return (i : s) 

먼저, 당신은 모든 구문 분석합니다. 어디 everything입니다 :

everything :: Parser String 
everything = Parser (\inp -> [(inp,"")]) 

그렇지 않으면 양식 c:cs의 경우, 다음 문자 i을 구문 분석과 두 개의 사례를 고려하십시오

  • 정지 문자열이 바로 구문 분석 스트림의 앞에 (c == i이고 문자열의 나머지 부분을 파싱하면 cs이 빈 결과를 제공하므로 ""을 반환하십시오. 또는

  • 스트림의 어딘가에 있으므로 더 자세히 살펴보십시오.

<|> 연산자는 역 추적에 사용됩니다. untilStop cs이 원하는 결과가 아닐 경우 번으로 untilStop (c:cs)을 대신 사용해야합니다.

+1

답장을 보내 주셔서 감사합니다. 그러나 이것은 올바르게 작동하지 않습니다. 'parse (untilStop "end") "abcdef end"'는'[("abcd", "ef end")]'를 준다. 또한 실제로 목표가되어야한다고 생각하는 조합기를 사용하지 않습니다. – elfeck

+0

당신 말이 맞아요. 나는 그것이 지금 작동한다고 생각한다. – Euge

+0

고마워 ** 많이 **, 그 이론에서 작동하지만 솔루션을 컴파일하고 복사 - 붙여 넣을 수 있도록 수정 제안. 서식 지정 등 – elfeck

관련 문제