{-# LANGUAGE LambdaCase #-}

-- | Parsec utils for parsing Strings into Strings
module L3.Parse.StringParsec where

import Control.Applicative (Alternative ((<|>)))
import Data.Char (isDigit)
import L3.Parse.Parsec
import L3.Parse.Parser

item :: Parser String Char
item :: Parser String Char
item = (String -> [(Char, String)]) -> Parser String Char
forall i o. (i -> [(o, i)]) -> Parser i o
Parser ((String -> [(Char, String)]) -> Parser String Char)
-> (String -> [(Char, String)]) -> Parser String Char
forall a b. (a -> b) -> a -> b
$ \case
  [] -> []
  (Char
c : String
cs) -> [(Char
c, String
cs)]

satisfy :: (Char -> Bool) -> Parser String Char
satisfy :: (Char -> Bool) -> Parser String Char
satisfy Char -> Bool
p =
  Parser String Char
item Parser String Char
-> (Char -> Parser String Char) -> Parser String Char
forall i o o'. Parser i o -> (o -> Parser i o') -> Parser i o'
`bind` \Char
c ->
    if Char -> Bool
p Char
c
      then Char -> Parser String Char
forall o i. o -> Parser i o
unit Char
c
      else (String -> [(Char, String)]) -> Parser String Char
forall i o. (i -> [(o, i)]) -> Parser i o
Parser ([(Char, String)] -> String -> [(Char, String)]
forall a b. a -> b -> a
const [])

oneOf :: String -> Parser String Char
oneOf :: String -> Parser String Char
oneOf String
s = (Char -> Bool) -> Parser String Char
satisfy (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
s)

char :: Char -> Parser String Char
char :: Char -> Parser String Char
char Char
c = (Char -> Bool) -> Parser String Char
satisfy (Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==)

letter :: Parser String Char
letter :: Parser String Char
letter = (Char -> Bool) -> Parser String Char
satisfy (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'a' .. Char
'z'] String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Char
'A' .. Char
'Z'] String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Char
'α' .. Char
'ω'] String -> String -> String
forall a. [a] -> [a] -> [a]
++ [Char
'Α' .. Char
'Ω'] String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_")

natural :: Parser String Integer
natural :: Parser String Integer
natural = String -> Integer
forall a. Read a => String -> a
read (String -> Integer)
-> Parser String String -> Parser String Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser String Char -> Parser String String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some ((Char -> Bool) -> Parser String Char
satisfy Char -> Bool
isDigit)

string :: String -> Parser String String
string :: String -> Parser String String
string [] = String -> Parser String String
forall (m :: * -> *) a. Monad m => a -> m a
return []
string (Char
c : String
cs) = do
  Char
_ <- Char -> Parser String Char
char Char
c
  String
_ <- String -> Parser String String
string String
cs
  String -> Parser String String
forall (m :: * -> *) a. Monad m => a -> m a
return (Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
cs)

token :: Parser String a -> Parser String a
token :: Parser String a -> Parser String a
token Parser String a
p = do
  a
a <- Parser String a
p
  String
_ <- Parser String String
spaces
  a -> Parser String a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a

reserved :: String -> Parser String String
reserved :: String -> Parser String String
reserved String
s = Parser String String -> Parser String String
forall a. Parser String a -> Parser String a
token (String -> Parser String String
string String
s)

space :: Parser String Char
space :: Parser String Char
space = String -> Parser String Char
oneOf String
" \n\r"

spaces :: Parser String String
spaces :: Parser String String
spaces = Parser String Char -> Parser String String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser String Char
space

digit :: Parser String Char
digit :: Parser String Char
digit = (Char -> Bool) -> Parser String Char
satisfy Char -> Bool
isDigit

number :: Parser String Int
number :: Parser String Int
number = do
  String
s <- String -> Parser String String
string String
"-" Parser String String
-> Parser String String -> Parser String String
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> Parser String String
forall (m :: * -> *) a. Monad m => a -> m a
return []
  String
cs <- Parser String Char -> Parser String String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some Parser String Char
digit
  String
_ <- Parser String String
spaces
  Int -> Parser String Int
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> Parser String Int) -> Int -> Parser String Int
forall a b. (a -> b) -> a -> b
$ String -> Int
forall a. Read a => String -> a
read (String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cs)

word :: Parser String String
word :: Parser String String
word = do
  String
cs <- Parser String Char -> Parser String String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some Parser String Char
letter
  String
_ <- Parser String String
spaces
  String -> Parser String String
forall (m :: * -> *) a. Monad m => a -> m a
return String
cs