2016-03-24 10 views
0

言語を解析していて、構文解析中に他のファイル$includeを使用したいと考えています。ParsecとliftIOコンパイルエラー

マイコード:

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 

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 '"'; 
      .... } 

どのように私はそれを動作させることができますか?

+1

'' Parser'の内部で 'IO'を実行することはできませんが、パーサーのタイプを' ParsecTString()IO'に変更すると動作します。 – user2407038

答えて

1

IMO解析ステージは、ファイルをインポートするのに適切な場所ではありません。私はあなたが完了した後にファイル全体を解析し、結果を処理することをお勧めします。

0

解析中に$includeディレクティブを処理する場合は、IO以上を実行する必要があります。 Parsecはこの目的のためにモナド変圧器をParsecTと呼びます。 notaIncludeのタイプをParsecT String() IO [SourceItem]に変更すると動作するはずです。

しかし、一般的に私は@soupi's suggestionの方がいいでしょうし、解析後は純粋な解析を続けて$includeを解決してください。しかし、あなたの特定のアプリケーションのために、このようにするのに十分な理由があるかもしれません。