{-# LANGUAGE LambdaCase #-}
module BNFC.Backend.TreeSitter.MatchesEmpty where
import BNFC.Utils((>.>))
import BNFC.CF(SentForm, Cat, Rule, rhsRule)
import qualified Data.Maybe as Maybe
import qualified Data.List as List
import qualified Data.Set as Set
type Sym = Either Cat String
newtype KnownEmpty = KnownEmpty (Set.Set Sym) deriving (KnownEmpty -> KnownEmpty -> Bool
(KnownEmpty -> KnownEmpty -> Bool)
-> (KnownEmpty -> KnownEmpty -> Bool) -> Eq KnownEmpty
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: KnownEmpty -> KnownEmpty -> Bool
== :: KnownEmpty -> KnownEmpty -> Bool
$c/= :: KnownEmpty -> KnownEmpty -> Bool
/= :: KnownEmpty -> KnownEmpty -> Bool
Eq, Int -> KnownEmpty -> ShowS
[KnownEmpty] -> ShowS
KnownEmpty -> [Char]
(Int -> KnownEmpty -> ShowS)
-> (KnownEmpty -> [Char])
-> ([KnownEmpty] -> ShowS)
-> Show KnownEmpty
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> KnownEmpty -> ShowS
showsPrec :: Int -> KnownEmpty -> ShowS
$cshow :: KnownEmpty -> [Char]
show :: KnownEmpty -> [Char]
$cshowList :: [KnownEmpty] -> ShowS
showList :: [KnownEmpty] -> ShowS
Show)
isKnownEmpty :: Sym -> KnownEmpty -> Bool
isKnownEmpty :: Sym -> KnownEmpty -> Bool
isKnownEmpty Sym
x KnownEmpty
ks = Sym
x Sym -> Set Sym -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` (KnownEmpty -> Set Sym
knownEmptySet KnownEmpty
ks)
knownEmptySet :: KnownEmpty -> Set.Set Sym
knownEmptySet :: KnownEmpty -> Set Sym
knownEmptySet (KnownEmpty Set Sym
x) = Set Sym
x
data OptSym =
Optional Sym |
NonOptional Sym deriving (OptSym -> OptSym -> Bool
(OptSym -> OptSym -> Bool)
-> (OptSym -> OptSym -> Bool) -> Eq OptSym
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: OptSym -> OptSym -> Bool
== :: OptSym -> OptSym -> Bool
$c/= :: OptSym -> OptSym -> Bool
/= :: OptSym -> OptSym -> Bool
Eq, Int -> OptSym -> ShowS
[OptSym] -> ShowS
OptSym -> [Char]
(Int -> OptSym -> ShowS)
-> (OptSym -> [Char]) -> ([OptSym] -> ShowS) -> Show OptSym
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> OptSym -> ShowS
showsPrec :: Int -> OptSym -> ShowS
$cshow :: OptSym -> [Char]
show :: OptSym -> [Char]
$cshowList :: [OptSym] -> ShowS
showList :: [OptSym] -> ShowS
Show)
type OptSentForm = [OptSym]
data MatchesEmpty a =
MatchesEmpty a |
NonEmpty a deriving (MatchesEmpty a -> MatchesEmpty a -> Bool
(MatchesEmpty a -> MatchesEmpty a -> Bool)
-> (MatchesEmpty a -> MatchesEmpty a -> Bool)
-> Eq (MatchesEmpty a)
forall a. Eq a => MatchesEmpty a -> MatchesEmpty a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => MatchesEmpty a -> MatchesEmpty a -> Bool
== :: MatchesEmpty a -> MatchesEmpty a -> Bool
$c/= :: forall a. Eq a => MatchesEmpty a -> MatchesEmpty a -> Bool
/= :: MatchesEmpty a -> MatchesEmpty a -> Bool
Eq, Int -> MatchesEmpty a -> ShowS
[MatchesEmpty a] -> ShowS
MatchesEmpty a -> [Char]
(Int -> MatchesEmpty a -> ShowS)
-> (MatchesEmpty a -> [Char])
-> ([MatchesEmpty a] -> ShowS)
-> Show (MatchesEmpty a)
forall a. Show a => Int -> MatchesEmpty a -> ShowS
forall a. Show a => [MatchesEmpty a] -> ShowS
forall a. Show a => MatchesEmpty a -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> MatchesEmpty a -> ShowS
showsPrec :: Int -> MatchesEmpty a -> ShowS
$cshow :: forall a. Show a => MatchesEmpty a -> [Char]
show :: MatchesEmpty a -> [Char]
$cshowList :: forall a. Show a => [MatchesEmpty a] -> ShowS
showList :: [MatchesEmpty a] -> ShowS
Show)
matchesEmpty :: MatchesEmpty a -> Bool
matchesEmpty :: forall a. MatchesEmpty a -> Bool
matchesEmpty (MatchesEmpty a
_) = Bool
True
matchesEmpty (NonEmpty a
_) = Bool
False
unMatchesEmpty :: MatchesEmpty a -> a
unMatchesEmpty :: forall a. MatchesEmpty a -> a
unMatchesEmpty (MatchesEmpty a
x) = a
x
unMatchesEmpty (NonEmpty a
x) = a
x
seqMatchesEmpty :: Semigroup a => MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a
seqMatchesEmpty :: forall a.
Semigroup a =>
MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a
seqMatchesEmpty (MatchesEmpty a
x) (MatchesEmpty a
y) = a -> MatchesEmpty a
forall a. a -> MatchesEmpty a
MatchesEmpty (a
x a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
y)
seqMatchesEmpty MatchesEmpty a
x MatchesEmpty a
y = a -> MatchesEmpty a
forall a. a -> MatchesEmpty a
NonEmpty (MatchesEmpty a -> a
forall a. MatchesEmpty a -> a
unMatchesEmpty MatchesEmpty a
x a -> a -> a
forall a. Semigroup a => a -> a -> a
<> MatchesEmpty a -> a
forall a. MatchesEmpty a -> a
unMatchesEmpty MatchesEmpty a
y)
seqListMatchesEmpty :: Monoid a => [MatchesEmpty a] -> MatchesEmpty a
seqListMatchesEmpty :: forall a. Monoid a => [MatchesEmpty a] -> MatchesEmpty a
seqListMatchesEmpty = (MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a)
-> MatchesEmpty a -> [MatchesEmpty a] -> MatchesEmpty a
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a
forall a.
Semigroup a =>
MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a
seqMatchesEmpty (a -> MatchesEmpty a
forall a. a -> MatchesEmpty a
MatchesEmpty a
forall a. Monoid a => a
mempty)
choiceMatchesEmpty :: Semigroup a => MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a
choiceMatchesEmpty :: forall a.
Semigroup a =>
MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a
choiceMatchesEmpty (NonEmpty a
x) (NonEmpty a
y) = a -> MatchesEmpty a
forall a. a -> MatchesEmpty a
NonEmpty (a
x a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
y)
choiceMatchesEmpty MatchesEmpty a
x MatchesEmpty a
y = a -> MatchesEmpty a
forall a. a -> MatchesEmpty a
MatchesEmpty (MatchesEmpty a -> a
forall a. MatchesEmpty a -> a
unMatchesEmpty MatchesEmpty a
x a -> a -> a
forall a. Semigroup a => a -> a -> a
<> MatchesEmpty a -> a
forall a. MatchesEmpty a -> a
unMatchesEmpty MatchesEmpty a
y)
choiceListMatchesEmpty :: Monoid a => [MatchesEmpty a] -> MatchesEmpty a
choiceListMatchesEmpty :: forall a. Monoid a => [MatchesEmpty a] -> MatchesEmpty a
choiceListMatchesEmpty = (MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a)
-> MatchesEmpty a -> [MatchesEmpty a] -> MatchesEmpty a
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a
forall a.
Semigroup a =>
MatchesEmpty a -> MatchesEmpty a -> MatchesEmpty a
choiceMatchesEmpty (a -> MatchesEmpty a
forall a. a -> MatchesEmpty a
NonEmpty a
forall a. Monoid a => a
mempty)
possiblyEmptySym :: KnownEmpty -> Sym -> OptSym
possiblyEmptySym :: KnownEmpty -> Sym -> OptSym
possiblyEmptySym KnownEmpty
knownEmpty Sym
sym =
if Sym
sym Sym -> KnownEmpty -> Bool
`isKnownEmpty` KnownEmpty
knownEmpty then
Sym -> OptSym
Optional Sym
sym
else
Sym -> OptSym
NonOptional Sym
sym
possiblyEmptyRule :: KnownEmpty -> SentForm -> MatchesEmpty [OptSentForm]
possiblyEmptyRule :: KnownEmpty -> SentForm -> MatchesEmpty [[OptSym]]
possiblyEmptyRule KnownEmpty
knownEmpty =
(Sym -> OptSym) -> SentForm -> [OptSym]
forall a b. (a -> b) -> [a] -> [b]
map (KnownEmpty -> Sym -> OptSym
possiblyEmptySym KnownEmpty
knownEmpty)
(SentForm -> [OptSym])
-> ([OptSym] -> MatchesEmpty [[OptSym]])
-> SentForm
-> MatchesEmpty [[OptSym]]
forall a b c. (a -> b) -> (b -> c) -> a -> c
>.> (OptSym -> MatchesEmpty [OptSym])
-> [OptSym] -> [MatchesEmpty [OptSym]]
forall a b. (a -> b) -> [a] -> [b]
map OptSym -> MatchesEmpty [OptSym]
fromOpt
([OptSym] -> [MatchesEmpty [OptSym]])
-> ([MatchesEmpty [OptSym]] -> MatchesEmpty [[OptSym]])
-> [OptSym]
-> MatchesEmpty [[OptSym]]
forall a b c. (a -> b) -> (b -> c) -> a -> c
>.> [MatchesEmpty [OptSym]] -> MatchesEmpty [OptSym]
forall a. Monoid a => [MatchesEmpty a] -> MatchesEmpty a
seqListMatchesEmpty
([MatchesEmpty [OptSym]] -> MatchesEmpty [OptSym])
-> (MatchesEmpty [OptSym] -> MatchesEmpty [[OptSym]])
-> [MatchesEmpty [OptSym]]
-> MatchesEmpty [[OptSym]]
forall a b c. (a -> b) -> (b -> c) -> a -> c
>.> \case
MatchesEmpty [OptSym]
sent -> [[OptSym]] -> MatchesEmpty [[OptSym]]
forall a. a -> MatchesEmpty a
MatchesEmpty ([OptSym] -> [[OptSym]]
subtractEmptyString [OptSym]
sent)
NonEmpty [OptSym]
sent -> [[OptSym]] -> MatchesEmpty [[OptSym]]
forall a. a -> MatchesEmpty a
NonEmpty [[OptSym]
sent]
where
fromOpt :: OptSym -> MatchesEmpty [OptSym]
fromOpt (Optional Sym
x) = [OptSym] -> MatchesEmpty [OptSym]
forall a. a -> MatchesEmpty a
MatchesEmpty [Sym -> OptSym
Optional Sym
x]
fromOpt (NonOptional Sym
x) = [OptSym] -> MatchesEmpty [OptSym]
forall a. a -> MatchesEmpty a
NonEmpty [Sym -> OptSym
NonOptional Sym
x]
subtractEmptyString :: [OptSym] -> [[OptSym]]
subtractEmptyString = ([OptSym] -> Maybe [OptSym]) -> [[OptSym]] -> [[OptSym]]
forall a b. (a -> Maybe b) -> [a] -> [b]
Maybe.mapMaybe [OptSym] -> Maybe [OptSym]
headNonOptional ([[OptSym]] -> [[OptSym]])
-> ([OptSym] -> [[OptSym]]) -> [OptSym] -> [[OptSym]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [OptSym] -> [[OptSym]]
forall a. [a] -> [[a]]
List.tails
headNonOptional :: [OptSym] -> Maybe [OptSym]
headNonOptional (Optional Sym
x : [OptSym]
xs) = [OptSym] -> Maybe [OptSym]
forall a. a -> Maybe a
Just (Sym -> OptSym
NonOptional Sym
x OptSym -> [OptSym] -> [OptSym]
forall a. a -> [a] -> [a]
: [OptSym]
xs)
headNonOptional (NonOptional Sym
_ : [OptSym]
_) = [Char] -> Maybe [OptSym]
forall a. HasCallStack => [Char] -> a
error [Char]
"headNonOptional: unexpected that head is already NonOptional"
headNonOptional [] = Maybe [OptSym]
forall a. Maybe a
Nothing
possiblyEmptyCat :: KnownEmpty -> (Cat, [Rule]) -> MatchesEmpty [OptSentForm]
possiblyEmptyCat :: KnownEmpty -> (Cat, [Rule]) -> MatchesEmpty [[OptSym]]
possiblyEmptyCat KnownEmpty
knownEmpty (Cat
_, [Rule]
rules) =
[MatchesEmpty [[OptSym]]] -> MatchesEmpty [[OptSym]]
forall a. Monoid a => [MatchesEmpty a] -> MatchesEmpty a
choiceListMatchesEmpty ([MatchesEmpty [[OptSym]]] -> MatchesEmpty [[OptSym]])
-> [MatchesEmpty [[OptSym]]] -> MatchesEmpty [[OptSym]]
forall a b. (a -> b) -> a -> b
$ (Rule -> MatchesEmpty [[OptSym]])
-> [Rule] -> [MatchesEmpty [[OptSym]]]
forall a b. (a -> b) -> [a] -> [b]
map (KnownEmpty -> SentForm -> MatchesEmpty [[OptSym]]
possiblyEmptyRule KnownEmpty
knownEmpty (SentForm -> MatchesEmpty [[OptSym]])
-> (Rule -> SentForm) -> Rule -> MatchesEmpty [[OptSym]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rule -> SentForm
forall function. Rul function -> SentForm
rhsRule) [Rule]
rules
possiblyEmptyCats :: [(Cat, [Rule])] -> KnownEmpty -> KnownEmpty
possiblyEmptyCats :: [(Cat, [Rule])] -> KnownEmpty -> KnownEmpty
possiblyEmptyCats [(Cat, [Rule])]
cats KnownEmpty
knownEmpty =
Set Sym -> KnownEmpty
KnownEmpty (Set Sym -> KnownEmpty) -> Set Sym -> KnownEmpty
forall a b. (a -> b) -> a -> b
$
SentForm -> Set Sym
forall a. Ord a => [a] -> Set a
Set.fromList (((Cat, [Rule]) -> Sym) -> [(Cat, [Rule])] -> SentForm
forall a b. (a -> b) -> [a] -> [b]
map (Cat -> Sym
forall a b. a -> Either a b
Left (Cat -> Sym) -> ((Cat, [Rule]) -> Cat) -> (Cat, [Rule]) -> Sym
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cat, [Rule]) -> Cat
forall a b. (a, b) -> a
fst) [(Cat, [Rule])]
newEmptyCats)
Set Sym -> Set Sym -> Set Sym
forall a. Ord a => Set a -> Set a -> Set a
`Set.union` KnownEmpty -> Set Sym
knownEmptySet KnownEmpty
knownEmpty
where
newEmptyCats :: [(Cat, [Rule])]
newEmptyCats = ((Cat, [Rule]) -> Bool) -> [(Cat, [Rule])] -> [(Cat, [Rule])]
forall a. (a -> Bool) -> [a] -> [a]
filter (MatchesEmpty [[OptSym]] -> Bool
forall a. MatchesEmpty a -> Bool
matchesEmpty (MatchesEmpty [[OptSym]] -> Bool)
-> ((Cat, [Rule]) -> MatchesEmpty [[OptSym]])
-> (Cat, [Rule])
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. KnownEmpty -> (Cat, [Rule]) -> MatchesEmpty [[OptSym]]
possiblyEmptyCat KnownEmpty
knownEmpty) [(Cat, [Rule])]
cats
fixPointKnownEmpty :: [(Cat, [Rule])] -> KnownEmpty
fixPointKnownEmpty :: [(Cat, [Rule])] -> KnownEmpty
fixPointKnownEmpty [(Cat, [Rule])]
cats = KnownEmpty -> KnownEmpty
go (Set Sym -> KnownEmpty
KnownEmpty Set Sym
forall a. Set a
Set.empty)
where
step :: KnownEmpty -> KnownEmpty
step = [(Cat, [Rule])] -> KnownEmpty -> KnownEmpty
possiblyEmptyCats [(Cat, [Rule])]
cats
go :: KnownEmpty -> KnownEmpty
go KnownEmpty
x = if KnownEmpty
x KnownEmpty -> KnownEmpty -> Bool
forall a. Eq a => a -> a -> Bool
== KnownEmpty
x' then KnownEmpty
x else KnownEmpty -> KnownEmpty
go KnownEmpty
x'
where x' :: KnownEmpty
x' = KnownEmpty -> KnownEmpty
step KnownEmpty
x
transformEmptyMatches :: KnownEmpty -> SentForm -> [OptSentForm]
transformEmptyMatches :: KnownEmpty -> SentForm -> [[OptSym]]
transformEmptyMatches KnownEmpty
knownEmpty = MatchesEmpty [[OptSym]] -> [[OptSym]]
forall a. MatchesEmpty a -> a
unMatchesEmpty (MatchesEmpty [[OptSym]] -> [[OptSym]])
-> (SentForm -> MatchesEmpty [[OptSym]]) -> SentForm -> [[OptSym]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. KnownEmpty -> SentForm -> MatchesEmpty [[OptSym]]
possiblyEmptyRule KnownEmpty
knownEmpty