Skip to content

Instantly share code, notes, and snippets.

@cocreature
Created March 22, 2018 21:12
Show Gist options
  • Save cocreature/8db4a6b72fdabf28f7537b73e9d037ec to your computer and use it in GitHub Desktop.
Save cocreature/8db4a6b72fdabf28f7537b73e9d037ec to your computer and use it in GitHub Desktop.
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}
import Control.Monad
import Data.Text (Text)
import Data.Void
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as Lexer
type Parser = Parsec Void Text
sc :: Parser ()
sc = Lexer.space (void (takeWhile1P Nothing f)) lineComment empty
where f x = x `elem` [' ', '\t']
scn :: Parser ()
scn = Lexer.space space1 lineComment empty
lineComment :: Parser ()
lineComment = Lexer.skipLineComment "#"
symbol :: Text -> Parser Text
symbol = Lexer.symbol sc
parseList :: Parser [Either (ParseError Char Void) Text]
parseList =
many (withRecovery recover (Right <$> p)) <* eof
where
recover e =
-- Changing this to skipManyTill anyChar (eof <|> void newline) will lead to an infinite loop since skipManyTill anyChar eof will always succeed.
Left e <$ skipManyTill anyChar (void newline)
p = do
s <- try (symbol "foobar" <* notFollowedBy alphaNumChar)
scn
pure s
main :: IO ()
main = do
-- This works fine
parseTest parseList ("foobar2\nfoobar3\n")
-- This will fail completely since we have nothing to sync up on.
parseTest parseList ("foobar2\nfoobar3")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment