packages feed

grammatical-parsers 0.6 → 0.7

raw patch · 36 files changed

+1695/−1186 lines, 36 filesdep ~input-parsersdep ~monoid-subclassesdep ~rank2classesPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: input-parsers, monoid-subclasses, rank2classes

API changes (from Hackage documentation)

- Text.Grampa: LiteralDescription :: s -> FailureDescription s
- Text.Grampa: StaticDescription :: String -> FailureDescription s
- Text.Grampa.ContextFree.Continued: instance Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.Continued.Parser g s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.Continued.Parser g s)
- Text.Grampa.ContextFree.LeftRecursive: BackParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
- Text.Grampa.ContextFree.LeftRecursive: CycleParser :: p g s a -> p g s a -> ResultAppend p g s a -> Dependencies g -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
- Text.Grampa.ContextFree.LeftRecursive: FrontParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
- Text.Grampa.ContextFree.LeftRecursive: [appendResultsArrow] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> ResultAppend p g s a
- Text.Grampa.ContextFree.LeftRecursive: [backParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
- Text.Grampa.ContextFree.LeftRecursive: [cycleParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
- Text.Grampa.ContextFree.LeftRecursive: [dependencies] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> Dependencies g
- Text.Grampa.ContextFree.LeftRecursive: data Fixed p g s a
- Text.Grampa.ContextFree.LeftRecursive: data SeparatedParser p (g :: (Type -> Type) -> Type) s a
- Text.Grampa.ContextFree.LeftRecursive: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s, GHC.Show.Show s, Text.Grampa.Internal.TraceableParsing (p g s), Text.Parser.Input.ParserInput (p g s) GHC.Types.~ s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s, Text.Parser.Input.ConsumedInputParsing (p g s), Text.Parser.Input.ParserInput (p g s) GHC.Types.~ s) => Text.Parser.Input.ConsumedInputParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s, Text.Parser.Input.InputParsing (p g s), Text.Parser.Input.ParserInput (p g s) GHC.Types.~ s) => Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (GHC.Base.Alternative (p g s), Control.Monad.Fail.MonadFail (p g s)) => Control.Monad.Fail.MonadFail (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (GHC.Base.Alternative (p g s), GHC.Base.Monad (p g s)) => GHC.Base.Monad (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (GHC.Base.Alternative (p g s), GHC.Base.Monoid x) => GHC.Base.Monoid (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s x)
- Text.Grampa.ContextFree.LeftRecursive: instance (GHC.Base.Alternative (p g s), GHC.Base.Semigroup x) => GHC.Base.Semigroup (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s x)
- Text.Grampa.ContextFree.LeftRecursive: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s, Text.Parser.Input.InputCharParsing (p g s), Text.Parser.Input.ParserInput (p g s) GHC.Types.~ s) => Text.Parser.Input.InputCharParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Rank2.Apply g, Rank2.Distributive g) => GHC.Base.Monoid (Text.Grampa.ContextFree.LeftRecursive.Union g)
- Text.Grampa.ContextFree.LeftRecursive: instance (Rank2.Apply g, Rank2.Distributive g) => GHC.Base.Semigroup (Text.Grampa.ContextFree.LeftRecursive.Union g)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Grampa.Class.CommittedParsing (p g s), Text.Grampa.Class.CommittedResults (p g s) GHC.Types.~ Text.Grampa.Class.ParseResults s) => Text.Grampa.Class.CommittedParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Grampa.Class.GrammarFunctor (p g s) GHC.Types.~ f s, Text.Grampa.ContextFree.LeftRecursive.LeftRecParsing p g s f) => Text.Grampa.Class.GrammarParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Grampa.Class.GrammarFunctor (p g s) GHC.Types.~ f s, Text.Grampa.ContextFree.LeftRecursive.LeftRecParsing p g s f) => Text.Grampa.Class.MultiParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Parser.Char.CharParsing (p g s), Text.Parser.Input.InputCharParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s), Data.Monoid.Textual.TextualMonoid s, s GHC.Types.~ Text.Parser.Input.ParserInput (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s), GHC.Show.Show s) => Text.Parser.Char.CharParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Parser.Combinators.Parsing (p g s), Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)) => Text.Parser.Combinators.Parsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s), Text.Parser.Deterministic.DeterministicParsing (p g s)) => Text.Parser.Deterministic.DeterministicParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Parser.LookAhead.LookAheadParsing (p g s), Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)) => Text.Parser.LookAhead.LookAheadParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance GHC.Base.Alternative (p g s) => GHC.Base.Alternative (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance GHC.Base.Alternative (p g s) => GHC.Base.Applicative (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance GHC.Base.Functor (p g s) => GHC.Base.Functor (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance GHC.Base.MonadPlus (p g s) => GHC.Base.MonadPlus (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance GHC.Show.Show (Text.Grampa.ContextFree.LeftRecursive.Dependencies g) => GHC.Show.Show (Text.Grampa.ContextFree.LeftRecursive.ParserFlags g)
- Text.Grampa.ContextFree.LeftRecursive: instance GHC.Show.Show (g (Data.Functor.Const.Const GHC.Types.Bool)) => GHC.Show.Show (Text.Grampa.ContextFree.LeftRecursive.Dependencies g)
- Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.Class.AmbiguousParsing (p g s) => Text.Grampa.Class.AmbiguousParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance Witherable.Filterable (p g s) => Witherable.Filterable (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: liftPositive :: p g s a -> Fixed p g s a
- Text.Grampa.ContextFree.LeftRecursive: liftPure :: Alternative (p g s) => p g s a -> Fixed p g s a
- Text.Grampa.ContextFree.LeftRecursive: longest :: Fixed Parser g s a -> Fixed Parser g [(s, g (ResultList g s))] a
- Text.Grampa.ContextFree.LeftRecursive: mapPrimitive :: forall p g s a b. AmbiguityDecidable b => (p g s a -> p g s b) -> Fixed p g s a -> Fixed p g s b
- Text.Grampa.ContextFree.LeftRecursive: parseSeparated :: forall p g rl s. (Apply g, Foldable g, Eq s, FactorialMonoid s, LeftReductive s, TailsParsing (p g s), GrammarConstraint (p g s) g, GrammarFunctor (p g s) ~ rl s, FallibleResults rl, s ~ ParserInput (p g s)) => g (SeparatedParser p g s) -> s -> [(s, g (GrammarFunctor (p g s)))]
- Text.Grampa.ContextFree.LeftRecursive: peg :: Ord s => Fixed Parser g [(s, g (ResultList g s))] a -> Fixed Parser g s a
- Text.Grampa.ContextFree.LeftRecursive: separated :: forall p g s. (Alternative (p g s), Apply g, Distributive g, Traversable g, AmbiguousAlternative (GrammarFunctor (p g s))) => g (Fixed p g s) -> g (SeparatedParser p g s)
- Text.Grampa.ContextFree.LeftRecursive: terminalPEG :: (Monoid s, Ord s) => Fixed Parser g s a -> Fixed Parser g s a
- Text.Grampa.ContextFree.LeftRecursive: type Parser = Fixed Parser
- Text.Grampa.ContextFree.LeftRecursive.Transformer: BackParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: CycleParser :: p g s a -> p g s a -> ResultAppend p g s a -> Dependencies g -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: FrontParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: [appendResultsArrow] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> ResultAppend p g s a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: [backParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: [cycleParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: [dependencies] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> Dependencies g
- Text.Grampa.ContextFree.LeftRecursive.Transformer: class AmbiguityDecidable a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: data SeparatedParser p (g :: (Type -> Type) -> Type) s a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: lift :: (Applicative m, Ord s) => m a -> ParserT m g s a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: liftPositive :: p g s a -> Fixed p g s a
- Text.Grampa.ContextFree.LeftRecursive.Transformer: parseSeparated :: forall p g rl s. (Apply g, Foldable g, Eq s, FactorialMonoid s, LeftReductive s, TailsParsing (p g s), GrammarConstraint (p g s) g, GrammarFunctor (p g s) ~ rl s, FallibleResults rl, s ~ ParserInput (p g s)) => g (SeparatedParser p g s) -> s -> [(s, g (GrammarFunctor (p g s)))]
- Text.Grampa.ContextFree.LeftRecursive.Transformer: separated :: forall p g s. (Alternative (p g s), Apply g, Distributive g, Traversable g, AmbiguousAlternative (GrammarFunctor (p g s))) => g (Fixed p g s) -> g (SeparatedParser p g s)
- Text.Grampa.ContextFree.LeftRecursive.Transformer: tbind :: (Monad m, AmbiguityDecidable b) => ParserT m g s a -> (a -> m b) -> ParserT m g s b
- Text.Grampa.ContextFree.LeftRecursive.Transformer: tmap :: AmbiguityDecidable b => (m a -> m b) -> ParserT m g s a -> ParserT m g s b
- Text.Grampa.ContextFree.LeftRecursive.Transformer: type ParserT m = Fixed (ParserT m)
- Text.Grampa.ContextFree.Parallel: instance Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.Parallel.Parser g s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
- Text.Grampa.ContextFree.SortedMemoizing: instance Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
- Text.Grampa.ContextFree.SortedMemoizing.Transformer: (<<|>) :: DeterministicParsing m => m a -> m a -> m a
- Text.Grampa.ContextFree.SortedMemoizing.Transformer: [resultFailures] :: ResultListT m g s r -> !ParseFailure Pos s
- Text.Grampa.ContextFree.SortedMemoizing.Transformer: [resultSuccesses] :: ResultListT m g s r -> ![ResultsOfLengthT m g s r]
- Text.Grampa.ContextFree.SortedMemoizing.Transformer: infixl 3 <<|>
- Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
- Text.Grampa.PEG.Backtrack: instance Text.Parser.Input.InputParsing (Text.Grampa.PEG.Backtrack.Parser g s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.PEG.Backtrack.Parser g s)
- Text.Grampa.PEG.Packrat: instance (Text.Parser.Input.InputParsing (Text.Grampa.PEG.Packrat.Parser g s), GHC.Base.Monoid s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.PEG.Packrat.Parser g s)
+ Text.Grampa: FailureDescription :: [String] -> [s] -> FailureDescription s
+ Text.Grampa: [literalDescriptions] :: FailureDescription s -> [s]
+ Text.Grampa: [staticDescriptions] :: FailureDescription s -> [String]
+ Text.Grampa: chainLongestRecursive :: (GrammarParsing m, g ~ ParserGrammar m, f ~ GrammarFunctor m, GrammarConstraint m g) => (f a -> g f -> g f) -> m a -> m a -> m a
+ Text.Grampa: chainRecursive :: (GrammarParsing m, g ~ ParserGrammar m, f ~ GrammarFunctor m, GrammarConstraint m g) => (f a -> g f -> g f) -> m a -> m a -> m a
+ Text.Grampa: type CommittedResults m :: Type -> Type;
+ Text.Grampa: type GrammarFunctor m :: Type -> Type;
+ Text.Grampa: type ParserGrammar m :: (Type -> Type) -> Type;
+ Text.Grampa: type ResultFunctor m :: Type -> Type;
+ Text.Grampa.ContextFree.Continued: instance (Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.Continued.Parser g s), Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.Continued.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: EmptyTree :: BinTree a
+ Text.Grampa.ContextFree.Memoizing: Fork :: !BinTree a -> !BinTree a -> BinTree a
+ Text.Grampa.ContextFree.Memoizing: Leaf :: !a -> BinTree a
+ Text.Grampa.ContextFree.Memoizing: Parser :: ([(s, g (ResultList g s))] -> ResultList g s r) -> Parser g s r
+ Text.Grampa.ContextFree.Memoizing: ResultList :: !BinTree (ResultInfo g s r) -> ParseFailure Pos s -> ResultList g s r
+ Text.Grampa.ContextFree.Memoizing: [applyParser] :: Parser g s r -> [(s, g (ResultList g s))] -> ResultList g s r
+ Text.Grampa.ContextFree.Memoizing: data BinTree a
+ Text.Grampa.ContextFree.Memoizing: data ResultList g s r
+ Text.Grampa.ContextFree.Memoizing: instance (Data.Monoid.Null.MonoidNull s, GHC.Classes.Ord s) => Text.Parser.Combinators.Parsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (Data.Monoid.Null.MonoidNull s, GHC.Classes.Ord s) => Text.Parser.Deterministic.DeterministicParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (Data.Monoid.Null.MonoidNull s, GHC.Classes.Ord s) => Text.Parser.LookAhead.LookAheadParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s, GHC.Classes.Ord s) => Text.Grampa.Class.MultiParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s, GHC.Classes.Ord s) => Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (GHC.Base.Monoid x, GHC.Classes.Ord s) => GHC.Base.Monoid (Text.Grampa.ContextFree.Memoizing.Parser g s x)
+ Text.Grampa.ContextFree.Memoizing: instance (GHC.Base.Semigroup x, GHC.Classes.Ord s) => GHC.Base.Semigroup (Text.Grampa.ContextFree.Memoizing.Parser g s x)
+ Text.Grampa.ContextFree.Memoizing: instance (GHC.Classes.Ord s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.GrammarParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (GHC.Classes.Ord s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.TailsParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (GHC.Classes.Ord s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Char.CharParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (GHC.Classes.Ord s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Input.InputCharParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (GHC.Show.Show s, GHC.Show.Show r) => GHC.Show.Show (Text.Grampa.ContextFree.Memoizing.ResultInfo g s r)
+ Text.Grampa.ContextFree.Memoizing: instance (GHC.Show.Show s, GHC.Show.Show r) => GHC.Show.Show (Text.Grampa.ContextFree.Memoizing.ResultList g s r)
+ Text.Grampa.ContextFree.Memoizing: instance (Rank2.Functor g, GHC.Base.Monoid s) => Text.Grampa.Internal.Storable.Storable (Text.Grampa.ContextFree.Memoizing.ResultInfo g s r) (Text.Grampa.Internal.ParserFlags g)
+ Text.Grampa.ContextFree.Memoizing: instance (Rank2.Functor g, GHC.Base.Monoid s) => Text.Grampa.Internal.Storable.Storable [(s, g (Text.Grampa.ContextFree.Memoizing.ResultList g s))] (Text.Grampa.Internal.Dependencies g)
+ Text.Grampa.ContextFree.Memoizing: instance (Rank2.Functor g, GHC.Base.Monoid s, GHC.Classes.Ord s) => Text.Grampa.Internal.Storable.Storable1 (Text.Grampa.ContextFree.Memoizing.ResultList g s) (Text.Grampa.Internal.ParserFlags g)
+ Text.Grampa.ContextFree.Memoizing: instance Data.Foldable.Foldable (Text.Grampa.ContextFree.Memoizing.ResultInfo g s)
+ Text.Grampa.ContextFree.Memoizing: instance Data.Traversable.Traversable (Text.Grampa.ContextFree.Memoizing.ResultInfo g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Base.Functor (Text.Grampa.ContextFree.Memoizing.Parser g i)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Base.Functor (Text.Grampa.ContextFree.Memoizing.ResultInfo g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Base.Functor (Text.Grampa.ContextFree.Memoizing.ResultList g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => Control.Monad.Fail.MonadFail (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => GHC.Base.Alternative (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => GHC.Base.Alternative (Text.Grampa.ContextFree.Memoizing.ResultList g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => GHC.Base.Applicative (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => GHC.Base.Applicative (Text.Grampa.ContextFree.Memoizing.ResultInfo g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => GHC.Base.Applicative (Text.Grampa.ContextFree.Memoizing.ResultList g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => GHC.Base.Monad (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => GHC.Base.MonadPlus (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => GHC.Base.Monoid (Text.Grampa.ContextFree.Memoizing.ResultList g s r)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => GHC.Base.Semigroup (Text.Grampa.ContextFree.Memoizing.ResultList g s r)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Classes.Ord s => Text.Grampa.Internal.AmbiguousAlternative (Text.Grampa.ContextFree.Memoizing.ResultList g s)
+ Text.Grampa.ContextFree.Memoizing: instance GHC.Show.Show s => Data.Functor.Classes.Show1 (Text.Grampa.ContextFree.Memoizing.ResultList g s)
+ Text.Grampa.ContextFree.Memoizing: instance Text.Grampa.Internal.FallibleResults (Text.Grampa.ContextFree.Memoizing.ResultList g)
+ Text.Grampa.ContextFree.Memoizing: instance Text.Grampa.Internal.Storable.Storable1 (Text.Grampa.ContextFree.Memoizing.ResultList g s) GHC.Types.Bool
+ Text.Grampa.ContextFree.Memoizing: instance Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.Memoizing.Parser g s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance Witherable.Filterable (Text.Grampa.ContextFree.Memoizing.Parser g i)
+ Text.Grampa.ContextFree.Memoizing: instance Witherable.Filterable (Text.Grampa.ContextFree.Memoizing.ResultList g s)
+ Text.Grampa.ContextFree.Memoizing: longest :: Parser g s a -> Parser g [(s, g (ResultList g s))] a
+ Text.Grampa.ContextFree.Memoizing: newtype Parser g s r
+ Text.Grampa.ContextFree.Memoizing: peg :: Ord s => Parser g [(s, g (ResultList g s))] a -> Parser g s a
+ Text.Grampa.ContextFree.Memoizing: reparseTails :: Functor g => g (Parser g s) -> [(s, g (ResultList g s))] -> [(s, g (ResultList g s))]
+ Text.Grampa.ContextFree.Memoizing: terminalPEG :: (Monoid s, Ord s) => Parser g s a -> Parser g s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: BackParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: CycleParser :: p g s a -> p g s a -> ResultAppend p g s a -> Dependencies g -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: FrontParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: [appendResultsArrow] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> ResultAppend p g s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: [backParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: [cycleParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: [dependencies] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> Dependencies g
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: autochain :: forall p g s f rl (cb :: Type -> Type). (cb ~ Const (g (Const Bool)), f ~ GrammarFunctor (p g s), f ~ rl s, LeftRecParsing p g s rl, DeterministicParsing (p g s), Apply g, Traversable g, Distributive g, Logistic g) => g (Fixed p g s) -> g (Fixed p g s)
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: data Fixed p g s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: data SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: liftPositive :: p g s a -> Fixed p g s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: liftPure :: Alternative (p g s) => p g s a -> Fixed p g s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: longest :: Fixed Parser g s a -> Fixed Parser g [(s, g (ResultList g s))] a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: mapPrimitive :: forall p g s a b. AmbiguityDecidable b => (p g s a -> p g s b) -> Fixed p g s a -> Fixed p g s b
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: parseSeparated :: forall p g rl s. (Apply g, Foldable g, Eq s, FactorialMonoid s, LeftReductive s, TailsParsing (p g s), GrammarConstraint (p g s) g, GrammarFunctor (p g s) ~ rl s, FallibleResults rl, s ~ ParserInput (p g s)) => g (SeparatedParser p g s) -> s -> [(s, g (GrammarFunctor (p g s)))]
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: peg :: Ord s => Fixed Parser g [(s, g (ResultList g s))] a -> Fixed Parser g s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: separated :: forall p g s. (Alternative (p g s), Apply g, Distributive g, Traversable g, AmbiguousAlternative (GrammarFunctor (p g s))) => g (Fixed p g s) -> g (SeparatedParser p g s)
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: terminalPEG :: (Monoid s, Ord s) => Fixed Parser g s a -> Fixed Parser g s a
+ Text.Grampa.ContextFree.Memoizing.LeftRecursive: type Parser = Fixed Parser
+ Text.Grampa.ContextFree.Parallel: instance (Data.Monoid.Factorial.FactorialMonoid s, Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.Parallel.Parser g s)) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance (Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s), Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: BackParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: CycleParser :: p g s a -> p g s a -> ResultAppend p g s a -> Dependencies g -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: FrontParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: [appendResultsArrow] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> ResultAppend p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: [backParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: [cycleParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: [dependencies] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> Dependencies g
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: autochain :: forall p g s f rl (cb :: Type -> Type). (cb ~ Const (g (Const Bool)), f ~ GrammarFunctor (p g s), f ~ rl s, LeftRecParsing p g s rl, DeterministicParsing (p g s), Apply g, Traversable g, Distributive g, Logistic g) => g (Fixed p g s) -> g (Fixed p g s)
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: data Fixed p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: data SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: liftPositive :: p g s a -> Fixed p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: liftPure :: Alternative (p g s) => p g s a -> Fixed p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: longest :: Fixed Parser g s a -> Fixed Parser g [(s, g (ResultList g s))] a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: mapPrimitive :: forall p g s a b. AmbiguityDecidable b => (p g s a -> p g s b) -> Fixed p g s a -> Fixed p g s b
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: parseSeparated :: forall p g rl s. (Apply g, Foldable g, Eq s, FactorialMonoid s, LeftReductive s, TailsParsing (p g s), GrammarConstraint (p g s) g, GrammarFunctor (p g s) ~ rl s, FallibleResults rl, s ~ ParserInput (p g s)) => g (SeparatedParser p g s) -> s -> [(s, g (GrammarFunctor (p g s)))]
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: peg :: Ord s => Fixed Parser g [(s, g (ResultList g s))] a -> Fixed Parser g s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: separated :: forall p g s. (Alternative (p g s), Apply g, Distributive g, Traversable g, AmbiguousAlternative (GrammarFunctor (p g s))) => g (Fixed p g s) -> g (SeparatedParser p g s)
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: terminalPEG :: (Monoid s, Ord s) => Fixed Parser g s a -> Fixed Parser g s a
+ Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive: type Parser = Fixed Parser
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: ROL :: !Int -> ![(s, g (ResultListT m g s))] -> !NonEmpty a -> ResultsOfLength m g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: ResultsOfLengthT :: ResultsOfLength m g s (m r) -> ResultsOfLengthT m g s r
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: [getResultsOfLength] :: ResultsOfLengthT m g s r -> ResultsOfLength m g s (m r)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: data ResultsOfLength m g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s), Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: newtype ResultsOfLengthT m g s r
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: BackParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: CycleParser :: p g s a -> p g s a -> ResultAppend p g s a -> Dependencies g -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: FrontParser :: p g s a -> SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: [appendResultsArrow] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> ResultAppend p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: [backParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: [cycleParser] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: [dependencies] :: SeparatedParser p (g :: (Type -> Type) -> Type) s a -> Dependencies g
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: autochain :: forall p g s f rl (cb :: Type -> Type). (cb ~ Const (g (Const Bool)), f ~ GrammarFunctor (p g s), f ~ rl s, LeftRecParsing p g s rl, DeterministicParsing (p g s), Apply g, Traversable g, Distributive g, Logistic g) => g (Fixed p g s) -> g (Fixed p g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: class AmbiguityDecidable a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: data SeparatedParser p (g :: (Type -> Type) -> Type) s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: lift :: (Applicative m, Ord s) => m a -> ParserT m g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: liftPositive :: p g s a -> Fixed p g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: parseSeparated :: forall p g rl s. (Apply g, Foldable g, Eq s, FactorialMonoid s, LeftReductive s, TailsParsing (p g s), GrammarConstraint (p g s) g, GrammarFunctor (p g s) ~ rl s, FallibleResults rl, s ~ ParserInput (p g s)) => g (SeparatedParser p g s) -> s -> [(s, g (GrammarFunctor (p g s)))]
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: separated :: forall p g s. (Alternative (p g s), Apply g, Distributive g, Traversable g, AmbiguousAlternative (GrammarFunctor (p g s))) => g (Fixed p g s) -> g (SeparatedParser p g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: tbind :: (Monad m, AmbiguityDecidable b) => ParserT m g s a -> (a -> m b) -> ParserT m g s b
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: tmap :: AmbiguityDecidable b => (m a -> m b) -> ParserT m g s a -> ParserT m g s b
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive: type ParserT m = Fixed (ParserT m)
+ Text.Grampa.PEG.Backtrack: instance (Text.Parser.Input.InputParsing (Text.Grampa.PEG.Backtrack.Parser g s), Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.PEG.Backtrack.Parser g s)
+ Text.Grampa.PEG.Packrat: instance (Text.Parser.Input.InputParsing (Text.Grampa.PEG.Packrat.Parser g s), Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Internal.TraceableParsing (Text.Grampa.PEG.Packrat.Parser g s)
- Text.Grampa: ParseFailure :: pos -> [FailureDescription s] -> [FailureDescription s] -> ParseFailure pos s
+ Text.Grampa: ParseFailure :: pos -> FailureDescription s -> [String] -> ParseFailure pos s
- Text.Grampa: [errorAlternatives] :: ParseFailure pos s -> [FailureDescription s]
+ Text.Grampa: [errorAlternatives] :: ParseFailure pos s -> [String]
- Text.Grampa: [expectedAlternatives] :: ParseFailure pos s -> [FailureDescription s]
+ Text.Grampa: [expectedAlternatives] :: ParseFailure pos s -> FailureDescription s
- Text.Grampa.ContextFree.Continued: NoParse :: ParseFailure Pos s -> Result (g :: (Type -> Type) -> Type) s v
+ Text.Grampa.ContextFree.Continued: NoParse :: {-# UNPACK #-} !ParseFailure Pos s -> Result (g :: (Type -> Type) -> Type) s v
- Text.Grampa.ContextFree.Parallel: ResultList :: !BinTree (ResultInfo s r) -> {-# UNPACK #-} !ParseFailure Pos s -> ResultList s r
+ Text.Grampa.ContextFree.Parallel: ResultList :: !BinTree (ResultInfo s r) -> ParseFailure Pos s -> ResultList s r
- Text.Grampa.ContextFree.SortedMemoizing: ParseFailure :: pos -> [FailureDescription s] -> [FailureDescription s] -> ParseFailure pos s
+ Text.Grampa.ContextFree.SortedMemoizing: ParseFailure :: pos -> FailureDescription s -> [String] -> ParseFailure pos s
- Text.Grampa.ContextFree.SortedMemoizing: ResultList :: ![ResultsOfLength g s r] -> !ParseFailure Pos s -> ResultList g s r
+ Text.Grampa.ContextFree.SortedMemoizing: ResultList :: ![ResultsOfLength g s r] -> ParseFailure Pos s -> ResultList g s r
- Text.Grampa.ContextFree.SortedMemoizing: [errorAlternatives] :: ParseFailure pos s -> [FailureDescription s]
+ Text.Grampa.ContextFree.SortedMemoizing: [errorAlternatives] :: ParseFailure pos s -> [String]
- Text.Grampa.ContextFree.SortedMemoizing: [expectedAlternatives] :: ParseFailure pos s -> [FailureDescription s]
+ Text.Grampa.ContextFree.SortedMemoizing: [expectedAlternatives] :: ParseFailure pos s -> FailureDescription s
- Text.Grampa.ContextFree.SortedMemoizing.Transformer: ResultList :: ![ResultsOfLengthT m g s r] -> !ParseFailure Pos s -> ResultListT m g s r
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: ResultList :: ![ResultsOfLengthT m g s r] -> ParseFailure Pos s -> ResultListT m g s r
- Text.Grampa.PEG.Packrat: NoParse :: ParseFailure Pos s -> Result g s v
+ Text.Grampa.PEG.Packrat: NoParse :: {-# UNPACK #-} !ParseFailure Pos s -> Result g s v

Files

CHANGELOG.md view
@@ -1,3 +1,21 @@+Version 0.7+---------------++* Reorganized the `LeftRecursive` modules and deprecated the old module names+* Re-exposed the `Text.Grampa.ContextFree.Memoizing` module+* Floated the `Rank2.Apply` constraint, which now may be necessary in calling contexts+* Turned `FailureDescription` from sum to product+* Added the `chainRecursive` & `chainLongestRecursive` methods+* Added `autochain`+* Improved performance by making `instance Semigroup ParseFailure` lazier+* Improved performance by shortcutting non-left-recursive grammars+* Improved the output of `TraceableParsing` instances+* Fixed comments+* Incremented dependency bounds+* Factored out several internal utility functions+* Updated code to compile with GHC 9.4.2+* Updated GitHub actions+ Version 0.6 --------------- * Updated code to compile with GHC 9.2.2
README.md view
@@ -17,7 +17,8 @@ import Data.Char (isDigit) import Data.Functor.Classes (Show1, showsPrec1) import Text.Grampa-import Text.Grampa.ContextFree.LeftRecursive (Parser)+import Text.Grampa.ContextFree.Memoizing.LeftRecursive (Parser)+import qualified Rank2 import qualified Rank2.TH ~~~ @@ -26,7 +27,7 @@ like this:  ~~~ {.haskell}-arithmetic :: GrammarBuilder Arithmetic g Parser String+arithmetic :: Rank2.Apply g => GrammarBuilder Arithmetic g Parser String arithmetic Arithmetic{..} = Arithmetic{    sum= product          <|> string "-" *> (negate <$> product)@@ -89,9 +90,9 @@ -- >>> parseComplete grammar "1+2*3" -- Arithmetic{ --   sum=Compose (Right [7]),---   product=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = [StaticDescription "end of input"], errorAlternatives = []})),---   factor=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = [StaticDescription "end of input"], errorAlternatives = []})),---   number=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = [StaticDescription "end of input"], errorAlternatives = []}))}+--   product=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = FailureDescription {staticDescriptions = ["end of input"], literalDescriptions = []}, errorAlternatives = []})),+--   factor=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = FailureDescription {staticDescriptions = ["end of input"], literalDescriptions = []}, errorAlternatives = []})),+--   number=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = FailureDescription {staticDescriptions = ["end of input"], literalDescriptions = []}, errorAlternatives = []}))} -- >>> parsePrefix grammar "1+2*3 apples" -- Arithmetic{ --   sum=Compose (Compose (Right [("+2*3 apples",1),("*3 apples",3),(" apples",7)])),
examples/Arithmetic.hs view
@@ -8,7 +8,7 @@ import Text.Parser.Token (symbol)  import Text.Grampa-import Text.Grampa.ContextFree.LeftRecursive (Parser)+import Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive (Parser) import Utilities (infixJoin)  import qualified Rank2
examples/BooleanTransformations.hs view
@@ -18,7 +18,7 @@                     GrammarBuilder, ParseResults,                     fixGrammar, parseComplete,                     char, identifier, keyword, takeCharsWhile)-import Text.Grampa.ContextFree.LeftRecursive.Transformer (ParserT, lift, tmap)+import Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive (ParserT, lift, tmap) import qualified Boolean import Boolean(Boolean(..)) 
examples/Combined.hs view
@@ -8,9 +8,10 @@ import qualified Data.Bool import Data.Map (Map) import qualified Data.Map as Map+import qualified Rank2 import qualified Rank2.TH import Text.Grampa (TokenParsing, LexicalParsing, GrammarBuilder)-import Text.Grampa.ContextFree.LeftRecursive (Parser)+import Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive (Parser) import qualified Arithmetic import qualified Boolean import qualified Comparisons@@ -119,11 +120,11 @@                            (", conditionalGrammar=" ++ showsPrec prec (conditionalGrammar g)                            (", lambdaGrammar=" ++ showsPrec prec (lambdaGrammar g) ("}" ++ rest)))))) +$(Rank2.TH.deriveAll ''Expression)+ instance TokenParsing (Parser Expression String) instance LexicalParsing (Parser Expression String) -$(Rank2.TH.deriveAll ''Expression)- {- instance Rank2.Functor Expression where    f <$> g = g{expr= f (expr g),@@ -191,7 +192,7 @@                   <*> Rank2.traverse f (lambdaGrammar g) -} -expression :: (LexicalParsing (Parser g String)) => GrammarBuilder Expression g Parser String+expression :: (Rank2.Apply g, LexicalParsing (Parser g String)) => GrammarBuilder Expression g Parser String expression Expression{..} =    let combinedExpr = Arithmetic.expr arithmeticGrammar                       <|> Boolean.expr booleanGrammar
examples/Conditionals.hs view
@@ -8,7 +8,7 @@ import qualified Rank2.TH  import Text.Grampa-import Text.Grampa.ContextFree.LeftRecursive (Parser)+import Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive (Parser)  class ConditionalDomain c e where    ifThenElse :: c -> e -> e -> e@@ -29,10 +29,10 @@                            (", test= " ++ showsPrec prec (test a)                             (", term= " ++ showsPrec prec (term a) ("}" ++ rest))) +$(Rank2.TH.deriveAll ''Conditionals)+ instance TokenParsing (Parser (Conditionals t e) String) instance LexicalParsing (Parser (Conditionals t e) String)--$(Rank2.TH.deriveAll ''Conditionals)  conditionals :: (ConditionalDomain t e, LexicalParsing (Parser g String))              => GrammarBuilder (Conditionals t e) g Parser String
examples/Lambda.hs view
@@ -8,10 +8,11 @@ import Data.Monoid ((<>)) import Text.Parser.Token (symbol, whiteSpace) +import qualified Rank2 import qualified Rank2.TH  import Text.Grampa-import Text.Grampa.ContextFree.LeftRecursive (Parser)+import Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive (Parser)  class LambdaDomain e where    apply :: e -> e -> e@@ -95,7 +96,8 @@  $(Rank2.TH.deriveAll ''Lambda) -lambdaCalculus :: (LexicalParsing (Parser g String), LambdaDomain e) => GrammarBuilder (Lambda e) g Parser String+lambdaCalculus :: (Rank2.Apply g, LexicalParsing (Parser g String), LambdaDomain e) =>+                  GrammarBuilder (Lambda e) g Parser String lambdaCalculus Lambda{..} = Lambda{    expr= abstraction,    abstraction= lambda <$> (symbol "\\" *> varName <* symbol "->") <*> abstraction
examples/Main.hs view
@@ -6,7 +6,7 @@ import Data.Map (Map) import qualified Rank2 import Text.Grampa (TokenParsing, LexicalParsing, GrammarBuilder, ParseResults, fixGrammar, parseComplete)-import Text.Grampa.ContextFree.LeftRecursive (Parser)+import Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive (Parser) import Arithmetic (Arithmetic, arithmetic) import qualified Arithmetic import qualified Boolean
examples/Utilities.hs view
@@ -6,7 +6,7 @@ import Data.Monoid.Textual (TextualMonoid, toString)  import Text.Grampa-import Text.Grampa.ContextFree.LeftRecursive+import Text.Grampa.ContextFree.Memoizing.LeftRecursive import qualified Rank2  parseUnique :: (Ord s, TextualMonoid s, Rank2.Traversable g, Rank2.Distributive g, Rank2.Apply g) =>
grammatical-parsers.cabal view
@@ -1,5 +1,5 @@ name:                grammatical-parsers-version:             0.6+version:             0.7 synopsis:            parsers that combine into grammars description:   /Gram/matical-/pa/rsers, or Grampa for short, is a library of parser types whose values are meant to be assigned@@ -33,26 +33,30 @@                        Text.Grampa.Combinators,                        Text.Grampa.PEG.Backtrack, Text.Grampa.PEG.Packrat,                        Text.Grampa.ContextFree.Continued, Text.Grampa.ContextFree.Parallel,+                       Text.Grampa.ContextFree.Memoizing,+                       Text.Grampa.ContextFree.Memoizing.LeftRecursive,                        Text.Grampa.ContextFree.SortedMemoizing,+                       Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive,                        Text.Grampa.ContextFree.SortedMemoizing.Transformer,+                       Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive,                        Text.Grampa.ContextFree.LeftRecursive,                        Text.Grampa.ContextFree.LeftRecursive.Transformer-  other-modules:       Text.Grampa.Class, Text.Grampa.Internal,+  other-modules:       Text.Grampa.Class,+                       Text.Grampa.Internal, Text.Grampa.Internal.LeftRecursive, Text.Grampa.Internal.Storable,                        Text.Grampa.PEG.Backtrack.Measured,                        Text.Grampa.PEG.Continued, Text.Grampa.PEG.Continued.Measured,-                       Text.Grampa.ContextFree.Memoizing,                        Text.Grampa.ContextFree.Continued.Measured   default-language:    Haskell2010   ghc-options:         -Wall   build-depends:       base >=4.9 && <5,                        containers >= 0.4 && < 0.7,                        transformers >= 0.5 && < 0.6,-                       monoid-subclasses >=1.0 && <1.2,+                       monoid-subclasses >=1.0 && <1.3,                        parsers < 0.13,-                       input-parsers < 0.3,+                       input-parsers < 0.4,                        attoparsec >= 0.13 && < 0.15,                        witherable == 0.4.*,-                       rank2classes >= 1.0.2 && < 1.5+                       rank2classes >= 1.4.6 && < 1.5  executable             arithmetic   hs-source-dirs:      examples@@ -62,7 +66,7 @@   build-depends:       base >=4.9 && <5, containers >= 0.5.7.0 && < 0.7,                        parsers < 0.13,                        rank2classes >= 1.0.2 && < 1.5, grammatical-parsers,-                       monoid-subclasses >=1.0 && <1.2+                       monoid-subclasses  executable             boolean-transformations   hs-source-dirs:      examples@@ -72,14 +76,14 @@   build-depends:       base >=4.9 && <5, containers >= 0.5.7.0 && < 0.7,                        parsers < 0.13,                        rank2classes >= 1.0.2 && < 1.5, grammatical-parsers,-                       monoid-subclasses >=1.0 && <1.2+                       monoid-subclasses  test-suite           quicktests   type:              exitcode-stdio-1.0   hs-source-dirs:    test, examples   x-uses-tf:         true   build-depends:     base >=4.9 && < 5, containers >= 0.5.7.0 && < 0.7,-                     monoid-subclasses < 1.2, parsers < 0.13,+                     monoid-subclasses, parsers < 0.13,                      witherable == 0.4.*,                      rank2classes >= 1.0.2 && < 1.5, grammatical-parsers,                      QuickCheck >= 2 && < 3, checkers >= 0.4.6 && < 0.6,@@ -104,7 +108,7 @@   hs-source-dirs:    test, examples   ghc-options:       -O2 -Wall -rtsopts -main-is Benchmark.main   Build-Depends:     base >=4.9 && < 5, rank2classes >= 1.0.2 && < 1.5, grammatical-parsers,-                     monoid-subclasses >=1.0 && <1.2, parsers < 0.13,+                     monoid-subclasses, parsers < 0.13,                      criterion >= 1.0, deepseq >= 1.1, containers >= 0.5.7.0 && < 0.7, text >= 1.1   main-is:           Benchmark.hs   other-modules:     Main, Arithmetic, Boolean, Combined, Comparisons, Conditionals, Lambda, Utilities
src/Text/Grampa.hs view
@@ -1,6 +1,7 @@ -- | A collection of parsing algorithms with a common interface, operating on grammars represented as records with -- rank-2 field types.-{-# LANGUAGE FlexibleContexts, KindSignatures, OverloadedStrings, RankNTypes, ScopedTypeVariables, TypeFamilies #-}+{-# LANGUAGE FlexibleContexts, KindSignatures, OverloadedStrings, RankNTypes, ScopedTypeVariables,+             TypeFamilies, TypeOperators #-} module Text.Grampa (    -- * Applying parsers    failureDescription, simply,@@ -83,12 +84,12 @@ -- | Given the textual parse input, the parse failure on the input, and the number of lines preceding the failure to -- show, produce a human-readable failure description. failureDescription :: forall s pos. (Ord s, TextualMonoid s, Position pos) => s -> ParseFailure pos s -> Int -> s-failureDescription input (ParseFailure pos expected erroneous) contextLineCount =+failureDescription input (ParseFailure pos (FailureDescription expected inputs) erroneous) contextLineCount =    Position.context input pos contextLineCount    <> mconcat       (intersperse ", but " $ filter (not . null)-       [onNonEmpty ("expected " <>) $ oxfordComma " or " (fromDescription <$> expected),-        oxfordComma " and " (fromDescription <$> erroneous)])+       [onNonEmpty ("expected " <>) $ oxfordComma " or " ((fromString <$> expected) <> (fromLiteral <$> inputs)),+        oxfordComma " and " (fromString <$> erroneous)])    where oxfordComma :: s -> [s] -> s          oxfordComma _ [] = ""          oxfordComma _ [x] = x@@ -98,5 +99,4 @@          onLast _ [] = []          onLast f [x] = [f x]          onLast f (x:xs) = x : onLast f xs-         fromDescription (StaticDescription s) = fromString s-         fromDescription (LiteralDescription s) = "string \"" <> s <> "\""+         fromLiteral s = "string \"" <> s <> "\""
src/Text/Grampa/Class.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE AllowAmbiguousTypes, ConstraintKinds, DefaultSignatures, DeriveDataTypeable, DeriveFunctor,              FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, OverloadedStrings,-             RankNTypes, ScopedTypeVariables, TypeApplications, TypeFamilies, TypeSynonymInstances,+             RankNTypes, ScopedTypeVariables, TypeApplications, TypeFamilies, TypeOperators, TypeSynonymInstances,              UndecidableInstances #-} -- | The core classes supported by all the parsers in this library. module Text.Grampa.Class (MultiParsing(..), GrammarParsing(..),@@ -40,8 +40,8 @@ -- | A 'ParseFailure' contains the offset of the parse failure and the list of things expected at that offset. data ParseFailure pos s =    ParseFailure {failurePosition :: pos,-                 expectedAlternatives :: [FailureDescription s],  -- ^ expected input alternatives-                 errorAlternatives ::    [FailureDescription s]   -- ^ erroneous input descriptions+                 expectedAlternatives :: FailureDescription s,  -- ^ expected input alternatives+                 errorAlternatives ::    [String]               -- ^ erroneous alternatives                 }    deriving (Eq, Functor, Show) @@ -49,26 +49,38 @@ type Pos = Down Int  -- | An expected or erroneous input can be described using 'String' or using the input type-data FailureDescription s = StaticDescription String   -- ^ a readable description of the expected input-                          | LiteralDescription s       -- ^ a literal piece of expected input+data FailureDescription s = FailureDescription {staticDescriptions  :: [String],+                                                literalDescriptions :: [s]}                             deriving (Functor, Eq, Ord, Read, Show)  instance (Ord pos, Ord s) => Semigroup (ParseFailure pos s) where-   ParseFailure pos1 exp1 err1 <> ParseFailure pos2 exp2 err2 = ParseFailure pos' exp' err'-      where (pos', exp', err') | pos1 > pos2 = (pos1, exp1, err1)-                               | pos1 < pos2 = (pos2, exp2, err2)-                               | otherwise = (pos1, merge exp1 exp2, merge err1 err2)-            merge [] xs = xs-            merge xs [] = xs-            merge xs@(x:xs') ys@(y:ys')-               | x < y = x : merge xs' ys-               | x > y = y : merge xs ys'-               | otherwise = x : merge xs' ys'+   f1@(ParseFailure pos1 exp1 err1) <> f2@(ParseFailure pos2 exp2 err2) = ParseFailure pos' exp' err'+      where ParseFailure pos' exp' err'+               | pos1 > pos2 = f1+               | pos1 < pos2 = f2+               | otherwise = ParseFailure pos1 (exp1 <> exp2) (mergeSorted err1 err2) +instance Ord s => Semigroup (FailureDescription s) where+   exp1 <> exp2 =+      FailureDescription+         (mergeSorted (staticDescriptions exp1) (staticDescriptions exp2))+         (mergeSorted (literalDescriptions exp1) (literalDescriptions exp2))++mergeSorted :: Ord a => [a] -> [a] -> [a]+mergeSorted [] xs = xs+mergeSorted xs [] = xs+mergeSorted xs@(x:xs') ys@(y:ys')+   | x < y = x : mergeSorted xs' ys+   | x > y = y : mergeSorted xs ys'+   | otherwise = x : mergeSorted xs' ys'+ instance Ord s => Monoid (ParseFailure Pos s) where-   mempty = ParseFailure (Down maxBound) [] []+   mempty = ParseFailure (Down maxBound) mempty []    mappend = (<>) +instance Ord s => Monoid (FailureDescription s) where+   mempty = FailureDescription mempty mempty+ -- | An 'Ambiguous' parse result, produced by the 'ambiguous' combinator, contains a 'NonEmpty' list of -- alternative results. newtype Ambiguous a = Ambiguous{getAmbiguous :: NonEmpty a} deriving (Data, Eq, Ord, Show, Typeable)@@ -106,7 +118,7 @@ completeParser (Compose (Left failure)) = Compose (Left failure) completeParser (Compose (Right (Compose results))) =    case filter (Null.null . fst) results-   of [] -> Compose (Left $ ParseFailure 0 [StaticDescription "a complete parse"] [])+   of [] -> Compose (Left $ ParseFailure 0 (FailureDescription ["a complete parse"] []) [])       completeResults -> Compose (Right $ snd <$> completeResults)  -- | Choose one of the instances of this class to parse with.@@ -139,6 +151,34 @@    fixGrammar :: (g ~ ParserGrammar m, GrammarConstraint m g, Rank2.Distributive g) => (g m -> g m) -> g m    -- | Mark a parser that relies on primitive recursion to prevent an infinite loop in 'fixGrammar'.    recursive :: m a -> m a+   -- | Convert a left-recursive parser to a non-left-recursive one. For example, you can replace the left-recursive+   -- production+   --+   -- > foo = BinOp <$> foo <*> bar <|> baz+   --+   -- in the field @foo@ of grammar @g@ with+   --+   -- > foo = chainRecursive (\x g-> g{foo = x}) baz (BinOp <$> foo <*> bar)+   --+   -- This method works on individual parsers left-recursive on themselves, not on grammars with mutually+   -- left-recursive productions. Use "Text.Grampa.ContextFree.Memoizing.LeftRecursive" for the latter.+   chainRecursive :: (g ~ ParserGrammar m, f ~ GrammarFunctor m, GrammarConstraint m g)+                  => (f a -> g f -> g f) -- ^ setter for the parsed results of each iteration+                  -> m a -- ^ the non-recursive base case+                  -> m a -- ^ the recursive case to iterate+                  -> m a+   -- | Line 'chainRecursive' but produces only the longest possible parse. The modified example+   --+   -- > foo = chainLongestRecursive (\x g-> g{foo = x}) baz (BinOp <$> foo <*> bar)+   --+   -- would be equivalent to the left-recursive production with biased choice+   --+   -- > foo = BinOp <$> foo <*> bar <<|> baz+   chainLongestRecursive :: (g ~ ParserGrammar m, f ~ GrammarFunctor m, GrammarConstraint m g)+                         => (f a -> g f -> g f) -- ^ setter for the parsed results of each iteration+                         -> m a -- ^ the non-recursive base case+                         -> m a -- ^ the recursive case to iterate+                         -> m a     selfReferring = Rank2.cotraverse nonTerminal id    {-# INLINE selfReferring #-}
src/Text/Grampa/Combinators.hs view
@@ -1,11 +1,11 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies, TypeOperators #-} -- | A collection of useful parsing combinators not found in dependent libraries. module Text.Grampa.Combinators (moptional, concatMany, concatSome, someNonEmpty,                                 flag, count, upto,                                 delimiter, operator, keyword) where -import Control.Applicative(Applicative(..), Alternative(..))-import Data.List.NonEmpty (NonEmpty((:|)), fromList)+import Control.Applicative(Alternative(..))+import Data.List.NonEmpty (NonEmpty((:|))) import Data.Monoid (Monoid, (<>)) import Data.Monoid.Factorial (FactorialMonoid) import Data.Semigroup (Semigroup(sconcat))
src/Text/Grampa/ContextFree/Continued.hs view
@@ -34,12 +34,12 @@ import Text.Grampa.Class (CommittedParsing(..), DeterministicParsing(..),                           InputParsing(..), InputCharParsing(..), MultiParsing(..),                           ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (expected, TraceableParsing(..))+import Text.Grampa.Internal (emptyFailure, erroneous, expected, expectedInput, replaceExpected, TraceableParsing(..))  data Result (g :: (Type -> Type) -> Type) s v =      Parsed{parsedPrefix :: !v,             parsedSuffix :: !s}-   | NoParse (ParseFailure Pos s)+   | NoParse {-# UNPACK #-} !(ParseFailure Pos s)  -- | Parser type for context-free grammars that uses a continuation-passing algorithm, fast for grammars in LL(1) -- class but with potentially exponential performance for longer ambiguous prefixes.@@ -67,7 +67,7 @@    {-# INLINABLE (<*>) #-}  instance (Factorial.FactorialMonoid s, Ord s) => Alternative (Parser g s) where-   empty = Parser (\rest _ failure-> failure $ ParseFailure (fromEnd $ Factorial.length rest) [] [])+   empty = Parser (\rest _ failure-> failure $ emptyFailure $ fromEnd $ Factorial.length rest)    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator@@ -105,8 +105,7 @@ #if MIN_VERSION_base(4,13,0) instance Factorial.FactorialMonoid s => MonadFail (Parser g s) where #endif-   fail msg = Parser (\rest _ failure->-                       failure $ ParseFailure (fromEnd $ Factorial.length rest) [] [StaticDescription msg])+   fail msg = Parser (\rest _ failure-> failure $ erroneous (fromEnd $ Factorial.length rest) msg)  instance (Factorial.FactorialMonoid s, Ord s) => MonadPlus (Parser g s) where    mzero = empty@@ -124,21 +123,17 @@    try (Parser p) = Parser q       where q :: forall x. s -> (a -> s -> (ParseFailure Pos s -> x) -> x) -> (ParseFailure Pos s -> x) -> x             q input success failure = p input success (failure . rewindFailure)-               where rewindFailure ParseFailure{} = ParseFailure (fromEnd $ Factorial.length input) [] []+               where rewindFailure ParseFailure{} = emptyFailure (fromEnd $ Factorial.length input)    (<?>) :: forall a. Parser g s a -> String -> Parser g s a    Parser p <?> msg  = Parser q       where q :: forall x. s -> (a -> s -> (ParseFailure Pos s -> x) -> x) -> (ParseFailure Pos s -> x) -> x-            q input success failure = p input success (failure . replaceFailure)-               where replaceFailure (ParseFailure pos msgs erroneous) =-                        ParseFailure pos (if pos == fromEnd (Factorial.length input) then [StaticDescription msg]-                                          else msgs) erroneous+            q input success failure = p input success (failure . replaceExpected (fromEnd $ Factorial.length input) msg)     eof = Parser p       where p rest success failure                | Null.null rest = success () rest failure                | otherwise = failure (expected (fromEnd $ Factorial.length rest) "end of input")-   unexpected msg = Parser (\t _ failure ->-                             failure $ ParseFailure (fromEnd $ Factorial.length t) [] [StaticDescription msg])+   unexpected msg = Parser (\t _ failure -> failure $ erroneous (fromEnd $ Factorial.length t) msg)    notFollowedBy (Parser p) = Parser q       where q :: forall x. s -> (() -> s -> (ParseFailure Pos s -> x) -> x) -> (ParseFailure Pos s -> x) -> x             q input success failure = p input success' failure'@@ -234,17 +229,18 @@       p :: forall x. s -> (s -> s -> (ParseFailure Pos s -> x) -> x) -> (ParseFailure Pos s -> x) -> x       p s' success failure          | Just suffix <- Cancellative.stripPrefix s s' = success s suffix failure-         | otherwise = failure (ParseFailure (fromEnd $ Factorial.length s') [LiteralDescription s] [])+         | otherwise = failure (expectedInput (fromEnd $ Factorial.length s') s)    {-# INLINABLE string #-} -instance InputParsing (Parser g s)  => TraceableParsing (Parser g s) where+instance (InputParsing (Parser g s), FactorialMonoid s)  => TraceableParsing (Parser g s) where    traceInput :: forall a. (s -> String) -> Parser g s a -> Parser g s a    traceInput description (Parser p) = Parser q       where q :: forall x. s -> (a -> s -> (ParseFailure Pos s -> x) -> x) -> (ParseFailure Pos s -> x) -> x             q rest success failure = traceWith "Parsing " (p rest success' failure')                where traceWith prefix = trace (prefix <> description rest)                      failure' f = traceWith "Failed " (failure f)-                     success' r suffix failure'' = traceWith "Parsed " (success r suffix failure'')+                     success' r suffix failure'' = trace ("Parsed " <> description prefix) (success r suffix failure'')+                        where prefix = Factorial.take (Factorial.length rest - Factorial.length suffix) rest  instance (Ord s, Show s, TextualMonoid s) => InputCharParsing (Parser g s) where    satisfyCharInput predicate = Parser p
src/Text/Grampa/ContextFree/Continued/Measured.hs view
@@ -33,13 +33,13 @@ import Text.Parser.Input.Position (fromEnd) import Text.Grampa.Class (CommittedParsing(..), DeterministicParsing(..),                           InputParsing(..), InputCharParsing(..), ConsumedInputParsing(..),-                          MultiParsing(..), ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (expected, erroneous, TraceableParsing(..))+                          MultiParsing(..), ParseResults, ParseFailure(..), Pos)+import Text.Grampa.Internal (emptyFailure, erroneous, expected, expectedInput, replaceExpected, TraceableParsing(..))  data Result (g :: (Type -> Type) -> Type) s v =      Parsed{parsedPrefix :: !v,             parsedSuffix :: !s}-   | NoParse (ParseFailure Pos s)+   | NoParse {-# UNPACK #-} !(ParseFailure Pos s)  -- | Parser type for context-free grammars that uses a continuation-passing algorithm, fast for grammars in LL(1) -- class but with potentially exponential performance for longer ambiguous prefixes.@@ -67,7 +67,7 @@    {-# INLINABLE (<*>) #-}  instance (Factorial.FactorialMonoid s, Ord s) => Alternative (Parser g s) where-   empty = Parser (\rest _ failure-> failure $ ParseFailure (fromEnd $ Factorial.length rest) [] [])+   empty = Parser (\rest _ failure-> failure $ emptyFailure $ fromEnd $ Factorial.length rest)    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator@@ -120,14 +120,11 @@    try (Parser p) = Parser q       where q :: forall x. s -> (a -> Int -> s -> (ParseFailure Pos s -> x) -> x) -> (ParseFailure Pos s -> x) -> x             q input success failure = p input success (failure . rewindFailure)-               where rewindFailure ParseFailure{} = ParseFailure (fromEnd $ Factorial.length input) [] []+               where rewindFailure ParseFailure{} = emptyFailure (fromEnd $ Factorial.length input)    (<?>) :: forall a. Parser g s a -> String -> Parser g s a    Parser p <?> msg  = Parser q       where q :: forall x. s -> (a -> Int -> s -> (ParseFailure Pos s -> x) -> x) -> (ParseFailure Pos s -> x) -> x-            q input success failure = p input success (failure . replaceFailure)-               where replaceFailure (ParseFailure pos msgs erroneous') =-                        ParseFailure pos (if pos == fromEnd (Factorial.length input) then [StaticDescription msg]-                                          else msgs) erroneous'+            q input success failure = p input success (failure . replaceExpected (fromEnd $ Factorial.length input) msg)    eof = Parser p       where p rest success failure                | Null.null rest = success () 0 rest failure@@ -234,7 +231,7 @@       p :: forall x. s -> (s -> Int -> s -> (ParseFailure Pos s -> x) -> x) -> (ParseFailure Pos s -> x) -> x       p s' success failure          | Just suffix <- Cancellative.stripPrefix s s', !len <- Factorial.length s = success s len suffix failure-         | otherwise = failure (ParseFailure (fromEnd $ Factorial.length s') [LiteralDescription s] [])+         | otherwise = failure (expectedInput (fromEnd $ Factorial.length s') s)    {-# INLINABLE string #-}  instance (Cancellative.LeftReductive s, FactorialMonoid s, Ord s) => ConsumedInputParsing (Parser g s) where@@ -244,14 +241,15 @@             q rest success failure = p rest success' failure                where success' r !len suffix failure' = success (Factorial.take len rest, r) len suffix failure' -instance InputParsing (Parser g s)  => TraceableParsing (Parser g s) where+instance (InputParsing (Parser g s), FactorialMonoid s)  => TraceableParsing (Parser g s) where    traceInput :: forall a. (s -> String) -> Parser g s a -> Parser g s a    traceInput description (Parser p) = Parser q       where q :: forall x. s -> (a -> Int -> s -> (ParseFailure Pos s -> x) -> x) -> (ParseFailure Pos s -> x) -> x             q rest success failure = traceWith "Parsing " (p rest success' failure')                where traceWith prefix = trace (prefix <> description rest)                      failure' f = traceWith "Failed " (failure f)-                     success' r !len suffix failure'' = traceWith "Parsed " (success r len suffix failure'')+                     success' r !len suffix failure'' =+                        trace ("Parsed " <> description (Factorial.take len rest)) (success r len suffix failure'')  instance (Ord s, Show s, TextualMonoid s) => InputCharParsing (Parser g s) where    satisfyCharInput predicate = Parser p
src/Text/Grampa/ContextFree/LeftRecursive.hs view
@@ -1,881 +1,7 @@-{-# LANGUAGE ConstraintKinds, CPP, FlexibleContexts, FlexibleInstances, GADTs, GeneralizedNewtypeDeriving, InstanceSigs,-             RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeFamilies, TypeOperators,-             UndecidableInstances #-}-{-# OPTIONS -fno-full-laziness #-} -- | A context-free memoizing parser that can handle left-recursive grammars.-module Text.Grampa.ContextFree.LeftRecursive (Fixed, Parser, SeparatedParser(..),-                                              longest, peg, terminalPEG,-                                              liftPositive, liftPure, mapPrimitive,-                                              parseSeparated, separated)+module Text.Grampa.ContextFree.LeftRecursive+       {-# DEPRECATED "Use Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive instead" #-}+       (module Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive) where -import Control.Applicative-import Control.Monad (Monad(..), MonadPlus(..), void)-#if MIN_VERSION_base(4,13,0)-import Control.Monad (MonadFail(fail))-#endif-import Control.Monad.Trans.State.Lazy (State, evalState, get, put)--import Data.Functor.Compose (Compose(..))-import Data.Kind (Type)-import Data.Maybe (isJust)--import Data.Semigroup (Semigroup(..))-import Data.Monoid (Monoid(mempty), All(..), Any(..))-import Data.Monoid.Null (MonoidNull(null))-import Data.Monoid.Factorial (FactorialMonoid)-import Data.Monoid.Textual (TextualMonoid)-import Data.Semigroup.Cancellative (LeftReductive)-import qualified Data.Monoid.Factorial as Factorial-import qualified Data.Monoid.Textual as Textual-import Data.String (fromString)-import Data.Type.Equality ((:~:)(Refl))-import Witherable (Filterable(mapMaybe))--import qualified Text.Parser.Char as Char-import Text.Parser.Char (CharParsing)-import Text.Parser.Combinators (Parsing(..))-import Text.Parser.LookAhead (LookAheadParsing(..))--import qualified Rank2-import Text.Grampa.Class (GrammarParsing(..), InputParsing(..), InputCharParsing(..), MultiParsing(..),-                          AmbiguousParsing(..), CommittedParsing(..), ConsumedInputParsing(..),-                          DeterministicParsing(..),-                          TailsParsing(parseTails, parseAllTails), ParseResults, ParseFailure(..), Pos)-import Text.Grampa.Internal (ResultList(..), FallibleResults(..),-                             AmbiguousAlternative(ambiguousOr), AmbiguityDecidable(..), AmbiguityWitness(..),-                             TraceableParsing(..))-import qualified Text.Grampa.ContextFree.SortedMemoizing as Memoizing-import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack--import Prelude hiding (cycle, null, span, take, takeWhile)---- | A parser for left-recursive grammars-type Parser = Fixed Memoizing.Parser--type ResultAppend p (g :: (Type -> Type) -> Type) s =-   GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s)---- | A transformer that adds left-recursive powers to a memoizing parser @p@ over grammar @g@-data Fixed p g s a =-   -- | a fully general parser-   Parser {-      complete, direct, direct0, direct1, indirect :: p g s a,-      isAmbiguous :: Maybe (AmbiguityWitness a),-      cyclicDescendants :: Rank2.Apply g => g (Const (ParserFlags g)) -> ParserFlags g}-   -- | a parser that doesn't start with a 'nonTerminal'-   | DirectParser {-      complete, direct0, direct1 :: p g s a}-   -- | a parser that doesn't start with a 'nonTerminal' and always consumes some input-   | PositiveDirectParser {-      complete :: p g s a}---- | A type of parsers analyzed for their left-recursion class-data SeparatedParser p (g :: (Type -> Type) -> Type) s a =-   -- | a parser that doesn't start with any 'nonTerminal' so it can run first-   FrontParser (p g s a)-   -- | a left-recursive parser that may add to the set of parse results every time it's run-   | CycleParser {-        cycleParser  :: p g s a,-        backParser   :: p g s a,-        appendResultsArrow :: ResultAppend p g s a,-        dependencies :: Dependencies g}-   -- | a parser that depends on other non-terminals but is not left-recursive-   | BackParser {-        backParser :: p g s a}--data ParserFlags g = ParserFlags {-   nullable :: Bool,-   dependsOn :: Dependencies g}--deriving instance Show (Dependencies g) => Show (ParserFlags g)--data Dependencies g = DynamicDependencies-                    | StaticDependencies (g (Const Bool))--deriving instance Show (g (Const Bool)) => Show (Dependencies g)--data ParserFunctor p g s a = ParserResultsFunctor {parserResults :: GrammarFunctor (p g s) a}-                           | ParserFlagsFunctor {parserFlags :: ParserFlags g}--newtype Union (g :: (Type -> Type) -> Type) = Union{getUnion :: g (Const Bool)}----instance Rank2.Applicative g => Monoid (Union g) where---   mempty = Union (Rank2.pure $ Const False)--instance (Rank2.Apply g, Rank2.Distributive g) => Semigroup (Union g) where-   Union g1 <> Union g2 = Union (Rank2.liftA2 union g1 g2)--instance (Rank2.Apply g, Rank2.Distributive g) => Monoid (Union g) where-   mempty = Union (Rank2.cotraverse (Const . getConst) (Const False))-   mappend = (<>)--mapPrimitive :: forall p g s a b. AmbiguityDecidable b => (p g s a -> p g s b) -> Fixed p g s a -> Fixed p g s b-mapPrimitive f p@PositiveDirectParser{} = PositiveDirectParser{complete= f (complete p)}-mapPrimitive f p@DirectParser{} = DirectParser{complete= f (complete p),-                                               direct0= f (direct0 p),-                                               direct1= f (direct1 p)}-mapPrimitive f p@Parser{} = Parser{complete= f (complete p),-                                   isAmbiguous= ambiguityWitness @b,-                                   cyclicDescendants= cyclicDescendants p,-                                   indirect= f (indirect p),-                                   direct= f (direct p),-                                   direct0= f (direct0 p),-                                   direct1= f (direct1 p)}--general, general' :: Alternative (p g s) => Fixed p g s a -> Fixed p g s a--general p = Parser{-   complete= complete p,-   direct = direct p',-   direct0= direct0 p',-   direct1= direct1 p',-   indirect= indirect p',-   isAmbiguous= case p-                of Parser{isAmbiguous= a} -> a-                   _ -> Nothing,-   cyclicDescendants= cyclicDescendants p'}-   where p' = general' p--general' p@PositiveDirectParser{} = Parser{-   complete= complete p,-   direct = complete p,-   direct0= empty,-   direct1= complete p,-   indirect= empty,-   isAmbiguous= Nothing,-   cyclicDescendants= \cd-> ParserFlags False (StaticDependencies $ const (Const False) Rank2.<$> cd)}-general' p@DirectParser{} = Parser{-   complete= complete p,-   direct = complete p,-   direct0= direct0 p,-   direct1= direct1 p,-   indirect= empty,-   isAmbiguous= Nothing,-   cyclicDescendants= \cd-> ParserFlags True (StaticDependencies $ const (Const False) Rank2.<$> cd)}-general' p@Parser{} = p--type LeftRecParsing p g s f = (Eq s, LeftReductive s, FactorialMonoid s, Alternative (p g s),-                               TailsParsing (p g s), GrammarConstraint (p g s) g, ParserGrammar (p g s) ~ g,-                               Functor (ResultFunctor (p g s)), s ~ ParserInput (p g s), FallibleResults f,-                               AmbiguousAlternative (GrammarFunctor (p g s)))---- | Parser transformer for left-recursive grammars.------ @--- 'parseComplete' :: ("Rank2".'Rank2.Apply' g, "Rank2".'Rank2.Traversable' g, 'FactorialMonoid' s) =>---                  g (LeftRecursive.'Parser' g s) -> s -> g ('Compose' ('ParseResults' s) [])--- @-instance (GrammarFunctor (p g s) ~ f s, LeftRecParsing p g s f) => MultiParsing (Fixed p g s) where-   type GrammarConstraint (Fixed p g s) g' = (GrammarConstraint (p g s) g', g ~ g',-                                              Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g)-   type ResultFunctor (Fixed p g s) = ResultFunctor (p g s)-   -- parsePrefix :: (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g, Eq s, FactorialMonoid s) =>-   --                g (Fixed p g s) -> s -> g (Compose (ResultFunctor (p g s)) ((,) s))-   parsePrefix g input = Rank2.fmap (Compose . parsingResult @(p g s) input)-                                    (snd $ head $ parseRecursive g input)-   {-# INLINE parsePrefix #-}-   -- parseComplete :: (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g, Eq s, FactorialMonoid s) =>-   --                  g (Fixed p g s) -> s -> g (ResultFunctor (p g s))-   parseComplete g = \input-> let close :: g (p g s)-                                  close = Rank2.fmap (<* eof) selfReferring-                              in Rank2.fmap ((snd <$>) . parsingResult @(p g s) input)-                                            (snd $ head $ parseAllTails close $ parseSeparated g' input)-      where g' = separated g-   {-# INLINE parseComplete #-}---- | Parser transformer for left-recursive grammars.-instance (GrammarFunctor (p g s) ~ f s, LeftRecParsing p g s f) => GrammarParsing (Fixed p g s) where-   type ParserGrammar (Fixed p g s) = g-   type GrammarFunctor (Fixed p g s) = ParserFunctor p g s-   parsingResult :: s -> ParserFunctor p g s a -> ResultFunctor (p g s) (s, a)-   parsingResult s = parsingResult @(p g s) s . parserResults-   nonTerminal :: (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g) =>-                  (g (ParserFunctor p g s) -> ParserFunctor p g s a) -> Fixed p g s a-   nonTerminal f = Parser{-      complete= ind,-      direct= empty,-      direct0= empty,-      direct1= empty,-      indirect= ind,-      isAmbiguous= Nothing,-      cyclicDescendants= parserFlags . f . Rank2.fmap (ParserFlagsFunctor . getConst) . addSelf}-      where ind = nonTerminal (parserResults . f . Rank2.fmap ParserResultsFunctor)-            addSelf g = Rank2.liftA2 adjust bits g-            adjust :: forall b. Const (g (Const Bool)) b -> Const (ParserFlags g) b -> Const (ParserFlags g) b-            adjust (Const bit) (Const (ParserFlags n (StaticDependencies d))) =-               Const ParserFlags{-                  nullable= n, -                  dependsOn= StaticDependencies (Rank2.liftA2 union bit d)}-            adjust _ flags@(Const (ParserFlags _ DynamicDependencies)) = flags-   {-# INLINE nonTerminal #-}-   recursive = general--bits :: forall (g :: (Type -> Type) -> Type). (Rank2.Distributive g, Rank2.Traversable g) => g (Const (g (Const Bool)))-bits = start `seq` Rank2.fmap oneBit start-   where start = evalState (Rank2.traverse next (Rank2.distributeJoin Nothing)) 0-         oneBit :: Const Int a -> Const (g (Const Bool)) a-         next :: f a -> State Int (Const Int a)-         oneBit (Const i) = Const (Rank2.fmap (Const . (i ==) . getConst) start)-         next _ = do {i <- get; let {i' = succ i}; seq i' (put i'); return (Const i)}--instance Functor (p g s) => Functor (Fixed p g s) where-   fmap f (PositiveDirectParser p) = PositiveDirectParser (fmap f p)-   fmap f p@DirectParser{} = DirectParser{-      complete= fmap f (complete p),-      direct0= fmap f (direct0 p),-      direct1= fmap f (direct1 p)}-   fmap f p@Parser{} = p{-      complete= fmap f (complete p),-      direct= fmap f (direct p),-      direct0= fmap f (direct0 p),-      direct1= fmap f (direct1 p),-      indirect= fmap f (indirect p),-      isAmbiguous= Nothing}-   {-# INLINABLE fmap #-}--instance Alternative (p g s) => Applicative (Fixed p g s) where-   pure a = DirectParser{complete= pure a,-                         direct0= pure a,-                         direct1= empty}-   p@PositiveDirectParser{} <*> q = PositiveDirectParser{-      complete= complete p <*> complete q}-   p@DirectParser{} <*> q@PositiveDirectParser{} = PositiveDirectParser{-      complete= complete p <*> complete q}-   p@DirectParser{} <*> q@DirectParser{} = DirectParser{-      complete= complete p <*> complete q,-      direct0= direct0 p <*> direct0 q,-      direct1= direct0 p <*> direct1 q <|> direct1 p <*> complete q}-   p <*> q@Parser{} = Parser{-      complete= complete p' <*> complete q,-      direct= direct0 p' <*> direct q <|> direct1 p' <*> complete q,-      direct0= direct0 p' <*> direct0 q,-      direct1= direct0 p' <*> direct1 q <|> direct1 p' <*> complete q,-      indirect= direct0 p' <*> indirect q <|> indirect p' <*> complete q,-      isAmbiguous= Nothing,-      cyclicDescendants= \deps-> let-           pcd@(ParserFlags pn pd) = cyclicDescendants p' deps-           ParserFlags qn qd = cyclicDescendants q deps-        in if pn-           then ParserFlags qn (depUnion pd qd)-           else pcd}-      where p'@Parser{} = general' p-   p <*> q = Parser{-      complete= complete p' <*> complete q',-      direct= direct p' <*> complete q',-      direct0= direct0 p' <*> direct0 q',-      direct1= direct0 p' <*> direct1 q' <|> direct1 p' <*> complete q',-      indirect= indirect p' <*> complete q',-      isAmbiguous= Nothing,-      cyclicDescendants= \deps-> let-           pcd@(ParserFlags pn pd) = cyclicDescendants p' deps-           ParserFlags qn qd = cyclicDescendants q' deps-        in if pn-           then ParserFlags qn (depUnion pd qd)-           else pcd}-      where p'@Parser{} = general' p-            q'@Parser{} = general' q-   {-# INLINABLE pure #-}-   {-# INLINABLE (<*>) #-}--instance Alternative (p g s) => Alternative (Fixed p g s) where-   empty = PositiveDirectParser{complete= empty}-   p@PositiveDirectParser{} <|> q@PositiveDirectParser{} = PositiveDirectParser{complete= complete p <|> complete q}-   p@PositiveDirectParser{} <|> q@DirectParser{} = DirectParser{-      complete= complete p <|> complete q,-      direct0 = direct0 q,-      direct1= complete p <|> direct1 q}-   p@DirectParser{} <|> q@PositiveDirectParser{} = DirectParser{-      complete= complete p <|> complete q,-      direct0 = direct0 p,-      direct1= direct1 p <|> complete q}-   p@DirectParser{} <|> q@DirectParser{} = DirectParser{-      complete= complete p <|> complete q,-      direct0 = direct0 p <|> direct0 q,-      direct1= direct1 p <|> direct1 q}-   p <|> q = Parser{complete= complete p' <|> complete q',-                    direct= direct p' <|> direct q',-                    direct0= direct0 p' <|> direct0 q',-                    direct1= direct1 p' <|> direct1 q',-                    indirect= indirect p' <|> indirect q',-                    isAmbiguous= Nothing,-                    cyclicDescendants= \deps-> let-                         ParserFlags pn pd = cyclicDescendants p' deps-                         ParserFlags qn qd = cyclicDescendants q' deps-                      in ParserFlags (pn || qn) (depUnion pd qd)}-      where p'@Parser{} = general p-            q'@Parser{} = general q-   many (PositiveDirectParser p) = DirectParser{-      complete= many p,-      direct0= pure [],-      direct1= some p}-   many p@DirectParser{} = DirectParser{-      complete= many (complete p),-      direct0= pure [] <|> (:[]) <$> direct0 p,-      direct1= (:) <$> direct1 p <*> many (complete p)}-   many p@Parser{} = Parser{-      complete= mcp,-      direct= d0 <|> d1,-      direct0= d0,-      direct1= d1,-      indirect= (:) <$> indirect p <*> mcp,-      isAmbiguous= Nothing,-      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}-      where d0 = pure [] <|> (:[]) <$> direct0 p-            d1 = (:) <$> direct1 p <*> mcp-            mcp = many (complete p)-   some (PositiveDirectParser p) = PositiveDirectParser{complete= some p}-   some p@DirectParser{} = DirectParser{-      complete= some (complete p),-      direct0= (:[]) <$> direct0 p,-      direct1= (:) <$> direct1 p <*> many (complete p)}-   some p@Parser{} = Parser{-      complete= some (complete p),-      direct= d0 <|> d1,-      direct0= d0,-      direct1= d1,-      indirect= (:) <$> indirect p <*> many (complete p),-      isAmbiguous= Nothing,-      cyclicDescendants= cyclicDescendants p}-      where d0 = (:[]) <$> direct0 p-            d1= (:) <$> direct1 p <*> many (complete p)-   {-# INLINABLE (<|>) #-}-   {-# INLINABLE many #-}-   {-# INLINABLE some #-}--instance Filterable (p g s) => Filterable (Fixed p g s) where-   mapMaybe f (PositiveDirectParser p) = PositiveDirectParser (mapMaybe f p)-   mapMaybe f p@DirectParser{} = DirectParser{-      complete= mapMaybe f (complete p),-      direct0= mapMaybe f (direct0 p),-      direct1= mapMaybe f (direct1 p)}-   mapMaybe f p@Parser{} = p{-      complete= mapMaybe f (complete p),-      direct= mapMaybe f (direct p),-      direct0= mapMaybe f (direct0 p),-      direct1= mapMaybe f (direct1 p),-      indirect= mapMaybe f (indirect p),-      isAmbiguous= Nothing}-   {-# INLINABLE mapMaybe #-}--union :: Const Bool x -> Const Bool x -> Const Bool x-union (Const False) d = d-union (Const True) _ = Const True--depUnion :: Rank2.Apply g => Dependencies g -> Dependencies g -> Dependencies g-depUnion (StaticDependencies d1) (StaticDependencies d2) = StaticDependencies (Rank2.liftA2 union d1 d2)-depUnion _ _ = DynamicDependencies--instance (Alternative (p g s), Monad (p g s)) => Monad (Fixed p g s) where-   return = pure-   (>>) = (*>)-   PositiveDirectParser p >>= cont = PositiveDirectParser (p >>= complete . cont)-   p@DirectParser{} >>= cont = Parser{-      complete= complete p >>= complete . cont,-      direct= d0 <|> d1,-      direct0= d0,-      direct1= d1,-      indirect= direct0 p >>= indirect . general' . cont,-      isAmbiguous= Nothing,-      cyclicDescendants= const (ParserFlags True DynamicDependencies)}-      where d0 = direct0 p >>= direct0 . general' . cont-            d1 = (direct0 p >>= direct1 . general' . cont) <|> (direct1 p >>= complete . cont)-   p >>= cont = Parser{-      complete= complete p >>= complete . cont,-      direct= d0 <|> d1,-      direct0= d0,-      direct1= d1,-      indirect= (indirect p >>= complete . cont) <|> (direct0 p >>= indirect . general' . cont),-      isAmbiguous= Nothing,-      cyclicDescendants= \cd->-         let pcd@(ParserFlags pn _) = cyclicDescendants p' cd-         in if pn-            then ParserFlags True DynamicDependencies-            else pcd}-      where d0 = direct0 p >>= direct0 . general' . cont-            d1 = (direct0 p >>= direct1 . general' . cont) <|> (direct1 p >>= complete . cont)-            p'@Parser{} = general' p--#if MIN_VERSION_base(4,13,0)-instance (Alternative (p g s), MonadFail (p g s)) => MonadFail (Fixed p g s) where-#endif-   fail msg = PositiveDirectParser{complete= fail msg}--instance MonadPlus (p g s) => MonadPlus (Fixed p g s) where-   mzero = empty-   mplus = (<|>)--instance (Alternative (p g s), Semigroup x) => Semigroup (Fixed p g s x) where-   (<>) = liftA2 (<>)--instance (Alternative (p g s), Monoid x) => Monoid (Fixed p g s x) where-   mempty = pure mempty-   mappend = (<>)--primitive :: p g s a -> p g s a -> p g s a -> Fixed p g s a-primitive d0 d1 d = DirectParser{complete= d,-                                 direct0= d0,-                                 direct1= d1}-{-# INLINE primitive #-}---- | Lifts a primitive positive parser (/i.e./, one that always consumes some input) into a left-recursive one-liftPositive :: p g s a -> Fixed p g s a-liftPositive p = PositiveDirectParser{complete= p}-{-# INLINE liftPositive #-}---- | Lifts a primitive pure parser (/i.e./, one that consumes no input) into a left-recursive one-liftPure :: Alternative (p g s) => p g s a -> Fixed p g s a-liftPure p = DirectParser{complete= p,-                          direct0= p,-                          direct1= empty}-{-# INLINE liftPure #-}--instance (Parsing (p g s), InputParsing (Fixed p g s)) => Parsing (Fixed p g s) where-   eof = primitive eof empty eof-   try (PositiveDirectParser p) = PositiveDirectParser (try p)-   try p@DirectParser{} = DirectParser{-      complete= try (complete p),-      direct0= try (direct0 p),-      direct1= try (direct1 p)}-   try p@Parser{} = p{-      complete= try (complete p),-      direct= try (direct p),-      direct0= try (direct0 p),-      direct1= try (direct1 p),-      indirect= try (indirect p)}-   PositiveDirectParser p <?> msg = PositiveDirectParser (p <?> msg)-   p@DirectParser{} <?> msg = DirectParser{-      complete= complete p <?> msg,-      direct0= direct0 p <?> msg,-      direct1= direct1 p <?> msg}-   p@Parser{} <?> msg = p{-      complete= complete p <?> msg,-      direct= direct p <?> msg,-      direct0= direct0 p <?> msg,-      direct1= direct1 p <?> msg,-      indirect= indirect p <?> msg}-   notFollowedBy p@PositiveDirectParser{} = DirectParser{-      complete= notFollowedBy (complete p),-      direct0= notFollowedBy (complete p),-      direct1= empty}-   notFollowedBy p@DirectParser{} = DirectParser{-      complete= notFollowedBy (complete p),-      direct0= notFollowedBy (complete p),-      direct1= empty}-   notFollowedBy p@Parser{} = Parser{-      complete= notFollowedBy (complete p),-      direct= notFollowedBy (direct p),-      direct0= notFollowedBy (direct p),-      direct1= empty,-      isAmbiguous= Nothing,-      indirect= notFollowedBy (indirect p),-      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}-   unexpected msg = liftPositive (unexpected msg)--instance (InputParsing (Fixed p g s), DeterministicParsing (p g s)) => DeterministicParsing (Fixed p g s) where-   p@DirectParser{} <<|> q@PositiveDirectParser{} = DirectParser{-      complete= complete p <<|> complete q,-      direct0 = direct0 p,-      direct1= direct1 p <<|> complete q}-   p@DirectParser{} <<|> q@DirectParser{} = DirectParser{-      complete= complete p <<|> complete q,-      direct0 = direct0 p <<|> direct0 q,-      direct1= direct1 p <<|> direct1 q}-   p <<|> q = Parser{complete= complete p' <<|> complete q',-                     direct= direct p' <<|> notFollowedBy (void $ complete p') *> direct q',-                     direct0= direct0 p' <<|> notFollowedBy (void $ complete p') *> direct0 q',-                     direct1= direct1 p' <<|> notFollowedBy (void $ complete p') *> direct1 q',-                     indirect= indirect p' <<|> notFollowedBy (void $ complete p') *> indirect q',-                     isAmbiguous= Nothing,-                     cyclicDescendants= \deps-> let-                           ParserFlags pn pd = cyclicDescendants p' deps-                           ParserFlags qn qd = cyclicDescendants q' deps-                        in ParserFlags (pn || qn) (depUnion pd qd)}-      where p'@Parser{} = general p-            q'@Parser{} = general q-   takeSome p = (:) <$> p <*> takeMany p-   takeMany (PositiveDirectParser p) = DirectParser{-      complete = takeMany p,-      direct0= [] <$ notFollowedBy (void p),-      direct1= takeSome p}-   takeMany p@DirectParser{} = DirectParser{-      complete = takeMany (complete p),-      direct0= (:[]) <$> direct0 p <<|> [] <$ notFollowedBy (void $ complete p),-      direct1= (:) <$> direct1 p <*> takeMany (complete p)}-   takeMany p@Parser{} = Parser{-      complete= mcp,-      direct= d1 <<|> d0,-      direct0= d0,-      direct1= d1,-      indirect= (:) <$> indirect p <*> mcp,-      isAmbiguous= Nothing,-      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}-      where d0 = (:[]) <$> direct0 p <<|> [] <$ notFollowedBy (void $ direct p)-            d1 = (:) <$> direct1 p <*> mcp-            mcp = takeMany (complete p)-   skipAll (PositiveDirectParser p) = DirectParser{-      complete = skipAll p,-      direct0= () <$ notFollowedBy (void p),-      direct1= p *> skipAll p}-   skipAll p@DirectParser{} = DirectParser{-      complete = skipAll (complete p),-      direct0= void (direct0 p) <<|> notFollowedBy (void $ complete p),-      direct1= direct1 p *> skipAll (complete p)}-   skipAll p@Parser{} = Parser{-      complete= mcp,-      direct= d1 <<|> d0,-      direct0= d0,-      direct1= d1,-      indirect= indirect p *> mcp,-      isAmbiguous= Nothing,-      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}-      where d0 = () <$ direct0 p <<|> notFollowedBy (void $ direct p)-            d1 = direct1 p *> mcp-            mcp = skipAll (complete p)--instance (CommittedParsing (p g s), CommittedResults (p g s) ~ ParseResults s) => CommittedParsing (Fixed p g s) where-   type CommittedResults (Fixed p g s) = ParseResults s-   commit (PositiveDirectParser p) = PositiveDirectParser (commit p)-   commit p@DirectParser{} = DirectParser{-      complete = commit (complete p),-      direct0= commit (direct0 p),-      direct1= commit (direct1 p)}-   commit p@Parser{} = Parser{-      complete= commit (complete p),-      direct= commit (direct p),-      direct0= commit (direct0 p),-      direct1= commit (direct1 p),-      indirect= commit (indirect p),-      isAmbiguous= Nothing,-      cyclicDescendants= cyclicDescendants p}-   admit :: Fixed p g s (CommittedResults (Fixed p g s) a) -> Fixed p g s a-   admit (PositiveDirectParser p) = PositiveDirectParser (admit p)-   admit p@DirectParser{} = DirectParser{-      complete = admit (complete p),-      direct0= admit (direct0 p),-      direct1= admit (direct1 p)}-   admit p@Parser{} = Parser{-      complete= admit (complete p),-      direct= admit (direct p),-      direct0= admit (direct0 p),-      direct1= admit (direct1 p),-      indirect= admit (indirect p),-      isAmbiguous= Nothing,-      cyclicDescendants= cyclicDescendants p}--instance (LookAheadParsing (p g s), InputParsing (Fixed p g s)) => LookAheadParsing (Fixed p g s) where-   lookAhead p@PositiveDirectParser{} = DirectParser{-      complete= lookAhead (complete p),-      direct0= lookAhead (complete p),-      direct1= empty}-   lookAhead p@DirectParser{} = DirectParser{-      complete= lookAhead (complete p),-      direct0= lookAhead (complete p),-      direct1= empty}-   lookAhead p@Parser{} = Parser{-      complete= lookAhead (complete p),-      direct= lookAhead (direct p),-      direct0= lookAhead (direct p),-      direct1= empty,-      isAmbiguous= isAmbiguous p,-      indirect= lookAhead (indirect p),-      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}--instance (LeftReductive s, FactorialMonoid s, InputParsing (p g s), ParserInput (p g s) ~ s) =>-         InputParsing (Fixed p g s) where-   type ParserInput (Fixed p g s) = s-   getInput = primitive getInput empty getInput-   anyToken = liftPositive anyToken-   satisfy predicate = liftPositive (satisfy predicate)-   notSatisfy predicate = primitive (notSatisfy predicate) empty (notSatisfy predicate)-   scan s0 f = primitive (mempty <$ notSatisfy test) (lookAhead (satisfy test) *> p) p-      where p = scan s0 f-            test = isJust . f s0-   string s-      | null s = primitive (string s) empty (string s)-      | otherwise = liftPositive (string s)-   take 0 = mempty-   take n = liftPositive (take n)-   takeWhile predicate = primitive (mempty <$ notSatisfy predicate)-                                               (takeWhile1 predicate) (takeWhile predicate)-   takeWhile1 predicate = liftPositive (takeWhile1 predicate)--   {-# INLINABLE string #-}--instance (LeftReductive s, FactorialMonoid s, Show s, TraceableParsing (p g s), ParserInput (p g s) ~ s) =>-         TraceableParsing (Fixed p g s) where-   traceInput description p@PositiveDirectParser{} = p{-      complete= traceInput (\s-> "direct+ " <> description s) (complete p)}-   traceInput description p@DirectParser{} = p{-      complete= traceInput (\s-> "direct " <> description s) (complete p),-      direct0= traceInput (\s-> "direct0 " <> description s) (direct0 p),-      direct1= traceInput (\s-> "direct1 " <> description s) (direct1 p)}-   traceInput description p@Parser{} = p{-      complete= traceBy "complete" (complete p),-      direct= traceBy "direct" (direct p),-      direct0= traceBy "direct0" (direct0 p),-      direct1= traceBy "direct1" (direct1 p),-      indirect= traceBy "indirect" (indirect p)}-      where traceBy mode = traceInput (\s-> "(" <> mode <> ") " <> description s)--instance (LeftReductive s, FactorialMonoid s,-          ConsumedInputParsing (p g s), ParserInput (p g s) ~ s) => ConsumedInputParsing (Fixed p g s) where-   match (PositiveDirectParser p) = PositiveDirectParser (match p)-   match p@DirectParser{} = DirectParser{-      complete= match (complete p),-      direct0 = match (direct0 p),-      direct1 = match (direct1 p)}-   match p@Parser{} = Parser{-      complete= match (complete p),-      direct =  match (direct p),-      direct0 = match (direct0 p),-      direct1 = match (direct1 p),-      indirect= match (indirect p),-      isAmbiguous= Nothing,-      cyclicDescendants= cyclicDescendants p}--instance (Show s, TextualMonoid s, InputCharParsing (p g s), ParserInput (p g s) ~ s) =>-         InputCharParsing (Fixed p g s) where-   satisfyCharInput predicate = liftPositive (satisfyCharInput predicate)-   notSatisfyChar predicate = primitive (notSatisfyChar predicate) empty (notSatisfyChar predicate)-   scanChars s0 f = primitive (mempty <$ notSatisfyChar test) (lookAhead (Char.satisfy test) *> p) p-      where p = scanChars s0 f-            test = isJust . f s0-   takeCharsWhile predicate = primitive (mempty <$ notSatisfyChar predicate)-                                        (takeCharsWhile1 predicate) (takeCharsWhile predicate)-   takeCharsWhile1 predicate = liftPositive (takeCharsWhile1 predicate)--instance (CharParsing (p g s), InputCharParsing (Fixed p g s), TextualMonoid s,-          s ~ ParserInput (Fixed p g s), Show s) => CharParsing (Fixed p g s) where-   satisfy predicate = liftPositive (Char.satisfy predicate)-   string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t)--instance AmbiguousParsing (p g s) => AmbiguousParsing (Fixed p g s) where-   ambiguous (PositiveDirectParser p) = PositiveDirectParser (ambiguous p)-   ambiguous p@DirectParser{} = DirectParser{complete= ambiguous (complete p),-                                             direct0=  ambiguous (direct0 p),-                                             direct1=  ambiguous (direct1 p)}-   ambiguous p@Parser{} = Parser{complete= ambiguous (complete p),-                                 direct=   ambiguous (direct p),-                                 direct0=  ambiguous (direct0 p),-                                 direct1=  ambiguous (direct1 p),-                                 indirect= ambiguous (indirect p),-                                 isAmbiguous= Just (AmbiguityWitness Refl),-                                 cyclicDescendants= cyclicDescendants p}-   {-# INLINABLE ambiguous #-}---- | Turns a context-free parser into a backtracking PEG parser that consumes the longest possible prefix of the list--- of input tails, opposite of 'peg'-longest :: Fixed Memoizing.Parser g s a -> Fixed Backtrack.Parser g [(s, g (ResultList g s))] a-longest (PositiveDirectParser p) = PositiveDirectParser (Memoizing.longest p)-longest p@DirectParser{} = DirectParser{complete= Memoizing.longest (complete p),-                                        direct0=  Memoizing.longest (direct0 p),-                                        direct1=  Memoizing.longest (direct1 p)}-longest p@Parser{} = Parser{complete= Memoizing.longest (complete p),-                            direct=  Memoizing.longest (direct p),-                            direct0=  Memoizing.longest (direct0 p),-                            direct1=  Memoizing.longest (direct1 p),-                            indirect=  Memoizing.longest (indirect p),-                            isAmbiguous= Nothing,-                            cyclicDescendants= cyclicDescendants p}---- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest'-peg :: Ord s => Fixed Backtrack.Parser g [(s, g (ResultList g s))] a -> Fixed Memoizing.Parser g s a-peg (PositiveDirectParser p) = PositiveDirectParser (Memoizing.peg p)-peg p@DirectParser{} = DirectParser{complete= Memoizing.peg (complete p),-                                        direct0=  Memoizing.peg (direct0 p),-                                        direct1=  Memoizing.peg (direct1 p)}-peg p@Parser{} = Parser{complete= Memoizing.peg (complete p),-                        direct=  Memoizing.peg (direct p),-                        direct0=  Memoizing.peg (direct0 p),-                        direct1=  Memoizing.peg (direct1 p),-                        indirect=  Memoizing.peg (indirect p),-                        isAmbiguous= Nothing,-                        cyclicDescendants= cyclicDescendants p}---- | Turns a backtracking PEG parser into a context-free parser-terminalPEG :: (Monoid s, Ord s) => Fixed Backtrack.Parser g s a -> Fixed Memoizing.Parser g s a-terminalPEG (PositiveDirectParser p) = PositiveDirectParser (Memoizing.terminalPEG p)-terminalPEG p@DirectParser{} = DirectParser{complete= Memoizing.terminalPEG (complete p),-                                            direct0=  Memoizing.terminalPEG (direct0 p),-                                            direct1=  Memoizing.terminalPEG (direct1 p)}-terminalPEG p@Parser{} = Parser{complete= Memoizing.terminalPEG (complete p),-                                direct=  Memoizing.terminalPEG (direct p),-                                direct0=  Memoizing.terminalPEG (direct0 p),-                                direct1=  Memoizing.terminalPEG (direct1 p),-                                indirect=  Memoizing.terminalPEG (indirect p),-                                isAmbiguous= Nothing,-                                cyclicDescendants= cyclicDescendants p}--parseRecursive :: forall p g s rl. (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g,-                                    Eq s, FactorialMonoid s, LeftReductive s, Alternative (p g s),-                                    TailsParsing (p g s), GrammarConstraint (p g s) g,-                                    s ~ ParserInput (p g s), GrammarFunctor (p g s) ~ rl s, FallibleResults rl,-                                    AmbiguousAlternative (GrammarFunctor (p g s))) =>-                  g (Fixed p g s) -> s -> [(s, g (GrammarFunctor (p g s)))]-parseRecursive = parseSeparated . separated-{-# INLINE parseRecursive #-}---- | Analyze the grammar's production interdependencies and produce a 'SeparatedParser' from each production's parser.-separated :: forall p g s. (Alternative (p g s), Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g,-                            AmbiguousAlternative (GrammarFunctor (p g s))) =>-             g (Fixed p g s) -> g (SeparatedParser p g s)-separated g = Rank2.liftA4 reseparate circulars cycleFollowers descendants g-   where descendants :: g (Const (Dependencies g))-         cycleFollowers, circulars :: g (Const Bool)-         cyclicDescendantses :: g (Const (ParserFlags g))-         appendResults :: forall a. Maybe (AmbiguityWitness a)-                       -> GrammarFunctor (p g s) a -> GrammarFunctor (p g s) a -> GrammarFunctor (p g s) a-         leftRecursive :: forall a. Const (g (Const Bool)) a -> Const (ParserFlags g) a -> Const Bool a-         leftRecursiveDeps :: forall a. Const Bool a -> Const (ParserFlags g) a -> Const (g (Const Bool)) a-         reseparate :: forall a. Const Bool a -> Const Bool a -> Const (Dependencies g) a -> Fixed p g s a-                    -> SeparatedParser p g s a-         reseparate (Const circular) (Const follower) (Const d@(StaticDependencies deps)) p-            | circular || leader && follower =-              CycleParser (indirect p) (direct p) (Rank2.Arrow (Rank2.Arrow . appendResults (isAmbiguous p))) d-            | follower = BackParser (complete p)-            | otherwise = FrontParser (complete p)-            where leader = getAny (Rank2.foldMap (Any . getConst) $ Rank2.liftA2 intersection circulars deps)-         reseparate _ _ (Const d@DynamicDependencies) p =-              CycleParser (indirect p) (direct p) (Rank2.Arrow (Rank2.Arrow . appendResults (isAmbiguous p))) d-         appendResults (Just (AmbiguityWitness Refl)) = ambiguousOr-         appendResults Nothing = (<|>)-         descendants = Rank2.fmap (Const . dependsOn . getConst) cyclicDescendantses-         cyclicDescendantses = fixDescendants (Rank2.fmap (\p-> Const $ cyclicDescendants $ general p) g)-         circulars = Rank2.liftA2 leftRecursive bits cyclicDescendantses-         cycleFollowers = getUnion (Rank2.foldMap (Union . getConst) $-                                    Rank2.liftA2 leftRecursiveDeps circulars cyclicDescendantses)-         leftRecursive (Const bit) (Const ParserFlags{dependsOn= StaticDependencies deps}) =-            Const (getAny $ Rank2.foldMap (Any . getConst) $ Rank2.liftA2 intersection bit deps)-         leftRecursive _ (Const ParserFlags{dependsOn= DynamicDependencies}) = Const True-         leftRecursiveDeps (Const True) (Const ParserFlags{dependsOn= StaticDependencies deps}) = Const deps-         leftRecursiveDeps (Const False) (Const ParserFlags{dependsOn= StaticDependencies deps}) =-            Const (Rank2.fmap (const $ Const False) deps)-         leftRecursiveDeps _ (Const ParserFlags{dependsOn= DynamicDependencies}) =-            Const (Rank2.fmap (const $ Const True) g)-         intersection (Const a) (Const b) = Const (a && b)-{-# INLINABLE separated #-}--fixDescendants :: forall g. (Rank2.Apply g, Rank2.Traversable g)-                     => g (Const (g (Const (ParserFlags g)) -> (ParserFlags g))) -> g (Const (ParserFlags g))-fixDescendants gf = go initial-   where go :: g (Const (ParserFlags g)) -> g (Const (ParserFlags g))-         go cd-            | getAll (Rank2.foldMap (All . getConst) $ Rank2.liftA2 agree cd cd') = cd-            | otherwise = go cd'-            where cd' = Rank2.liftA2 flagUnion cd (Rank2.fmap (\(Const f)-> Const (f cd)) gf)-         agree (Const (ParserFlags _xn (StaticDependencies xd))) (Const (ParserFlags _yn (StaticDependencies yd))) =-            Const (getAll (Rank2.foldMap (All . getConst) (Rank2.liftA2 agree' xd yd)))-         agree (Const (ParserFlags _xn DynamicDependencies)) (Const (ParserFlags _yn DynamicDependencies)) = Const True-         agree _ _ = Const False-         agree' (Const x) (Const y) = Const (x == y)-         flagUnion (Const ParserFlags{dependsOn= old}) (Const (ParserFlags n new)) = -            Const (ParserFlags n $ depUnion old new)-         initial = Rank2.liftA2 (\_ (Const n)-> Const (ParserFlags n deps)) gf nullabilities-         deps = StaticDependencies (const (Const False) Rank2.<$> gf)-         nullabilities = fixNullabilities gf-{-# INLINABLE fixDescendants #-}--fixNullabilities :: forall g. (Rank2.Apply g, Rank2.Traversable g)-                    => g (Const (g (Const (ParserFlags g)) -> (ParserFlags g))) -> g (Const Bool)-fixNullabilities gf = Const . nullable . getConst Rank2.<$> go initial-   where go :: g (Const (ParserFlags g)) -> g (Const (ParserFlags g))-         go cd-            | getAll (Rank2.foldMap (All . getConst) $ Rank2.liftA2 agree cd cd') = cd-            | otherwise = go cd'-            where cd' = Rank2.fmap (\(Const f)-> Const (f cd)) gf-         agree (Const flags1) (Const flags2) = Const (nullable flags1 == nullable flags2)-         initial = const (Const (ParserFlags True (StaticDependencies $ const (Const False) Rank2.<$> gf))) Rank2.<$> gf-{-# INLINABLE fixNullabilities #-}---- | Parse the given input using a context-free grammar 'separated' into left-recursive and other productions.-parseSeparated :: forall p g rl s. (Rank2.Apply g, Rank2.Foldable g, Eq s, FactorialMonoid s, LeftReductive s,-                                    TailsParsing (p g s), GrammarConstraint (p g s) g,-                                    GrammarFunctor (p g s) ~ rl s, FallibleResults rl,-                                    s ~ ParserInput (p g s)) =>-                  g (SeparatedParser p g s) -> s -> [(s, g (GrammarFunctor (p g s)))]-parseSeparated parsers input = foldr parseTail [] (Factorial.tails input)-   where parseTail s parsedTail = parsed-            where parsed = (s,d''):parsedTail-                  d      = Rank2.fmap (($ (s,d):parsedTail) . parseTails) directs-                  d'     = fixRecursive s parsedTail d-                  d''    = Rank2.liftA2 f parsers d'-                  f :: forall a. SeparatedParser p g s a -> GrammarFunctor (p g s) a -> GrammarFunctor (p g s) a-                  f (FrontParser p) _ = parseTails p ((s,d''):parsedTail)-                  f _ result = result-         fixRecursive :: s -> [(s, g (GrammarFunctor (p g s)))]-                      -> g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s))-         whileAnyContinues :: (g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s)))-                           -> (g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s)))-                           -> g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s))-         recurseTotal :: s -> g (GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s))-                      -> [(s, g (GrammarFunctor (p g s)))]-                      -> g (GrammarFunctor (p g s))-                      -> g (GrammarFunctor (p g s))-         recurseMarginal :: s -> [(s, g (GrammarFunctor (p g s)))]-                      -> g (GrammarFunctor (p g s))-                      -> g (GrammarFunctor (p g s))-         maybeDependencies :: g (Const (Maybe (Dependencies g)))-         maybeDependency :: SeparatedParser p g s r -> Const (Maybe (Dependencies g)) r-         appends :: g (ResultAppend p g s)-         parserAppend :: SeparatedParser p g s r -> ResultAppend p g s r--         directs = Rank2.fmap backParser parsers-         indirects = Rank2.fmap (\p-> case p of {CycleParser{}-> cycleParser p; _ -> empty}) parsers-         appends = Rank2.fmap parserAppend parsers-         parserAppend p@CycleParser{} = appendResultsArrow p-         parserAppend _ = Rank2.Arrow (Rank2.Arrow . const)-         maybeDependencies = Rank2.fmap maybeDependency parsers-         maybeDependency p@CycleParser{} = Const (Just $ dependencies p)-         maybeDependency _ = Const Nothing--         -- Fix the recursive knot on the head of the input, given its already-fixed tail and the initial record of-         -- directly parsed results.-         fixRecursive s parsedTail initial =-            whileAnyContinues (recurseTotal s (appends Rank2.<*> initial) parsedTail)-                              (recurseMarginal s parsedTail)-                              initial initial--         -- Loop accumulating the total parsing results from marginal results as long as there is any new marginal-         -- result to expand a total one or a new failure expactation to augment an existing failure.-         whileAnyContinues ft fm total marginal =-            Rank2.liftA3 choiceWhile maybeDependencies total (whileAnyContinues ft fm (ft total) (fm marginal))-            where choiceWhile :: Const (Maybe (Dependencies g)) x-                              -> GrammarFunctor (p g s) x -> GrammarFunctor (p g s) x-                              -> GrammarFunctor (p g s) x-                  choiceWhile (Const Nothing) t _ = t-                  choiceWhile (Const (Just (StaticDependencies deps))) t t'-                     | getAny (Rank2.foldMap (Any . getConst) (Rank2.liftA2 combine deps marginal)) = t'-                     | hasSuccess t = t-                     | otherwise =-                        failWith (failureOf $-                                  if getAny (Rank2.foldMap (Any . getConst) $-                                             Rank2.liftA2 (combineFailures $ failureOf t) deps marginal)-                                  then t' else t)-                     where combine :: Const Bool x -> GrammarFunctor (p g s) x -> Const Bool x-                           combineFailures :: ParseFailure Pos s -> Const Bool x -> GrammarFunctor (p g s) x-                                           -> Const Bool x-                           combine (Const False) _ = Const False-                           combine (Const True) results = Const (hasSuccess results)-                           combineFailures _ (Const False) _ = Const False-                           combineFailures (ParseFailure pos expected erroneous) (Const True) rl =-                              Const (pos < pos'-                                     || pos == pos' && (any (`notElem` expected) expected'-                                                        || any (`notElem` erroneous) erroneous'))-                              where ParseFailure pos' expected' erroneous' = failureOf rl-                  choiceWhile (Const (Just DynamicDependencies)) t t'-                     | getAny (Rank2.foldMap (Any . hasSuccess) marginal) = t'-                     | hasSuccess t = t-                     | ParseFailure _ [] [] <- failureOf t = t'-                     | otherwise = t--         -- Adds another round of indirect parsing results to the total results accumulated so far.-         recurseTotal s initialAppends parsedTail total = Rank2.liftA2 reparse initialAppends indirects-            where reparse :: (GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s)) a -> p g s a-                          -> GrammarFunctor (p g s) a-                  reparse append p = Rank2.apply append (parseTails p $ (s, total) : parsedTail)-         -- Calculates the next round of indirect parsing results from the previous marginal round.-         recurseMarginal s parsedTail marginal =-            flip parseTails ((s, marginal) : parsedTail) Rank2.<$> indirects-{-# NOINLINE parseSeparated #-}+import Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive
src/Text/Grampa/ContextFree/LeftRecursive/Transformer.hs view
@@ -1,26 +1,8 @@-{-# Language GADTs #-} -- | A context-free parser that can handle left-recursive grammars and carry a -- monadic computation with each parsing result.-module Text.Grampa.ContextFree.LeftRecursive.Transformer (ParserT, SeparatedParser(..), AmbiguityDecidable,-                                                          lift, liftPositive, tbind, tmap,-                                                          parseSeparated, separated)+module Text.Grampa.ContextFree.LeftRecursive.Transformer+       {-# DEPRECATED "Use Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive instead" #-}+       (module Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive) where -import Text.Grampa.ContextFree.LeftRecursive (Fixed, SeparatedParser(..),-                                              liftPositive, liftPure, mapPrimitive, parseSeparated, separated)-import qualified Text.Grampa.ContextFree.SortedMemoizing.Transformer as Transformer-import Text.Grampa.Internal (AmbiguityDecidable)--type ParserT m = Fixed (Transformer.ParserT m)---- | Lift a parse-free computation into the parser.-lift :: (Applicative m, Ord s) => m a -> ParserT m g s a-lift = liftPure . Transformer.lift---- | Transform the computation carried by the parser using the monadic bind ('>>=').-tbind :: (Monad m, AmbiguityDecidable b) => ParserT m g s a -> (a -> m b) -> ParserT m g s b-tbind p f = mapPrimitive (`Transformer.tbind` f) p---- | Transform the computation carried by the parser.-tmap :: AmbiguityDecidable b => (m a -> m b) -> ParserT m g s a -> ParserT m g s b-tmap = mapPrimitive . Transformer.tmap+import Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive
src/Text/Grampa/ContextFree/Memoizing.hs view
@@ -1,10 +1,8 @@-{-# LANGUAGE CPP, FlexibleContexts, GeneralizedNewtypeDeriving, InstanceSigs,-             RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-}+{-# LANGUAGE CPP, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, InstanceSigs, MultiParamTypeClasses,+             RankNTypes, ScopedTypeVariables, TypeFamilies, TypeOperators, UndecidableInstances #-} -- | A context-free parser with packrat-like memoization of parse results. module Text.Grampa.ContextFree.Memoizing-       {-# DEPRECATED "Use Text.Grampa.ContextFree.SortedMemoizing instead" #-}-       (ResultList(..), Parser(..), BinTree(..),-        reparseTails, longest, peg, terminalPEG)+       (ResultList(..), Parser(..), BinTree(..), reparseTails, longest, peg, terminalPEG) where  import Control.Applicative@@ -33,6 +31,7 @@ import qualified Text.Parser.Char import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..))+import Text.Parser.Input.Position (fromEnd) import Text.Parser.LookAhead (LookAheadParsing(..))  import qualified Rank2@@ -40,7 +39,10 @@ import Text.Grampa.Class (GrammarParsing(..), MultiParsing(..),                           DeterministicParsing(..), InputParsing(..), InputCharParsing(..),                           TailsParsing(parseTails), ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (BinTree(..), TraceableParsing(..), expected, erroneous)+import Text.Grampa.Internal (BinTree(..), AmbiguousAlternative (..), FallibleResults (..), TraceableParsing(..),+                             Dependencies (..), ParserFlags (..),+                             emptyFailure, erroneous, expected, expectedInput, replaceExpected)+import Text.Grampa.Internal.Storable (Storable(..), Storable1(..)) import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack  import Prelude hiding (iterate, length, null, showList, span, takeWhile)@@ -49,8 +51,8 @@ -- grammars. newtype Parser g s r = Parser{applyParser :: [(s, g (ResultList g s))] -> ResultList g s r} -data ResultList g s r = ResultList !(BinTree (ResultInfo g s r)) {-# UNPACK #-} !(ParseFailure Pos s)-data ResultInfo g s r = ResultInfo !Int ![(s, g (ResultList g s))] !r+data ResultList g s r = ResultList !(BinTree (ResultInfo g s r)) (ParseFailure Pos s)+data ResultInfo g s r = ResultInfo !Int ![(s, g (ResultList g s))] r  instance (Show s, Show r) => Show (ResultList g s r) where    show (ResultList l f) = "ResultList (" ++ shows l (") (" ++ shows f ")")@@ -65,6 +67,10 @@ instance Functor (ResultInfo g s) where    fmap f (ResultInfo l t r) = ResultInfo l t (f r) +instance Ord s => Applicative (ResultInfo g s) where+   pure = ResultInfo 0 mempty+   ResultInfo l1 _ f <*> ResultInfo l2 t2 x = ResultInfo (l1 + l2) t2 (f x)+ instance Foldable (ResultInfo g s) where    foldMap f (ResultInfo _ _ r) = f r @@ -84,6 +90,41 @@    mempty = ResultList mempty mempty    mappend = (<>) +instance FallibleResults (ResultList g) where+   hasSuccess (ResultList EmptyTree _) = False+   hasSuccess _ = True+   failureOf (ResultList _ failure) = failure+   failWith = ResultList EmptyTree++instance Ord s => Applicative (ResultList g s) where+   pure a = ResultList (Leaf $ pure a) mempty+   ResultList rl1 f1 <*> ResultList rl2 f2 = ResultList ((<*>) <$> rl1 <*> rl2) (f1 <> f2)++instance Ord s => Alternative (ResultList g s) where+   empty = mempty+   (<|>) = (<>)++instance Ord s => AmbiguousAlternative (ResultList g s) where+   ambiguousOr (ResultList rl1 f1) (ResultList rl2 f2) = ResultList (Fork rl1 rl2) (f1 <> f2)++instance Storable1 (ResultList g s) Bool where+   store1 bit = ResultList EmptyTree (emptyFailure $ if bit then 1 else 0)+   reuse1 (ResultList _ (ParseFailure pos _ _)) = pos /= 0++instance (Rank2.Functor g, Monoid s, Ord s) => Storable1 (ResultList g s) (ParserFlags g) where+   store1 a = ResultList (Leaf $ store a) mempty+   reuse1 (ResultList (Leaf s) _) = reuse s++instance (Rank2.Functor g, Monoid s) => Storable (ResultInfo g s r) (ParserFlags g) where+   store (ParserFlags n d) = ResultInfo (if n then 1 else 0) (store d) (error "unused")+   reuse (ResultInfo n d _) = ParserFlags (n /= 0) (reuse d)++instance (Rank2.Functor g, Monoid s) => Storable [(s, g (ResultList g s))] (Dependencies g) where+   store DynamicDependencies = []+   store (StaticDependencies deps) = [(mempty, store deps)]+   reuse [] = DynamicDependencies+   reuse [(_, deps)] = StaticDependencies (reuse deps)+ instance Functor (Parser g i) where    fmap f (Parser p) = Parser (fmap f . p)    {-# INLINABLE fmap #-}@@ -100,7 +141,7 @@    {-# INLINABLE (<*>) #-}  instance Ord s => Alternative (Parser g s) where-   empty = Parser (\rest-> ResultList mempty $ ParseFailure (Down $ length rest) [] [])+   empty = Parser (ResultList mempty . emptyFailure . Down . length)    Parser p <|> Parser q = Parser r where       r rest = p rest <> q rest    {-# INLINABLE (<|>) #-}@@ -143,6 +184,22 @@       p ((_, d) : _) = f d       p _ = ResultList mempty (expected 0 "NonTerminal at endOfInput")    {-# INLINE nonTerminal #-}+   chainRecursive assign (Parser base) (Parser recurse) = Parser q+      where q [] = base []+            q ((s, d):t) = case base ((s, assign mempty d) : t)+                           of r@(ResultList EmptyTree _) -> r+                              r -> iter r r+               where iter marginal total = case recurse ((s, assign marginal d) : t)+                                           of ResultList EmptyTree _ -> total+                                              r -> iter r (total <> r)+   chainLongestRecursive assign (Parser base) (Parser recurse) = Parser q+      where q [] = base []+            q ((s, d):t) = case base ((s, assign mempty d) : t)+                           of r@(ResultList EmptyTree _) -> r+                              r -> iter r+               where iter r = case recurse ((s, assign r d) : t)+                              of ResultList EmptyTree _ -> r+                                 r' -> iter r'  instance (Ord s, LeftReductive s, FactorialMonoid s) => TailsParsing (Parser g s) where    parseTails = applyParser@@ -216,7 +273,7 @@    string s = Parser p where       p rest@((s', _) : _)          | s `isPrefixOf` s' = ResultList (Leaf $ ResultInfo l (Factorial.drop l rest) s) mempty-      p rest = ResultList mempty (ParseFailure (Down $ length rest) [LiteralDescription s] [])+      p rest = ResultList mempty (expectedInput (fromEnd $ length rest) s)       l = Factorial.length s    notSatisfy predicate = Parser p       where p rest@((s, _):_)@@ -264,25 +321,22 @@ instance (MonoidNull s, Ord s) => Parsing (Parser g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)-               where rewindFailure (ResultList rl _) = ResultList rl (ParseFailure (Down $ length rest) [] [])+               where rewindFailure (ResultList rl _) = ResultList rl (emptyFailure $ fromEnd $ length rest)    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)-               where replaceFailure (ResultList EmptyTree (ParseFailure pos msgs erroneous')) =-                        ResultList EmptyTree (ParseFailure pos-                                                 (if pos == Down (length rest) then [StaticDescription msg]-                                                  else msgs)-                                                 erroneous')+               where replaceFailure (ResultList EmptyTree f) =+                        ResultList EmptyTree (replaceExpected (fromEnd $ length rest) msg f)                      replaceFailure rl = rl    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))       where rewind t (ResultList EmptyTree _) = ResultList (Leaf $ ResultInfo 0 t ()) mempty             rewind t ResultList{} = ResultList mempty (expected (Down $ length t) "notFollowedBy")    skipMany p = go       where go = pure () <|> p *> go-   unexpected msg = Parser (\t-> ResultList mempty $ expected (Down $ length t) msg)+   unexpected msg = Parser (\t-> ResultList mempty $ erroneous (Down $ length t) msg)    eof = Parser f       where f rest@((s, _):_)                | null s = ResultList (Leaf $ ResultInfo 0 rest ()) mempty-               | otherwise = ResultList mempty (expected (Down $ length rest) "endOfInput")+               | otherwise = ResultList mempty (expected (Down $ length rest) "end of input")             f [] = ResultList (Leaf $ ResultInfo 0 [] ()) mempty  instance (MonoidNull s, Ord s) => DeterministicParsing (Parser g s) where@@ -329,22 +383,20 @@ longest :: Parser g s a -> Backtrack.Parser g [(s, g (ResultList g s))] a longest p = Backtrack.Parser q where    q rest = case applyParser p rest-            of ResultList EmptyTree (ParseFailure pos positive negative)-                  -> Backtrack.NoParse (ParseFailure pos (map message positive) (map message negative))+            of ResultList EmptyTree (ParseFailure pos (FailureDescription expected inputs) errors)+                  -> Backtrack.NoParse (ParseFailure pos (FailureDescription expected $ map wrap inputs) errors)                ResultList rs _ -> parsed (maximumBy (compare `on` resultLength) rs)    resultLength (ResultInfo l _ _) = l    parsed (ResultInfo l s r) = Backtrack.Parsed l r s-   message (StaticDescription msg) = StaticDescription msg-   message (LiteralDescription s) = LiteralDescription [(s, error "longest")]+   wrap s = [(s, error "longest")]  -- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest' peg :: Ord s => Backtrack.Parser g [(s, g (ResultList g s))] a -> Parser g s a peg p = Parser q where    q rest = case Backtrack.applyParser p rest             of Backtrack.Parsed l result suffix -> ResultList (Leaf $ ResultInfo l suffix result) mempty-               Backtrack.NoParse (ParseFailure pos positive negative)-                  -> ResultList mempty (ParseFailure pos (original <$> positive) (original <$> negative))-      where original = (fst . head <$>)+               Backtrack.NoParse (ParseFailure pos (FailureDescription expected inputs) errors)+                  -> ResultList mempty (ParseFailure pos (FailureDescription expected (fst . head <$> inputs)) errors)  -- | Turns a backtracking PEG parser into a context-free parser terminalPEG :: (Monoid s, Ord s) => Backtrack.Parser g s a -> Parser g s a
+ src/Text/Grampa/ContextFree/Memoizing/LeftRecursive.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE ConstraintKinds, CPP, FlexibleContexts, FlexibleInstances, GADTs, GeneralizedNewtypeDeriving, InstanceSigs,+             RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeFamilies, TypeOperators,+             UndecidableInstances #-}+-- | A context-free memoizing parser that can handle left-recursive grammars.+module Text.Grampa.ContextFree.Memoizing.LeftRecursive (+   Fixed, Parser, SeparatedParser(..),+   autochain, liftPositive, liftPure, mapPrimitive,+   longest, peg, terminalPEG,+   parseSeparated, separated)+where++import Text.Grampa.Internal.LeftRecursive (Fixed(..), SeparatedParser(..),+                                           autochain, asLeaf, liftPositive, liftPure, mapPrimitive,+                                           parseSeparated, separated)+import Text.Grampa.ContextFree.Memoizing (ResultList (..))+import qualified Text.Grampa.ContextFree.Memoizing as Memoizing+import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack++-- | A parser for left-recursive grammars on top of the memoizing 'Memoizing.Parser'+type Parser = Fixed Memoizing.Parser++-- | Turns a context-free parser into a backtracking PEG parser that consumes the longest possible prefix of the list+-- of input tails, opposite of 'peg'+longest :: Fixed Memoizing.Parser g s a -> Fixed Backtrack.Parser g [(s, g (ResultList g s))] a+longest (PositiveDirectParser p) = PositiveDirectParser (Memoizing.longest p)+longest p@DirectParser{} = DirectParser{complete= Memoizing.longest (complete p),+                                        direct0=  Memoizing.longest (direct0 p),+                                        direct1=  Memoizing.longest (direct1 p)}+longest p@Parser{} = asLeaf Parser{+   complete= Memoizing.longest (complete p),+   direct=  Memoizing.longest (direct p),+   direct0=  Memoizing.longest (direct0 p),+   direct1=  Memoizing.longest (direct1 p),+   indirect=  Memoizing.longest (indirect p),+   choices= undefined,+   isAmbiguous= Nothing,+   cyclicDescendants= cyclicDescendants p}++-- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest'+peg :: Ord s => Fixed Backtrack.Parser g [(s, g (ResultList g s))] a -> Fixed Memoizing.Parser g s a+peg (PositiveDirectParser p) = PositiveDirectParser (Memoizing.peg p)+peg p@DirectParser{} = DirectParser{complete= Memoizing.peg (complete p),+                                        direct0=  Memoizing.peg (direct0 p),+                                        direct1=  Memoizing.peg (direct1 p)}+peg p@Parser{} = asLeaf Parser{+   complete= Memoizing.peg (complete p),+   direct=  Memoizing.peg (direct p),+   direct0=  Memoizing.peg (direct0 p),+   direct1=  Memoizing.peg (direct1 p),+   indirect=  Memoizing.peg (indirect p),+   choices= undefined,+   isAmbiguous= Nothing,+   cyclicDescendants= cyclicDescendants p}++-- | Turns a backtracking PEG parser into a context-free parser+terminalPEG :: (Monoid s, Ord s) => Fixed Backtrack.Parser g s a -> Fixed Memoizing.Parser g s a+terminalPEG (PositiveDirectParser p) = PositiveDirectParser (Memoizing.terminalPEG p)+terminalPEG p@DirectParser{} = DirectParser{complete= Memoizing.terminalPEG (complete p),+                                            direct0=  Memoizing.terminalPEG (direct0 p),+                                            direct1=  Memoizing.terminalPEG (direct1 p)}+terminalPEG p@Parser{} = asLeaf Parser{+   complete= Memoizing.terminalPEG (complete p),+   direct=  Memoizing.terminalPEG (direct p),+   direct0=  Memoizing.terminalPEG (direct0 p),+   direct1=  Memoizing.terminalPEG (direct1 p),+   indirect=  Memoizing.terminalPEG (indirect p),+   choices= undefined,+   isAmbiguous= Nothing,+   cyclicDescendants= cyclicDescendants p}
src/Text/Grampa/ContextFree/Parallel.hs view
@@ -13,6 +13,7 @@ import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.Kind (Type)+import Data.List (intercalate) import Data.Semigroup (Semigroup(..)) import qualified Data.Semigroup.Cancellative as Cancellative import Data.Monoid (Monoid(mappend, mempty))@@ -36,8 +37,9 @@  import Text.Grampa.Class (CommittedParsing(..), DeterministicParsing(..),                           InputParsing(..), InputCharParsing(..), MultiParsing(..),-                          ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (BinTree(..), expected, noFailure, TraceableParsing(..))+                          ParseResults, ParseFailure(..), Pos)+import Text.Grampa.Internal (BinTree(..), emptyFailure, erroneous, expected, expectedInput, replaceExpected, noFailure,+                             TraceableParsing(..))  import Prelude hiding (iterate, null, showList, span, takeWhile) @@ -45,7 +47,7 @@ -- support. newtype Parser (g :: (Type -> Type) -> Type) s r = Parser{applyParser :: s -> ResultList s r} -data ResultList s r = ResultList !(BinTree (ResultInfo s r)) {-# UNPACK #-} !(ParseFailure Pos s)+data ResultList s r = ResultList !(BinTree (ResultInfo s r)) (ParseFailure Pos s) data ResultInfo s r = ResultInfo !s !r  instance (Show s, Show r) => Show (ResultList s r) where@@ -92,7 +94,7 @@   instance (FactorialMonoid s, Ord s) => Alternative (Parser g s) where-   empty = Parser (\s-> ResultList mempty $ ParseFailure (fromEnd $ Factorial.length s) [] [])+   empty = Parser (ResultList mempty . emptyFailure . fromEnd . Factorial.length)    Parser p <|> Parser q = Parser r where       r rest = p rest <> q rest @@ -113,7 +115,7 @@ #if MIN_VERSION_base(4,13,0) instance (FactorialMonoid s, Ord s) => MonadFail (Parser g s) where #endif-   fail msg = Parser (\s-> ResultList mempty $ ParseFailure (fromEnd $ Factorial.length s) [] [StaticDescription msg])+   fail msg = Parser (\s-> ResultList mempty $ erroneous (fromEnd $ Factorial.length s) msg)  instance (FactorialMonoid s, Ord s) => MonadPlus (Parser g s) where    mzero = empty@@ -176,14 +178,16 @@                else ResultList (Leaf $ ResultInfo suffix prefix) noFailure    string s = Parser p where       p s' | Just suffix <- Cancellative.stripPrefix s s' = ResultList (Leaf $ ResultInfo suffix s) noFailure-           | otherwise = ResultList mempty (ParseFailure (fromEnd $ Factorial.length s') [LiteralDescription s] [])+           | otherwise = ResultList mempty (expectedInput (fromEnd $ Factorial.length s') s) -instance InputParsing (Parser g s)  => TraceableParsing (Parser g s) where+instance (FactorialMonoid s, InputParsing (Parser g s))  => TraceableParsing (Parser g s) where    traceInput description (Parser p) = Parser q-      where q s = case traceWith "Parsing " (p s)-                  of rl@(ResultList EmptyTree _) -> traceWith "Failed " rl-                     rl -> traceWith "Parsed " rl-               where traceWith prefix = trace (prefix <> description s)+      where q s = case trace ("Parsing " <> description s) (p s)+                  of rl@(ResultList EmptyTree _) -> trace ("Failed " <> description s) rl+                     rl@(ResultList rs _) ->+                        trace ("Parsed [" <> intercalate ", " (describeResult <$> toList rs) <> "]") rl+               where describeResult (ResultInfo s' _) =+                        description (Factorial.take (Factorial.length s - Factorial.length s') s)  instance (Ord s, TextualMonoid s) => InputCharParsing (Parser g s) where    satisfyCharInput predicate = Parser p@@ -212,23 +216,18 @@ instance (FactorialMonoid s, Ord s) => Parsing (Parser g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)-               where rewindFailure (ResultList rl _) =-                        ResultList rl (ParseFailure (fromEnd $ Factorial.length rest) [] [])+               where rewindFailure (ResultList rl _) = ResultList rl (emptyFailure $ fromEnd $ Factorial.length rest)    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)-               where replaceFailure (ResultList EmptyTree (ParseFailure pos msgs erroneous)) =-                        ResultList EmptyTree (ParseFailure pos-                                                           (if pos == fromEnd (Factorial.length rest)-                                                            then [StaticDescription msg] else msgs)-                                                           erroneous)+               where replaceFailure (ResultList EmptyTree f) =+                        ResultList EmptyTree (replaceExpected (fromEnd $ Factorial.length rest) msg f)                      replaceFailure rl = rl    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))       where rewind t (ResultList EmptyTree _) = ResultList (Leaf $ ResultInfo t ()) noFailure             rewind t ResultList{} = ResultList mempty (expected (fromEnd $ Factorial.length t) "notFollowedBy")    skipMany p = go       where go = pure () <|> try p *> go-   unexpected msg = Parser (\t-> ResultList mempty-                                 $ ParseFailure (fromEnd $ Factorial.length t) [] [StaticDescription msg])+   unexpected msg = Parser (\t-> ResultList mempty $ erroneous (fromEnd $ Factorial.length t) msg)    eof = Parser f       where f s | null s = ResultList (Leaf $ ResultInfo s ()) noFailure                 | otherwise = ResultList mempty (expected (fromEnd $ Factorial.length s) "end of input")
src/Text/Grampa/ContextFree/SortedMemoizing.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE BangPatterns, CPP, FlexibleContexts, GeneralizedNewtypeDeriving, InstanceSigs,-             RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-}+             RankNTypes, ScopedTypeVariables, TypeFamilies, TypeOperators, UndecidableInstances #-} -- | A context-free memoizing parser that handles all alternatives in parallel. module Text.Grampa.ContextFree.SortedMemoizing         (ParseFailure(..), ResultList(..), Parser(..),@@ -13,6 +13,7 @@ #endif import Data.Either (partitionEithers) import Data.Functor.Compose (Compose(..))+import Data.List (intercalate) import Data.List.NonEmpty (NonEmpty((:|)), nonEmpty, toList) import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Null (MonoidNull(null))@@ -30,6 +31,7 @@ import qualified Text.Parser.Char import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..))+import Text.Parser.Input.Position (fromEnd) import Text.Parser.LookAhead (LookAheadParsing(..))  import qualified Rank2@@ -39,7 +41,8 @@                           ConsumedInputParsing(..), DeterministicParsing(..),                           TailsParsing(parseTails, parseAllTails), ParseResults, ParseFailure(..),                           FailureDescription(..))-import Text.Grampa.Internal (ResultList(..), ResultsOfLength(..), TraceableParsing(..), expected, erroneous)+import Text.Grampa.Internal (ResultList(..), ResultsOfLength(..), TraceableParsing(..),+                             emptyFailure, expected, expectedInput, replaceExpected, erroneous) import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack  import Prelude hiding (iterate, null, showList, span, takeWhile)@@ -64,7 +67,7 @@    {-# INLINABLE (<*>) #-}  instance Ord s => Alternative (Parser g s) where-   empty = Parser (\rest-> ResultList mempty $ ParseFailure (Down $ length rest) [] [])+   empty = Parser (ResultList mempty . emptyFailure . Down . length)    Parser p <|> Parser q = Parser r where       r rest = p rest <> q rest    {-# INLINE (<|>) #-}@@ -101,7 +104,7 @@    mappend = (<>)  -- | Memoizing parser guarantees O(n²) performance for grammars with unambiguous productions. Can be wrapped with--- 'Text.Grampa.ContextFree.LeftRecursive.Fixed' to provide left recursion support.+-- 'Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive.Fixed' to provide left recursion support. instance (Ord s, LeftReductive s, FactorialMonoid s) => GrammarParsing (Parser g s) where    type ParserGrammar (Parser g s) = g    type GrammarFunctor (Parser g s) = ResultList g s@@ -111,17 +114,33 @@       p input@((_, d) : _) = ResultList rs' failure          where ResultList rs failure = f d                rs' = sync <$> rs-               -- in left-recursive grammars the stored input remainder may be wrong, so revert to the complete input+               -- in left-recursive grammars the stored input remainder may be wrong, so revert to the current input                sync (ResultsOfLength 0 _remainder r) = ResultsOfLength 0 input r                sync rol = rol       p _ = ResultList mempty (expected 0 "NonTerminal at endOfInput")    {-# INLINE nonTerminal #-}+   chainRecursive assign (Parser base) (Parser recurse) = Parser q+      where q [] = base []+            q ((s, d):t) = case base ((s, assign mempty d) : t)+                           of r@(ResultList [] _) -> r+                              r -> iter r r+               where iter marginal total = case recurse ((s, assign marginal d) : t)+                                           of ResultList [] _ -> total+                                              r -> iter r (total <> r)+   chainLongestRecursive assign (Parser base) (Parser recurse) = Parser q+      where q [] = base []+            q ((s, d):t) = case base ((s, assign mempty d) : t)+                           of r@(ResultList [] _) -> r+                              r -> iter r+               where iter r = case recurse ((s, assign r d) : t)+                              of ResultList [] _ -> r+                                 r' -> iter r'  instance (Ord s, LeftReductive s, FactorialMonoid s) => TailsParsing (Parser g s) where    parseTails = applyParser  -- | Memoizing parser guarantees O(n²) performance for grammars with unambiguous productions. Can be wrapped with--- 'Text.Grampa.ContextFree.LeftRecursive.Fixed' to provide left recursion support.+-- 'Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive.Fixed' to provide left recursion support. -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>@@ -191,7 +210,7 @@    string s = Parser p where       p rest@((s', _) : _)          | s `isPrefixOf` s' = ResultList [ResultsOfLength l (Factorial.drop l rest) (s:|[])] mempty-      p rest = ResultList mempty (ParseFailure (Down $ length rest) [LiteralDescription s] [])+      p rest = ResultList mempty (expectedInput (fromEnd $ length rest) s)       l = Factorial.length s    notSatisfy predicate = Parser p       where p rest@((s, _):_)@@ -200,12 +219,13 @@             p rest = ResultList [ResultsOfLength 0 rest (():|[])] mempty    {-# INLINABLE string #-} -instance InputParsing (Parser g s)  => TraceableParsing (Parser g s) where+instance (InputParsing (Parser g s), FactorialMonoid s) => TraceableParsing (Parser g s) where    traceInput description (Parser p) = Parser q-      where q rest@((s, _):_) = case traceWith "Parsing " (p rest)-                                of rl@(ResultList [] _) -> traceWith "Failed " rl-                                   rl -> traceWith "Parsed " rl-               where traceWith prefix = trace (prefix <> description s)+      where q rest@((s, _):_) = case trace ("Parsing " <> description s) (p rest) of+               rl@(ResultList [] _) -> trace ("Failed " <> descriptionWith id) rl+               rl@(ResultList rs _) -> trace ("Parsed [" <> intercalate ", " (describeResult <$> rs) <> "]") rl+               where describeResult (ResultsOfLength len _ _) = descriptionWith (Factorial.take len)+                     descriptionWith f = description (f s)             q [] = p []  instance (Ord s, Show s, TextualMonoid s) => InputCharParsing (Parser g s) where@@ -246,19 +266,17 @@ instance (MonoidNull s, Ord s) => Parsing (Parser g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)-               where rewindFailure (ResultList rl _) = ResultList rl (ParseFailure (Down $ length rest) [] [])+               where rewindFailure (ResultList rl _) = ResultList rl (emptyFailure $ fromEnd $ length rest)    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)-               where replaceFailure (ResultList [] (ParseFailure pos msgs erroneous')) =-                        ResultList [] (ParseFailure pos (if pos == Down (length rest) then [StaticDescription msg]-                                                         else msgs) erroneous')+               where replaceFailure (ResultList [] f) = ResultList [] (replaceExpected (fromEnd $ length rest) msg f)                      replaceFailure rl = rl    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))       where rewind t (ResultList [] _) = ResultList [ResultsOfLength 0 t (():|[])] mempty             rewind t ResultList{} = ResultList mempty (expected (Down $ length t) "notFollowedBy")    skipMany p = go       where go = pure () <|> try p *> go-   unexpected msg = Parser (\t-> ResultList mempty $ expected (Down $ length t) msg)+   unexpected msg = Parser (\t-> ResultList mempty $ erroneous (Down $ length t) msg)    eof = Parser f       where f rest@((s, _):_)                | null s = ResultList [ResultsOfLength 0 rest (():|[])] mempty@@ -323,20 +341,19 @@ longest :: Parser g s a -> Backtrack.Parser g [(s, g (ResultList g s))] a longest p = Backtrack.Parser q where    q rest = case applyParser p rest-            of ResultList [] (ParseFailure pos positive negative)-                  -> Backtrack.NoParse (ParseFailure pos (map message positive) (map message negative))+            of ResultList [] (ParseFailure pos (FailureDescription expected inputs) errors)+                  -> Backtrack.NoParse (ParseFailure pos (FailureDescription expected $ map wrap inputs) errors)                ResultList rs _ -> parsed (last rs)    parsed (ResultsOfLength l s (r:|_)) = Backtrack.Parsed l r s-   message (StaticDescription msg) = StaticDescription msg-   message (LiteralDescription s) = LiteralDescription [(s, error "longest")]+   wrap s = [(s, error "longest")]  -- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest' peg :: Ord s => Backtrack.Parser g [(s, g (ResultList g s))] a -> Parser g s a peg p = Parser q where    q rest = case Backtrack.applyParser p rest             of Backtrack.Parsed l result suffix -> ResultList [ResultsOfLength l suffix (result:|[])] mempty-               Backtrack.NoParse (ParseFailure pos positive negative)-                 -> ResultList mempty (ParseFailure pos ((fst . head <$>) <$> positive) ((fst . head <$>) <$> negative))+               Backtrack.NoParse (ParseFailure pos (FailureDescription expected inputs) errors)+                  -> ResultList mempty (ParseFailure pos (FailureDescription expected (fst . head <$> inputs)) errors)  -- | Turns a backtracking PEG parser into a context-free parser terminalPEG :: Monoid s => Ord s => Backtrack.Parser g s a -> Parser g s a
+ src/Text/Grampa/ContextFree/SortedMemoizing/LeftRecursive.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE ConstraintKinds, CPP, FlexibleContexts, FlexibleInstances, GADTs, GeneralizedNewtypeDeriving, InstanceSigs,+             RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeFamilies, TypeOperators,+             UndecidableInstances #-}+-- | A context-free memoizing parser that can handle ambiguous left-recursive grammars.+module Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive (+   Fixed, Parser, SeparatedParser(..),+   autochain, liftPositive, liftPure, mapPrimitive,+   longest, peg, terminalPEG,+   parseSeparated, separated)+where++import Text.Grampa.Internal.LeftRecursive (Fixed(..), SeparatedParser(..),+                                           autochain, asLeaf, liftPositive, liftPure, mapPrimitive,+                                           parseSeparated, separated)+import Text.Grampa.ContextFree.SortedMemoizing (ResultList (..))+import qualified Text.Grampa.ContextFree.SortedMemoizing as Memoizing+import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack++-- | A parser for left-recursive grammars on top of the sorted memoizing 'Memoizing.Parser'. It's slightly slower than+-- the parser from "Text.Grampa.ContextFree.Memoizing.LeftRecursive" but provides more features.+type Parser = Fixed Memoizing.Parser++-- | Turns a context-free parser into a backtracking PEG parser that consumes the longest possible prefix of the list+-- of input tails, opposite of 'peg'+longest :: Fixed Memoizing.Parser g s a -> Fixed Backtrack.Parser g [(s, g (ResultList g s))] a+longest (PositiveDirectParser p) = PositiveDirectParser (Memoizing.longest p)+longest p@DirectParser{} = DirectParser{complete= Memoizing.longest (complete p),+                                        direct0=  Memoizing.longest (direct0 p),+                                        direct1=  Memoizing.longest (direct1 p)}+longest p@Parser{} = asLeaf Parser{+   complete= Memoizing.longest (complete p),+   direct=  Memoizing.longest (direct p),+   direct0=  Memoizing.longest (direct0 p),+   direct1=  Memoizing.longest (direct1 p),+   indirect=  Memoizing.longest (indirect p),+   choices= undefined,+   isAmbiguous= Nothing,+   cyclicDescendants= cyclicDescendants p}++-- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest'+peg :: Ord s => Fixed Backtrack.Parser g [(s, g (ResultList g s))] a -> Fixed Memoizing.Parser g s a+peg (PositiveDirectParser p) = PositiveDirectParser (Memoizing.peg p)+peg p@DirectParser{} = DirectParser{complete= Memoizing.peg (complete p),+                                        direct0=  Memoizing.peg (direct0 p),+                                        direct1=  Memoizing.peg (direct1 p)}+peg p@Parser{} = asLeaf Parser{+   complete= Memoizing.peg (complete p),+   direct=  Memoizing.peg (direct p),+   direct0=  Memoizing.peg (direct0 p),+   direct1=  Memoizing.peg (direct1 p),+   indirect=  Memoizing.peg (indirect p),+   choices= undefined,+   isAmbiguous= Nothing,+   cyclicDescendants= cyclicDescendants p}++-- | Turns a backtracking PEG parser into a context-free parser+terminalPEG :: (Monoid s, Ord s) => Fixed Backtrack.Parser g s a -> Fixed Memoizing.Parser g s a+terminalPEG (PositiveDirectParser p) = PositiveDirectParser (Memoizing.terminalPEG p)+terminalPEG p@DirectParser{} = DirectParser{complete= Memoizing.terminalPEG (complete p),+                                            direct0=  Memoizing.terminalPEG (direct0 p),+                                            direct1=  Memoizing.terminalPEG (direct1 p)}+terminalPEG p@Parser{} = asLeaf Parser{+   complete= Memoizing.terminalPEG (complete p),+   direct=  Memoizing.terminalPEG (direct p),+   direct0=  Memoizing.terminalPEG (direct0 p),+   direct1=  Memoizing.terminalPEG (direct1 p),+   indirect=  Memoizing.terminalPEG (indirect p),+   choices= undefined,+   isAmbiguous= Nothing,+   cyclicDescendants= cyclicDescendants p}
src/Text/Grampa/ContextFree/SortedMemoizing/Transformer.hs view
@@ -1,8 +1,10 @@ {-# LANGUAGE BangPatterns, CPP, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, InstanceSigs,-             RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-}+             RankNTypes, ScopedTypeVariables, TypeFamilies, TypeOperators, UndecidableInstances #-} -- | A context-free memoizing parser that handles all alternatives in parallel -- and carries a monadic computation with each parsing result.-module Text.Grampa.ContextFree.SortedMemoizing.Transformer (ResultListT(..), ParserT(..), (<<|>),+module Text.Grampa.ContextFree.SortedMemoizing.Transformer (ParserT(Parser, applyParser), ResultListT(ResultList),+                                                            ResultsOfLengthT(ResultsOfLengthT, getResultsOfLength),+                                                            ResultsOfLength(ROL),                                                             tbind, lift, tmap, longest, peg, terminalPEG) where @@ -17,6 +19,7 @@ import Data.Function (on) import Data.Functor.Compose (Compose(..)) import Data.Functor.Identity (Identity(..))+import Data.List (intercalate) import Data.List.NonEmpty (NonEmpty((:|)), groupBy, nonEmpty, fromList, toList) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid, splitPrimePrefix)@@ -33,6 +36,7 @@ import qualified Text.Parser.Char import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..))+import Text.Parser.Input.Position (fromEnd) import Text.Parser.LookAhead (LookAheadParsing(..))  import qualified Rank2@@ -41,7 +45,8 @@                           ConsumedInputParsing(..), CommittedParsing(..), DeterministicParsing(..),                           AmbiguousParsing(..), Ambiguous(Ambiguous),                           TailsParsing(..), ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (expected, FallibleResults(..), AmbiguousAlternative(..), TraceableParsing(..))+import Text.Grampa.Internal (emptyFailure, erroneous, expected, expectedInput, replaceExpected,+                             FallibleResults(..), AmbiguousAlternative(..), TraceableParsing(..)) import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack  import Prelude hiding (iterate, null, showList, span, takeWhile)@@ -53,7 +58,7 @@ newtype ResultsOfLengthT m g s r = ResultsOfLengthT{getResultsOfLength :: ResultsOfLength m g s (m r)} data ResultsOfLength m g s a = ROL !Int ![(s, g (ResultListT m g s))] !(NonEmpty a) data ResultListT m g s r = ResultList{resultSuccesses :: ![ResultsOfLengthT m g s r],-                                      resultFailures  :: !(ParseFailure Pos s)}+                                      resultFailures  :: (ParseFailure Pos s)}  singleResult :: (Applicative m, Ord s) => Int -> [(s, g (ResultListT m g s))] -> r -> ResultListT m g s r singleResult len rest a = ResultList [ResultsOfLengthT $ ROL len rest (pure a:|[])] mempty@@ -74,7 +79,7 @@    {-# INLINABLE (<*>) #-}  instance (Applicative m, Ord s) => Alternative (ParserT m g s) where-   empty = Parser (\rest-> ResultList mempty $ ParseFailure (Down $ length rest) [] [])+   empty = Parser (ResultList mempty . emptyFailure . Down . length)    Parser p <|> Parser q = Parser r where       r rest = p rest <> q rest    {-# INLINE (<|>) #-}@@ -107,7 +112,7 @@ instance (Monad m, Traversable m, Ord s) => MonadFail (ParserT m g s) where #endif    fail msg = Parser p-      where p rest = ResultList mempty (ParseFailure (Down $ length rest) [] [StaticDescription msg])+      where p rest = ResultList mempty (erroneous (Down $ length rest) msg)  instance (Foldable m, Monad m, Traversable m, Ord s) => MonadPlus (ParserT m g s) where    mzero = empty@@ -145,7 +150,7 @@    mappend = (<>)  -- | Memoizing parser that carries an applicative computation. Can be wrapped with--- 'Text.Grampa.ContextFree.LeftRecursive.Fixed' to provide left recursion support.+-- 'Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive.Fixed' to provide left recursion support. -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>@@ -164,7 +169,7 @@       where close = Rank2.fmap (<* eof) g  -- | Memoizing parser that carries an applicative computation. Can be wrapped with--- 'Text.Grampa.ContextFree.LeftRecursive.Fixed' to provide left recursion support.+-- 'Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive.Fixed' to provide left recursion support. instance (Applicative m, Ord s, LeftReductive s, FactorialMonoid s) => GrammarParsing (ParserT m g s) where    type ParserGrammar (ParserT m g s) = g    type GrammarFunctor (ParserT m g s) = ResultListT m g s@@ -179,6 +184,22 @@                sync rols = rols       p _ = ResultList mempty (expected 0 "NonTerminal at endOfInput")    {-# INLINE nonTerminal #-}+   chainRecursive assign (Parser base) (Parser recurse) = Parser q+      where q [] = base []+            q ((s, d):t) = case base ((s, assign mempty d) : t)+                           of r@(ResultList [] _) -> r+                              r -> iter r r+               where iter marginal total = case recurse ((s, assign marginal d) : t)+                                           of ResultList [] _ -> total+                                              r -> iter r (total <> r)+   chainLongestRecursive assign (Parser base) (Parser recurse) = Parser q+      where q [] = base []+            q ((s, d):t) = case base ((s, assign mempty d) : t)+                           of r@(ResultList [] _) -> r+                              r -> iter r+               where iter r = case recurse ((s, assign r d) : t)+                              of ResultList [] _ -> r+                                 r' -> iter r'  instance (Applicative m, Ord s, LeftReductive s, FactorialMonoid s, Rank2.Functor g) =>          TailsParsing (ParserT m g s) where@@ -230,7 +251,7 @@    string s = Parser p where       p rest@((s', _) : _)          | s `isPrefixOf` s' = singleResult l (drop l rest) s-      p rest = ResultList mempty (ParseFailure (Down $ length rest) [LiteralDescription s] [])+      p rest = ResultList mempty (expectedInput (fromEnd $ length rest) s)       l = Factorial.length s    notSatisfy predicate = Parser p       where p rest@((s, _):_)@@ -239,12 +260,14 @@             p rest = singleResult 0 rest ()    {-# INLINABLE string #-} -instance InputParsing (ParserT m g s) => TraceableParsing (ParserT m g s) where+instance (InputParsing (ParserT m g s), FactorialMonoid s) => TraceableParsing (ParserT m g s) where    traceInput description (Parser p) = Parser q-      where q rest = case traceWith "Parsing " (p rest)-                     of rl@(ResultList [] _) -> traceWith "Failed " rl-                        rl -> traceWith "Parsed " rl-               where traceWith prefix = trace (prefix <> case rest of ((s, _):_) -> description s; [] -> "EOF")+      where q rest@((s, _):_) = case trace ("Parsing " <> description s) (p rest) of+               rl@(ResultList [] _) -> trace ("Failed " <> descriptionWith id) rl+               rl@(ResultList rs _) -> trace ("Parsed [" <> intercalate ", " (describeResult <$> rs) <> "]") rl+               where describeResult (ResultsOfLengthT (ROL len _ _)) = descriptionWith (Factorial.take len)+                     descriptionWith f = description (f s)+            q [] = p []  instance (Applicative m, Ord s, Show s, TextualMonoid s) => InputCharParsing (ParserT m g s) where    satisfyCharInput predicate = Parser p@@ -286,19 +309,17 @@ instance (Applicative m, MonoidNull s, Ord s) => Parsing (ParserT m g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)-               where rewindFailure (ResultList rl _) = ResultList rl (ParseFailure (Down $ length rest) [] [])+               where rewindFailure (ResultList rl _) = ResultList rl (emptyFailure $ fromEnd $ length rest)    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)-               where replaceFailure (ResultList [] (ParseFailure pos msgs erroneous)) =-                        ResultList [] (ParseFailure pos (if pos == Down (length rest) then [StaticDescription msg]-                                                         else msgs) erroneous)+               where replaceFailure (ResultList [] f) = ResultList [] (replaceExpected (fromEnd $ length rest) msg f)                      replaceFailure rl = rl    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))       where rewind t (ResultList [] _) = singleResult 0 t ()             rewind t ResultList{} = ResultList mempty (expected (Down $ length t) "notFollowedBy")    skipMany p = go       where go = pure () <|> try p *> go-   unexpected msg = Parser (\t-> ResultList mempty $ expected (Down $ length t) msg)+   unexpected msg = Parser (\t-> ResultList mempty $ erroneous (Down $ length t) msg)    eof = Parser f       where f rest@((s, _):_)                | null s = singleResult 0 rest ()@@ -370,20 +391,19 @@ longest :: ParserT Identity g s a -> Backtrack.Parser g [(s, g (ResultListT Identity g s))] a longest p = Backtrack.Parser q where    q rest = case applyParser p rest-            of ResultList [] (ParseFailure pos positive negative)-                  -> Backtrack.NoParse (ParseFailure pos (map message positive) (map message negative))+            of ResultList [] (ParseFailure pos (FailureDescription expected inputs) errors)+                  -> Backtrack.NoParse (ParseFailure pos (FailureDescription expected $ map wrap inputs) errors)                ResultList rs _ -> parsed (last rs)    parsed (ResultsOfLengthT (ROL l s (Identity r:|_))) = Backtrack.Parsed l r s-   message (StaticDescription msg) = StaticDescription msg-   message (LiteralDescription s) = LiteralDescription [(s, error "longest")]+   wrap s = [(s, error "longest")]  -- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest' peg :: (Applicative m, Ord s) => Backtrack.Parser g [(s, g (ResultListT m g s))] a -> ParserT m g s a peg p = Parser q where    q rest = case Backtrack.applyParser p rest             of Backtrack.Parsed l result suffix -> singleResult l suffix result-               Backtrack.NoParse (ParseFailure pos positive negative) ->-                  ResultList mempty (ParseFailure pos ((fst . head <$>) <$> positive) ((fst . head <$>) <$> negative))+               Backtrack.NoParse (ParseFailure pos (FailureDescription expected inputs) errors)+                  -> ResultList mempty (ParseFailure pos (FailureDescription expected (fst . head <$> inputs)) errors)  -- | Turns a backtracking PEG parser into a context-free parser terminalPEG :: (Applicative m, Monoid s, Ord s) => Backtrack.Parser g s a -> ParserT m g s a
+ src/Text/Grampa/ContextFree/SortedMemoizing/Transformer/LeftRecursive.hs view
@@ -0,0 +1,29 @@+{-# Language GADTs #-}+-- | A context-free parser that can handle ambiguous left-recursive grammars and carry a monadic computation with each+-- parsing result.+module Text.Grampa.ContextFree.SortedMemoizing.Transformer.LeftRecursive (+   ParserT, SeparatedParser(..), AmbiguityDecidable,+   lift, liftPositive, tbind, tmap,+   autochain, parseSeparated, separated)+where++import Text.Grampa.Internal.LeftRecursive (Fixed, SeparatedParser(..),+                                           liftPositive, liftPure, mapPrimitive,+                                           autochain, parseSeparated, separated)+import qualified Text.Grampa.ContextFree.SortedMemoizing.Transformer as Transformer+import Text.Grampa.Internal (AmbiguityDecidable)++-- | Parser transformer for left-recursive grammars on top of 'Transformer.ParserT'.+type ParserT m = Fixed (Transformer.ParserT m)++-- | Lift a parse-free computation into the parser.+lift :: (Applicative m, Ord s) => m a -> ParserT m g s a+lift = liftPure . Transformer.lift++-- | Transform the computation carried by the parser using the monadic bind ('>>=').+tbind :: (Monad m, AmbiguityDecidable b) => ParserT m g s a -> (a -> m b) -> ParserT m g s b+tbind p f = mapPrimitive (`Transformer.tbind` f) p++-- | Transform the computation carried by the parser.+tmap :: AmbiguityDecidable b => (m a -> m b) -> ParserT m g s a -> ParserT m g s b+tmap = mapPrimitive . Transformer.tmap
src/Text/Grampa/Internal.hs view
@@ -1,14 +1,17 @@ {-# LANGUAGE ConstrainedClassMethods, FlexibleContexts, FlexibleInstances, GADTs,-             RankNTypes, TypeOperators #-}+             RankNTypes, StandaloneDeriving, TypeOperators, UndecidableInstances #-}  module Text.Grampa.Internal (BinTree(..), ResultList(..), ResultsOfLength(..), FallibleResults(..),                              AmbiguousAlternative(..), AmbiguityDecidable(..), AmbiguityWitness(..),+                             ParserFlags (ParserFlags, nullable, dependsOn),+                             Dependencies (DynamicDependencies, StaticDependencies),                              TraceableParsing(..),-                             noFailure, expected, erroneous) where+                             emptyFailure, erroneous, expected, expectedInput, replaceExpected, noFailure) where  import Control.Applicative (Applicative(..), Alternative(..)) import Data.Foldable (toList) import Data.Functor.Classes (Show1(..))+import Data.Functor.Const (Const) import Data.List.NonEmpty (NonEmpty, nonEmpty) import Data.Monoid (Monoid(mappend, mempty)) import Data.Ord (Down(Down))@@ -20,15 +23,24 @@  import Prelude hiding (length, showList) -data ResultsOfLength g s r = ResultsOfLength !Int ![(s, g (ResultList g s))] !(NonEmpty r)+data ResultsOfLength g s r = ResultsOfLength !Int ![(s, g (ResultList g s))] {-# UNPACK #-} !(NonEmpty r) -data ResultList g s r = ResultList ![ResultsOfLength g s r] !(ParseFailure Pos s)+data ResultList g s r = ResultList ![ResultsOfLength g s r] (ParseFailure Pos s)  data BinTree a = Fork !(BinTree a) !(BinTree a)                | Leaf !a                | EmptyTree                deriving (Show) +data ParserFlags g = ParserFlags {+   nullable :: Bool,+   dependsOn :: Dependencies g}++data Dependencies g = DynamicDependencies+                    | StaticDependencies (g (Const Bool))++deriving instance Show (g (Const Bool)) => Show (Dependencies g)+ data AmbiguityWitness a where    AmbiguityWitness :: (a :~: Ambiguous b) -> AmbiguityWitness a @@ -42,14 +54,25 @@    ambiguityWitness = Just (AmbiguityWitness Refl)  noFailure :: ParseFailure Pos s-noFailure = ParseFailure (Down maxBound) [] []+noFailure = emptyFailure (Down maxBound) +emptyFailure :: Pos -> ParseFailure Pos s+emptyFailure pos = ParseFailure pos (FailureDescription [] []) []+ expected :: Pos -> String -> ParseFailure Pos s-expected pos msg = ParseFailure pos [StaticDescription msg] []+expected pos msg = ParseFailure pos (FailureDescription [msg] []) [] +expectedInput :: Pos -> s -> ParseFailure Pos s+expectedInput pos s = ParseFailure pos (FailureDescription [] [s]) []+ erroneous :: Pos -> String -> ParseFailure Pos s-erroneous pos msg = ParseFailure pos [] [StaticDescription msg]+erroneous pos msg = ParseFailure pos (FailureDescription [] []) [msg] +replaceExpected :: Pos -> String -> ParseFailure Pos s -> ParseFailure Pos s+replaceExpected pos msg f@(ParseFailure pos' msgs errs) = ParseFailure pos' msgs' errs+   where msgs' | pos == pos' = FailureDescription [msg] []+               | otherwise = msgs+ instance (Show s, Show r) => Show (ResultList g s r) where    show (ResultList l f) = "ResultList (" ++ shows l (") (" ++ shows f ")") @@ -116,6 +139,12 @@    fmap f (Fork left right) = Fork (fmap f left) (fmap f right)    fmap f (Leaf a) = Leaf (f a)    fmap _ EmptyTree = EmptyTree++instance Applicative BinTree where+  pure = Leaf+  EmptyTree <*> _ = EmptyTree+  Leaf f <*> t = f <$> t+  Fork f1 f2 <*> t = Fork (f1 <*> t) (f2 <*> t)  instance Foldable BinTree where    foldMap f (Fork left right) = foldMap f left `mappend` foldMap f right
+ src/Text/Grampa/Internal/LeftRecursive.hs view
@@ -0,0 +1,982 @@+{-# LANGUAGE ConstraintKinds, CPP, FlexibleContexts, FlexibleInstances, GADTs, GeneralizedNewtypeDeriving, InstanceSigs,+             RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeFamilies, TypeOperators,+             UndecidableInstances #-}+-- | A context-free memoizing parser that can handle left-recursive grammars.+module Text.Grampa.Internal.LeftRecursive (Fixed(..), SeparatedParser(..),+                                           autochain, asLeaf, liftPositive, liftPure, mapPrimitive,+                                           parseSeparated, separated)+where++import Control.Applicative+import Control.Monad (Monad(..), MonadPlus(..), void)+#if MIN_VERSION_base(4,13,0)+import Control.Monad (MonadFail(fail))+#endif+import Control.Monad.Trans.State.Lazy (State, evalState)+import qualified Control.Monad.Trans.State.Lazy as State++import Data.Functor.Compose (Compose(..))+import Data.Kind (Type)+import Data.Maybe (isJust)++import Data.Semigroup (Semigroup(..))+import Data.Monoid (Monoid(mempty), All(..), Any(..))+import Data.Monoid.Null (MonoidNull(null))+import Data.Monoid.Factorial (FactorialMonoid)+import Data.Monoid.Textual (TextualMonoid)+import Data.Semigroup.Cancellative (LeftReductive)+import qualified Data.Monoid.Factorial as Factorial+import qualified Data.Monoid.Textual as Textual+import Data.String (fromString)+import Data.Type.Equality ((:~:)(Refl))+import Witherable (Filterable(mapMaybe))++import qualified Text.Parser.Char as Char+import Text.Parser.Char (CharParsing)+import Text.Parser.Combinators (Parsing(..))+import Text.Parser.LookAhead (LookAheadParsing(..))++import qualified Rank2+import Text.Grampa.Class (GrammarParsing(..), InputParsing(..), InputCharParsing(..), MultiParsing(..),+                          AmbiguousParsing(..), CommittedParsing(..), ConsumedInputParsing(..),+                          DeterministicParsing(..),+                          TailsParsing(parseTails, parseAllTails),+                          ParseResults, ParseFailure(..), FailureDescription(..), Pos)+import Text.Grampa.Internal (FallibleResults(..),+                             AmbiguousAlternative(ambiguousOr), AmbiguityDecidable(..), AmbiguityWitness(..),+                             ParserFlags (ParserFlags, nullable, dependsOn),+                             Dependencies (DynamicDependencies, StaticDependencies),+                             TraceableParsing(..))+import Text.Grampa.Internal.Storable (Storable1(reuse1), Storable11(reuse11, store11))++import Prelude hiding (cycle, null, span, take, takeWhile)++type ResultAppend p (g :: (Type -> Type) -> Type) s =+   GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s)++-- | A transformer that adds left-recursive powers to a memoizing parser @p@ over grammar @g@+data Fixed p g s a =+   -- | a fully general parser+   Parser {+      complete, direct, direct0, direct1, indirect :: p g s a,+      choices :: ChoiceTree (Fixed p g s a),+      isAmbiguous :: Maybe (AmbiguityWitness a),+      cyclicDescendants :: g (Const (ParserFlags g)) -> ParserFlags g}+   -- | a parser that doesn't start with a 'nonTerminal'+   | DirectParser {+      complete, direct0, direct1 :: p g s a}+   -- | a parser that doesn't start with a 'nonTerminal' and always consumes some input+   | PositiveDirectParser {+      complete :: p g s a}++-- | Binary tree with two different choice nodes+data ChoiceTree a =+   Leaf a+   | SymmetricChoice (ChoiceTree a) (ChoiceTree a)+   | LeftBiasedChoice (ChoiceTree a) (ChoiceTree a)+   deriving Show++instance Functor ChoiceTree where+  fmap f (Leaf a) = Leaf (f a)+  fmap f (SymmetricChoice a b) = SymmetricChoice (fmap f a) (fmap f b)+  fmap f (LeftBiasedChoice a b) = LeftBiasedChoice (fmap f a) (fmap f b)++instance Foldable ChoiceTree where+  foldMap f (Leaf a) = f a+  foldMap f (SymmetricChoice a b) = foldMap f a <> foldMap f b+  foldMap f (LeftBiasedChoice a b) = foldMap f a <> foldMap f b++collapseChoices :: (Alternative p,  DeterministicParsing p) => ChoiceTree (p a) -> p a+collapseChoices (SymmetricChoice p q) = collapseChoices p <|> collapseChoices q+collapseChoices (LeftBiasedChoice p q) = collapseChoices p <<|> collapseChoices q+collapseChoices (Leaf p) = p++-- | A type of parsers analyzed for their left-recursion class+data SeparatedParser p (g :: (Type -> Type) -> Type) s a =+   -- | a parser that no left-recursive nonterminal depends on+   FrontParser (p g s a)+   -- | a left-recursive parser that may add to the set of parse results every time it's run+   | CycleParser {+        cycleParser  :: p g s a,+        backParser   :: p g s a,+        appendResultsArrow :: ResultAppend p g s a,+        dependencies :: Dependencies g}+   -- | a parser that doesn't start with any 'nonTerminal' so it can run first+   | BackParser {+        backParser :: p g s a}++newtype Union (g :: (Type -> Type) -> Type) = Union{getUnion :: g (Const Bool)}++--instance Rank2.Applicative g => Monoid (Union g) where+--   mempty = Union (Rank2.pure $ Const False)++instance (Rank2.Apply g, Rank2.Distributive g) => Semigroup (Union g) where+   Union g1 <> Union g2 = Union (Rank2.liftA2 union g1 g2)++instance (Rank2.Apply g, Rank2.Distributive g) => Monoid (Union g) where+   mempty = Union (Rank2.cotraverse (Const . getConst) (Const False))+   mappend = (<>)++asLeaf :: Fixed p g s a -> Fixed p g s a+asLeaf p@Parser{} = p'+   where p' = p{choices= Leaf p'}+asLeaf p = p++mapPrimitive :: forall p g s a b. AmbiguityDecidable b => (p g s a -> p g s b) -> Fixed p g s a -> Fixed p g s b+mapPrimitive f p@PositiveDirectParser{} = PositiveDirectParser{complete= f (complete p)}+mapPrimitive f p@DirectParser{} = DirectParser{complete= f (complete p),+                                               direct0= f (direct0 p),+                                               direct1= f (direct1 p)}+mapPrimitive f p@Parser{} = asLeaf Parser{+   complete= f (complete p),+   choices= undefined,+   isAmbiguous= ambiguityWitness @b,+   cyclicDescendants= cyclicDescendants p,+   indirect= f (indirect p),+   direct= f (direct p),+   direct0= f (direct0 p),+   direct1= f (direct1 p)}++general, general' :: (Rank2.Apply g, Alternative (p g s)) => Fixed p g s a -> Fixed p g s a+general p = Parser{+   complete= complete p,+   direct = direct p',+   direct0= direct0 p',+   direct1= direct1 p',+   indirect= indirect p',+   choices= choices p',+   isAmbiguous= case p+                of Parser{isAmbiguous= a} -> a+                   _ -> Nothing,+   cyclicDescendants= cyclicDescendants p'}+   where p' = general' p+general' p@PositiveDirectParser{} = asLeaf Parser{+   complete= complete p,+   direct = complete p,+   direct0= empty,+   direct1= complete p,+   indirect= empty,+   choices= undefined,+   isAmbiguous= Nothing,+   cyclicDescendants= \cd-> ParserFlags False (StaticDependencies $ const (Const False) Rank2.<$> cd)}+general' p@DirectParser{} = asLeaf Parser{+   complete= complete p,+   direct = complete p,+   direct0= direct0 p,+   direct1= direct1 p,+   indirect= empty,+   choices= undefined,+   isAmbiguous= Nothing,+   cyclicDescendants= \cd-> ParserFlags True (StaticDependencies $ const (Const False) Rank2.<$> cd)}+general' p@Parser{} = p++type LeftRecParsing p g s f = (Eq s, LeftReductive s, FactorialMonoid s, Alternative (p g s),+                               TailsParsing (p g s), GrammarConstraint (p g s) g, ParserGrammar (p g s) ~ g,+                               Functor (ResultFunctor (p g s)), s ~ ParserInput (p g s), FallibleResults f,+                               Storable1 (GrammarFunctor (p g s)) (ParserFlags g),+                               Storable1 (GrammarFunctor (p g s)) Bool,+                               AmbiguousAlternative (GrammarFunctor (p g s)))++-- | Parser transformer for left-recursive grammars.+--+-- @+-- 'parseComplete' :: ("Rank2".'Rank2.Apply' g, "Rank2".'Rank2.Traversable' g, 'FactorialMonoid' s) =>+--                  g (LeftRecursive.'Parser' g s) -> s -> g ('Compose' ('ParseResults' s) [])+-- @+instance (Rank2.Apply g, GrammarFunctor (p g s) ~ f s, LeftRecParsing p g s f) => MultiParsing (Fixed p g s) where+   type GrammarConstraint (Fixed p g s) g' = (GrammarConstraint (p g s) g', g ~ g',+                                              Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g)+   type ResultFunctor (Fixed p g s) = ResultFunctor (p g s)+   -- parsePrefix :: (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g, Eq s, FactorialMonoid s) =>+   --                g (Fixed p g s) -> s -> g (Compose (ResultFunctor (p g s)) ((,) s))+   parsePrefix g input+      | Just directs <- Rank2.traverse getDirect g' = parsePrefix directs input+      | otherwise = Rank2.fmap (Compose . parsingResult @(p g s) input) (snd $ head $ parseSeparated g' input)+      where g' = separated g+            getDirect (FrontParser p) = Just p+            getDirect (BackParser p) = Just p+            getDirect CycleParser{} = Nothing+   {-# INLINE parsePrefix #-}+   -- parseComplete :: (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g, Eq s, FactorialMonoid s) =>+   --                  g (Fixed p g s) -> s -> g (ResultFunctor (p g s))+   parseComplete g input+      | Just directs <- Rank2.traverse getDirect g' = parseComplete directs input+      | otherwise = Rank2.fmap ((snd <$>) . parsingResult @(p g s) input)+                    $ snd $ head $ parseAllTails close $ parseSeparated g' input+      where g' = separated g+            getDirect (FrontParser p) = Just p+            getDirect (BackParser p) = Just p+            getDirect CycleParser{} = Nothing+            close :: g (p g s)+            close = Rank2.fmap (<* eof) selfReferring+   {-# INLINE parseComplete #-}++-- | Parser transformer for left-recursive grammars.+instance (Rank2.Apply g, GrammarFunctor (p g s) ~ f s, LeftRecParsing p g s f) => GrammarParsing (Fixed p g s) where+   type ParserGrammar (Fixed p g s) = g+   type GrammarFunctor (Fixed p g s) = GrammarFunctor (p g s)+   parsingResult :: s -> GrammarFunctor (p g s) a -> ResultFunctor (p g s) (s, a)+   parsingResult s = parsingResult @(p g s) s+   nonTerminal :: (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g) =>+                  (g (GrammarFunctor (p g s)) -> GrammarFunctor (p g s) a) -> Fixed p g s a+   nonTerminal f = asLeaf Parser{+      complete= ind,+      direct= empty,+      direct0= empty,+      direct1= empty,+      indirect= ind,+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= reuse1 . f . Rank2.fmap store11 . addSelf}+      where ind = nonTerminal f+            addSelf g = Rank2.liftA2 adjust bits g+            adjust :: forall b. Const (g (Const Bool)) b -> Const (ParserFlags g) b -> Const (ParserFlags g) b+            adjust (Const bit) (Const (ParserFlags n (StaticDependencies d))) =+               Const ParserFlags{+                  nullable= n, +                  dependsOn= StaticDependencies (Rank2.liftA2 union bit d)}+            adjust _ flags@(Const (ParserFlags _ DynamicDependencies)) = flags+   {-# INLINE nonTerminal #-}+   recursive = general+   chainRecursive = chainWith chainRecursive+   {-# INLINABLE chainRecursive #-}+   chainLongestRecursive = chainWith chainLongestRecursive+   {-# INLINABLE chainLongestRecursive #-}++chainWith :: (Rank2.Apply g, GrammarFunctor (p g s) ~ f, f ~ rl s, LeftRecParsing p g s rl)+          => ((f a -> g f -> g f) -> p g s a -> p g s a -> p g s a)+          -> ((f a -> g f -> g f) -> Fixed p g s a -> Fixed p g s a -> Fixed p g s a)+chainWith f assign = chain+  where chain base recurse@Parser{} = asLeaf Parser{+           complete= f assign (complete base) (complete recurse),+           direct= f assign (direct base) (complete recurse),+           direct0= f assign (direct0 base) (complete recurse),+           direct1= f assign (direct1 base) (complete recurse),+           indirect= f assign (indirect base) (complete recurse),+           choices= undefined,+           isAmbiguous= isAmbiguous base <|> isAmbiguous recurse,+           cyclicDescendants= \deps-> let ParserFlags pn pd = cyclicDescendants base deps+                                          ParserFlags qn qd = cyclicDescendants recurse deps+                                          qd' = case qd+                                                of DynamicDependencies -> DynamicDependencies+                                                   StaticDependencies g -> StaticDependencies (clearOwnDep g)+                                      in ParserFlags (pn && qn) (depUnion pd qd')}+        chain base recurse = recurse <|> base+        clearOwnDep = Rank2.fmap reuse11 . assign (store11 $ Const False) . Rank2.fmap store11+{-# INLINE chainWith #-}++bits :: forall (g :: (Type -> Type) -> Type). (Rank2.Distributive g, Rank2.Traversable g) => g (Const (g (Const Bool)))+bits = start `seq` Rank2.fmap oneBit start+   where start = evalState (Rank2.traverse next (Rank2.distributeJoin Nothing)) 0+         oneBit :: Const Int a -> Const (g (Const Bool)) a+         next :: f a -> State Int (Const Int a)+         oneBit (Const i) = Const (Rank2.fmap (Const . (i ==) . getConst) start)+         next _ = do {i <- State.get; let {i' = succ i}; seq i' (State.put i'); return (Const i)}++instance Functor (p g s) => Functor (Fixed p g s) where+   fmap f (PositiveDirectParser p) = PositiveDirectParser (fmap f p)+   fmap f p@DirectParser{} = DirectParser{+      complete= fmap f (complete p),+      direct0= fmap f (direct0 p),+      direct1= fmap f (direct1 p)}+   fmap f p@Parser{} = p{+      complete= fmap f (complete p),+      direct= fmap f (direct p),+      direct0= fmap f (direct0 p),+      direct1= fmap f (direct1 p),+      indirect= fmap f (indirect p),+      choices= fmap f <$> choices p,+      isAmbiguous= Nothing}+   {-# INLINABLE fmap #-}++instance (Rank2.Apply g, Alternative (p g s)) => Applicative (Fixed p g s) where+   pure a = DirectParser{complete= pure a,+                         direct0= pure a,+                         direct1= empty}+   p@PositiveDirectParser{} <*> q = PositiveDirectParser{+      complete= complete p <*> complete q}+   p@DirectParser{} <*> q@PositiveDirectParser{} = PositiveDirectParser{+      complete= complete p <*> complete q}+   p@DirectParser{} <*> q@DirectParser{} = DirectParser{+      complete= complete p <*> complete q,+      direct0= direct0 p <*> direct0 q,+      direct1= direct0 p <*> direct1 q <|> direct1 p <*> complete q}+   p <*> q@Parser{} = asLeaf Parser{+      complete= complete p' <*> complete q,+      direct= direct0 p' <*> direct q <|> direct1 p' <*> complete q,+      direct0= direct0 p' <*> direct0 q,+      direct1= direct0 p' <*> direct1 q <|> direct1 p' <*> complete q,+      indirect= direct0 p' <*> indirect q <|> indirect p' <*> complete q,+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= \deps-> let+           pcd@(ParserFlags pn pd) = cyclicDescendants p' deps+           ParserFlags qn qd = cyclicDescendants q deps+        in if pn+           then ParserFlags qn (depUnion pd qd)+           else pcd}+      where p'@Parser{} = general' p+   p <*> q = asLeaf Parser{+      complete= complete p' <*> complete q',+      direct= direct p' <*> complete q',+      direct0= direct0 p' <*> direct0 q',+      direct1= direct0 p' <*> direct1 q' <|> direct1 p' <*> complete q',+      indirect= indirect p' <*> complete q',+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= \deps-> let+           pcd@(ParserFlags pn pd) = cyclicDescendants p' deps+           ParserFlags qn qd = cyclicDescendants q' deps+        in if pn+           then ParserFlags qn (depUnion pd qd)+           else pcd}+      where p'@Parser{} = general' p+            q'@Parser{} = general' q+   {-# INLINABLE pure #-}+   {-# INLINABLE (<*>) #-}++instance (Rank2.Apply g, Alternative (p g s)) => Alternative (Fixed p g s) where+   empty = PositiveDirectParser{complete= empty}+   p@PositiveDirectParser{} <|> q@PositiveDirectParser{} = PositiveDirectParser{complete= complete p <|> complete q}+   p@PositiveDirectParser{} <|> q@DirectParser{} = DirectParser{+      complete= complete p <|> complete q,+      direct0 = direct0 q,+      direct1= complete p <|> direct1 q}+   p@DirectParser{} <|> q@PositiveDirectParser{} = DirectParser{+      complete= complete p <|> complete q,+      direct0 = direct0 p,+      direct1= direct1 p <|> complete q}+   p@DirectParser{} <|> q@DirectParser{} = DirectParser{+      complete= complete p <|> complete q,+      direct0 = direct0 p <|> direct0 q,+      direct1= direct1 p <|> direct1 q}+   p <|> q = Parser{complete= complete p' <|> complete q',+                    direct= direct p' <|> direct q',+                    direct0= direct0 p' <|> direct0 q',+                    direct1= direct1 p' <|> direct1 q',+                    indirect= indirect p' <|> indirect q',+                    choices= choices p' `SymmetricChoice` choices q',+                    isAmbiguous= Nothing,+                    cyclicDescendants= \deps-> let+                         ParserFlags pn pd = cyclicDescendants p' deps+                         ParserFlags qn qd = cyclicDescendants q' deps+                      in ParserFlags (pn || qn) (depUnion pd qd)}+      where p'@Parser{} = general p+            q'@Parser{} = general q+   many (PositiveDirectParser p) = DirectParser{+      complete= many p,+      direct0= pure [],+      direct1= some p}+   many p@DirectParser{} = DirectParser{+      complete= many (complete p),+      direct0= pure [] <|> (:[]) <$> direct0 p,+      direct1= (:) <$> direct1 p <*> many (complete p)}+   many p@Parser{} = asLeaf Parser{+      complete= mcp,+      direct= d0 <|> d1,+      direct0= d0,+      direct1= d1,+      indirect= (:) <$> indirect p <*> mcp,+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}+      where d0 = pure [] <|> (:[]) <$> direct0 p+            d1 = (:) <$> direct1 p <*> mcp+            mcp = many (complete p)+   some (PositiveDirectParser p) = PositiveDirectParser{complete= some p}+   some p@DirectParser{} = DirectParser{+      complete= some (complete p),+      direct0= (:[]) <$> direct0 p,+      direct1= (:) <$> direct1 p <*> many (complete p)}+   some p@Parser{} = asLeaf Parser{+      complete= some (complete p),+      direct= d0 <|> d1,+      direct0= d0,+      direct1= d1,+      indirect= (:) <$> indirect p <*> many (complete p),+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= cyclicDescendants p}+      where d0 = (:[]) <$> direct0 p+            d1= (:) <$> direct1 p <*> many (complete p)+   {-# INLINABLE (<|>) #-}+   {-# INLINABLE many #-}+   {-# INLINABLE some #-}++instance Filterable (p g s) => Filterable (Fixed p g s) where+   mapMaybe f (PositiveDirectParser p) = PositiveDirectParser (mapMaybe f p)+   mapMaybe f p@DirectParser{} = DirectParser{+      complete= mapMaybe f (complete p),+      direct0= mapMaybe f (direct0 p),+      direct1= mapMaybe f (direct1 p)}+   mapMaybe f p@Parser{} = p{+      complete= mapMaybe f (complete p),+      direct= mapMaybe f (direct p),+      direct0= mapMaybe f (direct0 p),+      direct1= mapMaybe f (direct1 p),+      indirect= mapMaybe f (indirect p),+      choices= mapMaybe f <$> choices p,+      isAmbiguous= Nothing}+   {-# INLINABLE mapMaybe #-}++complement :: Const Bool x -> Const Bool x+complement (Const a) = Const (not a)++intersection :: Const Bool x -> Const Bool x -> Const Bool x+intersection (Const True) x = x+intersection (Const False) _ = Const False++union :: Const Bool x -> Const Bool x -> Const Bool x+union (Const False) x = x+union (Const True) _ = Const True++depUnion :: Rank2.Apply g => Dependencies g -> Dependencies g -> Dependencies g+depUnion (StaticDependencies d1) (StaticDependencies d2) = StaticDependencies (Rank2.liftA2 union d1 d2)+depUnion _ _ = DynamicDependencies++instance (Rank2.Apply g, Alternative (p g s), Monad (p g s)) => Monad (Fixed p g s) where+   return = pure+   (>>) = (*>)+   PositiveDirectParser p >>= cont = PositiveDirectParser (p >>= complete . cont)+   p@DirectParser{} >>= cont = asLeaf Parser{+      complete= complete p >>= complete . cont,+      direct= d0 <|> d1,+      direct0= d0,+      direct1= d1,+      indirect= direct0 p >>= indirect . general' . cont,+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= const (ParserFlags True DynamicDependencies)}+      where d0 = direct0 p >>= direct0 . general' . cont+            d1 = (direct0 p >>= direct1 . general' . cont) <|> (direct1 p >>= complete . cont)+   p >>= cont = asLeaf Parser{+      complete= complete p >>= complete . cont,+      direct= d0 <|> d1,+      direct0= d0,+      direct1= d1,+      indirect= (indirect p >>= complete . cont) <|> (direct0 p >>= indirect . general' . cont),+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= \cd->+         let pcd@(ParserFlags pn _) = cyclicDescendants p' cd+         in if pn+            then ParserFlags True DynamicDependencies+            else pcd}+      where d0 = direct0 p >>= direct0 . general' . cont+            d1 = (direct0 p >>= direct1 . general' . cont) <|> (direct1 p >>= complete . cont)+            p'@Parser{} = general' p++#if MIN_VERSION_base(4,13,0)+instance (Rank2.Apply g, Alternative (p g s), MonadFail (p g s)) => MonadFail (Fixed p g s) where+#endif+   fail msg = PositiveDirectParser{complete= fail msg}++instance (Rank2.Apply g, MonadPlus (p g s)) => MonadPlus (Fixed p g s) where+   mzero = empty+   mplus = (<|>)++instance (Rank2.Apply g, Alternative (p g s), Semigroup x) => Semigroup (Fixed p g s x) where+   (<>) = liftA2 (<>)++instance (Rank2.Apply g, Alternative (p g s), Monoid x) => Monoid (Fixed p g s x) where+   mempty = pure mempty+   mappend = (<>)++primitive :: p g s a -> p g s a -> p g s a -> Fixed p g s a+primitive d0 d1 d = DirectParser{complete= d,+                                 direct0= d0,+                                 direct1= d1}+{-# INLINE primitive #-}++-- | Lifts a primitive positive parser (/i.e./, one that always consumes some input) into a left-recursive one+liftPositive :: p g s a -> Fixed p g s a+liftPositive p = PositiveDirectParser{complete= p}+{-# INLINE liftPositive #-}++-- | Lifts a primitive pure parser (/i.e./, one that consumes no input) into a left-recursive one+liftPure :: Alternative (p g s) => p g s a -> Fixed p g s a+liftPure p = DirectParser{complete= p,+                          direct0= p,+                          direct1= empty}+{-# INLINE liftPure #-}++instance (Rank2.Apply g, Parsing (p g s), InputParsing (Fixed p g s)) => Parsing (Fixed p g s) where+   eof = primitive eof empty eof+   try (PositiveDirectParser p) = PositiveDirectParser (try p)+   try p@DirectParser{} = DirectParser{+      complete= try (complete p),+      direct0= try (direct0 p),+      direct1= try (direct1 p)}+   try p@Parser{} = asLeaf p{+      complete= try (complete p),+      direct= try (direct p),+      direct0= try (direct0 p),+      direct1= try (direct1 p),+      indirect= try (indirect p)}+   PositiveDirectParser p <?> msg = PositiveDirectParser (p <?> msg)+   p@DirectParser{} <?> msg = DirectParser{+      complete= complete p <?> msg,+      direct0= direct0 p <?> msg,+      direct1= direct1 p <?> msg}+   p@Parser{} <?> msg = asLeaf p{+      complete= complete p <?> msg,+      direct= direct p <?> msg,+      direct0= direct0 p <?> msg,+      direct1= direct1 p <?> msg,+      indirect= indirect p <?> msg}+   notFollowedBy p@PositiveDirectParser{} = DirectParser{+      complete= notFollowedBy (complete p),+      direct0= notFollowedBy (complete p),+      direct1= empty}+   notFollowedBy p@DirectParser{} = DirectParser{+      complete= notFollowedBy (complete p),+      direct0= notFollowedBy (complete p),+      direct1= empty}+   notFollowedBy p@Parser{} = asLeaf Parser{+      complete= notFollowedBy (complete p),+      direct= notFollowedBy (direct p),+      direct0= notFollowedBy (direct p),+      direct1= empty,+      indirect= notFollowedBy (indirect p),+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}+   unexpected msg = liftPositive (unexpected msg)++instance (Rank2.Apply g, InputParsing (Fixed p g s), DeterministicParsing (p g s)) =>+         DeterministicParsing (Fixed p g s) where+   p@DirectParser{} <<|> q@PositiveDirectParser{} = DirectParser{+      complete= complete p <<|> complete q,+      direct0 = direct0 p,+      direct1= direct1 p <<|> complete q}+   p@DirectParser{} <<|> q@DirectParser{} = DirectParser{+      complete= complete p <<|> complete q,+      direct0 = direct0 p <<|> direct0 q,+      direct1= direct1 p <<|> direct1 q}+   p <<|> q = Parser{complete= complete p' <<|> complete q',+                     direct= direct p' <<|> notFollowedBy (void $ complete p') *> direct q',+                     direct0= direct0 p' <<|> notFollowedBy (void $ complete p') *> direct0 q',+                     direct1= direct1 p' <<|> notFollowedBy (void $ complete p') *> direct1 q',+                     indirect= indirect p' <<|> notFollowedBy (void $ complete p') *> indirect q',+                     choices= choices p' `LeftBiasedChoice` choices q',+                     isAmbiguous= Nothing,+                     cyclicDescendants= \deps-> let+                           ParserFlags pn pd = cyclicDescendants p' deps+                           ParserFlags qn qd = cyclicDescendants q' deps+                        in ParserFlags (pn || qn) (depUnion pd qd)}+      where p'@Parser{} = general p+            q'@Parser{} = general q+   takeSome p = (:) <$> p <*> takeMany p+   takeMany (PositiveDirectParser p) = DirectParser{+      complete = takeMany p,+      direct0= [] <$ notFollowedBy (void p),+      direct1= takeSome p}+   takeMany p@DirectParser{} = DirectParser{+      complete = takeMany (complete p),+      direct0= (:[]) <$> direct0 p <<|> [] <$ notFollowedBy (void $ complete p),+      direct1= (:) <$> direct1 p <*> takeMany (complete p)}+   takeMany p@Parser{} = asLeaf Parser{+      complete= mcp,+      direct= d1 <<|> d0,+      direct0= d0,+      direct1= d1,+      indirect= (:) <$> indirect p <*> mcp,+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}+      where d0 = (:[]) <$> direct0 p <<|> [] <$ notFollowedBy (void $ direct p)+            d1 = (:) <$> direct1 p <*> mcp+            mcp = takeMany (complete p)+   skipAll (PositiveDirectParser p) = DirectParser{+      complete = skipAll p,+      direct0= () <$ notFollowedBy (void p),+      direct1= p *> skipAll p}+   skipAll p@DirectParser{} = DirectParser{+      complete = skipAll (complete p),+      direct0= void (direct0 p) <<|> notFollowedBy (void $ complete p),+      direct1= direct1 p *> skipAll (complete p)}+   skipAll p@Parser{} = asLeaf Parser{+      complete= mcp,+      direct= d1 <<|> d0,+      direct0= d0,+      direct1= d1,+      indirect= indirect p *> mcp,+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}+      where d0 = () <$ direct0 p <<|> notFollowedBy (void $ direct p)+            d1 = direct1 p *> mcp+            mcp = skipAll (complete p)++instance (Rank2.Apply g, CommittedParsing (p g s), CommittedResults (p g s) ~ ParseResults s) =>+         CommittedParsing (Fixed p g s) where+   type CommittedResults (Fixed p g s) = ParseResults s+   commit (PositiveDirectParser p) = PositiveDirectParser (commit p)+   commit p@DirectParser{} = DirectParser{+      complete = commit (complete p),+      direct0= commit (direct0 p),+      direct1= commit (direct1 p)}+   commit p@Parser{} = asLeaf Parser{+      complete= commit (complete p),+      direct= commit (direct p),+      direct0= commit (direct0 p),+      direct1= commit (direct1 p),+      indirect= commit (indirect p),+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= cyclicDescendants p}+   admit :: Fixed p g s (CommittedResults (Fixed p g s) a) -> Fixed p g s a+   admit (PositiveDirectParser p) = PositiveDirectParser (admit p)+   admit p@DirectParser{} = DirectParser{+      complete = admit (complete p),+      direct0= admit (direct0 p),+      direct1= admit (direct1 p)}+   admit p@Parser{} = asLeaf Parser{+      complete= admit (complete p),+      direct= admit (direct p),+      direct0= admit (direct0 p),+      direct1= admit (direct1 p),+      indirect= admit (indirect p),+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= cyclicDescendants p}++instance (Rank2.Apply g, LookAheadParsing (p g s), InputParsing (Fixed p g s)) => LookAheadParsing (Fixed p g s) where+   lookAhead p@PositiveDirectParser{} = DirectParser{+      complete= lookAhead (complete p),+      direct0= lookAhead (complete p),+      direct1= empty}+   lookAhead p@DirectParser{} = DirectParser{+      complete= lookAhead (complete p),+      direct0= lookAhead (complete p),+      direct1= empty}+   lookAhead p@Parser{} = asLeaf Parser{+      complete= lookAhead (complete p),+      direct= lookAhead (direct p),+      direct0= lookAhead (direct p),+      direct1= empty,+      isAmbiguous= isAmbiguous p,+      indirect= lookAhead (indirect p),+      choices= undefined,+      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}++instance (Rank2.Apply g, LeftReductive s, FactorialMonoid s, InputParsing (p g s), ParserInput (p g s) ~ s) =>+         InputParsing (Fixed p g s) where+   type ParserInput (Fixed p g s) = s+   getInput = primitive getInput empty getInput+   anyToken = liftPositive anyToken+   satisfy predicate = liftPositive (satisfy predicate)+   notSatisfy predicate = primitive (notSatisfy predicate) empty (notSatisfy predicate)+   scan s0 f = primitive (mempty <$ notSatisfy test) (lookAhead (satisfy test) *> p) p+      where p = scan s0 f+            test = isJust . f s0+   string s+      | null s = primitive (string s) empty (string s)+      | otherwise = liftPositive (string s)+   take 0 = mempty+   take n = liftPositive (take n)+   takeWhile predicate = primitive (mempty <$ notSatisfy predicate)+                                               (takeWhile1 predicate) (takeWhile predicate)+   takeWhile1 predicate = liftPositive (takeWhile1 predicate)++   {-# INLINABLE string #-}++instance (Rank2.Apply g, LeftReductive s, FactorialMonoid s, Show s,+          TraceableParsing (p g s), ParserInput (p g s) ~ s) =>+         TraceableParsing (Fixed p g s) where+   traceInput description p@PositiveDirectParser{} = p{+      complete= traceInput (\s-> "direct+ " <> description s) (complete p)}+   traceInput description p@DirectParser{} = p{+      complete= traceInput (\s-> "direct " <> description s) (complete p),+      direct0= traceInput (\s-> "direct0 " <> description s) (direct0 p),+      direct1= traceInput (\s-> "direct1 " <> description s) (direct1 p)}+   traceInput description p@Parser{} = asLeaf p{+      complete= traceBy "complete" (complete p),+      direct= traceBy "direct" (direct p),+      direct0= traceBy "direct0" (direct0 p),+      direct1= traceBy "direct1" (direct1 p),+      indirect= traceBy "indirect" (indirect p)}+      where traceBy mode = traceInput (\s-> "(" <> mode <> ") " <> description s)++instance (Rank2.Apply g, LeftReductive s, FactorialMonoid s,+          ConsumedInputParsing (p g s), ParserInput (p g s) ~ s) => ConsumedInputParsing (Fixed p g s) where+   match (PositiveDirectParser p) = PositiveDirectParser (match p)+   match p@DirectParser{} = DirectParser{+      complete= match (complete p),+      direct0 = match (direct0 p),+      direct1 = match (direct1 p)}+   match p@Parser{} = asLeaf Parser{+      complete= match (complete p),+      direct =  match (direct p),+      direct0 = match (direct0 p),+      direct1 = match (direct1 p),+      indirect= match (indirect p),+      choices= undefined,+      isAmbiguous= Nothing,+      cyclicDescendants= cyclicDescendants p}++instance (Rank2.Apply g, Show s, TextualMonoid s, InputCharParsing (p g s), ParserInput (p g s) ~ s) =>+         InputCharParsing (Fixed p g s) where+   satisfyCharInput predicate = liftPositive (satisfyCharInput predicate)+   notSatisfyChar predicate = primitive (notSatisfyChar predicate) empty (notSatisfyChar predicate)+   scanChars s0 f = primitive (mempty <$ notSatisfyChar test) (lookAhead (Char.satisfy test) *> p) p+      where p = scanChars s0 f+            test = isJust . f s0+   takeCharsWhile predicate = primitive (mempty <$ notSatisfyChar predicate)+                                        (takeCharsWhile1 predicate) (takeCharsWhile predicate)+   takeCharsWhile1 predicate = liftPositive (takeCharsWhile1 predicate)++instance (Rank2.Apply g, CharParsing (p g s), InputCharParsing (Fixed p g s), TextualMonoid s,+          s ~ ParserInput (Fixed p g s), Show s) => CharParsing (Fixed p g s) where+   satisfy predicate = liftPositive (Char.satisfy predicate)+   string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)+   text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t)++instance (AmbiguousParsing (p g s), Rank2.Apply g) => AmbiguousParsing (Fixed p g s) where+   ambiguous (PositiveDirectParser p) = PositiveDirectParser (ambiguous p)+   ambiguous p@DirectParser{} = DirectParser{complete= ambiguous (complete p),+                                             direct0=  ambiguous (direct0 p),+                                             direct1=  ambiguous (direct1 p)}+   ambiguous p@Parser{} = asLeaf Parser{+      complete= ambiguous (complete p),+      direct=   ambiguous (direct p),+      direct0=  ambiguous (direct0 p),+      direct1=  ambiguous (direct1 p),+      indirect= ambiguous (indirect p),+      choices= undefined,+      isAmbiguous= Just (AmbiguityWitness Refl),+      cyclicDescendants= cyclicDescendants p}+   {-# INLINABLE ambiguous #-}++-- | Automatically apply 'chainRecursive' and 'chainLongestRecursive' to left-recursive grammar productions where+-- possible.+autochain :: forall p g s f rl (cb :: Type -> Type).+             (cb ~ Const (g (Const Bool)), f ~ GrammarFunctor (p g s), f ~ rl s,+              LeftRecParsing p g s rl, DeterministicParsing (p g s),+              Rank2.Apply g, Rank2.Traversable g, Rank2.Distributive g, Rank2.Logistic g)+          => g (Fixed p g s) -> g (Fixed p g s)+autochain g = Rank2.liftA4 optimize Rank2.getters Rank2.setters candidates g+   where candidates :: g (Const Bool)+         optimize :: forall a. (Compose ((->) (g cb)) cb a)+                  -> (Rank2.Arrow (f Rank2.~> f) (Const (g f -> g f)) a)+                  -> Const Bool a+                  -> Fixed p g s a+                  -> Fixed p g s a+         optimize getter setter (Const True) p@Parser{choices= cs} =+            optimizeChoice (getCompose getter) (getConst . Rank2.apply setter . Rank2.Arrow . const) p cs+         optimize _ _ _ p = p+         optimizeChoice :: (g cb -> cb a)+                        -> (f a -> g f -> g f)+                        -- > (forall f. (f a -> f a) -> g f -> g f)+                        -- > (forall f. Rank2.Arrow f f a -> Const (g f -> g f) a)+                        -> Fixed p g s a+                        -> ChoiceTree (Fixed p g s a)+                        -> Fixed p g s a+         splitSymmetric :: (g cb -> cb a) -> ChoiceTree (Fixed p g s a) -> ([Fixed p g s a], [Fixed p g s a])+         isLeftRecursive :: (g cb -> cb a) -> ChoiceTree (Fixed p g s a) -> Bool+         leftRecursiveParser :: (g cb -> cb a) -> Fixed p g s a -> Bool+         optimizeChoice _ _ fallback Leaf{} = fallback+         optimizeChoice get set fallback (LeftBiasedChoice p q)+            | isLeftRecursive get q = fallback+            | not (isLeftRecursive get p) = fallback+            | LeftBiasedChoice p1 p2 <- p, not (isLeftRecursive get p2)+            = optimizeChoice get set fallback $ LeftBiasedChoice p1 (LeftBiasedChoice p2 q)+            | otherwise = chainLongestRecursive set (collapseChoices q) (collapseChoices p)+         optimizeChoice get set fallback c@SymmetricChoice{}+            | null base = fallback+            | null recursives = fallback+            | otherwise = chainRecursive set (foldr1 (<|>) base) (foldr1 (<|>) recursives)+            where (base, recursives) = splitSymmetric get c+         splitSymmetric get (SymmetricChoice p q) = splitSymmetric get p <> splitSymmetric get q+         splitSymmetric get c+            | isLeftRecursive get c = ([], [collapseChoices c])+            | otherwise = ([collapseChoices c], [])+         isLeftRecursive get = leftRecursiveParser get . collapseChoices+         leftRecursiveParser get Parser{cyclicDescendants= cds} =+            getAny $ Rank2.foldMap (Any . getConst) $ Rank2.liftA2 intersection (getConst $ get bits) (deps bits)+            where deps :: g cb -> g (Const Bool)+                  deps = getDependencies . dependsOn . cds+                         . Rank2.fmap (Const . ParserFlags False . StaticDependencies . getConst)+         leftRecursiveParser _ _ = False+         candidates = Rank2.liftA2 intersection (cyclicDependencies g) (complement Rank2.<$> cyclicDependencies g')+         g' = Rank2.liftA2 noDirectLeftRecursion bits g+         noDirectLeftRecursion (Const bit) p@Parser{cyclicDescendants= cd} = p{cyclicDescendants= excludeSelf . cd}+            where excludeSelf (ParserFlags n DynamicDependencies) = ParserFlags n DynamicDependencies+                  excludeSelf (ParserFlags n (StaticDependencies deps)) =+                     ParserFlags n $ StaticDependencies $ Rank2.liftA2 intersection (complement Rank2.<$> bit) deps+         noDirectLeftRecursion _ p = p++-- | Analyze the grammar's production interdependencies and produce a 'SeparatedParser' from each production's parser.+separated :: forall p g s. (Alternative (p g s), Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g,+                            AmbiguousAlternative (GrammarFunctor (p g s))) =>+             g (Fixed p g s) -> g (SeparatedParser p g s)+separated g = Rank2.liftA4 reseparate circulars cycleFollowers descendants g+   where descendants :: g (Const (Dependencies g))+         cycleFollowers, circulars :: g (Const Bool)+         appendResults :: forall a. Maybe (AmbiguityWitness a)+                       -> GrammarFunctor (p g s) a -> GrammarFunctor (p g s) a -> GrammarFunctor (p g s) a+         leftRecursiveDeps :: forall a. Const Bool a -> Const (Dependencies g) a -> Const (g (Const Bool)) a+         reseparate :: forall a. Const Bool a -> Const Bool a -> Const (Dependencies g) a -> Fixed p g s a+                    -> SeparatedParser p g s a+         reseparate (Const circular) (Const follower) (Const d@(StaticDependencies deps)) p+            | circular || leader && follower =+              CycleParser (indirect p) (direct p) (Rank2.Arrow (Rank2.Arrow . appendResults (isAmbiguous p))) d+            | follower = BackParser (complete p)+            | otherwise = FrontParser (complete p)+            where leader = getAny (Rank2.foldMap (Any . getConst) $ Rank2.liftA2 intersection circulars deps)+         reseparate _ _ (Const d@DynamicDependencies) p =+              CycleParser (indirect p) (direct p) (Rank2.Arrow (Rank2.Arrow . appendResults (isAmbiguous p))) d+         appendResults (Just (AmbiguityWitness Refl)) = ambiguousOr+         appendResults Nothing = (<|>)+         descendants = transitiveDescendants g+         circulars = Rank2.liftA2 leftRecursive bits descendants+         cycleFollowers = getUnion (Rank2.foldMap (Union . getConst) $+                                    Rank2.liftA2 leftRecursiveDeps circulars descendants)+         leftRecursiveDeps (Const True) (Const (StaticDependencies deps)) = Const deps+         leftRecursiveDeps (Const False) (Const (StaticDependencies deps)) =+            Const (Rank2.fmap (const $ Const False) deps)+         leftRecursiveDeps _ (Const DynamicDependencies) = Const (Rank2.fmap (const $ Const True) g)+{-# INLINABLE separated #-}++getDependencies :: Rank2.Distributive g => Dependencies g -> g (Const Bool)+getDependencies (StaticDependencies deps) = deps+getDependencies DynamicDependencies = Rank2.cotraverse (const $ Const True) Nothing++cyclicDependencies :: (Alternative (p g s), Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g)+                   => g (Fixed p g s) -> g (Const Bool)+cyclicDependencies = Rank2.liftA2 leftRecursive bits . transitiveDescendants++leftRecursive :: forall g a. (Rank2.Apply g, Rank2.Foldable g)+              => Const (g (Const Bool)) a -> Const (Dependencies g) a -> Const Bool a+leftRecursive (Const bit) (Const (StaticDependencies deps)) =+   Const (getAny $ Rank2.foldMap (Any . getConst) $ Rank2.liftA2 intersection bit deps)+leftRecursive _ (Const DynamicDependencies) = Const True++transitiveDescendants :: (Alternative (p g s), Rank2.Apply g, Rank2.Traversable g)+                      => g (Fixed p g s) -> g (Const (Dependencies g))+transitiveDescendants =+   Rank2.fmap (Const . dependsOn . getConst) . fixDescendants . Rank2.fmap (Const . cyclicDescendants . general)++fixDescendants :: forall g. (Rank2.Apply g, Rank2.Traversable g)+               => g (Const (g (Const (ParserFlags g)) -> (ParserFlags g))) -> g (Const (ParserFlags g))+fixDescendants gf = go initial+   where go :: g (Const (ParserFlags g)) -> g (Const (ParserFlags g))+         go cd+            | getAll (Rank2.foldMap (All . getConst) $ Rank2.liftA2 agree cd cd') = cd+            | otherwise = go cd'+            where cd' = Rank2.liftA2 flagUnion cd (Rank2.fmap (\(Const f)-> Const (f cd)) gf)+         agree (Const (ParserFlags _xn (StaticDependencies xd))) (Const (ParserFlags _yn (StaticDependencies yd))) =+            Const (getAll (Rank2.foldMap (All . getConst) (Rank2.liftA2 agree' xd yd)))+         agree (Const (ParserFlags _xn DynamicDependencies)) (Const (ParserFlags _yn DynamicDependencies)) = Const True+         agree _ _ = Const False+         agree' (Const x) (Const y) = Const (x == y)+         flagUnion (Const ParserFlags{dependsOn= old}) (Const (ParserFlags n new)) = +            Const (ParserFlags n $ depUnion old new)+         initial = Rank2.liftA2 (\_ (Const n)-> Const (ParserFlags n deps)) gf nullabilities+         deps = StaticDependencies (const (Const False) Rank2.<$> gf)+         nullabilities = fixNullabilities gf+{-# INLINABLE fixDescendants #-}++fixNullabilities :: forall g. (Rank2.Apply g, Rank2.Traversable g)+                    => g (Const (g (Const (ParserFlags g)) -> (ParserFlags g))) -> g (Const Bool)+fixNullabilities gf = Const . nullable . getConst Rank2.<$> go initial+   where go :: g (Const (ParserFlags g)) -> g (Const (ParserFlags g))+         go cd+            | getAll (Rank2.foldMap (All . getConst) $ Rank2.liftA2 agree cd cd') = cd+            | otherwise = go cd'+            where cd' = Rank2.fmap (\(Const f)-> Const (f cd)) gf+         agree (Const flags1) (Const flags2) = Const (nullable flags1 == nullable flags2)+         initial = const (Const (ParserFlags True (StaticDependencies $ const (Const False) Rank2.<$> gf))) Rank2.<$> gf+{-# INLINABLE fixNullabilities #-}++-- | Parse the given input using a context-free grammar 'separated' into left-recursive and other productions.+parseSeparated :: forall p g rl s. (Rank2.Apply g, Rank2.Foldable g, Eq s, FactorialMonoid s, LeftReductive s,+                                    TailsParsing (p g s), GrammarConstraint (p g s) g,+                                    GrammarFunctor (p g s) ~ rl s, FallibleResults rl,+                                    s ~ ParserInput (p g s)) =>+                  g (SeparatedParser p g s) -> s -> [(s, g (GrammarFunctor (p g s)))]+parseSeparated parsers input = foldr parseTail [] (Factorial.tails input)+   where parseTail s parsedTail = parsed+            where parsed = (s,d''):parsedTail+                  d      = Rank2.fmap (($ (s,d):parsedTail) . parseTails) directs+                  d'     = fixRecursive s parsedTail d+                  d''    = Rank2.liftA2 f parsers d'+                  f :: forall a. SeparatedParser p g s a -> GrammarFunctor (p g s) a -> GrammarFunctor (p g s) a+                  f (FrontParser p) _ = parseTails p ((s,d''):parsedTail)+                  f _ result = result+         fixRecursive :: s -> [(s, g (GrammarFunctor (p g s)))]+                      -> g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s))+         whileAnyContinues :: (g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s)))+                           -> (g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s)))+                           -> g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s)) -> g (GrammarFunctor (p g s))+         recurseTotal :: s -> g (GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s))+                      -> [(s, g (GrammarFunctor (p g s)))]+                      -> g (GrammarFunctor (p g s))+                      -> g (GrammarFunctor (p g s))+         recurseMarginal :: s -> [(s, g (GrammarFunctor (p g s)))]+                      -> g (GrammarFunctor (p g s))+                      -> g (GrammarFunctor (p g s))+         maybeDependencies :: g (Const (Maybe (Dependencies g)))+         maybeDependency :: SeparatedParser p g s r -> Const (Maybe (Dependencies g)) r+         appends :: g (ResultAppend p g s)+         parserAppend :: SeparatedParser p g s r -> ResultAppend p g s r++         directs = Rank2.fmap backParser parsers+         indirects = Rank2.fmap (\p-> case p of {CycleParser{}-> cycleParser p; _ -> empty}) parsers+         appends = Rank2.fmap parserAppend parsers+         parserAppend p@CycleParser{} = appendResultsArrow p+         parserAppend _ = Rank2.Arrow (Rank2.Arrow . const)+         maybeDependencies = Rank2.fmap maybeDependency parsers+         maybeDependency p@CycleParser{} = Const (Just $ dependencies p)+         maybeDependency _ = Const Nothing++         -- Fix the recursive knot on the head of the input, given its already-fixed tail and the initial record of+         -- directly parsed results.+         fixRecursive s parsedTail initial =+            whileAnyContinues (recurseTotal s (appends Rank2.<*> initial) parsedTail)+                              (recurseMarginal s parsedTail)+                              initial initial++         -- Loop accumulating the total parsing results from marginal results as long as there is any new marginal+         -- result to expand a total one or a new failure expactation to augment an existing failure.+         whileAnyContinues ft fm total marginal =+            Rank2.liftA3 choiceWhile maybeDependencies total (whileAnyContinues ft fm (ft total) (fm marginal))+            where choiceWhile :: Const (Maybe (Dependencies g)) x+                              -> GrammarFunctor (p g s) x -> GrammarFunctor (p g s) x+                              -> GrammarFunctor (p g s) x+                  choiceWhile (Const Nothing) t _ = t+                  choiceWhile (Const (Just (StaticDependencies deps))) t t'+                     | getAny (Rank2.foldMap (Any . getConst) (Rank2.liftA2 combine deps marginal)) = t'+                     | hasSuccess t = t+                     | otherwise =+                        failWith (failureOf $+                                  if getAny (Rank2.foldMap (Any . getConst) $+                                             Rank2.liftA2 (combineFailures $ failureOf t) deps marginal)+                                  then t' else t)+                     where combine :: Const Bool x -> GrammarFunctor (p g s) x -> Const Bool x+                           combineFailures :: ParseFailure Pos s -> Const Bool x -> GrammarFunctor (p g s) x+                                           -> Const Bool x+                           combine (Const False) _ = Const False+                           combine (Const True) results = Const (hasSuccess results)+                           combineFailures _ (Const False) _ = Const False+                           combineFailures (ParseFailure pos (FailureDescription expected inputs) errors) (Const True) rl =+                              Const (pos < pos'+                                     || pos == pos' && (any (`notElem` expected) expected'+                                                        || any (`notElem` expected) expected')+                                                        || any (`notElem` errors) errors')+                              where ParseFailure pos' (FailureDescription expected' inputs') errors' = failureOf rl+                  choiceWhile (Const (Just DynamicDependencies)) t t'+                     | getAny (Rank2.foldMap (Any . hasSuccess) marginal) = t'+                     | hasSuccess t = t+                     | ParseFailure _ (FailureDescription [] []) [] <- failureOf t = t'+                     | otherwise = t++         -- Adds another round of indirect parsing results to the total results accumulated so far.+         recurseTotal s initialAppends parsedTail total = Rank2.liftA2 reparse initialAppends indirects+            where reparse :: (GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s)) a -> p g s a+                          -> GrammarFunctor (p g s) a+                  reparse append p = Rank2.apply append (parseTails p $ (s, total) : parsedTail)+         -- Calculates the next round of indirect parsing results from the previous marginal round.+         recurseMarginal s parsedTail marginal =+            flip parseTails ((s, marginal) : parsedTail) Rank2.<$> indirects+{-# NOINLINE parseSeparated #-}
+ src/Text/Grampa/Internal/Storable.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}++module Text.Grampa.Internal.Storable (Storable(..), Storable1(..), Storable11(..),+                                      Dependencies(..), ParserFlags(..)) where++import Data.Functor.Const (Const(Const, getConst))+import qualified Rank2+import Text.Grampa.Class (ParseFailure(ParseFailure))+import Text.Grampa.Internal (ResultList(ResultList), ResultsOfLength(ResultsOfLength),+                             ParserFlags (ParserFlags, nullable, dependsOn),+                             Dependencies (DynamicDependencies, StaticDependencies))+import qualified Text.Grampa.ContextFree.SortedMemoizing.Transformer as Transformer++class Storable s a where+   store :: a -> s+   reuse :: s -> a++class Storable1 s a where+   store1 :: a -> s b+   reuse1 :: s b -> a++class Storable11 s t where+   store11 :: t a -> s b+   reuse11 :: s b -> t a++instance Storable a a where+   store = id+   reuse = id++instance Storable1 (Const a) a where+   store1 = Const+   reuse1 = getConst++instance Storable1 s a => Storable11 s (Const a) where+   store11 = store1 . getConst+   reuse11 = Const . reuse1++instance (Storable1 f a, Rank2.Functor g) => Storable (g f) (g (Const a)) where+   store = Rank2.fmap (store1 . getConst)+   reuse = Rank2.fmap (Const . reuse1)++instance Ord s => Storable1 (ResultList g s) Bool where+   store1 bit = ResultList [] (ParseFailure (if bit then 1 else 0) mempty [])+   reuse1 (ResultList _ (ParseFailure pos _ _)) = pos /= 0++instance (Rank2.Functor g, Monoid s, Ord s) => Storable1 (ResultList g s) (ParserFlags g) where+   store1 a = ResultList [store a] mempty+   reuse1 (ResultList [s] _) = reuse s++instance (Rank2.Functor g, Monoid s, Ord s) => Storable (ResultsOfLength g s r) (ParserFlags g) where+   store (ParserFlags n d) = ResultsOfLength (if n then 1 else 0) (store d) (pure $ error "unused")+   reuse (ResultsOfLength n d _) = ParserFlags (n /= 0) (reuse d)++instance (Rank2.Functor g, Monoid s, Ord s) => Storable [(s, g (ResultList g s))] (Dependencies g) where+   store DynamicDependencies = []+   store (StaticDependencies deps) = [(mempty, store deps)]+   reuse [] = DynamicDependencies+   reuse [(_, deps)] = StaticDependencies (reuse deps)++instance Ord s => Storable1 (Transformer.ResultListT m g s) Bool where+   store1 bit = Transformer.ResultList [] (ParseFailure (if bit then 1 else 0) mempty [])+   reuse1 (Transformer.ResultList _ (ParseFailure pos _ _)) = pos /= 0++instance (Rank2.Functor g, Monoid s, Ord s) => Storable1 (Transformer.ResultListT m g s) (ParserFlags g) where+   store1 a = Transformer.ResultList [store a] mempty+   reuse1 (Transformer.ResultList [s] _) = reuse s++instance (Rank2.Functor g, Monoid s, Ord s) => Storable (Transformer.ResultsOfLengthT m g s r) (ParserFlags g) where+   store = Transformer.ResultsOfLengthT . store+   reuse = reuse . Transformer.getResultsOfLength++instance (Rank2.Functor g, Monoid s, Ord s) => Storable (Transformer.ResultsOfLength m g s r) (ParserFlags g) where+   store (ParserFlags n d) = Transformer.ROL (if n then 1 else 0) (store d) (pure $ error "unused")+   reuse (Transformer.ROL n d _) = ParserFlags (n /= 0) (reuse d)++instance (Rank2.Functor g, Monoid s, Ord s) => Storable [(s, g (Transformer.ResultListT m g s))] (Dependencies g) where+   store DynamicDependencies = []+   store (StaticDependencies deps) = [(mempty, store deps)]+   reuse [] = DynamicDependencies+   reuse [(_, deps)] = StaticDependencies (reuse deps)
src/Text/Grampa/PEG/Backtrack.hs view
@@ -34,7 +34,7 @@ import Text.Grampa.Class (CommittedParsing(..), DeterministicParsing(..),                           InputParsing(..), InputCharParsing(..), MultiParsing(..),                           ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (expected, TraceableParsing(..))+import Text.Grampa.Internal (emptyFailure, erroneous, expected, expectedInput, replaceExpected, TraceableParsing(..))  data Result (g :: (Type -> Type) -> Type) s v =      Parsed{parsedPrefix :: !v,@@ -71,7 +71,7 @@    {-# INLINABLE (<*>) #-}  instance Factorial.FactorialMonoid s => Alternative (Parser g s) where-   empty = Parser (\rest-> NoParse $ ParseFailure (fromEnd $ Factorial.length rest) [] [])+   empty = Parser (NoParse . emptyFailure . fromEnd . Factorial.length)    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator@@ -94,7 +94,7 @@  #if MIN_VERSION_base(4,13,0) instance Factorial.FactorialMonoid s => MonadFail (Parser g s) where-   fail msg = Parser (\rest-> NoParse $ ParseFailure (fromEnd $ Factorial.length rest) [] [StaticDescription msg])+   fail msg = Parser (\rest-> NoParse $ erroneous (fromEnd $ Factorial.length rest) msg) #endif  instance Factorial.FactorialMonoid s => MonadPlus (Parser g s) where@@ -111,22 +111,17 @@ instance Factorial.FactorialMonoid s => Parsing (Parser g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)-               where rewindFailure NoParse{} = NoParse (ParseFailure (fromEnd $ Factorial.length rest) [] [])+               where rewindFailure NoParse{} = NoParse (emptyFailure $ fromEnd $ Factorial.length rest)                      rewindFailure parsed = parsed    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)-               where replaceFailure (NoParse (ParseFailure pos msgs _)) =-                        NoParse (ParseFailure pos-                                              (if pos == fromEnd (Factorial.length rest) then [StaticDescription msg]-                                               else msgs)-                                              [])+               where replaceFailure (NoParse f) = NoParse (replaceExpected (fromEnd $ Factorial.length rest) msg f)                      replaceFailure parsed = parsed    eof = Parser p       where p rest                | Null.null rest = Parsed () rest-               | otherwise = NoParse (ParseFailure (fromEnd $ Factorial.length rest)-                                                   [StaticDescription "end of input"] [])-   unexpected msg = Parser (\t-> NoParse $ ParseFailure (fromEnd $ Factorial.length t) [] [StaticDescription msg])+               | otherwise = NoParse (expected (fromEnd $ Factorial.length rest) "end of input")+   unexpected msg = Parser (\t-> NoParse $ erroneous (fromEnd $ Factorial.length t) msg)    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))       where rewind t Parsed{} = NoParse (expected (fromEnd $ Factorial.length t) "notFollowedBy")             rewind t NoParse{} = Parsed () t@@ -198,13 +193,15 @@                         else Parsed prefix suffix    string s = Parser p where       p s' | Just suffix <- Cancellative.stripPrefix s s' = Parsed s suffix-           | otherwise = NoParse (ParseFailure (fromEnd $ Factorial.length s') [LiteralDescription s] [])+           | otherwise = NoParse (expectedInput (fromEnd $ Factorial.length s') s)    {-# INLINABLE string #-} -instance InputParsing (Parser g s)  => TraceableParsing (Parser g s) where+instance (InputParsing (Parser g s), FactorialMonoid s)  => TraceableParsing (Parser g s) where    traceInput description (Parser p) = Parser q       where q s = case traceWith "Parsing " (p s)-                  of r@Parsed{} -> traceWith "Parsed " r+                  of r@Parsed{}+                        | let prefix = Factorial.take (Factorial.length s - Factorial.length (parsedSuffix r)) s+                          -> trace ("Parsed " <> description prefix) r                      r@NoParse{} -> traceWith "Failed " r                where traceWith prefix = trace (prefix <> description s) 
src/Text/Grampa/PEG/Backtrack/Measured.hs view
@@ -33,8 +33,8 @@ import Text.Parser.Input.Position (fromEnd) import Text.Grampa.Class (CommittedParsing(..), DeterministicParsing(..),                           InputParsing(..), InputCharParsing(..), ConsumedInputParsing(..),-                          MultiParsing(..), ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (expected, TraceableParsing(..))+                          MultiParsing(..), ParseResults, ParseFailure(..), Pos)+import Text.Grampa.Internal (emptyFailure, erroneous, expected, expectedInput, replaceExpected, TraceableParsing(..))  data Result (g :: (Type -> Type) -> Type) s v =      Parsed{parsedLength :: !Int,@@ -74,7 +74,7 @@    {-# INLINABLE (<*>) #-}  instance FactorialMonoid s => Alternative (Parser g s) where-   empty = Parser (\rest-> NoParse $ ParseFailure (fromEnd $ Factorial.length rest) [] [])+   empty = Parser (NoParse . emptyFailure . fromEnd . Factorial.length)    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator@@ -104,7 +104,7 @@ #if MIN_VERSION_base(4,13,0) instance FactorialMonoid s => MonadFail (Parser g s) where #endif-   fail msg = Parser (\rest-> NoParse $ ParseFailure (fromEnd $ Factorial.length rest) [] [StaticDescription msg])+   fail msg = Parser (\rest-> NoParse $ erroneous (fromEnd $ Factorial.length rest) msg)  instance FactorialMonoid s => MonadPlus (Parser g s) where    mzero = empty@@ -120,24 +120,19 @@ instance FactorialMonoid s => Parsing (Parser g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)-               where rewindFailure NoParse{} = NoParse (ParseFailure (fromEnd $ Factorial.length rest) [] [])+               where rewindFailure NoParse{} = NoParse (emptyFailure $ fromEnd $ Factorial.length rest)                      rewindFailure parsed = parsed    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)-               where replaceFailure (NoParse (ParseFailure pos msgs erroneous)) =-                        NoParse (ParseFailure pos-                                    (if pos == fromEnd (Factorial.length rest) then [StaticDescription msg] else msgs)-                                    erroneous)+               where replaceFailure (NoParse f) = NoParse (replaceExpected (fromEnd $ Factorial.length rest) msg f)                      replaceFailure parsed = parsed    eof = Parser p       where p rest                | Null.null rest = Parsed 0 () rest-               | otherwise = NoParse (ParseFailure (fromEnd $ Factorial.length rest)-                                                   [StaticDescription "end of input"] [])-   unexpected msg = Parser (\t-> NoParse $ ParseFailure (fromEnd $ Factorial.length t) [] [StaticDescription msg])+               | otherwise = NoParse (expected (fromEnd $ Factorial.length rest) "end of input")+   unexpected msg = Parser (\t-> NoParse $ erroneous (fromEnd $ Factorial.length t) msg)    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))-      where rewind t Parsed{} = NoParse (ParseFailure (fromEnd $ Factorial.length t)-                                                      [StaticDescription "notFollowedBy"] [])+      where rewind t Parsed{} = NoParse (expected (fromEnd $ Factorial.length t) "notFollowedBy")             rewind t NoParse{} = Parsed 0 () t  instance FactorialMonoid s => CommittedParsing (Parser g s) where@@ -208,7 +203,7 @@                         else Parsed (Factorial.length prefix) prefix suffix    string s = Parser p where       p s' | Just suffix <- Cancellative.stripPrefix s s' = Parsed l s suffix-           | otherwise = NoParse (ParseFailure (fromEnd $ Factorial.length s') [LiteralDescription s] [])+           | otherwise = NoParse (expectedInput (fromEnd $ Factorial.length s') s)       l = Factorial.length s    {-# INLINABLE string #-} @@ -218,10 +213,10 @@                      of Parsed l prefix suffix -> Parsed l (Factorial.take l rest, prefix) suffix                         NoParse failure -> NoParse failure -instance InputParsing (Parser g s)  => TraceableParsing (Parser g s) where+instance (InputParsing (Parser g s), FactorialMonoid s)  => TraceableParsing (Parser g s) where    traceInput description (Parser p) = Parser q       where q s = case traceWith "Parsing " (p s)-                  of r@Parsed{} -> traceWith "Parsed " r+                  of r@Parsed{} -> trace ("Parsed " <> description (Factorial.take (parsedLength r) s)) r                      r@NoParse{} -> traceWith "Failed " r                where traceWith prefix = trace (prefix <> description s) 
src/Text/Grampa/PEG/Continued.hs view
@@ -33,12 +33,12 @@ import Text.Parser.Input.Position (fromEnd) import Text.Grampa.Class (CommittedParsing(..), DeterministicParsing(..),                           InputParsing(..), InputCharParsing(..), MultiParsing(..),-                          ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (expected, TraceableParsing(..))+                          ParseResults, ParseFailure(..), Pos)+import Text.Grampa.Internal (emptyFailure, erroneous, expected, expectedInput, replaceExpected, TraceableParsing(..))  data Result (g :: (Type -> Type) -> Type) s v = Parsed{parsedPrefix :: !v,-                                              parsedSuffix :: !s}-                                     | NoParse (ParseFailure Pos s)+                                                       parsedSuffix :: !s}+                                              | NoParse (ParseFailure Pos s)  -- | Parser type for Parsing Expression Grammars that uses a continuation-passing algorithm, fast for grammars in -- LL(1) class but with potentially exponential performance for longer ambiguous prefixes.@@ -55,8 +55,7 @@  instance Factorial.FactorialMonoid s => Filterable (Result g s) where    mapMaybe f (Parsed a rest) =-      maybe (NoParse $ ParseFailure (fromEnd $ Factorial.length rest) [StaticDescription "filter"] [])-            (`Parsed` rest) (f a)+      maybe (NoParse $ expected (fromEnd $ Factorial.length rest) "filter") (`Parsed` rest) (f a)    mapMaybe _ (NoParse failure) = NoParse failure     instance Functor (Parser g s) where@@ -72,7 +71,7 @@    {-# INLINABLE (<*>) #-}  instance (FactorialMonoid s, Ord s) => Alternative (Parser g s) where-   empty = Parser (\rest _ failure-> failure $ ParseFailure (fromEnd $ Factorial.length rest) [] [])+   empty = Parser (\rest _ failure-> failure $ emptyFailure $ fromEnd $ Factorial.length rest)    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator@@ -103,8 +102,7 @@ #if MIN_VERSION_base(4,13,0) instance (FactorialMonoid s, Ord s) => MonadFail (Parser g s) where #endif-   fail msg = Parser (\rest _ failure-> failure $-                       ParseFailure (fromEnd $ Factorial.length rest) [StaticDescription msg] [])+   fail msg = Parser (\rest _ failure-> failure $ erroneous (fromEnd $ Factorial.length rest) msg)  instance (FactorialMonoid s, Ord s) => MonadPlus (Parser g s) where    mzero = empty@@ -121,27 +119,20 @@    try :: forall a. Parser g s a -> Parser g s a    try (Parser p) = Parser q       where q :: forall x. s -> (a -> s -> x) -> (ParseFailure Pos s -> x) -> x-            q input success failure = p input success (const $ failure-                                                       $ ParseFailure (fromEnd $ Factorial.length input) [] [])+            q input success failure = p input success (const $ failure $ emptyFailure $ fromEnd $ Factorial.length input)    (<?>) :: forall a. Parser g s a -> String -> Parser g s a    Parser p <?> msg  = Parser q       where q :: forall x. s -> (a -> s -> x) -> (ParseFailure Pos s -> x) -> x-            q input success failure = p input success (failure . replaceFailure)-               where replaceFailure (ParseFailure pos msgs erroneous) =-                        ParseFailure pos (if pos == fromEnd (Factorial.length input) then [StaticDescription msg]-                                          else msgs) erroneous+            q input success failure = p input success (failure . replaceExpected (fromEnd $ Factorial.length input) msg)    eof = Parser p       where p rest success failure                | Null.null rest = success () rest-               | otherwise = failure (ParseFailure (fromEnd $ Factorial.length rest)-                                                   [StaticDescription "end of input"] [])-   unexpected msg = Parser (\t _ failure ->-                             failure $ ParseFailure (fromEnd $ Factorial.length t) [] [StaticDescription msg])+               | otherwise = failure (expected (fromEnd $ Factorial.length rest) "end of input")+   unexpected msg = Parser (\t _ failure -> failure $ erroneous (fromEnd $ Factorial.length t) msg)    notFollowedBy (Parser p) = Parser q       where q :: forall x. s -> (() -> s -> x) -> (ParseFailure Pos s -> x) -> x             q input success failure = p input success' failure'-               where success' _ _ =-                        failure (ParseFailure (fromEnd $ Factorial.length input) [StaticDescription "notFollowedBy"] [])+               where success' _ _ = failure (expected (fromEnd $ Factorial.length input)  "notFollowedBy")                      failure' _ = success () input  instance (FactorialMonoid s, Ord s) => CommittedParsing (Parser g s) where@@ -229,17 +220,18 @@       p :: forall x. s -> (s -> s -> x) -> (ParseFailure Pos s -> x) -> x       p s' success failure          | Just suffix <- stripPrefix s s' = success s suffix-         | otherwise = failure (ParseFailure (fromEnd $ Factorial.length s') [LiteralDescription s] [])+         | otherwise = failure (expectedInput (fromEnd $ Factorial.length s') s)    {-# INLINABLE string #-} -instance InputParsing (Parser g s)  => TraceableParsing (Parser g s) where+instance (InputParsing (Parser g s), FactorialMonoid s)  => TraceableParsing (Parser g s) where    traceInput :: forall a. (s -> String) -> Parser g s a -> Parser g s a    traceInput description (Parser p) = Parser q       where q :: forall x. s -> (a -> s -> x) -> (ParseFailure Pos s -> x) -> x             q rest success failure = traceWith "Parsing " (p rest success' failure')                where traceWith prefix = trace (prefix <> description rest)                      failure' f = traceWith "Failed " (failure f)-                     success' r suffix = traceWith "Parsed " (success r suffix)+                     success' r suffix = trace ("Parsed " <> description prefix) (success r suffix)+                        where prefix = Factorial.take (Factorial.length rest - Factorial.length prefix) rest  instance (Ord s, Show s, TextualMonoid s) => InputCharParsing (Parser g s) where    satisfyCharInput predicate = Parser p
src/Text/Grampa/PEG/Continued/Measured.hs view
@@ -33,7 +33,7 @@ import Text.Grampa.Class (CommittedParsing(..), DeterministicParsing(..),                           InputParsing(..), InputCharParsing(..), ConsumedInputParsing(..),                           MultiParsing(..), ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (TraceableParsing(..), expected)+import Text.Grampa.Internal (TraceableParsing(..), emptyFailure, erroneous, expected, expectedInput, replaceExpected) import Text.Grampa.PEG.Continued (Result(..))  -- | Parser type for Parsing Expression Grammars that uses a continuation-passing algorithm and keeps track of the@@ -55,7 +55,7 @@    {-# INLINABLE (<*>) #-}  instance (FactorialMonoid s, Ord s) => Alternative (Parser g s) where-   empty = Parser (\rest _ failure-> failure $ ParseFailure (fromEnd $ Factorial.length rest) [] [])+   empty = Parser (\rest _ failure-> failure $ emptyFailure $ fromEnd $ Factorial.length rest)    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator@@ -105,20 +105,16 @@    try :: forall a. Parser g s a -> Parser g s a    try (Parser p) = Parser q       where q :: forall x. s -> (a -> Int -> s -> x) -> (ParseFailure Pos s -> x) -> x-            q input success failure =-               p input success (const $ failure $ ParseFailure (fromEnd $ Factorial.length input) [] [])+            q input success failure = p input success (const $ failure $ emptyFailure $ fromEnd $ Factorial.length input)    (<?>) :: forall a. Parser g s a -> String -> Parser g s a    Parser p <?> msg  = Parser q       where q :: forall x. s -> (a -> Int -> s -> x) -> (ParseFailure Pos s -> x) -> x-            q input success failure = p input success (failure . replaceFailure)-               where replaceFailure (ParseFailure pos msgs erroneous) =-                        ParseFailure pos (if pos == fromEnd (Factorial.length input) then [StaticDescription msg]-                                          else msgs) erroneous+            q input success failure = p input success (failure . replaceExpected (fromEnd $ Factorial.length input) msg)    eof = Parser p       where p rest success failure                | Null.null rest = success () 0 rest                | otherwise = failure (expected (fromEnd $ Factorial.length rest) "end of input")-   unexpected msg = Parser (\t _ failure -> failure $ expected (fromEnd $ Factorial.length t) msg)+   unexpected msg = Parser (\t _ failure -> failure $ erroneous (fromEnd $ Factorial.length t) msg)    notFollowedBy (Parser p) = Parser q       where q :: forall x. s -> (() -> Int -> s -> x) -> (ParseFailure Pos s -> x) -> x             q input success failure = p input success' failure'@@ -215,7 +211,7 @@       p :: forall x. s -> (s -> Int -> s -> x) -> (ParseFailure Pos s -> x) -> x       p s' success failure          | Just suffix <- stripPrefix s s', !len <- Factorial.length s = success s len suffix-         | otherwise = failure (ParseFailure (fromEnd $ Factorial.length s') [LiteralDescription s] [])+         | otherwise = failure (expectedInput (fromEnd $ Factorial.length s') s)    {-# INLINABLE string #-}  instance (LeftReductive s, FactorialMonoid s, Ord s) => ConsumedInputParsing (Parser g s) where@@ -225,14 +221,15 @@             q rest success failure = p rest success' failure                where success' r !len suffix = success (Factorial.take len rest, r) len suffix -instance InputParsing (Parser g s)  => TraceableParsing (Parser g s) where+instance (InputParsing (Parser g s), FactorialMonoid s)  => TraceableParsing (Parser g s) where    traceInput :: forall a. (s -> String) -> Parser g s a -> Parser g s a    traceInput description (Parser p) = Parser q       where q :: forall x. s -> (a -> Int -> s -> x) -> (ParseFailure Pos s -> x) -> x             q rest success failure = traceWith "Parsing " (p rest success' failure')                where traceWith prefix = trace (prefix <> description rest)                      failure' f = traceWith "Failed " (failure f)-                     success' r !len suffix = traceWith "Parsed " (success r len suffix)+                     success' r !len suffix =+                        trace ("Parsed " <> description (Factorial.take len rest)) (success r len suffix)  instance (Ord s, Show s, TextualMonoid s) => InputCharParsing (Parser g s) where    satisfyCharInput predicate = Parser p
src/Text/Grampa/PEG/Packrat.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, FlexibleContexts, TypeFamilies, UndecidableInstances #-}+{-# LANGUAGE CPP, FlexibleContexts, TypeFamilies, TypeOperators, UndecidableInstances #-} -- | Packrat parser module Text.Grampa.PEG.Packrat (Parser(..), Result(..)) where @@ -34,12 +34,13 @@ import Text.Grampa.Class (CommittedParsing(..), DeterministicParsing(..),                           InputParsing(..), InputCharParsing(..),                           GrammarParsing(..), MultiParsing(..),-                          TailsParsing(parseTails), ParseResults, ParseFailure(..), FailureDescription(..), Pos)-import Text.Grampa.Internal (expected, TraceableParsing(..))+                          TailsParsing(parseTails), ParseResults, ParseFailure(..), Pos)+import Text.Grampa.Internal (emptyFailure, erroneous, expected, expectedInput, replaceExpected, noFailure,+                             TraceableParsing(..))  data Result g s v = Parsed{parsedPrefix :: !v,                             parsedSuffix :: ![(s, g (Result g s))]}-                  | NoParse (ParseFailure Pos s)+                  | NoParse {-# UNPACK #-} !(ParseFailure Pos s)  -- | Parser type for Parsing Expression Grammars that uses an improved packrat algorithm, with O(1) performance bounds -- but with worse constants and more memory consumption than the backtracking 'Text.Grampa.PEG.Backtrack.Parser'. The@@ -70,7 +71,7 @@                   NoParse failure -> NoParse failure  instance Alternative (Parser g s) where-   empty = Parser (\rest-> NoParse $ ParseFailure (Down $ length rest) [] [])+   empty = Parser (NoParse . emptyFailure . Down . length)    Parser p <|> Parser q = Parser r where       r rest = case p rest                of x@Parsed{} -> x@@ -90,7 +91,7 @@ #if MIN_VERSION_base(4,13,0) instance MonadFail (Parser g s) where #endif-   fail msg = Parser (\rest-> NoParse $ ParseFailure (Down $ length rest) [] [StaticDescription msg])+   fail msg = Parser (\rest-> NoParse $ erroneous (Down $ length rest) msg)  instance MonadPlus (Parser g s) where    mzero = empty@@ -106,22 +107,19 @@ instance FactorialMonoid s => Parsing (Parser g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)-               where rewindFailure NoParse{} = NoParse (ParseFailure (Down $ length rest) [] [])+               where rewindFailure NoParse{} = NoParse (emptyFailure $ fromEnd $ length rest)                      rewindFailure parsed = parsed    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)-               where replaceFailure (NoParse (ParseFailure pos msgs erroneous)) =-                        NoParse (ParseFailure pos-                                              (if pos == Down (length rest) then [StaticDescription msg] else msgs)-                                              erroneous)+               where replaceFailure (NoParse f) = NoParse (replaceExpected (fromEnd $ Factorial.length rest) msg f)                      replaceFailure parsed = parsed    eof = Parser p       where p rest@((s, _) : _)-               | not (Null.null s) = NoParse (ParseFailure (Down $ length rest) [StaticDescription "end of input"] [])+               | not (Null.null s) = NoParse (expected (Down $ length rest) "end of input")             p rest = Parsed () rest-   unexpected msg = Parser (\t-> NoParse $ ParseFailure (Down $ length t) [] [StaticDescription msg])+   unexpected msg = Parser (\t-> NoParse $ erroneous (Down $ length t) msg)    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))-      where rewind t Parsed{} = NoParse (ParseFailure (Down $ length t) [StaticDescription "notFollowedBy"] [])+      where rewind t Parsed{} = NoParse (expected (Down $ length t) "notFollowedBy")             rewind t NoParse{} = Parsed () t  instance FactorialMonoid s => CommittedParsing (Parser g s) where@@ -166,6 +164,16 @@    nonTerminal f = Parser p where       p ((_, d) : _) = f d       p _ = NoParse (expected 0 "NonTerminal at endOfInput")+   chainRecursive = chainLongestRecursive+   chainLongestRecursive assign (Parser base) (Parser recurse) = Parser q+      where q [] = base []+            q ((s, d):t) = case base initialInput+                           of r@NoParse{} -> r+                              r -> iter r+               where iter r = case recurse ((s, assign r d) : t)+                              of NoParse{} -> r+                                 r'@Parsed{} -> iter r'+                     initialInput = (s, assign (NoParse noFailure) d) : t  instance (Eq s, LeftReductive s, FactorialMonoid s) => TailsParsing (Parser g s) where    parseTails = applyParser@@ -212,16 +220,20 @@    string s = Parser p where       p rest@((s', _) : _)          | s `isPrefixOf` s' = Parsed s (Factorial.drop (Factorial.length s) rest)-      p rest = NoParse (ParseFailure (Down $ length rest) [LiteralDescription s] [])+      p rest = NoParse (expectedInput (fromEnd $ length rest) s) -instance (InputParsing (Parser g s), Monoid s)  => TraceableParsing (Parser g s) where+instance (InputParsing (Parser g s), FactorialMonoid s)  => TraceableParsing (Parser g s) where    traceInput description (Parser p) = Parser q-      where q rest = case traceWith "Parsing " (p rest)-                  of r@Parsed{} -> traceWith "Parsed " r+      where q rest+              | let input = case rest+                            of ((s, _):_) -> s+                               [] -> mempty+                    traceWith prefix = trace (prefix <> description input)+              = case traceWith "Parsing " (p rest)+                  of r@Parsed{}+                        | let prefix = Factorial.take (Factorial.length input - Factorial.length (parsedSuffix r)) input+                        -> trace ("Parsed " <> description prefix) r                      r@NoParse{} -> traceWith "Failed " r-               where traceWith prefix = trace (prefix <> description (case rest-                                                                      of ((s, _):_) -> s-                                                                         [] -> mempty))  instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where    satisfyCharInput predicate = Parser p
test/README.lhs view
@@ -17,7 +17,8 @@ import Data.Char (isDigit) import Data.Functor.Classes (Show1, showsPrec1) import Text.Grampa-import Text.Grampa.ContextFree.LeftRecursive (Parser)+import Text.Grampa.ContextFree.Memoizing.LeftRecursive (Parser)+import qualified Rank2 import qualified Rank2.TH ~~~ @@ -26,7 +27,7 @@ like this:  ~~~ {.haskell}-arithmetic :: GrammarBuilder Arithmetic g Parser String+arithmetic :: Rank2.Apply g => GrammarBuilder Arithmetic g Parser String arithmetic Arithmetic{..} = Arithmetic{    sum= product          <|> string "-" *> (negate <$> product)@@ -89,9 +90,9 @@ -- >>> parseComplete grammar "1+2*3" -- Arithmetic{ --   sum=Compose (Right [7]),---   product=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = [StaticDescription "end of input"], errorAlternatives = []})),---   factor=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = [StaticDescription "end of input"], errorAlternatives = []})),---   number=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = [StaticDescription "end of input"], errorAlternatives = []}))}+--   product=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = FailureDescription {staticDescriptions = ["end of input"], literalDescriptions = []}, errorAlternatives = []})),+--   factor=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = FailureDescription {staticDescriptions = ["end of input"], literalDescriptions = []}, errorAlternatives = []})),+--   number=Compose (Left (ParseFailure {failurePosition = Down 4, expectedAlternatives = FailureDescription {staticDescriptions = ["end of input"], literalDescriptions = []}, errorAlternatives = []}))} -- >>> parsePrefix grammar "1+2*3 apples" -- Arithmetic{ --   sum=Compose (Compose (Right [("+2*3 apples",1),("*3 apples",3),(" apples",7)])),
test/Test.hs view
@@ -36,7 +36,7 @@ import Text.Grampa hiding (symbol) import qualified Text.Grampa.ContextFree.Parallel as Parallel import qualified Text.Grampa.ContextFree.SortedMemoizing as Memoizing-import qualified Text.Grampa.ContextFree.LeftRecursive as LeftRecursive+import qualified Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive as LeftRecursive  import qualified Test.Ambiguous import qualified Test.Examples@@ -49,11 +49,11 @@                              next :: f String} deriving instance (Show (f String), Show (f [String])) => Show (Recursive f) +$(Rank2.TH.deriveAll ''Recursive)+ instance TokenParsing (LeftRecursive.Parser Recursive String) instance LexicalParsing (LeftRecursive.Parser Recursive String) -$(Rank2.TH.deriveAll ''Recursive)- recursiveManyGrammar Recursive{..} = Recursive{    start= optional (string "[") *> (concat <$> rec) <* optional next,    rec= (:) <$> one <*> rec <|> pure [],@@ -142,9 +142,9 @@                testProperty "name list" $                  start (parseComplete nameListGrammar "foo, bar") == Compose (Right ["foo bar"]),                testProperty "filtered" $-                 start (parseComplete gf "") === Compose (Left (ParseFailure 0 [LiteralDescription "1"] [])),+                 start (parseComplete gf "") === Compose (Left (ParseFailure 0 (FailureDescription [] ["1"]) [])),                testProperty "monadic" $-                 start (parseComplete gm "") === Compose (Left (ParseFailure 0 [] [StaticDescription "empty"])),+                 start (parseComplete gm "") === Compose (Left (ParseFailure 0 mempty ["empty"])),                testProperty "null monadic" $                  start (parseComplete gn "23") === Compose (Right ["23"])               ],@@ -195,7 +195,7 @@                    simpleParse (string xs) (xs <> ys) == Right [(ys, xs)],               testProperty "string" $ \(xs::[Word8]) ys-> not (xs `isPrefixOf` ys)                 ==> simpleParse (string xs) ys-                    === Left (ParseFailure (fromIntegral $ length ys) [LiteralDescription xs] []),+                    === Left (ParseFailure (fromIntegral $ length ys) (FailureDescription [] [xs]) []),               testProperty "eof mempty" $ simpleParse eof "" === Right [("", ())],               testProperty "eof failure" $ \s->                    s /= "" ==> simpleParse eof s === Left (expected (fromIntegral $ length s) "end of input")],@@ -374,7 +374,7 @@ binary nm op = liftA2 (\(DescribedParser d1 p1) (DescribedParser d2 p2)-> DescribedParser (d1 <> nm <> d2) (op p1 p2))  expected :: Pos -> String -> ParseFailure Pos s-expected pos msg = ParseFailure pos [StaticDescription msg] []+expected pos msg = ParseFailure pos (FailureDescription [msg] []) []  --instance {-# OVERLAPS #-} (Ord s, Arbitrary s) => Arbitrary (s -> Bool) where --   arbitrary = elements [(<=), const False]
test/Test/Ambiguous.hs view
@@ -8,7 +8,7 @@ import qualified Rank2.TH import Text.Grampa import Text.Grampa.Combinators-import Text.Grampa.ContextFree.LeftRecursive (Parser)+import Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive (Parser)  import Debug.Trace @@ -22,6 +22,8 @@    amb :: p (Ambiguous Amb)    } +$(Rank2.TH.deriveAll ''Test)+ grammar :: Test (Parser Test String) -> Test (Parser Test String) grammar Test{..} = Test{    amb = ambiguous (Xy1 <$> string "x" <*> moptional (string "y")@@ -29,5 +31,3 @@                     <|> Xyz <$> amb <*> string "z"                     <|> Xyzw <$> amb <*> string "w")    }--$(Rank2.TH.deriveAll ''Test)
test/Test/Examples.hs view
@@ -13,7 +13,7 @@  import qualified Rank2 import Text.Grampa-import Text.Grampa.ContextFree.LeftRecursive (Parser)+import Text.Grampa.ContextFree.SortedMemoizing.LeftRecursive (Parser) import qualified Arithmetic import qualified Comparisons import qualified Boolean