{- HLINT ignore "Use <$>" -}
{-# OPTIONS_GHC -Wno-name-shadowing #-}

module Language.Fluent.Parser (module Language.Fluent.Parser, Parser) where

import Control.Applicative (Alternative (many, some), optional, (<|>))
import Control.Monad (replicateM, unless, when)
import Data.Attoparsec.Combinator (choice, eitherP, endOfInput, lookAhead, sepBy)
import Data.Attoparsec.Text
    ( Parser
    , char
    , endOfLine
    , match
    , parseOnly
    , peekChar
    , satisfy
    , string
    , takeWhile
    , takeWhile1
    )
import Data.Bifunctor (first)
import Data.Char (chr, isAsciiLower, isAsciiUpper, isDigit, isHexDigit, ord)
import Data.Either (isLeft, isRight, rights)
import Data.Functor (void, (<&>))
import Data.List qualified as List
import Data.List.NonEmpty (some1)
import Data.List.NonEmpty qualified as NonEmpty
import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing)
import Data.Text (Text)
import Data.Text qualified as Text
import GHC.Ix (inRange)
import Language.Fluent.AST
import Numeric (readHex)
import Prelude hiding (take, takeWhile)

parse :: Parser a -> Text -> Either String a
parse :: forall a. Parser a -> Text -> Either String a
parse Parser a
p = Parser a -> Text -> Either String a
forall a. Parser a -> Text -> Either String a
parseOnly (Parser a -> Text -> Either String a)
-> Parser a -> Text -> Either String a
forall a b. (a -> b) -> a -> b
$ Parser a
p Parser a -> Parser Text () -> Parser a
forall a b. Parser Text a -> Parser Text b -> Parser Text a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text ()
forall t. Chunk t => Parser t ()
endOfInput

parseNamed :: String -> Parser a -> Text -> Either String a
parseNamed :: forall a. String -> Parser a -> Text -> Either String a
parseNamed String
name Parser a
p Text
t = (String -> String) -> Either String a -> Either String a
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (String -> String -> String
forall a b. a -> b -> a
const (String -> String -> String) -> String -> String -> String
forall a b. (a -> b) -> a -> b
$ String
"Invalid " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
": " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a. Show a => a -> String
show Text
t) (Either String a -> Either String a)
-> Either String a -> Either String a
forall a b. (a -> b) -> a -> b
$ Parser a -> Text -> Either String a
forall a. Parser a -> Text -> Either String a
parse Parser a
p Text
t

parseIdentifier :: Text -> Either String Identifier
parseIdentifier :: Text -> Either String Identifier
parseIdentifier = String -> Parser Identifier -> Text -> Either String Identifier
forall a. String -> Parser a -> Text -> Either String a
parseNamed String
"identifier" Parser Identifier
identifier

parseResource :: Text -> Either String Resource
parseResource :: Text -> Either String Resource
parseResource = String -> Parser Resource -> Text -> Either String Resource
forall a. String -> Parser a -> Text -> Either String a
parseNamed String
"resource" Parser Resource
resource

resource :: Parser Resource
resource :: Parser Resource
resource = [Entry] -> Resource
Resource ([Entry] -> Resource)
-> ([Either () Entry] -> [Entry]) -> [Either () Entry] -> Resource
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Either () Entry] -> [Entry]
forall a b. [Either a b] -> [b]
rights ([Either () Entry] -> Resource)
-> Parser Text [Either () Entry] -> Parser Resource
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text (Either () Entry) -> Parser Text [Either () Entry]
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser Text ()
-> Parser Text Entry -> Parser Text (Either () Entry)
forall (f :: * -> *) a b.
Alternative f =>
f a -> f b -> f (Either a b)
eitherP Parser Text ()
blankBlock Parser Text Entry
entryOrJunk)

entryOrJunk :: Parser Entry
entryOrJunk :: Parser Text Entry
entryOrJunk = Parser Text Entry
entry Parser Text Entry -> Parser Text () -> Parser Text Entry
forall a b. Parser Text a -> Parser Text b -> Parser Text a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text () -> Parser Text ()
forall i a. Parser i a -> Parser i a
lookAhead Parser Text ()
entryEnd Parser Text Entry -> Parser Text Entry -> Parser Text Entry
forall a. Parser Text a -> Parser Text a -> Parser Text a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> Entry
JunkEntry (Text -> Entry) -> Parser Text Text -> Parser Text Entry
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text
junk

entryEnd :: Parser ()
entryEnd :: Parser Text ()
entryEnd = Parser Text () -> Parser Text ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void Parser Text ()
endOfLine Parser Text () -> Parser Text () -> Parser Text ()
forall a. Parser Text a -> Parser Text a -> Parser Text a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Text ()
forall t. Chunk t => Parser t ()
endOfInput

junk :: Parser Text
junk :: Parser Text Text
junk = do
    first <- Parser Text Text
line
    when (Text.null first) $ fail "nothing left to skip"
    rest <- many $ beforeEntry *> line
    pure . mconcat $ first : rest
  where
    beforeEntry :: Parser ()
    beforeEntry :: Parser Text ()
beforeEntry = do
        next <- Parser (Maybe Char)
peekChar
        case next of
            Just Char
c | Char -> Bool
beginsEntry Char
c -> String -> Parser Text ()
forall a. String -> Parser Text a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"the next entry begins here"
            Just Char
_ -> () -> Parser Text ()
forall a. a -> Parser Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
            Maybe Char
Nothing -> String -> Parser Text ()
forall a. String -> Parser Text a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"end of input"
    beginsEntry :: Char -> Bool
    beginsEntry :: Char -> Bool
beginsEntry Char
c = Char -> Bool
isAsciiLower Char
c Bool -> Bool -> Bool
|| Char -> Bool
isAsciiUpper Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'#'

line :: Parser Text
line :: Parser Text Text
line = do
    text <- (Char -> Bool) -> Parser Text Text
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\n')
    ending <- Text.singleton <$> char '\n' <|> pure mempty
    pure $ text <> ending

entry :: Parser Entry
entry :: Parser Text Entry
entry =
    [Parser Text Entry] -> Parser Text Entry
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice
        [ Parser Text Entry
commented
        , Message -> Entry
MessageEntry (Message -> Entry) -> Parser Text Message -> Parser Text Entry
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Comment -> Parser Text Message
message Maybe Comment
forall a. Maybe a
Nothing
        , Term -> Entry
TermEntry (Term -> Entry) -> Parser Text Term -> Parser Text Entry
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Comment -> Parser Text Term
term Maybe Comment
forall a. Maybe a
Nothing
        ]

commented :: Parser Entry
commented :: Parser Text Entry
commented = do
    (hashes, Comment -> comment) <- Parser (Int, Text)
commentBlock
    case hashes of
        Int
1 ->
            Parser Text (Either Message Term)
-> Parser Text (Maybe (Either Message Term))
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional
                ( (Parser Text ()
endOfLine Parser Text ()
-> Parser Text (Either Message Term)
-> Parser Text (Either Message Term)
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*>)
                    (Parser Text (Either Message Term)
 -> Parser Text (Either Message Term))
-> (Maybe Comment -> Parser Text (Either Message Term))
-> Maybe Comment
-> Parser Text (Either Message Term)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Parser Text (Either Message Term)
-> Parser Text () -> Parser Text (Either Message Term)
forall a b. Parser Text a -> Parser Text b -> Parser Text a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text () -> Parser Text ()
forall i a. Parser i a -> Parser i a
lookAhead Parser Text ()
entryEnd)
                    (Parser Text (Either Message Term)
 -> Parser Text (Either Message Term))
-> (Maybe Comment -> Parser Text (Either Message Term))
-> Maybe Comment
-> Parser Text (Either Message Term)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Text Message
-> Parser Text Term -> Parser Text (Either Message Term)
forall (f :: * -> *) a b.
Alternative f =>
f a -> f b -> f (Either a b)
eitherP (Maybe Comment -> Parser Text Message
message (Maybe Comment -> Parser Text Message)
-> Maybe Comment -> Parser Text Message
forall a b. (a -> b) -> a -> b
$ Comment -> Maybe Comment
forall a. a -> Maybe a
Just Comment
comment)
                    (Parser Text Term -> Parser Text (Either Message Term))
-> (Maybe Comment -> Parser Text Term)
-> Maybe Comment
-> Parser Text (Either Message Term)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Comment -> Parser Text Term
term
                    (Maybe Comment -> Parser Text (Either Message Term))
-> Maybe Comment -> Parser Text (Either Message Term)
forall a b. (a -> b) -> a -> b
$ Comment -> Maybe Comment
forall a. a -> Maybe a
Just Comment
comment
                )
                Parser Text (Maybe (Either Message Term))
-> (Maybe (Either Message Term) -> Entry) -> Parser Text Entry
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
                    Maybe (Either Message Term)
Nothing -> Comment -> Entry
CommentEntry Comment
comment
                    Just (Left Message
message) -> Message -> Entry
MessageEntry Message
message
                    Just (Right Term
term) -> Term -> Entry
TermEntry Term
term
        Int
