2016-03-24 14 views
0

Ich analysiere eine Sprache und ich möchte Syntax zu $include andere Dateien während der Analyse haben.Parsec und liftIO, Kompilierungsfehler

Mein Code:

import Text.ParserCombinators.Parsec 
import Text.Parsec.Prim (parserZero) 
import Text.ParserCombinators.Parsec.Char 
import Control.Monad.Trans 
import Data.Functor.Identity 

notaInclude :: Parser [SourcesItem] 
notaInclude = do 
    try $ string "$Include" >> blanks1 
    char '"' 
    fileName <- quotedStringParser 
    char '"' 
    i <- getInput 
    included <- liftIO $ readFile fileName 
    setInput included 
    si <- sources 
    setInput i 
    return si 

Die Fehlermeldung von GHC:

Lazi/Lazi'nh/Language/Sources/Parser.hs:65:17: 
    No instance for (MonadIO Identity) arising from a use of `liftIO' 
    Possible fix: add an instance declaration for (MonadIO Identity) 
    In the expression: liftIO 
    In a stmt of a 'do' block: included <- liftIO $ readFile fileName 
    In the expression: 
     do { try 
      (do { string "$Include"; 
        blanks1 }); 
      char '"'; 
      fileName <- quotedStringParser; 
      char '"'; 
      .... } 

Wie kann ich es funktioniert?

+1

Sie können 'IO' nicht in einem' Parser' verwenden, aber es funktioniert, wenn Sie den Parsertyp in 'ParsecT String() IO' ändern. – user2407038

Antwort

1

IMO die Parsing-Phase ist nicht der richtige Ort, um Dateien zu importieren. Ich schlage vor, Sie analysieren die Datei als Ganzes und verarbeiten das Ergebnis, nachdem Sie fertig sind.

0

Wenn Sie die $include-Anweisungen während der Analyse verarbeiten möchten, müssen Sie über IO laufen. Parsec legt zu diesem Zweck einen Monaden-Transformator mit der Bezeichnung ParsecT offen; Wenn Sie den Typ notaInclude zu ParsecT String() IO [SourceItem] ändern, sollte es funktionieren.

Allerdings würde ich im Allgemeinen Seite mit @soupi's suggestion, und halten Sie Parsen rein und lösen Sie $include s nach dem Parsen. Aber vielleicht haben Sie einen guten Grund, dies für Ihre spezielle Anwendung zu tun.