Reputation: 1
I'm parsing a language and I want to have syntax to $include
other files while parsing.
My 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
The error message from 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 '"';
.... }
How can I make it work?
Upvotes: 0
Views: 194
Reputation: 27636
If you want to process the $include
directives while parsing, you'll need to run over IO
. Parsec exposes a monad transformer for this purpose called ParsecT
; if you change the type of notaInclude
to ParsecT String () IO [SourceItem]
it should work.
However, in general I would side with @soupi's suggestion, and keep parsing pure and resolve $include
s after parsing. But maybe you have some good reason to do it this way for your particular application.
Upvotes: 0
Reputation: 1013
IMO the parsing stage is not the right place to import files. I suggest you parse the file as a whole and process the result after you are done.
Upvotes: 1