2011-06-25 20 views
16

Przetwarzam wyrażenie za pomocą Parsec i chcę śledzić zmienne w tych wyrażeniach przy użyciu stanu użytkownika w Parsec. Niestety tak naprawdę nie wiem, jak to zrobić.Stan użytkownika w Parsec

Biorąc pod uwagę następujący kod:

import Data.Set as Set 
inp = "$x = $y + $z" 

data Var = V String 

var = do char '$' 
     n <- many1 letter 
     let v = Var n 
     -- I want to modify the set of variables here 
     return v 

parseAssignment = ... -- parses the above assignment 

run = case runIdentity $ runParserT parseAssignment Set.empty "" inp of 
        Left err -> ... 
        Right -> ... 

Tak, u w ParsecT s u m a byłby Set.Set. Ale jak mogę zintegrować aktualizację stanu do var?

Próbowałem czegoś takiego jak modify $ Set.insert v, ale to nie działa, ponieważ Set.Set nie jest monadą państwową.

Odpowiedz

16

Niestety, propozycja Juraś od updateParserState nie jest optymalny (chcesz używać tej funkcji, jeśli szukasz, aby zmodyfikować stan wewnętrzny parsec za także); Zamiast tego należy przekazać funkcję, która działa na niestandardowym stanie użytkownika (czyli typu u -> u) do modifyState, tak jak w tym przykładzie:

expr = do 
    x <- identifier 
    modifyState (+1) 
    --^in this example, our type u is Int 
    return (Id x) 

lub użyć dowolnej kombinacji funkcji getState i putState. W Twoim przypadku, można by zrobić coś takiego:

modifyState (Set.insert v) 

Zobacz this link aby uzyskać więcej informacji.

Aby uzyskać bardziej przypominający samouczek wstęp do pracy ze stanem użytkownika w Parsec, this document, chociaż stary, powinien być odpowiedni.

+0

Dzięki! To jest dokładnie to, czego potrzebuję - mogłem wcześniej przyjrzeć się tej funkcji ... jakoś myślałem, że modifiedState było związane z modyfikacją z Control.Monad.State. – bzn

+0

@bzn: Jest to jednak powiązane! Jeśli uważasz Parsec za stanową monadę trzymającą tylko stan użytkownika, robią to samo. Różnią się tylko dlatego, że 'modifyState' ignoruje wewnętrzny stan Parsec. –

1

Można użyć updateParserState

+0

dziękuję, że działa, ale jak powiedział Raeez Lorgat, modifyState wydaje się być funkcją, której potrzebuję. – bzn