2 -> Entry -> Parser Text Entry
forall a. a -> Parser Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Entry -> Parser Text Entry) -> Entry -> Parser Text Entry
forall a b. (a -> b) -> a -> b
$ Comment -> Entry
GroupCommentEntry Comment
comment
        Int
_ -> Entry -> Parser Text Entry
forall a. a -> Parser Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Entry -> Parser Text Entry) -> Entry -> Parser Text Entry
forall a b. (a -> b) -> a -> b
$ Comment -> Entry
ResourceCommentEntry Comment
comment

commentBlock :: Parser (Int, Text)
commentBlock :: Parser (Int, Text)
commentBlock = do
    (hashes, first) <- Parser (Int, Text)
commentLine
    rest <- many $ endOfLine *> ofSameKind hashes
    pure (hashes, Text.intercalate "\n" (first : rest))
  where
    ofSameKind :: Int -> Parser Text
    ofSameKind :: Int -> Parser Text Text
ofSameKind Int
hashes = do
        (found, content) <- Parser (Int, Text)
commentLine
        unless (found == hashes) . fail $
            "expected a " <> replicate hashes '#' <> " comment, found a " <> replicate found '#' <> " one"
        pure content

commentLine :: Parser (Int, Text)
commentLine :: Parser (Int, Text)
commentLine = do
    let hash :: Parser Text Char
hash = Char -> Parser Text Char
char Char
'#'
    hashes <- String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (String -> Int) -> ([Maybe Char] -> String) -> [Maybe Char] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe Char] -> String
