{-# LANGUAGE AllowAmbiguousTypes #-}
module Parsers.Brainfuck.Attoparsec where

import Control.Applicative
import Data.Attoparsec.Combinator
import Data.ByteString as BS
import Data.Functor (($>))
import Data.Text as T
import qualified Data.Attoparsec.Internal.Types as AP

import Parsers.Utils.Attoparsec as AP
import Parsers.Brainfuck.Types

parser :: forall inp. AP.Inputable inp => AP.Parser inp [Instruction]
parser :: forall inp. Inputable inp => Parser inp [Instruction]
parser = Parser inp ()
whitespace Parser inp ()
-> Parser inp [Instruction] -> Parser inp [Instruction]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser inp [Instruction]
bf Parser inp [Instruction]
-> Parser inp () -> Parser inp [Instruction]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser inp ()
forall t. Chunk t => Parser t ()
endOfInput
  where
  whitespace :: Parser inp ()
whitespace = Parser inp (Token inp) -> Parser inp ()
forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany ((Token inp -> Bool) -> Parser inp (Token inp)
forall inp.
Inputable inp =>
(Token inp -> Bool) -> Parser inp (Token inp)
AP.satisfy (forall inp. Inputable inp => String -> Token inp -> Bool
AP.notInClass @inp String
"<>+-.,[]"))
  lexeme :: AP.Parser inp a -> AP.Parser inp a
  lexeme :: forall a. Parser inp a -> Parser inp a
lexeme Parser inp a
p = Parser inp a
p Parser inp a -> Parser inp () -> Parser inp a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser inp ()
whitespace
  bf :: Parser inp [Instruction]
bf = Parser inp Instruction -> Parser inp [Instruction]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser inp Instruction -> Parser inp Instruction
forall a. Parser inp a -> Parser inp a
lexeme (Char -> Parser inp Char
forall inp. Inputable inp => Char -> Parser inp Char
AP.char Char
'>' Parser inp Char -> Instruction -> Parser inp Instruction
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Instruction
Forward)
    Parser inp Instruction
-> Parser inp Instruction -> Parser inp Instruction
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser inp Instruction -> Parser inp Instruction
forall a. Parser inp a -> Parser inp a
lexeme (Char -> Parser inp Char
forall inp. Inputable inp => Char -> Parser inp Char
AP.char Char
'<' Parser inp Char -> Instruction -> Parser inp Instruction
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Instruction
Backward)
    Parser inp Instruction
-> Parser inp Instruction -> Parser inp Instruction
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser inp Instruction -> Parser inp Instruction
forall a. Parser inp a -> Parser inp a
lexeme (Char -> Parser inp Char
forall inp. Inputable inp => Char -> Parser inp Char
AP.char Char
'+' Parser inp Char -> Instruction -> Parser inp Instruction
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Instruction
Increment)
    Parser inp Instruction
-> Parser inp Instruction -> Parser inp Instruction
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser inp Instruction -> Parser inp Instruction
forall a. Parser inp a -> Parser inp a
lexeme (Char -> Parser inp Char
forall inp. Inputable inp => Char -> Parser inp Char
AP.char Char
'-' Parser inp Char -> Instruction -> Parser inp Instruction
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Instruction
Decrement)
    Parser inp Instruction
-> Parser inp Instruction -> Parser inp Instruction
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser inp Instruction -> Parser inp Instruction
forall a. Parser inp a -> Parser inp a
lexeme (Char -> Parser inp Char
forall inp. Inputable inp => Char -> Parser inp Char
AP.char Char
'.' Parser inp Char -> Instruction -> Parser inp Instruction
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Instruction
Output)
    Parser inp Instruction
-> Parser inp Instruction -> Parser inp Instruction
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser inp Instruction -> Parser inp Instruction
forall a. Parser inp a -> Parser inp a
lexeme (Char -> Parser inp Char
forall inp. Inputable inp => Char -> Parser inp Char
AP.char Char
',' Parser inp Char -> Instruction -> Parser inp Instruction
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Instruction
Input)
    Parser inp Instruction
-> Parser inp Instruction -> Parser inp Instruction
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser inp Char
-> Parser inp Char
-> Parser inp Instruction
-> Parser inp Instruction
forall (f :: * -> *) a b c.
Applicative f =>
f a -> f b -> f c -> f c
between (Parser inp Char -> Parser inp Char
forall a. Parser inp a -> Parser inp a
lexeme (Char -> Parser inp Char
forall inp. Inputable inp => Char -> Parser inp Char
AP.char Char
'[')) (Parser inp Char -> Parser inp Char
forall a. Parser inp a -> Parser inp a
lexeme (Char -> Parser inp Char
forall inp. Inputable inp => Char -> Parser inp Char
AP.char Char
']')) ([Instruction] -> Instruction
Loop ([Instruction] -> Instruction)
-> Parser inp [Instruction] -> Parser inp Instruction
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser inp [Instruction]
bf))
-- Specializing is essential to keep best performances.
{-# SPECIALIZE parser :: AP.Parser T.Text [Instruction] #-}
{-# SPECIALIZE parser :: AP.Parser BS.ByteString [Instruction] #-}