{-# 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
= 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)
= 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)
= 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
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