forall a. [Maybe a] -> [a]
catMaybes ([Maybe Char] -> Int)
-> Parser Text [Maybe Char] -> Parser Text Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Parser (Maybe Char)] -> Parser Text [Maybe Char]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence [Char -> Maybe Char
forall a. a -> Maybe a
Just (Char -> Maybe Char) -> Parser Text Char -> Parser (Maybe Char)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char
hash, Parser Text Char -> Parser (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text Char
hash, Parser Text Char -> Parser (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text Char
hash]
    content <-
        choice
            [ char ' ' *> lineText
            , mempty <$ lookAhead (void (string "\r\n") <|> void (char '\n') <|> endOfInput)
            ]
    pure (hashes, content)

lineText :: Parser Text
lineText :: Parser Text Text
lineText = do
    text <- (Char -> Bool) -> Parser Text Text
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\n')
    end <- peekChar
    pure if end == Just '\n' then fromMaybe text $ Text.stripSuffix "\r" text else text

message :: Maybe Comment -> Parser Message
message :: Maybe Comment -> Parser Text Message
message Maybe Comment
comment = do
    id <- Parser Identifier
identifier
    optional blankInline
    char '='
    optional blankInline
    value <- optional pattern
    attributes <- many attribute
    when (isNothing value && null attributes) $
        fail "Message must have either a pattern or attributes"
    pure Message{..}

term :: Maybe Comment -> Parser Term
term :: Maybe Comment -> Parser Text Term
term Maybe Comment
comment = do
    Char -> Parser Text Char
char Char
'-'
    id <- Parser Identifier
identifier
    optional blankInline
    char '='
    optional blankInline
    value <- pattern
    attributes <- many attribute
    pure Term{..}

attribute :: Parser Attribute
attribute :: Parser Text Attribute
attribute = do
    Parser Text ()
endOfLine
    Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blank
    Char -> Parser Text Char
char Char
'.'
    i <- Parser Identifier
identifier
    optional blankInline
    char '='
    optional blankInline
    p <- pattern
    pure $ Attribute i p

pattern :: Parser Pattern
pattern :: Parser Text Pattern
pattern = NonEmpty PatternElement -> Pattern
Pattern (NonEmpty PatternElement -> Pattern)
-> (NonEmpty PatternElement -> NonEmpty PatternElement)
-> NonEmpty PatternElement
-> Pattern
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [PatternElement] -> NonEmpty PatternElement
forall a. HasCallStack => [a] -> NonEmpty a
NonEmpty.fromList ([PatternElement] -> NonEmpty PatternElement)
-> (NonEmpty PatternElement -> [PatternElement])
-> NonEmpty PatternElement
-> NonEmpty PatternElement
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [PatternElement] -> [PatternElement]
dedent ([PatternElement] -> [PatternElement])
-> (NonEmpty PatternElement -> [PatternElement])
-> NonEmpty PatternElement
-> [PatternElement]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty PatternElement -> [PatternElement]
forall a. NonEmpty a -> [a]
NonEmpty.toList (NonEmpty PatternElement -> Pattern)
-> Parser Text (NonEmpty PatternElement) -> Parser Text Pattern
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text PatternElement -> Parser Text (NonEmpty PatternElement)
forall (f :: * -> *) a. Alternative f => f a -> f (NonEmpty a)
some1 Parser Text PatternElement
patternElement

-- | Apply <https://projectfluent.org/fluent/guide/multiline multi-line rules>
-- to the raw pattern elements.
dedent :: [PatternElement] -> [PatternElement]
dedent :: [PatternElement] -> [PatternElement]
dedent [PatternElement]
elements =
    (PatternElement -> PatternElement)
-> [PatternElement] -> [PatternElement]
forall a. (a -> a) -> [a] -> [a]
onLast ((Text -> Text) -> PatternElement -> PatternElement
mapText ((Text -> Text) -> PatternElement -> PatternElement)
-> (Text -> Text) -> PatternElement -> PatternElement
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Text -> Text
Text.dropWhileEnd (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
blanks))
        ([PatternElement] -> [PatternElement])
-> ([PatternElement] -> [PatternElement])
-> [PatternElement]
-> [PatternElement]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PatternElement -> PatternElement)
-> [PatternElement] -> [PatternElement]
forall a. (a -> a) -> [a] -> [a]
onFirst ((Text -> Text) -> PatternElement -> PatternElement
mapText ((Text -> Text) -> PatternElement -> PatternElement)
-> (Text -> Text) -> PatternElement -> PatternElement
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Text -> Text
Text.dropWhile (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
newlines))
        ([PatternElement] -> [PatternElement])
-> [PatternElement] -> [PatternElement]
forall a b. (a -> b) -> a -> b
$ PatternElement -> PatternElement
strip (PatternElement -> PatternElement)
-> [PatternElement] -> [PatternElement]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [PatternElement]
elements
  where
    newlines :: String
newlines = String
"\r\n" :: String
    blanks :: String
blanks = String
" \r\n" :: String
    commonIndent :: Int
    commonIndent :: Int
commonIndent =
        [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$
            Int
forall a. Bounded a => a
maxBound
                Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Text -> Int
indentWidth Text
t | BlockText Text
t <- [PatternElement]
elements]
                    [Int] -> [Int] -> [Int]
forall a. Semigroup a => a -> a -> a
<> [Int
indent | Placeable (BlockPlaceable Int
indent Expression
_) <- [PatternElement]
elements]
    indentWidth :: Text -> Int
    indentWidth :: Text -> Int
indentWidth = Text -> Int
Text.length (Text -> Int) -> (Text -> Text) -> Text -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Text
Text.takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ') (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Text
Text.dropWhile (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
newlines)
    strip :: PatternElement -> PatternElement
    strip :: PatternElement -> PatternElement
strip (BlockText ((Char -> Bool) -> Text -> (Text, Text)
Text.span (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
newlines) -> (Text
ns, Text
rest))) =
        Text -> PatternElement
BlockText (Text
ns Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text -> Text
Text.drop Int
commonIndent Text
rest)
    strip PatternElement
e = PatternElement
e
    mapText :: (Text -> Text) -> PatternElement -> PatternElement
    mapText :: (Text -> Text) -> PatternElement -> PatternElement
mapText Text -> Text
f (InlineText Text
t) = Text -> PatternElement
InlineText (Text -> Text
f Text
t)
    mapText Text -> Text
f (BlockText Text
t) = Text -> PatternElement
BlockText (Text -> Text
f Text
t)
    mapText Text -> Text
_ PatternElement
e = PatternElement
e
    onFirst, onLast :: (a -> a) -> [a] -> [a]
    onFirst :: forall a. (a -> a) -> [a] -> [a]
onFirst a -> a
f (a
x : [a]
xs) = a -> a
f a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
xs
    onFirst a -> a
_ [] = []
    onLast :: forall a. (a -> a) -> [a] -> [a]
onLast a -> a
f = [a] -> [a]
forall a. [a] -> [a]
reverse ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a) -> [a] -> [a]
forall a. (a -> a) -> [a] -> [a]
onFirst a -> a
f ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [a]
forall a. [a] -> [a]
reverse

patternElement :: Parser PatternElement
patternElement :: Parser Text PatternElement
patternElement =
    [Parser Text PatternElement] -> Parser Text PatternElement
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice
        [ Text -> PatternElement
InlineText (Text -> PatternElement)
-> Parser Text Text -> Parser Text PatternElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text
inlineText
        , Text -> PatternElement
BlockText (Text -> PatternElement)
-> Parser Text Text -> Parser Text PatternElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text
blockText
        , Placeable -> PatternElement
Placeable (Placeable -> PatternElement)
-> Parser Text Placeable -> Parser Text PatternElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Placeable
placeable
        ]

