2017-05-29 1 views
0

Ich baue einen Compiler für Java für Universitätsprojekt, in meinem Projekt sind meine Parser meistens StateT (Scope,SymbolTable) String m a wo Scope der Bereich ist, in dem wir jetzt sind (Methode, Klasse, etc) und SymbolTable hält die bis jetzt definierten Symbole.wie megaparsecs Kombinatoren auf StateT verwenden

Ich wollte megaparsec die combinators auf diesen Parser verwenden, für parens, braces es ist nicht Problem, ich mapStateT gerade, aber ich diese Funktion entwickelt für sepBy und andere verwenden:

mapsequence :: (Monoid s,Monad m) => (m (a,(b,s)) -> m [(a,(b,s))]) -> StateT (b,s) m a -> StateT (b,s) m [a] 
mapsequence f stm = do 
         s <- get 
         ases <- lift $ f $ runStateT stm s 
         case ases of 
         (_:_) -> do 
           put ((fst . snd . last) ases,(mconcat . map (snd . snd)) ases) 
           return $ map fst ases 
         [] -> return [] 

Jetzt f zum Beispiel wäre:

\p -> p `sepBy` semi 

auf jeden Fall wurde mir klar, in letzter Zeit, dass die Funktion über falsch ist, wird die Funktion des Parsers (eingekapselt inlaufen) füttere es den Zustand, den wir jetzt haben, der s ist, dann wird es es wieder laufen lassen, aber anstatt es den neuen Zustand zu geben, der vom ersten Lauf resultiert, wird es ihn s immer wieder füttern und ....

Wie benutze ich megaparsecs Kombinatoren wie sepBy, sepEndBy und etc, so dass ich den Parser viele Male laufen lasse, aber den resultierenden Zustand vom ersten zum zweiten bis zum dritten usw. verkette?

+1

Das sieht falsch aus. 'runState' sollte dir' ((b, s), a) ', nicht' [a] 'bringen, damit du diesen Zustand" putten "kannst. –

+0

@BartekBanachewicz der Zustand ist '(b, s)' so 'runState' würde zurückgeben' (a, (b, s)) ', ich führe die Funktion' f' auf das Ergebnis, um '[((b, s), a)] ' – niceman

+1

Also, da ist dein Problem. Sie haben mehrere Zustände. Welchen solltest du jetzt auswählen? –

Antwort

0

Ich weiß nicht, warum ich dachte, dass ich eine besondere Funktion, dies zu tun brauchte, sepBy und andere sind auf Alternative definiert und weil jeder StateT hat eine Alternative Instanz Funktionen wie sepBy, many, etc. können direkt aufgerufen werden.

Mein Problem war, wahrscheinlich, weil ich symbol verwenden musste, char, etc, die ich sind ParsecT ... gedacht, aber dann wurde mir klar, diese Funktionen in Bezug auf die MonadParsec typeclass definiert sind, die StateT wieder Instanz hat für so habe ich nicht einmal lift brauchen oder mapStateT.

Also alles, was ich tat ist, um Funktionen Signaturen mit MonadParsec zu arbeiten und mein Problem wurde gelöst.

0

Megaparsec hat einen monadisch Transformator Schnittstelle ParsecT:

data ParsecT e s m a 

ParsecT e s m a ist ein Parser mit benutzerdefinierter Datenkomponente des Fehlers e, Stream-Typ s, monadisch zugrunde liegende m und Rücktyp a.

Sie sollten in der Lage sein, diese wie type Parser = ParsecT Dec Text (State (Scope, SymbolTable)) mit etwas zu verwenden, der hinzufügt Funktionalität der zugrunde liegenden State (Scope, SymbolTable) Monade Parsen.

+0

alle meine Parser sind 'StateT (Scope, SymbolTable) Zeichenfolge (ParsecT ...) a 'hier, ich habe eine Menge von ihnen, ich kann sie nicht leicht ändern, trotzdem fand ich die Lösung und ich Ich werde es posten – niceman

Verwandte Themen