{-# LANGUAGE RankNTypes #-}

module LearnParsers where

import Text.Trifecta
import Text.Parser.Combinators

stop :: Parser a
stop = unexpected "stop"

one = char '1'
two = char '2'
three = char '3'

one' = one >> stop

-- read two characters, '1' and '2'
oneTwo = char '1' >> char '2'

-- read two characters, '1' and '2', then die
oneTwo' = oneTwo >> stop

testParse :: Parser Char -> IO ()
testParse p =
  print $ parseString p mempty "123"

testEOF :: Parser () -> IO ()
testEOF p =
  print $ parseString p mempty "123"

-- string parsers

type S = forall m. CharParsing m => m String

oneS :: S
oneS = string "1"

oneTwoS :: S
oneTwoS = string "12"

oneTwoThreeS :: S
oneTwoThreeS = string "123"

testParse' :: Parser String -> IO ()
testParse' p =
  print $ parseString p mempty "123"

-- One Parser rules them all
-- how do we prevent >> to drop it on the floor?

--

pNL s = putStrLn ('\n' : s)

main = do
  pNL "stop:"
  testParse stop
  pNL "one:"
  testParse one
  pNL "one':"
  testParse one'
  pNL "oneTwo:"
  testParse oneTwo
  pNL "oneTwo':"
  testParse oneTwo'
  pNL "one >> EOF:"
  testEOF (one >> eof)
  pNL "oneTwo >> EOF"
  testEOF (oneTwo >> eof)
  pNL "string \"1\", \"12\", \"123\""
  testParse' (choice [ oneTwoThreeS
                     , oneTwoS
                     , oneS
                     , stop ])
  pNL "char \"1\", \"12\", \"123\""
  testParse (choice [ one >> two >> three
                    , one >> two
                    , one
                    , stop ])