placeable :: Parser Placeable
placeable :: Parser Text Placeable
placeable =
    [Parser Text Placeable] -> Parser Text Placeable
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice
        [ Expression -> Placeable
InlinePlaceable (Expression -> Placeable)
-> Parser Text Expression -> Parser Text Placeable
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Expression
inlinePlaceable
        , Parser Text Placeable
blockPlaceable
        ]

inlinePlaceable :: Parser Expression
inlinePlaceable :: Parser Text Expression
inlinePlaceable = do
    Char -> Parser Text Char
char Char
'{'
    Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blank
    e <- Parser Text Expression
expression
    optional blank
    char '}'
    pure e

blockPlaceable :: Parser Placeable
blockPlaceable :: Parser Text Placeable
blockPlaceable = do
    Parser Text ()
blankBlock
    indent <- Int -> (Text -> Int) -> Maybe Text -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 Text -> Int
Text.length (Maybe Text -> Int) -> Parser Text (Maybe Text) -> Parser Text Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text -> Parser Text (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional ((Char -> Bool) -> Parser Text Text
takeWhile1 (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' '))
    BlockPlaceable indent <$> inlinePlaceable

expression :: Parser Expression
expression :: Parser Text Expression
expression = do
    i <- Parser InlineExpression
inlineExpression
    choice
        [ Select <$> do
            optional blank
            string "->"
            optional blankInline
            unless (choosesVariant i) $ fail "failed to choose a variant"
            vs <- variantList
            pure $ SelectExpression i vs
        , do
            unless (usableAsPlaceable i) $ fail "Attributes of terms cannot be used as placeables"
            pure $ Inline i
        ]
  where
    choosesVariant :: InlineExpression -> Bool
    choosesVariant :: InlineExpression -> Bool
choosesVariant (StringLiteralExpression StringLiteral
_) = Bool
True
    choosesVariant (NumberLiteralExpression NumberLiteral
_) = Bool
True
    choosesVariant (VariableReference Identifier
_) = Bool
True
    choosesVariant (FunctionReference Identifier
_ CallArguments
_) = Bool
True
    choosesVariant (TermReference Identifier
_ Maybe AttributeAccessor
attribute Maybe CallArguments
_) = Maybe AttributeAccessor -> Bool
forall a. Maybe a -> Bool
isJust Maybe AttributeAccessor
attribute
    choosesVariant InlineExpression
_ = Bool
False

    usableAsPlaceable :: InlineExpression -> Bool
    usableAsPlaceable :: InlineExpression -> Bool
usableAsPlaceable (TermReference Identifier
_ (Just AttributeAccessor
_) Maybe CallArguments
_) = Bool
False
    usableAsPlaceable InlineExpression
_ = Bool
True

inlineExpression :: Parser InlineExpression
inlineExpression :: Parser InlineExpression
inlineExpression =
    [Parser InlineExpression] -> Parser InlineExpression
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice
        [ StringLiteral -> InlineExpression
StringLiteralExpression (StringLiteral -> InlineExpression)
-> Parser Text StringLiteral -> Parser InlineExpression
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text StringLiteral
stringLiteral
        , NumberLiteral -> InlineExpression
NumberLiteralExpression (NumberLiteral -> InlineExpression)
-> Parser Text NumberLiteral -> Parser InlineExpression
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text NumberLiteral
numberLiteral
        , Identifier -> CallArguments -> InlineExpression
FunctionReference (Identifier -> CallArguments -> InlineExpression)
-> Parser Identifier
-> Parser Text (CallArguments -> InlineExpression)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Identifier
functionName Parser Text (CallArguments -> InlineExpression)
-> Parser Text CallArguments -> Parser InlineExpression
forall a b. Parser Text (a -> b) -> Parser Text a -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text CallArguments
callArguments
        , Identifier -> Maybe AttributeAccessor -> InlineExpression
MessageReference (Identifier -> Maybe AttributeAccessor -> InlineExpression)
-> Parser Identifier
-> Parser Text (Maybe AttributeAccessor -> InlineExpression)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Identifier
identifier Parser Text (Maybe AttributeAccessor -> InlineExpression)
-> Parser Text (Maybe AttributeAccessor) -> Parser InlineExpression
forall a b. Parser Text (a -> b) -> Parser Text a -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text AttributeAccessor
-> Parser Text (Maybe AttributeAccessor)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text AttributeAccessor
attributeAccessor
        , Identifier
-> Maybe AttributeAccessor
-> Maybe CallArguments
-> InlineExpression
TermReference
            (Identifier
 -> Maybe AttributeAccessor
 -> Maybe CallArguments
 -> InlineExpression)
-> Parser Identifier
-> Parser
     Text
     (Maybe AttributeAccessor
      -> Maybe CallArguments -> InlineExpression)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Parser Text Char
char Char
'-' Parser Text Char -> Parser Identifier -> Parser Identifier
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Identifier
identifier)
            Parser
  Text
  (Maybe AttributeAccessor
   -> Maybe CallArguments -> InlineExpression)
-> Parser Text (Maybe AttributeAccessor)
-> Parser Text (Maybe CallArguments -> InlineExpression)
forall a b. Parser Text (a -> b) -> Parser Text a -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text AttributeAccessor
-> Parser Text (Maybe AttributeAccessor)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text AttributeAccessor
attributeAccessor
            Parser Text (Maybe CallArguments -> InlineExpression)
-> Parser Text (Maybe CallArguments) -> Parser InlineExpression
forall a b. Parser Text (a -> b) -> Parser Text a -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text CallArguments -> Parser Text (Maybe CallArguments)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text CallArguments
callArguments
        , Identifier -> InlineExpression
VariableReference (Identifier -> InlineExpression)
-> Parser Identifier -> Parser InlineExpression
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Parser Text Char
char Char
'$' Parser Text Char -> Parser Identifier -> Parser Identifier
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Identifier
identifier)
        , Expression -> InlineExpression
