我正在解析一种语言,我想在解析时为$include
其他文件提供语法。
我的代码:
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 '"';
.... }
我怎样才能让它发挥作用?
答案 0 :(得分:1)
IMO解析阶段不是导入文件的正确位置。我建议您将文件整体解析,并在完成后处理结果。
答案 1 :(得分:0)
如果要在解析时处理$include
指令,则需要运行IO
。 Parsec为此目的公开了一个名为ParsecT
的monad变换器;如果您将notaInclude
的类型更改为ParsecT String () IO [SourceItem]
则应该有效。
但是,一般来说,我会支持@soupi's suggestion,并在解析后继续解析纯粹并解析$include
。但也许你有充分的理由以这种方式为你的特定应用做到这一点。