PlaceableExpression (Expression -> InlineExpression)
-> Parser Text Expression -> Parser InlineExpression
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Expression
inlinePlaceable
        ]

attributeAccessor :: Parser AttributeAccessor
attributeAccessor :: Parser Text AttributeAccessor
attributeAccessor = Identifier -> AttributeAccessor
AttributeAccessor (Identifier -> AttributeAccessor)
-> Parser Identifier -> Parser Text AttributeAccessor
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Parser Text Char
char Char
'.' Parser Text Char -> Parser Identifier -> Parser Identifier
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Identifier
identifier)

variant :: Parser Variant
variant :: Parser Variant
variant = do
    Parser Text ()
endOfLine
    Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blank
    isDefault <- Maybe Char -> Bool
forall a. Maybe a -> Bool
isJust (Maybe Char -> Bool) -> Parser (Maybe Char) -> Parser Text Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Char -> Parser Text Char
char Char
'*')
    key <- variantKey
    optional blankInline
    value <- pattern
    pure Variant{..}

variantKey :: Parser VariantKey
variantKey :: Parser VariantKey
variantKey = do
    Char -> Parser Text Char
char Char
'['
    Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blank
    vk <- Parser Text NumberLiteral
-> Parser Identifier
-> Parser Text (Either NumberLiteral Identifier)
forall (f :: * -> *) a b.
Alternative f =>
f a -> f b -> f (Either a b)
eitherP Parser Text NumberLiteral
numberLiteral Parser Identifier
identifier
    optional blank
    char ']'
    pure $ VariantKey vk

variantList :: Parser VariantList
variantList :: Parser VariantList
variantList = do
    variants <- Parser Variant -> Parser Text (NonEmpty Variant)
forall (f :: * -> *) a. Alternative f => f a -> f (NonEmpty a)
some1 Parser Variant
variant
    unless (any isDefault variants) $ fail "VariantList must have at least one default variant"
    endOfLine
    pure $ VariantList variants

callArguments :: Parser CallArguments
callArguments :: Parser Text CallArguments
callArguments = do
    Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blank
    Char -> Parser Text Char
char Char
'('
    Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blank
    args <- Parser Text (Either NamedArgument InlineExpression)
-> Parser Text ()
-> Parser Text [Either NamedArgument InlineExpression]
forall (f :: * -> *) a s. Alternative f => f a -> f s -> f [a]
sepBy (Parser Text NamedArgument
-> Parser InlineExpression
-> Parser Text (Either NamedArgument InlineExpression)
forall (f :: * -> *) a b.
Alternative f =>
f a -> f b -> f (Either a b)
eitherP Parser Text NamedArgument
namedArgument Parser InlineExpression
inlineExpression) Parser Text ()
comma
    unless (null args) . void $ optional comma
    optional blank
    char ')'
    unless (all isLeft $ dropWhile isRight args) $
        fail "an argument standing on its place follows one that is named"
    let names = [Identifier
name | Left (NamedArgument Identifier
name Either StringLiteral NumberLiteral
_) <- [Either NamedArgument InlineExpression]
args]
    unless (length (List.nub names) == length names) $ fail "a name is given twice"
    pure $ CallArguments args
  where
    comma :: Parser ()
    comma :: Parser Text ()
comma = Parser Text (Maybe ()) -> Parser Text ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser Text (Maybe ()) -> Parser Text ())
-> Parser Text (Maybe ()) -> Parser Text ()
forall a b. (a -> b) -> a -> b
$ Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blank Parser Text (Maybe ()) -> Parser Text Char -> Parser Text Char
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Char -> Parser Text Char
char Char
',' Parser Text Char
-> Parser Text (Maybe ()) -> Parser Text (Maybe ())
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blank

namedArgument :: Parser NamedArgument
namedArgument :: Parser Text NamedArgument
namedArgument = do
    i <- Parser Identifier
identifier
    optional blank
    char ':'
    optional blank
    l <- eitherP stringLiteral numberLiteral
    pure $ NamedArgument i l

identifier :: Parser Identifier
identifier :: Parser Identifier
identifier = Text -> Identifier
Identifier (Text -> Identifier) -> Parser Text Text -> Parser Identifier
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Text -> Text
Text.cons (Char -> Text -> Text)
-> Parser Text Char -> Parser Text (Text -> Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> Parser Text Char
satisfy Char -> Bool
isAsciiLetter Parser Text (Text -> Text) -> Parser Text Text -> Parser Text Text
forall a b. Parser Text (a -> b) -> Parser Text a -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text Text
tailLetters)
  where
    isAsciiLetter :: Char -> Bool
isAsciiLetter Char
c = Char -> Bool
isAsciiLower Char
c Bool -> Bool -> Bool
|| Char -> Bool
isAsciiUpper Char
c
    tailLetters :: Parser Text Text
tailLetters = (Char -> Bool) -> Parser Text Text
takeWhile \Char
c -> Char -> Bool
isAsciiLetter Char
c Bool -> Bool -> Bool
|| Char -> Bool
isDigit Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'

functionName :: Parser Identifier
functionName :: Parser Identifier
functionName = do
    name@(Identifier text) <- Parser Identifier
identifier
    unless (Text.all capital text) $ fail "a function name should be written in all capitals"
    pure name
  where
    capital :: Char -> Bool
    capital :: Char -> Bool
capital Char
c = Char -> Bool
isAsciiUpper Char
c Bool -> Bool -> Bool
|| Char -> Bool
isDigit Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'

numberLiteral :: Parser NumberLiteral
numberLiteral :: Parser Text NumberLiteral
numberLiteral = do
    sign <- Parser Text Text -> Parser Text (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Parser Text Text -> Parser Text (Maybe Text))
-> Parser Text Text -> Parser Text (Maybe Text)
forall a b. (a -> b) -> a -> b
$ Text -> Parser Text Text
string Text
"-"
    i <- digits
    f <- optional $ Text.cons <$> char '.' <*> digits
    pure . NumberLiteral . mconcat . catMaybes $ [sign, Just i, f]
  where
    digits :: Parser Text Text
digits = (Char -> Bool) -> Parser Text Text
takeWhile1 (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'0' .. Char
'9'])

stringLiteral :: Parser StringLiteral
stringLiteral :: Parser Text StringLiteral
stringLiteral = do
    Char -> Parser Text Char
char Char
'"'
    (raw, value) <- Parser Text Text -> Parser (Text, Text)
forall a. Parser a -> Parser (Text, a)
match (Parser Text Text -> Parser (Text, Text))
-> Parser Text Text -> Parser (Text, Text)
forall a b. (a -> b) -> a -> b
$ String -> Text
Text.pack (String -> Text) -> Parser Text String -> Parser Text Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser Text Char
quotedChar
    char '"'
    pure StringLiteral{..}

quotedChar :: Parser Char
quotedChar :: Parser Text Char
quotedChar =
    [Parser Text Char] -> Parser Text Char
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice
        [ (Char -> Bool) -> Parser Text Char
satisfy \Char
c -> Char -> Bool
isAnyChar Char
c Bool -> Bool -> Bool
&& Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
notElem Char
c (String
"\\\"\r\n" :: String)
        , Char -> Parser Text Char
char Char
'\\'
            Parser Text Char -> Parser Text Char -> Parser Text Char
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> [Parser Text Char] -> Parser Text Char
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice
                [ (Char -> Bool) -> Parser Text Char
satisfy (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (String
"\\\"" :: String))
                , Char -> Parser Text Char
char Char
'u' Parser Text Char -> Parser Text Char -> Parser Text Char
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> Parser Text Char
hexString Int
4
                , Char -> Parser Text Char
char Char
'U' Parser Text Char -> Parser Text Char -> Parser Text Char
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Int -> Parser Text Char
hexString Int
6
                ]
        ]
  where
    hexDigit :: Parser Char
    hexDigit :: Parser Text Char
hexDigit = (Char -> Bool) -> Parser Text Char
satisfy Char -> Bool
isHexDigit
    hexString :: Int -> Parser Char
    hexString :: Int -> Parser Text Char
hexString Int
len = do
        [(num, "")] <- ReadS Int
forall a. (Eq a, Num a) => ReadS a
readHex ReadS Int -> Parser Text String -> Parser Text [(Int, String)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
len Parser Text Char
hexDigit
        pure $ chr num

isAnyChar :: Char -> Bool
isAnyChar :: Char -> Bool
isAnyChar = (Int, Int) -> Int -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (Int
0, Int
0x10FFFF) (Int -> Bool) -> (Char -> Int) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
ord

anyChar :: Parser Char
anyChar :: Parser Text Char
anyChar = (Char -> Bool) -> Parser Text Char
satisfy Char -> Bool
isAnyChar

inlineText :: Parser Text
inlineText :: Parser Text Text
inlineText = (Char -> Bool) -> Parser Text Text
takeWhile1 (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` (String
"{}\r\n" :: String))

blockText :: Parser Text
blockText :: Parser Text Text
blockText =
    ([Text] -> Text) -> Parser Text [Text] -> Parser Text Text
forall a b. (a -> b) -> Parser Text a -> Parser Text b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat (Parser Text [Text] -> Parser Text Text)
-> ([Parser Text Text] -> Parser Text [Text])
-> [Parser Text Text]
-> Parser Text Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Parser Text Text] -> Parser Text [Text]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence ([Parser Text Text] -> Parser Text Text)
-> [Parser Text Text] -> Parser Text Text
forall a b. (a -> b) -> a -> b
$
        [ [Text] -> Text
Text.concat ([Text] -> Text) -> Parser Text [Text] -> Parser Text Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text -> Parser Text [Text]
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some (Text
"\n" Text -> Parser Text () -> Parser Text Text
forall a b. a -> Parser Text b -> Parser Text a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ (Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blankInline Parser Text (Maybe ()) -> Parser Text () -> Parser Text ()
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text ()
endOfLine))
        , (Char -> Bool) -> Parser Text Text
takeWhile1 (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ')
        , Char -> Text -> Text
Text.cons (Char -> Text -> Text)
-> Parser Text Char -> Parser Text (Text -> Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char
indentedChar Parser Text (Text -> Text) -> Parser Text Text -> Parser Text Text
forall a b. Parser Text (a -> b) -> Parser Text a -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Parser Text Text
inlineText Parser Text Text -> Parser Text Text -> Parser Text Text
forall a. Parser Text a -> Parser Text a -> Parser Text a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> Parser Text Text
forall a. a -> Parser Text a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
forall a. Monoid a => a
mempty)
        ]

indentedChar :: Parser Char
indentedChar :: Parser Text Char
indentedChar = (Char -> Bool) -> Parser Text Char
satisfy (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` (String
"{}[*.\r\n" :: String))

blankInline :: Parser ()
blankInline :: Parser Text ()
blankInline = Parser Text String -> Parser Text ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser Text String -> Parser Text ())
-> (Char -> Parser Text String) -> Char -> Parser Text ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Text Char -> Parser Text String
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some (Parser Text Char -> Parser Text String)
-> (Char -> Parser Text Char) -> Char -> Parser Text String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Parser Text Char
char (Char -> Parser Text ()) -> Char -> Parser Text ()
forall a b. (a -> b) -> a -> b
$ Char
' '

blank :: Parser ()
blank :: Parser Text ()
blank = Parser Text [()] -> Parser Text ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser Text [()] -> Parser Text ())
-> (Parser Text () -> Parser Text [()])
-> Parser Text ()
-> Parser Text ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Text () -> Parser Text [()]
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some (Parser Text () -> Parser Text ())
-> Parser Text () -> Parser Text ()
forall a b. (a -> b) -> a -> b
$ Parser Text ()
blankInline Parser Text () -> Parser Text () -> Parser Text ()
forall a. Parser Text a -> Parser Text a -> Parser Text a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Text ()
endOfLine

blankBlock :: Parser ()
blankBlock :: Parser Text ()
blankBlock = Parser Text [()] -> Parser Text ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser Text [()] -> Parser Text ())
-> (Parser Text () -> Parser Text [()])
-> Parser Text ()
-> Parser Text ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser Text () -> Parser Text [()]
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some (Parser Text () -> Parser Text ())
-> Parser Text () -> Parser Text ()
forall a b. (a -> b) -> a -> b
$ Parser Text () -> Parser Text (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Text ()
blankInline Parser Text (Maybe ()) -> Parser Text () -> Parser Text ()
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text ()
endOfLine