packages feed

grammatical-parsers 0.4.1.2 → 0.5

raw patch · 35 files changed

+2132/−1440 lines, 35 filesdep +attoparsecdep +bytestringdep +input-parsersdep ~containersdep ~monoid-subclassesdep ~rank2classesnew-component:exe:boolean-transformationsPVP ok

version bump matches the API change (PVP)

Dependencies added: attoparsec, bytestring, input-parsers

Dependency ranges changed: containers, monoid-subclasses, rank2classes

API changes (from Hackage documentation)

- Text.Grampa: class Lexical (g :: (* -> *) -> *) where {
- Text.Grampa: class MonoidParsing m
- Text.Grampa: endOfInput :: (MonoidParsing m, FactorialMonoid s) => m s ()
- Text.Grampa: offsetContext :: (Eq s, IsString s, FactorialMonoid s) => s -> Int -> Int -> s
- Text.Grampa: offsetLineAndColumn :: (Eq s, IsString s, FactorialMonoid s) => s -> Int -> ([s], Int)
- Text.Grampa: positionOffset :: FactorialMonoid s => s -> Position s -> Int
- Text.Grampa: satisfyChar :: (MonoidParsing m, TextualMonoid s) => (Char -> Bool) -> m s Char
- Text.Grampa: type LexicalConstraint m g s = (Applicative (m g ()), Monad (m g s), CharParsing (m g s), MonoidParsing (m g), Show s, TextualMonoid s);
- Text.Grampa.ContextFree.Continued: instance (Text.Grampa.Class.Lexical g, Text.Grampa.Class.LexicalConstraint Text.Grampa.ContextFree.Continued.Parser g s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.ContextFree.Continued.Parser g s)
- Text.Grampa.ContextFree.Continued: instance Data.Functor.Classes.Show1 (Text.Grampa.ContextFree.Continued.Result g s)
- Text.Grampa.ContextFree.Continued: instance Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.Continued.Parser g)
- Text.Grampa.ContextFree.Continued: instance Text.Grampa.Class.MultiParsing Text.Grampa.ContextFree.Continued.Parser
- Text.Grampa.ContextFree.LeftRecursive: (<<|>) :: Parser g s a -> Parser g s a -> Parser g s a
- Text.Grampa.ContextFree.LeftRecursive: infixl 3 <<|>
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Grampa.Class.Lexical g, Text.Grampa.Class.LexicalConstraint (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.SortedMemoizing.Parser) g s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Grampa.Class.Lexical g, Text.Grampa.Class.LexicalConstraint (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.PEG.Backtrack.Measured.Parser) g s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.PEG.Backtrack.Measured.Parser g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Parser.Combinators.Parsing (p g s), Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g)) => Text.Parser.Combinators.Parsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Parser.Combinators.Parsing (p g s), Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g), GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Char.CharParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance (Text.Parser.LookAhead.LookAheadParsing (p g s), Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g)) => Text.Parser.LookAhead.LookAheadParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.Class.AmbiguousParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
- Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.Class.GrammarParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.SortedMemoizing.Parser)
- Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.SortedMemoizing.Parser g)
- Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.PEG.Backtrack.Measured.Parser g)
- Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.Class.MultiParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.SortedMemoizing.Parser)
- Text.Grampa.ContextFree.Memoizing: (<<|>) :: Parser g s a -> Parser g s a -> Parser g s a
- Text.Grampa.ContextFree.Memoizing: infixl 3 <<|>
- Text.Grampa.ContextFree.Memoizing: instance (Text.Grampa.Class.Lexical g, Text.Grampa.Class.LexicalConstraint Text.Grampa.ContextFree.Memoizing.Parser g s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
- Text.Grampa.ContextFree.Memoizing: instance Data.Functor.Classes.Show1 (Text.Grampa.ContextFree.Memoizing.ResultList g s)
- Text.Grampa.ContextFree.Memoizing: instance GHC.Show.Show r => GHC.Show.Show (Text.Grampa.ContextFree.Memoizing.ResultInfo g s r)
- Text.Grampa.ContextFree.Memoizing: instance GHC.Show.Show r => GHC.Show.Show (Text.Grampa.ContextFree.Memoizing.ResultList g s r)
- Text.Grampa.ContextFree.Memoizing: instance Text.Grampa.Class.GrammarParsing Text.Grampa.ContextFree.Memoizing.Parser
- Text.Grampa.ContextFree.Memoizing: instance Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.Memoizing.Parser g)
- Text.Grampa.ContextFree.Memoizing: instance Text.Grampa.Class.MultiParsing Text.Grampa.ContextFree.Memoizing.Parser
- Text.Grampa.ContextFree.Parallel: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Char.CharParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
- Text.Grampa.ContextFree.Parallel: instance (Text.Grampa.Class.Lexical g, Text.Grampa.Class.LexicalConstraint Text.Grampa.ContextFree.Parallel.Parser g s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
- Text.Grampa.ContextFree.Parallel: instance Data.Functor.Classes.Show1 (Text.Grampa.ContextFree.Parallel.ResultList s)
- Text.Grampa.ContextFree.Parallel: instance GHC.Base.Monoid Text.Grampa.ContextFree.Parallel.FailureInfo
- Text.Grampa.ContextFree.Parallel: instance GHC.Base.Semigroup Text.Grampa.ContextFree.Parallel.FailureInfo
- Text.Grampa.ContextFree.Parallel: instance GHC.Classes.Eq Text.Grampa.ContextFree.Parallel.FailureInfo
- Text.Grampa.ContextFree.Parallel: instance GHC.Show.Show Text.Grampa.ContextFree.Parallel.FailureInfo
- Text.Grampa.ContextFree.Parallel: instance Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.Parallel.Parser g)
- Text.Grampa.ContextFree.Parallel: instance Text.Grampa.Class.MultiParsing Text.Grampa.ContextFree.Parallel.Parser
- Text.Grampa.ContextFree.SortedMemoizing: (<<|>) :: Parser g s a -> Parser g s a -> Parser g s a
- Text.Grampa.ContextFree.SortedMemoizing: infixl 3 <<|>
- Text.Grampa.ContextFree.SortedMemoizing: instance (Text.Grampa.Class.Lexical g, Text.Grampa.Class.LexicalConstraint Text.Grampa.ContextFree.SortedMemoizing.Parser g s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
- Text.Grampa.ContextFree.SortedMemoizing: instance Text.Grampa.Class.GrammarParsing Text.Grampa.ContextFree.SortedMemoizing.Parser
- Text.Grampa.ContextFree.SortedMemoizing: instance Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g)
- Text.Grampa.ContextFree.SortedMemoizing: instance Text.Grampa.Class.MultiParsing Text.Grampa.ContextFree.SortedMemoizing.Parser
- Text.Grampa.ContextFree.SortedMemoizing: reparseTails :: Functor g => g (Parser g s) -> [(s, g (ResultList g s))] -> [(s, g (ResultList g s))]
- Text.Grampa.PEG.Backtrack: instance (Text.Grampa.Class.Lexical g, Text.Grampa.Class.LexicalConstraint Text.Grampa.PEG.Backtrack.Parser g s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.PEG.Backtrack.Parser g s)
- Text.Grampa.PEG.Backtrack: instance Data.Functor.Classes.Show1 (Text.Grampa.PEG.Backtrack.Result g s)
- Text.Grampa.PEG.Backtrack: instance Text.Grampa.Class.MonoidParsing (Text.Grampa.PEG.Backtrack.Parser g)
- Text.Grampa.PEG.Backtrack: instance Text.Grampa.Class.MultiParsing Text.Grampa.PEG.Backtrack.Parser
- Text.Grampa.PEG.Packrat: instance (Text.Grampa.Class.Lexical g, Text.Grampa.Class.LexicalConstraint Text.Grampa.PEG.Packrat.Parser g s, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.PEG.Packrat.Parser g s)
- Text.Grampa.PEG.Packrat: instance Data.Functor.Classes.Show1 (Text.Grampa.PEG.Packrat.Result g s)
- Text.Grampa.PEG.Packrat: instance Text.Grampa.Class.GrammarParsing Text.Grampa.PEG.Packrat.Parser
- Text.Grampa.PEG.Packrat: instance Text.Grampa.Class.MonoidParsing (Text.Grampa.PEG.Packrat.Parser g)
- Text.Grampa.PEG.Packrat: instance Text.Grampa.Class.MultiParsing Text.Grampa.PEG.Packrat.Parser
+ Text.Grampa: (<<|>) :: DeterministicParsing m => m a -> m a -> m a
+ Text.Grampa: -- parse.
+ Text.Grampa: Expected :: String -> Expected s
+ Text.Grampa: ExpectedInput :: s -> Expected s
+ Text.Grampa: [getAmbiguous] :: Ambiguous a -> NonEmpty a
+ Text.Grampa: class InputParsing m => ConsumedInputParsing (m :: Type -> Type)
+ Text.Grampa: class Parsing m => DeterministicParsing (m :: Type -> Type)
+ Text.Grampa: class (CharParsing m, InputParsing m) => InputCharParsing (m :: Type -> Type)
+ Text.Grampa: class LookAheadParsing m => InputParsing (m :: Type -> Type) where {
+ Text.Grampa: class (DeterministicParsing m, InputCharParsing m, TokenParsing m) => LexicalParsing m
+ Text.Grampa: class CharParsing m => TokenParsing (m :: Type -> Type)
+ Text.Grampa: concatAll :: (DeterministicParsing m, Monoid a) => m a -> m a
+ Text.Grampa: concatSome :: (Alternative p, Semigroup a) => p a -> p a
+ Text.Grampa: data Expected s
+ Text.Grampa: highlight :: TokenParsing m => Highlight -> m a -> m a
+ Text.Grampa: infixl 3 <<|>
+ Text.Grampa: match :: ConsumedInputParsing m => m a -> m (ParserInput m, a)
+ Text.Grampa: nesting :: TokenParsing m => m a -> m a
+ Text.Grampa: parsingResult :: GrammarParsing m => ParserInput m -> GrammarFunctor m a -> ResultFunctor m (ParserInput m, a)
+ Text.Grampa: semi :: TokenParsing m => m Char
+ Text.Grampa: skipAll :: DeterministicParsing m => m a -> m ()
+ Text.Grampa: someSpace :: TokenParsing m => m ()
+ Text.Grampa: take :: InputParsing m => Int -> m (ParserInput m)
+ Text.Grampa: takeMany :: DeterministicParsing m => m a -> m [a]
+ Text.Grampa: takeOptional :: DeterministicParsing m => m a -> m (Maybe a)
+ Text.Grampa: takeSome :: DeterministicParsing m => m a -> m [a]
+ Text.Grampa: token :: TokenParsing m => m a -> m a
+ Text.Grampa.ContextFree.Continued: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.MultiParsing (Text.Grampa.ContextFree.Continued.Parser g s)
+ Text.Grampa.ContextFree.Continued: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.Continued.Parser g s)
+ Text.Grampa.ContextFree.Continued: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Input.InputCharParsing (Text.Grampa.ContextFree.Continued.Parser g s)
+ Text.Grampa.ContextFree.Continued: instance Data.Monoid.Factorial.FactorialMonoid s => Text.Parser.Deterministic.DeterministicParsing (Text.Grampa.ContextFree.Continued.Parser g s)
+ Text.Grampa.ContextFree.Continued: instance GHC.Show.Show s => Data.Functor.Classes.Show1 (Text.Grampa.ContextFree.Continued.Result g s)
+ Text.Grampa.ContextFree.LeftRecursive: class FallibleWithExpectations f
+ Text.Grampa.ContextFree.LeftRecursive: expectations :: FallibleWithExpectations f => f s a -> [Expected s]
+ Text.Grampa.ContextFree.LeftRecursive: failWith :: FallibleWithExpectations f => FailureInfo s -> f s a
+ Text.Grampa.ContextFree.LeftRecursive: failureOf :: FallibleWithExpectations f => f s a -> FailureInfo s
+ Text.Grampa.ContextFree.LeftRecursive: hasSuccess :: FallibleWithExpectations f => f s a -> Bool
+ 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.Classes.Eq s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s, GHC.Base.Alternative (p g s), Text.Grampa.Class.TailsParsing (p g s), Text.Grampa.Class.GrammarConstraint (p g s) g, Text.Grampa.Class.ParserGrammar (p g s) GHC.Types.~ g, GHC.Base.Functor (Text.Grampa.Class.ResultFunctor (p g s)), s GHC.Types.~ Text.Parser.Input.ParserInput (p g s), Text.Grampa.Class.GrammarFunctor (p g s) GHC.Types.~ rl s, Text.Grampa.ContextFree.LeftRecursive.FallibleWithExpectations rl, Text.Grampa.Internal.AmbiguousAlternative (Text.Grampa.Class.GrammarFunctor (p g s))) => Text.Grampa.Class.GrammarParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
+ Text.Grampa.ContextFree.LeftRecursive: instance (GHC.Classes.Eq s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s, GHC.Base.Alternative (p g s), Text.Grampa.Class.TailsParsing (p g s), Text.Grampa.Class.GrammarConstraint (p g s) g, Text.Grampa.Class.ParserGrammar (p g s) GHC.Types.~ g, GHC.Base.Functor (Text.Grampa.Class.ResultFunctor (p g s)), s GHC.Types.~ Text.Parser.Input.ParserInput (p g s), Text.Grampa.Class.GrammarFunctor (p g s) GHC.Types.~ rl s, Text.Grampa.ContextFree.LeftRecursive.FallibleWithExpectations rl, Text.Grampa.Internal.AmbiguousAlternative (Text.Grampa.Class.GrammarFunctor (p g s))) => Text.Grampa.Class.MultiParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
+ 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 (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 Text.Grampa.Class.AmbiguousParsing (p g s) => Text.Grampa.Class.AmbiguousParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
+ Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.ContextFree.LeftRecursive.FallibleWithExpectations (Text.Grampa.Internal.ResultList g)
+ 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: mapPrimitive :: (p g s a -> p g s a) -> Fixed p g s a -> Fixed p g s a
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: BackParser :: p g s a -> SeparatedParser p (g :: (* -> *) -> *) s a
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: CycleParser :: p g s a -> p g s a -> ResultAppend p g s a -> g (Const Bool) -> SeparatedParser p (g :: (* -> *) -> *) s a
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: FrontParser :: p g s a -> SeparatedParser p (g :: (* -> *) -> *) s a
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: [appendResultsArrow] :: SeparatedParser p (g :: (* -> *) -> *) s a -> ResultAppend p g s a
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: [backParser] :: SeparatedParser p (g :: (* -> *) -> *) s a -> p g s a
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: [cycleParser] :: SeparatedParser p (g :: (* -> *) -> *) s a -> p g s a
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: [dependencies] :: SeparatedParser p (g :: (* -> *) -> *) s a -> g (Const Bool)
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: data SeparatedParser p (g :: (* -> *) -> *) s a
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: instance Text.Grampa.ContextFree.LeftRecursive.FallibleWithExpectations (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultListT m g)
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: lift :: Applicative m => 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, FallibleWithExpectations 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: tmap :: (m a -> m a) -> ParserT m g s a -> ParserT m g s a
+ Text.Grampa.ContextFree.LeftRecursive.Transformer: type ParserT m = Fixed (ParserT m)
+ Text.Grampa.ContextFree.Memoizing: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid 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) => Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
+ Text.Grampa.ContextFree.Memoizing: instance (GHC.Classes.Eq 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.Eq 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.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 Data.Monoid.Null.MonoidNull s => Text.Parser.Deterministic.DeterministicParsing (Text.Grampa.ContextFree.Memoizing.Parser 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.Parallel: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.MultiParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
+ Text.Grampa.ContextFree.Parallel: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
+ Text.Grampa.ContextFree.Parallel: instance Data.Monoid.Factorial.FactorialMonoid s => Text.Parser.Deterministic.DeterministicParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
+ Text.Grampa.ContextFree.Parallel: instance Data.Monoid.Textual.TextualMonoid s => Text.Parser.Char.CharParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
+ Text.Grampa.ContextFree.Parallel: instance Data.Monoid.Textual.TextualMonoid s => Text.Parser.Input.InputCharParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
+ Text.Grampa.ContextFree.Parallel: instance GHC.Show.Show s => Data.Functor.Classes.Show1 (Text.Grampa.ContextFree.Parallel.ResultList s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.MultiParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Parser.Input.ConsumedInputParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance (GHC.Classes.Eq s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.GrammarParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance (GHC.Classes.Eq s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.TailsParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Input.InputCharParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance Data.Monoid.Null.MonoidNull s => Text.Parser.Deterministic.DeterministicParsing (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: FailureInfo :: Int -> [Expected s] -> FailureInfo s
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: Parser :: ([(s, g (ResultListT m g s))] -> ResultListT m g s r) -> ParserT m g s r
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: ResultList :: ![ResultsOfLengthT m g s r] -> !FailureInfo s -> ResultListT m g s r
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: [applyParser] :: ParserT m g s r -> [(s, g (ResultListT m g s))] -> ResultListT m g s r
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: [resultFailures] :: ResultListT m g s r -> !FailureInfo s
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: [resultSuccesses] :: ResultListT m g s r -> ![ResultsOfLengthT m g s r]
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: data FailureInfo s
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: data ResultListT m g s r
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: infixl 3 <<|>
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (Data.Foldable.Foldable m, GHC.Base.Monad m, Data.Traversable.Traversable m) => GHC.Base.MonadPlus (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, Data.Monoid.Null.MonoidNull s) => Text.Parser.Combinators.Parsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, Data.Monoid.Null.MonoidNull s) => Text.Parser.Deterministic.DeterministicParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, Data.Monoid.Null.MonoidNull s) => Text.Parser.LookAhead.LookAheadParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.MultiParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Parser.Input.ConsumedInputParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Parser.Input.InputParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, GHC.Base.Monoid x) => GHC.Base.Monoid (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s x)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, GHC.Base.Semigroup x) => GHC.Base.Semigroup (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s x)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, GHC.Classes.Eq (m ())) => Text.Grampa.Class.AmbiguousParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, GHC.Classes.Eq s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s, Rank2.Functor g) => Text.Grampa.Class.GrammarParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, GHC.Classes.Eq s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s, Rank2.Functor g) => Text.Grampa.Class.TailsParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Char.CharParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Applicative m, GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Input.InputCharParsing (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance (GHC.Base.Monad m, Data.Traversable.Traversable m) => GHC.Base.Monad (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Applicative m => GHC.Base.Alternative (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Applicative m => GHC.Base.Alternative (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultListT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Applicative m => GHC.Base.Applicative (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Applicative m => GHC.Base.Applicative (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultListT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Applicative m => GHC.Base.Applicative (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultsOfLength m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Applicative m => GHC.Base.Applicative (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultsOfLengthT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Applicative m => Text.Grampa.Internal.AmbiguousAlternative (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultListT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Functor (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultsOfLength m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Functor m => GHC.Base.Functor (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ParserT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Functor m => GHC.Base.Functor (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultListT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Functor m => GHC.Base.Functor (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultsOfLengthT m g s)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Monoid (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultListT m g s r)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: instance GHC.Base.Semigroup (Text.Grampa.ContextFree.SortedMemoizing.Transformer.ResultListT m g s r)
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: lift :: m a -> ParserT m g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: longest :: ParserT Identity g s a -> Parser g [(s, g (ResultListT Identity g s))] a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: newtype ParserT m g s r
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: peg :: Applicative m => Parser g [(s, g (ResultListT m g s))] a -> ParserT m g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: terminalPEG :: (Applicative m, Monoid s) => Parser g s a -> ParserT m g s a
+ Text.Grampa.ContextFree.SortedMemoizing.Transformer: tmap :: (m a -> m b) -> ParserT m g s a -> ParserT m g s b
+ Text.Grampa.PEG.Backtrack: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.MultiParsing (Text.Grampa.PEG.Backtrack.Parser g s)
+ Text.Grampa.PEG.Backtrack: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Parser.Input.InputParsing (Text.Grampa.PEG.Backtrack.Parser g s)
+ Text.Grampa.PEG.Backtrack: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Input.InputCharParsing (Text.Grampa.PEG.Backtrack.Parser g s)
+ Text.Grampa.PEG.Backtrack: instance Data.Monoid.Factorial.FactorialMonoid s => Text.Parser.Deterministic.DeterministicParsing (Text.Grampa.PEG.Backtrack.Parser g s)
+ Text.Grampa.PEG.Backtrack: instance GHC.Show.Show s => Data.Functor.Classes.Show1 (Text.Grampa.PEG.Backtrack.Result g s)
+ Text.Grampa.PEG.Packrat: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.MultiParsing (Text.Grampa.PEG.Packrat.Parser g s)
+ Text.Grampa.PEG.Packrat: instance (Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Parser.Input.InputParsing (Text.Grampa.PEG.Packrat.Parser g s)
+ Text.Grampa.PEG.Packrat: instance (GHC.Classes.Eq s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.GrammarParsing (Text.Grampa.PEG.Packrat.Parser g s)
+ Text.Grampa.PEG.Packrat: instance (GHC.Classes.Eq s, Data.Semigroup.Cancellative.LeftReductive s, Data.Monoid.Factorial.FactorialMonoid s) => Text.Grampa.Class.TailsParsing (Text.Grampa.PEG.Packrat.Parser g s)
+ Text.Grampa.PEG.Packrat: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Input.InputCharParsing (Text.Grampa.PEG.Packrat.Parser g s)
+ Text.Grampa.PEG.Packrat: instance Data.Monoid.Factorial.FactorialMonoid s => Text.Parser.Deterministic.DeterministicParsing (Text.Grampa.PEG.Packrat.Parser g s)
+ Text.Grampa.PEG.Packrat: instance GHC.Show.Show s => Data.Functor.Classes.Show1 (Text.Grampa.PEG.Packrat.Result g s)
- Text.Grampa: -- | Some parser types produce a single result, others a list of results.
+ Text.Grampa: -- | For internal use by <tt>notTerminal</tt>
- Text.Grampa: ParseFailure :: Int -> [String] -> ParseFailure
+ Text.Grampa: ParseFailure :: Int -> [Expected s] -> ParseFailure s
- Text.Grampa: anyToken :: (MonoidParsing m, FactorialMonoid s) => m s s
+ Text.Grampa: anyToken :: InputParsing m => m (ParserInput m)
- Text.Grampa: class AmbiguousParsing m
+ Text.Grampa: class Alternative m => AmbiguousParsing m
- Text.Grampa: class MultiParsing m where {
+ Text.Grampa: class InputParsing m => MultiParsing m where {
- Text.Grampa: concatMany :: (MonoidParsing m, Monoid a, Alternative (m s)) => m s a -> m s a
+ Text.Grampa: concatMany :: (Alternative p, Monoid a) => p a -> p a
- Text.Grampa: data ParseFailure
+ Text.Grampa: data ParseFailure s
- Text.Grampa: data Position s
+ Text.Grampa: data Position
- Text.Grampa: failureDescription :: forall s. (Eq s, IsString s, FactorialMonoid s) => s -> ParseFailure -> Int -> s
+ Text.Grampa: failureDescription :: forall s. (Ord s, TextualMonoid s) => s -> ParseFailure s -> Int -> s
- Text.Grampa: fixGrammar :: forall g s. (GrammarParsing m, GrammarConstraint m g, Distributive g) => (g (m g s) -> g (m g s)) -> g (m g s)
+ Text.Grampa: fixGrammar :: (GrammarParsing m, g ~ ParserGrammar m, GrammarConstraint m g, Distributive g) => (g m -> g m) -> g m
- Text.Grampa: getInput :: (MonoidParsing m, FactorialMonoid s) => m s s
+ Text.Grampa: getInput :: InputParsing m => m (ParserInput m)
- Text.Grampa: getSourcePos :: (MonoidParsing m, FactorialMonoid s, Functor (m s)) => m s (Position s)
+ Text.Grampa: getSourcePos :: InputParsing m => m Position
- Text.Grampa: identifier :: (Lexical g, LexicalConstraint m g s, Monad (m g s), Alternative (m g s), Parsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s s
+ Text.Grampa: identifier :: (LexicalParsing m, TextualMonoid (ParserInput m)) => m (ParserInput m)
- Text.Grampa: identifierToken :: (Lexical g, LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s s -> m g s s
+ Text.Grampa: identifierToken :: LexicalParsing m => m (ParserInput m) -> m (ParserInput m)
- Text.Grampa: isIdentifierFollowChar :: Lexical g => Char -> Bool
+ Text.Grampa: isIdentifierFollowChar :: LexicalParsing m => Char -> Bool
- Text.Grampa: isIdentifierStartChar :: Lexical g => Char -> Bool
+ Text.Grampa: isIdentifierStartChar :: LexicalParsing m => Char -> Bool
- Text.Grampa: keyword :: (Lexical g, LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), Show s, TextualMonoid s) => s -> m g s ()
+ Text.Grampa: keyword :: (LexicalParsing m, Show (ParserInput m), TextualMonoid (ParserInput m)) => ParserInput m -> m ()
- Text.Grampa: lexicalComment :: (Lexical g, Alternative (m g s)) => m g s ()
+ Text.Grampa: lexicalComment :: LexicalParsing m => m ()
- Text.Grampa: lexicalSemicolon :: (Lexical g, LexicalConstraint m g s, CharParsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s Char
+ Text.Grampa: lexicalSemicolon :: LexicalParsing m => m Char
- Text.Grampa: lexicalToken :: (Lexical g, LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s a -> m g s a
+ Text.Grampa: lexicalToken :: LexicalParsing m => m a -> m a
- Text.Grampa: lexicalWhiteSpace :: (Lexical g, LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s ()
+ Text.Grampa: lexicalWhiteSpace :: LexicalParsing m => m ()
- Text.Grampa: nonTerminal :: (GrammarParsing m, GrammarConstraint m g) => (g (GrammarFunctor m g s) -> GrammarFunctor m g s a) -> m g s a
+ Text.Grampa: nonTerminal :: (GrammarParsing m, g ~ ParserGrammar m, GrammarConstraint m g) => (g (GrammarFunctor m) -> GrammarFunctor m a) -> m a
- Text.Grampa: notSatisfy :: (MonoidParsing m, FactorialMonoid s) => (s -> Bool) -> m s ()
+ Text.Grampa: notSatisfy :: InputParsing m => (ParserInput m -> Bool) -> m ()
- Text.Grampa: notSatisfyChar :: (MonoidParsing m, TextualMonoid s) => (Char -> Bool) -> m s ()
+ Text.Grampa: notSatisfyChar :: InputCharParsing m => (Char -> Bool) -> m ()
- Text.Grampa: parseComplete :: (MultiParsing m, GrammarConstraint m g, FactorialMonoid s) => g (m g s) -> s -> g (ResultFunctor m)
+ Text.Grampa: parseComplete :: (MultiParsing m, ParserInput m ~ s, GrammarConstraint m g, Eq s, FactorialMonoid s) => g m -> s -> g (ResultFunctor m)
- Text.Grampa: parsePrefix :: (MultiParsing m, GrammarConstraint m g, FactorialMonoid s) => g (m g s) -> s -> g (Compose (ResultFunctor m) ((,) s))
+ Text.Grampa: parsePrefix :: (MultiParsing m, ParserInput m ~ s, GrammarConstraint m g, Eq s, FactorialMonoid s) => g m -> s -> g (Compose (ResultFunctor m) ((,) s))
- Text.Grampa: recursive :: GrammarParsing m => m g s a -> m g s a
+ Text.Grampa: recursive :: GrammarParsing m => m a -> m a
- Text.Grampa: satisfy :: (MonoidParsing m, FactorialMonoid s) => (s -> Bool) -> m s s
+ Text.Grampa: satisfy :: InputParsing m => (ParserInput m -> Bool) -> m (ParserInput m)
- Text.Grampa: satisfyCharInput :: (MonoidParsing m, TextualMonoid s) => (Char -> Bool) -> m s s
+ Text.Grampa: satisfyCharInput :: InputCharParsing m => (Char -> Bool) -> m (ParserInput m)
- Text.Grampa: scan :: (MonoidParsing m, FactorialMonoid t) => s -> (s -> t -> Maybe s) -> m t t
+ Text.Grampa: scan :: InputParsing m => state -> (state -> ParserInput m -> Maybe state) -> m (ParserInput m)
- Text.Grampa: scanChars :: (MonoidParsing m, TextualMonoid t) => s -> (s -> Char -> Maybe s) -> m t t
+ Text.Grampa: scanChars :: InputCharParsing m => state -> (state -> Char -> Maybe state) -> m (ParserInput m)
- Text.Grampa: selfReferring :: (GrammarParsing m, GrammarConstraint m g, Distributive g) => g (m g s)
+ Text.Grampa: selfReferring :: (GrammarParsing m, g ~ ParserGrammar m, GrammarConstraint m g, Distributive g) => g m
- Text.Grampa: someLexicalSpace :: (Lexical g, LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s ()
+ Text.Grampa: someLexicalSpace :: LexicalParsing m => m ()
- Text.Grampa: string :: (MonoidParsing m, FactorialMonoid s, LeftReductiveMonoid s, Show s) => s -> m s s
+ Text.Grampa: string :: InputParsing m => ParserInput m -> m (ParserInput m)
- Text.Grampa: takeCharsWhile :: (MonoidParsing m, TextualMonoid s) => (Char -> Bool) -> m s s
+ Text.Grampa: takeCharsWhile :: InputCharParsing m => (Char -> Bool) -> m (ParserInput m)
- Text.Grampa: takeCharsWhile1 :: (MonoidParsing m, TextualMonoid s) => (Char -> Bool) -> m s s
+ Text.Grampa: takeCharsWhile1 :: InputCharParsing m => (Char -> Bool) -> m (ParserInput m)
- Text.Grampa: takeWhile :: (MonoidParsing m, FactorialMonoid s) => (s -> Bool) -> m s s
+ Text.Grampa: takeWhile :: InputParsing m => (ParserInput m -> Bool) -> m (ParserInput m)
- Text.Grampa: takeWhile1 :: (MonoidParsing m, FactorialMonoid s) => (s -> Bool) -> m s s
+ Text.Grampa: takeWhile1 :: InputParsing m => (ParserInput m -> Bool) -> m (ParserInput m)
- Text.Grampa: type ParseResults = Either ParseFailure
+ Text.Grampa: type ParseResults s = Either (ParseFailure s)
- Text.Grampa: type family LexicalConstraint (m :: ((* -> *) -> *) -> * -> * -> *) g s :: Constraint;
+ Text.Grampa: type family GrammarFunctor m :: * -> *;
- Text.Grampa.Combinators: concatMany :: (MonoidParsing m, Monoid a) => m s a -> m s a
+ Text.Grampa.Combinators: concatMany :: (Alternative p, Monoid a) => p a -> p a
- Text.Grampa.Combinators: concatSome :: (Monoid x, Applicative (p s), MonoidParsing p) => p s x -> p s x
+ Text.Grampa.Combinators: concatSome :: (Alternative p, Semigroup a) => p a -> p a
- Text.Grampa.Combinators: delimiter :: (Show s, FactorialMonoid s, LeftReductiveMonoid s, Parsing (p g s), MonoidParsing (p g), Lexical g, LexicalConstraint p g s) => s -> p g s s
+ Text.Grampa.Combinators: delimiter :: (Show s, FactorialMonoid s, LeftReductive s, s ~ ParserInput m, LexicalParsing m) => s -> m s
- Text.Grampa.Combinators: keyword :: (Lexical g, LexicalConstraint m g s) => s -> m g s ()
+ Text.Grampa.Combinators: keyword :: LexicalParsing m => ParserInput m -> m ()
- Text.Grampa.Combinators: moptional :: (Monoid x, Alternative p) => p x -> p x
+ Text.Grampa.Combinators: moptional :: (Alternative p, Monoid a) => p a -> p a
- Text.Grampa.Combinators: operator :: (Show s, FactorialMonoid s, LeftReductiveMonoid s, Parsing (p g s), MonoidParsing (p g), Lexical g, LexicalConstraint p g s) => s -> p g s s
+ Text.Grampa.Combinators: operator :: (Show s, FactorialMonoid s, LeftReductive s, s ~ ParserInput m, LexicalParsing m) => s -> m s
- Text.Grampa.ContextFree.Continued: NoParse :: FailureInfo -> Result (g :: (* -> *) -> *) s v
+ Text.Grampa.ContextFree.Continued: NoParse :: FailureInfo s -> Result (g :: (* -> *) -> *) s v
- Text.Grampa.ContextFree.Continued: Parser :: (forall x. s -> (r -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x) -> Parser (g :: (* -> *) -> *) s r
+ Text.Grampa.ContextFree.Continued: Parser :: (forall x. s -> (r -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x) -> Parser (g :: (* -> *) -> *) s r
- Text.Grampa.ContextFree.Continued: [applyParser] :: Parser (g :: (* -> *) -> *) s r -> forall x. s -> (r -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x
+ Text.Grampa.ContextFree.Continued: [applyParser] :: Parser (g :: (* -> *) -> *) s r -> forall x. s -> (r -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x
- Text.Grampa.ContextFree.LeftRecursive: BackParser :: p g s a -> SeparatedParser p g s a
+ Text.Grampa.ContextFree.LeftRecursive: BackParser :: p g s a -> SeparatedParser p (g :: (* -> *) -> *) s a
- Text.Grampa.ContextFree.LeftRecursive: CycleParser :: p g s a -> p g s a -> ResultAppend g s a -> g (Const Bool) -> SeparatedParser p g s a
+ Text.Grampa.ContextFree.LeftRecursive: CycleParser :: p g s a -> p g s a -> ResultAppend p g s a -> g (Const Bool) -> SeparatedParser p (g :: (* -> *) -> *) s a
- Text.Grampa.ContextFree.LeftRecursive: FrontParser :: p g s a -> SeparatedParser p g s a
+ Text.Grampa.ContextFree.LeftRecursive: FrontParser :: p g s a -> SeparatedParser p (g :: (* -> *) -> *) s a
- Text.Grampa.ContextFree.LeftRecursive: [appendResultsArrow] :: SeparatedParser p g s a -> ResultAppend g s a
+ Text.Grampa.ContextFree.LeftRecursive: [appendResultsArrow] :: SeparatedParser p (g :: (* -> *) -> *) s a -> ResultAppend p g s a
- Text.Grampa.ContextFree.LeftRecursive: [backParser] :: SeparatedParser p g s a -> p g s a
+ Text.Grampa.ContextFree.LeftRecursive: [backParser] :: SeparatedParser p (g :: (* -> *) -> *) s a -> p g s a
- Text.Grampa.ContextFree.LeftRecursive: [cycleParser] :: SeparatedParser p g s a -> p g s a
+ Text.Grampa.ContextFree.LeftRecursive: [cycleParser] :: SeparatedParser p (g :: (* -> *) -> *) s a -> p g s a
- Text.Grampa.ContextFree.LeftRecursive: [dependencies] :: SeparatedParser p g s a -> g (Const Bool)
+ Text.Grampa.ContextFree.LeftRecursive: [dependencies] :: SeparatedParser p (g :: (* -> *) -> *) s a -> g (Const Bool)
- Text.Grampa.ContextFree.LeftRecursive: data SeparatedParser p g s a
+ Text.Grampa.ContextFree.LeftRecursive: data SeparatedParser p (g :: (* -> *) -> *) s a
- Text.Grampa.ContextFree.LeftRecursive: parseSeparated :: forall g s. (Apply g, Foldable g, FactorialMonoid s) => g (SeparatedParser Parser g s) -> s -> [(s, g (ResultList g s))]
+ 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, FallibleWithExpectations rl, s ~ ParserInput (p g s)) => g (SeparatedParser p g s) -> s -> [(s, g (GrammarFunctor (p g s)))]
- Text.Grampa.ContextFree.LeftRecursive: separated :: forall g s. (Apply g, Distributive g, Traversable g) => g (Parser g s) -> g (SeparatedParser Parser g s)
+ 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.Memoizing: FailureInfo :: Int -> [String] -> FailureInfo
+ Text.Grampa.ContextFree.Memoizing: FailureInfo :: Int -> [Expected s] -> FailureInfo s
- Text.Grampa.ContextFree.Memoizing: ResultList :: !BinTree (ResultInfo g s r) -> {-# UNPACK #-} !FailureInfo -> ResultList g s r
+ Text.Grampa.ContextFree.Memoizing: ResultList :: !BinTree (ResultInfo g s r) -> {-# UNPACK #-} !FailureInfo s -> ResultList g s r
- Text.Grampa.ContextFree.Memoizing: data FailureInfo
+ Text.Grampa.ContextFree.Memoizing: data FailureInfo s
- Text.Grampa.ContextFree.Memoizing: fromResultList :: FactorialMonoid s => s -> ResultList g s r -> ParseResults [(s, r)]
+ Text.Grampa.ContextFree.Memoizing: fromResultList :: (Eq s, FactorialMonoid s) => s -> ResultList g s r -> ParseResults s [(s, r)]
- Text.Grampa.ContextFree.Parallel: FailureInfo :: Int -> [String] -> FailureInfo
+ Text.Grampa.ContextFree.Parallel: FailureInfo :: Int -> [Expected s] -> FailureInfo s
- Text.Grampa.ContextFree.Parallel: ResultList :: !BinTree (ResultInfo s r) -> {-# UNPACK #-} !FailureInfo -> ResultList s r
+ Text.Grampa.ContextFree.Parallel: ResultList :: !BinTree (ResultInfo s r) -> {-# UNPACK #-} !FailureInfo s -> ResultList s r
- Text.Grampa.ContextFree.Parallel: data FailureInfo
+ Text.Grampa.ContextFree.Parallel: data FailureInfo s
- Text.Grampa.ContextFree.Parallel: fromResultList :: FactorialMonoid s => s -> ResultList s r -> ParseResults [(s, r)]
+ Text.Grampa.ContextFree.Parallel: fromResultList :: (Eq s, FactorialMonoid s) => s -> ResultList s r -> ParseResults s [(s, r)]
- Text.Grampa.ContextFree.SortedMemoizing: FailureInfo :: Int -> [String] -> FailureInfo
+ Text.Grampa.ContextFree.SortedMemoizing: FailureInfo :: Int -> [Expected s] -> FailureInfo s
- Text.Grampa.ContextFree.SortedMemoizing: ResultList :: ![ResultsOfLength g s r] -> !FailureInfo -> ResultList g s r
+ Text.Grampa.ContextFree.SortedMemoizing: ResultList :: ![ResultsOfLength g s r] -> !FailureInfo s -> ResultList g s r
- Text.Grampa.ContextFree.SortedMemoizing: data FailureInfo
+ Text.Grampa.ContextFree.SortedMemoizing: data FailureInfo s
- Text.Grampa.PEG.Backtrack: NoParse :: FailureInfo -> Result (g :: (* -> *) -> *) s v
+ Text.Grampa.PEG.Backtrack: NoParse :: FailureInfo s -> Result (g :: (* -> *) -> *) s v
- Text.Grampa.PEG.Packrat: NoParse :: FailureInfo -> Result g s v
+ Text.Grampa.PEG.Packrat: NoParse :: FailureInfo s -> Result g s v

Files

CHANGELOG.md view
@@ -1,3 +1,14 @@+Version 0.5+---------------+* Replaced `MonoidParsing` by `InputParsing`+* Moved the `InputParsing` and `InputCharParser` classes into the `input-parsers` package+* Added the `Expected` data type to eliminate the `Show` constraint on `string`+* Fixed the signature of `scan` and `scanChars`+* Deprecated `endOfInput` and `satisfyChar`+* Replaced `Lexical g` with `LexicalParsing m`+* Added modules `SortedMemoizing.Transformer` and `LeftRecursive.Transformer`+* Added the `getAmbiguous` destructor+ Version 0.4.1.2 --------------- * Fixed the doctests using cabal-doctest
README.md view
@@ -89,9 +89,9 @@ -- >>> parseComplete grammar "1+2*3" -- Arithmetic{ --   sum=Compose (Right [7]),---   product=Compose (Left (ParseFailure 1 ["endOfInput"])),---   factor=Compose (Left (ParseFailure 1 ["endOfInput"])),---   number=Compose (Left (ParseFailure 1 ["endOfInput"]))}+--   product=Compose (Left (ParseFailure 1 [Expected "end of input"])),+--   factor=Compose (Left (ParseFailure 1 [Expected "end of input"])),+--   number=Compose (Left (ParseFailure 1 [Expected "end of input"]))} -- >>> parsePrefix grammar "1+2*3 apples" -- Arithmetic{ --   sum=Compose (Compose (Right [("+2*3 apples",1),("*3 apples",3),(" apples",7)])),
examples/Arithmetic.hs view
@@ -88,12 +88,13 @@                   <*> f (factor a)                   <*> f (primary a) -instance Lexical (Arithmetic e)+instance TokenParsing (Parser (Arithmetic e) String) where+   token = lexicalToken+instance LexicalParsing (Parser (Arithmetic e) String) -arithmetic :: (Lexical g, LexicalConstraint Parser g String, ArithmeticDomain e) =>-              GrammarBuilder (Arithmetic e) g Parser String+arithmetic :: (LexicalParsing (Parser g String), ArithmeticDomain e) => GrammarBuilder (Arithmetic e) g Parser String arithmetic Arithmetic{..} = Arithmetic{-   expr= sum,+   expr= lexicalWhiteSpace *> sum,    sum= product          <|> symbol "-" *> (negate <$> product)          <|> add <$> sum <* symbol "+" <*> product@@ -107,4 +108,4 @@  main :: IO () main = getContents >>=-       print . (getCompose . expr . parseComplete (fixGrammar arithmetic) :: String -> ParseResults [Int])+       print . (getCompose . expr . parseComplete (fixGrammar arithmetic) :: String -> ParseResults String [Int])
examples/Boolean.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleContexts, FlexibleInstances, KindSignatures, RecordWildCards, ScopedTypeVariables,-             TypeFamilies, TemplateHaskell #-}+             TypeFamilies, TemplateHaskell, UndecidableInstances #-} module Boolean where  import Control.Applicative@@ -43,13 +43,16 @@       factor :: f e}    deriving Show -instance Lexical (Boolean e)+instance CharParsing (p (Boolean e) String) => TokenParsing (p (Boolean e) String) +instance (DeterministicParsing (p (Boolean e) String),+          InputCharParsing (p (Boolean e) String), ParserInput (p (Boolean e) String) ~ String) =>+         LexicalParsing (p (Boolean e) String)+ $(Rank2.TH.deriveAll ''Boolean)  boolean :: forall e p (g :: (* -> *) -> *).-           (Lexical g, LexicalConstraint p g String,-            BooleanDomain e, TokenParsing (p g String), MonoidParsing (p g)) =>+           (BooleanDomain e, LexicalParsing (p g String), ParserInput (p g String) ~ String) =>            p g String e -> Boolean e (p g String) -> Boolean e (p g String) boolean p Boolean{..} = Boolean{    expr= term
+ examples/BooleanTransformations.hs view
@@ -0,0 +1,234 @@+{-# LANGUAGE FlexibleContexts, FlexibleInstances, KindSignatures, RankNTypes, RecordWildCards,+             StandaloneDeriving, UndecidableInstances #-}+module Main where++import Control.Applicative ((<|>), empty)+import Control.Arrow (first)+import Control.Monad (guard, join)+import Data.Char (isSpace)+import Data.List (isPrefixOf)+import Data.Functor.Compose (Compose(..))+import Data.Functor.Identity (Identity(..))+import Data.Maybe (mapMaybe)+import System.Environment (getArgs)+import Text.Parser.Token (TokenParsing(..), symbol)+import qualified Text.Grampa+import Text.Grampa (TokenParsing(someSpace), LexicalParsing(lexicalComment, lexicalWhiteSpace, someLexicalSpace),+                    GrammarBuilder, ParseResults,+                    fixGrammar, parseComplete,+                    char, identifier, keyword, takeCharsWhile)+import Text.Grampa.ContextFree.LeftRecursive.Transformer (ParserT, lift, tmap)+import qualified Boolean+import Boolean(Boolean(..))++-- |+-- >>> simplifiedSource "True && [comment] x"+-- "[comment] x"+-- >>> simplifiedSource "False || [comment1] (True || [comment2] x)"+-- "[comment1] True "+-- >>> simplifiedSource "False || [^ trailing comment] [leading comment] (True || [comment2] x)"+-- "[leading comment] True "+-- >>> simplifiedSource "False || [^ trailing comment] [leading comment] (True [operator leading] || [comment2] x)"+-- "[leading comment] True "+-- >>> simplifiedSource "([^1][1] True [^2][2] && [^3][3] x [^4][4])[^5][5] || [^6][6] False [^7][7]"+-- "[3] x [^4][^5]"++type Parser = ParserT ((,) [Ignorables])++data AST f = And (f (AST f)) (f (AST f))+           | Or (f (AST f)) (f (AST f))+           | Not (f (AST f))+           | Literal Bool+           | Variable String++deriving instance (Show (f (AST f)), Show (f Bool), Show (f String)) => Show (AST f)++instance Boolean.BooleanDomain (ParsedWrap (AST ParsedWrap)) where+   and = binary And+   or = binary Or+   not = bare . Not+   true = bare (Literal True)+   false = bare (Literal False)++binary :: (ParsedWrap (AST ParsedWrap) -> ParsedWrap (AST ParsedWrap) -> AST ParsedWrap)+       -> ParsedWrap (AST ParsedWrap) -> ParsedWrap (AST ParsedWrap) -> ParsedWrap (AST ParsedWrap)+binary f a b = bare (f a b)++type ParsedWrap = (,) ParsedIgnorables+type NodeWrap = (,) AttachedIgnorables+data AttachedIgnorables = Attached Ignorables AttachedIgnorables Ignorables+                        | Blank+                        | AttachedToOperator Ignorables Ignorables+                        | Parenthesized Ignorables AttachedIgnorables Ignorables+                        deriving Show+data ParsedIgnorables = Trailing Ignorables+                      | OperatorTrailing [Ignorables]+                      | ParenthesesTrailing Ignorables ParsedIgnorables Ignorables+                      deriving Show+type Ignorables = [Either WhiteSpace Comment]+newtype Comment    = Comment{getComment :: String} deriving Show+newtype WhiteSpace = WhiteSpace String deriving Show++type Grammar = Boolean.Boolean (ParsedWrap (AST ParsedWrap))++main :: IO ()+main = do args <- concat <$> getArgs+          let tree = parse args+          print tree+          case tree+             of Right [parsed] -> do let rearranged = completeRearranged mempty parsed+                                     print rearranged+                                     putStrLn (showSource $ simplified rearranged)+                other -> error (show other)++parse :: String -> ParseResults String [ParsedWrap (AST ParsedWrap)]+parse = getCompose . fmap snd . getCompose . Boolean.expr . parseComplete (fixGrammar grammar)++simplifiedSource :: String -> String+simplifiedSource input = case (parse input)+                         of Right [parsed] -> showSource (simplified $ completeRearranged mempty parsed)+                            other -> error (show other)++class ShowSource a where+   showSource :: a -> String+   showsSourcePrec :: Int -> a -> String -> String+   showSource a = showsSourcePrec 0 a mempty++instance ShowSource (NodeWrap (AST NodeWrap)) where+   showsSourcePrec prec (Attached lead Blank follow, node) rest =+      whiteString lead <> showsSourcePrec prec node (whiteString follow <> rest)+   showsSourcePrec prec (Parenthesized lead ws follow, node) rest =+      whiteString lead <> showsSourcePrec 0 (ws, node) (whiteString follow <> rest)++instance ShowSource (AST NodeWrap) where+   showsSourcePrec prec (Or left right) rest+      | prec < 1 = showsSourcePrec 1 left ("||" <> showsSourcePrec 0 right rest)+   showsSourcePrec prec (And left right) rest+      | prec < 2 = showsSourcePrec 2 left ("&&" <> showsSourcePrec 1 right rest)+   showsSourcePrec prec (Not expr) rest+      | prec < 3 = "not" <> showsSourcePrec 2 expr rest+   showsSourcePrec _ (Literal True) rest = "True" <> rest+   showsSourcePrec _ (Literal False) rest = "False" <> rest+   showsSourcePrec _ (Variable name) rest = name <> rest+   showsSourcePrec _ node rest =   "(" <> showsSourcePrec 0 node (")" <> rest)++completeRearranged :: Ignorables -> ParsedWrap (AST ParsedWrap) -> NodeWrap (AST NodeWrap)+completeRearranged ws node+   | ((ws', node'), trailing) <- rearranged ws node = (embed [] ws' trailing, node')++rearranged :: Ignorables -> ParsedWrap (AST ParsedWrap) -> (NodeWrap (AST NodeWrap), Ignorables)+rearranged leftover (Trailing follow, node)+   | (follow', lead') <- splitDirections follow, (lead'', node', follow'') <- rearrangedChildren [] node =+        ((Attached (leftover <> lead'') Blank (follow'' <> follow'), node'), lead')+rearranged leftover (OperatorTrailing [[], follow], node)+   | (follow', lead') <- splitDirections follow,+     (lead'', node', follow'') <- rearrangedChildren [[], lead'] node =+        ((Attached leftover (AttachedToOperator lead'' follow') [], node'), follow'')+rearranged leftover (ParenthesesTrailing lead ws follow, node)+   | (follow', lead') <- splitDirections follow, (ws', node') <- completeRearranged lead (ws, node) =+        ((Parenthesized leftover ws' follow', node'), lead')++embed leading Blank trailing = Attached leading Blank trailing+embed leading (Attached lead inside follow) trailing = embed (leading <> lead) inside (follow <> trailing)+embed leading (AttachedToOperator lead follow) trailing = AttachedToOperator (leading <> lead) (follow <> trailing)+embed leading (Parenthesized lead inside follow) trailing = Parenthesized (leading <> lead) inside (follow <> trailing)++rearrangedChildren :: [Ignorables] -> AST ParsedWrap -> (Ignorables, AST NodeWrap, Ignorables)+rearrangedChildren [left, right] (And a b)+   | (a', follow1) <- rearranged left a,+     (b', follow2) <- rearranged right b = (follow1, And a' b', follow2)+rearrangedChildren [left, right] (Or a b)+   | (a', follow1) <- rearranged left a,+     (b', follow2) <- rearranged right b = (follow1, Or a' b', follow2)+rearrangedChildren [leftover] (Not a)+   | (a', follow) <- rearranged leftover a = ([], Not a', follow)+rearrangedChildren [] (Literal a) = ([], Literal a, [])+rearrangedChildren [] (Variable name) = ([], Variable name, [])++-- | Separates the whitespace and comments that refer to the preceding construct.+splitDirections :: Ignorables -> (Ignorables, Ignorables)+splitDirections = span (either (const True) (isPrefixOf "^" . getComment))++-- | Simplifies the given expression according to the laws of Boolean algebra.+simplified :: NodeWrap (AST NodeWrap) -> NodeWrap (AST NodeWrap)+simplified e@(_, Literal{}) = e+simplified e@(_, Variable{}) = e+simplified (a, Not e) = case simplified e+                        of (b, Literal True) -> (raise a b, Literal False)+                           (b, Literal False) -> (raise a b, Literal True)+                           e' -> (a, Not e')+simplified (a, And l r) = case (simplified l, simplified r)+                          of ((b, Literal False), _) -> (raise a b, Literal False)+                             ((b, Literal True), (c, r')) -> (raise a c, r')+                             (_, (b, Literal False)) -> (raise a b, Literal False)+                             ((b, l'), (c, Literal True)) -> (raise a b, l')+                             (l', r') -> (a, And l' r')+simplified (a, Or l r) =  case (simplified l, simplified r)+                          of ((b, Literal False), (c, r')) -> (raise a c, r')+                             ((b, Literal True), _) -> (raise a b, Literal True)+                             ((b, l'), (c, Literal False)) -> (raise a b, l')+                             (_, (b, Literal True)) -> (raise a b, Literal True)+                             (l', r') -> (a, Or l' r')++raise :: AttachedIgnorables -> AttachedIgnorables -> AttachedIgnorables+raise Blank arg = arg+raise op Blank = op+raise AttachedToOperator{} arg = arg+raise (Parenthesized opl op opr) arg = Parenthesized opl (raise op arg) opr+raise (Attached opl inside opr) (Parenthesized l arg r) =+   Parenthesized (comments opl <> l) (raise inside arg) (r <> comments opr)+-- raise (AttachedToOperator opl opr) (Parenthesized l arg r) = Parenthesized (comments opl <> l) arg (r <> comments opr)+-- raise (AttachedToOperator opl opr) (Attached argl inside argr) =+--    Attached (comments opl <> argl) inside (argr <> comments opr)++comments :: Ignorables -> Ignorables+comments = mapMaybe (either (const Nothing) (Just . Right))++whiteString :: Ignorables -> String+whiteString (Left (WhiteSpace ws) : rest) = ws <> whiteString rest+whiteString (Right (Comment c) : rest) = "[" <> c <> "]" <> whiteString rest+whiteString [] = ""++grammar :: GrammarBuilder Grammar Grammar Parser String+grammar Boolean{..} = Boolean{+   expr= term+         <|> operatorTrailingWhiteSpace [mempty] (Boolean.or <$> term <* symbol "||" <*> expr),+   term= factor+         <|> operatorTrailingWhiteSpace [mempty] (Boolean.and <$> factor <* symbol "&&" <*> term),+   factor= trailingWhiteSpace (keyword "True" *> pure Boolean.true+                                 <|> keyword "False" *> pure Boolean.false+                                 <|> bare . Variable <$> identifier)+           <|> operatorTrailingWhiteSpace [] (keyword "not" *> (Boolean.not <$> factor))+           <|> parenthesizedWhiteSpace (symbol "(" *> expr <* symbol ")")}++bare :: a -> ParsedWrap a+bare a = (Trailing [], a)++operatorTrailingWhiteSpace :: [Ignorables] -> Parser Grammar String (ParsedWrap (AST ParsedWrap))+                           -> Parser Grammar String (ParsedWrap (AST ParsedWrap))+trailingWhiteSpace, parenthesizedWhiteSpace+   :: Parser Grammar String (ParsedWrap (AST ParsedWrap)) -> Parser Grammar String (ParsedWrap (AST ParsedWrap))+trailingWhiteSpace = tmap store+   where store ([ws], (Trailing ws', a)) = (mempty, (Trailing $ ws' <> ws, a))+operatorTrailingWhiteSpace prefix = tmap store+   where store (wss, (Trailing [], a)) = (mempty, (OperatorTrailing (prefix <> wss), a))+parenthesizedWhiteSpace = tmap store+   where store ([ws,ws'], (aws, a)) = ([], (ParenthesesTrailing ws aws ws', a))++instance {-# OVERLAPS #-} TokenParsing (Parser Grammar String) where+   someSpace = someLexicalSpace+   token p = p <* lexicalWhiteSpace++instance {-# OVERLAPS #-} LexicalParsing (Parser Grammar String) where+   lexicalWhiteSpace = tmap (first (\ws-> [concat ws])) $+                       do ws <- takeCharsWhile isSpace+                          lift ([[Left $ WhiteSpace ws]], ())+                          (lexicalComment *> lexicalWhiteSpace <|> pure ())+   lexicalComment = do char '['+                       comment <- takeCharsWhile (/= ']')+                       char ']'+                       lift ([[Right $ Comment comment]], ())+   identifierToken p = do ident <- p+                          guard (ident /= "True" && ident /= "False")+                          lexicalWhiteSpace+                          pure ident
examples/Combined.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, RecordWildCards, TemplateHaskell, UndecidableInstances #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, RecordWildCards,+             TemplateHaskell, UndecidableInstances #-}+{-# OPTIONS_GHC -Wno-simplifiable-class-constraints #-}  module Combined where @@ -7,7 +9,7 @@ import Data.Map (Map) import qualified Data.Map as Map import qualified Rank2.TH-import Text.Grampa (Lexical, LexicalConstraint, GrammarBuilder)+import Text.Grampa (TokenParsing, LexicalParsing, GrammarBuilder) import Text.Grampa.ContextFree.LeftRecursive (Parser) import qualified Arithmetic import qualified Boolean@@ -117,7 +119,8 @@                            (", conditionalGrammar=" ++ showsPrec prec (conditionalGrammar g)                            (", lambdaGrammar=" ++ showsPrec prec (lambdaGrammar g) ("}" ++ rest)))))) -instance Lexical Expression+instance TokenParsing (Parser Expression String)+instance LexicalParsing (Parser Expression String)  $(Rank2.TH.deriveAll ''Expression) @@ -188,7 +191,7 @@                   <*> Rank2.traverse f (lambdaGrammar g) -} -expression :: (Lexical g, LexicalConstraint Parser g String) => GrammarBuilder Expression g Parser String+expression :: (LexicalParsing (Parser g String)) => GrammarBuilder Expression g Parser String expression Expression{..} =    let combinedExpr = Arithmetic.expr arithmeticGrammar                       <|> Boolean.expr booleanGrammar
examples/Comparisons.hs view
@@ -62,9 +62,7 @@                   <$> f (test g)                   <*> f (term g) -comparisons :: (Lexical g, LexicalConstraint p g String,-                ComparisonDomain c e, TokenParsing (p g String), MonoidParsing (p g)) =>-               GrammarBuilder (Comparisons c e) g p String+comparisons :: (ComparisonDomain c e, LexicalParsing (p g String)) => GrammarBuilder (Comparisons c e) g p String comparisons Comparisons{..} =    Comparisons{       test= lessThan <$> term <* symbol "<" <*> term
examples/Conditionals.hs view
@@ -29,12 +29,12 @@                            (", test= " ++ showsPrec prec (test a)                             (", term= " ++ showsPrec prec (term a) ("}" ++ rest))) -instance Lexical (Conditionals t e) where-   type LexicalConstraint p (Conditionals t e) s = (p ~ Parser, s ~ String)+instance TokenParsing (Parser (Conditionals t e) String)+instance LexicalParsing (Parser (Conditionals t e) String)  $(Rank2.TH.deriveAll ''Conditionals) -conditionals :: (ConditionalDomain t e, Lexical g, LexicalConstraint Parser g String)+conditionals :: (ConditionalDomain t e, LexicalParsing (Parser g String))              => GrammarBuilder (Conditionals t e) g Parser String conditionals Conditionals{..} =    Conditionals{expr= ifThenElse <$> (keyword "if" *> test) <*> (keyword "then" *> term) <*> (keyword "else" *> term),
examples/Lambda.hs view
@@ -8,7 +8,6 @@ import Data.Monoid ((<>)) import Text.Parser.Token (symbol, whiteSpace) -import qualified Rank2 import qualified Rank2.TH  import Text.Grampa@@ -96,8 +95,7 @@  $(Rank2.TH.deriveAll ''Lambda) -lambdaCalculus :: (Lexical g, LexicalConstraint Parser g String, LambdaDomain e)-               => GrammarBuilder (Lambda e) g Parser String+lambdaCalculus :: (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
@@ -1,11 +1,11 @@-{-# LANGUAGE FlexibleInstances, RankNTypes, KindSignatures, UndecidableInstances #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, RankNTypes, KindSignatures, UndecidableInstances #-} module Main (main, arithmetic, comparisons, boolean, conditionals) where  import System.Environment (getArgs) import Data.Functor.Compose (Compose(..)) import Data.Map (Map) import qualified Rank2-import Text.Grampa (Lexical, LexicalConstraint, GrammarBuilder, ParseResults, fixGrammar, parseComplete)+import Text.Grampa (TokenParsing, LexicalParsing, GrammarBuilder, ParseResults, fixGrammar, parseComplete) import Text.Grampa.ContextFree.LeftRecursive (Parser) import Arithmetic (Arithmetic, arithmetic) import qualified Arithmetic@@ -24,35 +24,40 @@           -- let a = fixGrammar (Arithmetic.arithmetic (production id Arithmetic.expr a))           -- let a = fixGrammar (Arithmetic.arithmetic (recursive $ Arithmetic.expr a))           print (getCompose . Lambda.expr $ parseComplete (fixGrammar Lambda.lambdaCalculus) args-                 :: ParseResults [Lambda.LambdaInitial])-          -- print (((\f-> f (mempty :: Map String Int) [1 :: Int]) <$>) <$> parse (fixGrammar Lambda.lambdaCalculus) Lambda.expr args :: ParseResults Int)-          print (getCompose . Arithmetic.expr $ parseComplete (fixGrammar arithmetic) args :: ParseResults [Int])+                 :: ParseResults String [Lambda.LambdaInitial])+          -- print (((\f-> f (mempty :: Map String Int) [1 :: Int]) <$>) <$> parse (fixGrammar Lambda.lambdaCalculus) Lambda.expr args :: ParseResults String Int)+          print (getCompose . Arithmetic.expr $ parseComplete (fixGrammar arithmetic) args :: ParseResults String [Int])           print (getCompose . Comparisons.test . Rank2.snd $ parseComplete (fixGrammar comparisons) args-                 :: ParseResults [Bool])+                 :: ParseResults String [Bool])           print (getCompose . Boolean.expr . Rank2.snd $-                 parseComplete (fixGrammar boolean) args :: ParseResults [Bool])+                 parseComplete (fixGrammar boolean) args :: ParseResults String [Bool])           print (getCompose . Conditionals.expr . Rank2.snd $ parseComplete (fixGrammar conditionals) args-                 :: ParseResults [Int])+                 :: ParseResults String [Int])           print (((\f-> f (mempty :: Map String Combined.Tagged)) <$>)                  <$> (getCompose . Combined.expr $ parseComplete (fixGrammar Combined.expression) args)-                 :: ParseResults [Combined.Tagged])+                 :: ParseResults String [Combined.Tagged]) -comparisons :: (Lexical g, LexicalConstraint Parser g String) => GrammarBuilder ArithmeticComparisons g Parser String+comparisons :: (LexicalParsing (Parser g String)) => GrammarBuilder ArithmeticComparisons g Parser String comparisons (Rank2.Pair a c) =    Rank2.Pair (Arithmetic.arithmetic a) (Comparisons.comparisons c{Comparisons.term= Arithmetic.expr a}) -boolean :: (Lexical g, LexicalConstraint Parser g String) => GrammarBuilder ArithmeticComparisonsBoolean g Parser String+boolean :: (LexicalParsing (Parser g String)) => GrammarBuilder ArithmeticComparisonsBoolean g Parser String boolean (Rank2.Pair ac b) = Rank2.Pair (comparisons ac) (Boolean.boolean (Comparisons.test $ Rank2.snd ac) b) -conditionals :: (Lexical g, LexicalConstraint Parser g String) => GrammarBuilder ACBC g Parser String+conditionals :: (LexicalParsing (Parser g String)) => GrammarBuilder ACBC g Parser String conditionals (Rank2.Pair acb c) =    Rank2.Pair       (boolean acb)       (Conditionals.conditionals c{Conditionals.test= Boolean.expr (Rank2.snd acb),                                    Conditionals.term= Arithmetic.expr (Rank2.fst $ Rank2.fst acb)}) -instance Lexical ArithmeticComparisons-instance Lexical ArithmeticComparisonsBoolean-instance Lexical ACBC-instance Lexical (Lambda.Lambda Lambda.LambdaInitial)+instance TokenParsing (Parser ArithmeticComparisons String)+instance TokenParsing (Parser ArithmeticComparisonsBoolean String)+instance TokenParsing (Parser ACBC String)+instance TokenParsing (Parser (Lambda.Lambda Lambda.LambdaInitial) String)++instance LexicalParsing (Parser ArithmeticComparisons String)+instance LexicalParsing (Parser ArithmeticComparisonsBoolean String)+instance LexicalParsing (Parser ACBC String)+instance LexicalParsing (Parser (Lambda.Lambda Lambda.LambdaInitial) String) 
examples/Utilities.hs view
@@ -1,23 +1,20 @@ {-# LANGUAGE FlexibleContexts, FlexibleInstances, KindSignatures, RankNTypes, ScopedTypeVariables #-} module Utilities where -import Data.Char (isAlphaNum) import Data.Functor.Compose (Compose(..))-import Data.List (intercalate) import Data.Monoid ((<>))-import Data.Monoid.Factorial (FactorialMonoid)-import Data.Monoid.Textual (TextualMonoid)+import Data.Monoid.Textual (TextualMonoid, toString)  import Text.Grampa import Text.Grampa.ContextFree.LeftRecursive import qualified Rank2 -parseUnique :: (FactorialMonoid s, Rank2.Traversable g, Rank2.Distributive g, Rank2.Apply g) =>+parseUnique :: (Ord s, TextualMonoid s, Rank2.Traversable g, Rank2.Distributive g, Rank2.Apply g) =>                Grammar g Parser s -> (forall f. g f -> f r) -> s -> r-parseUnique g prod s = case getCompose (prod $ parseComplete g s)-                       of Left (ParseFailure pos expected) -> error ("Parse failure at " ++ show pos-                                                                     ++ ", expected " ++ intercalate " or " expected)-                          Right [x] -> x+parseUnique g prod s =+   case getCompose (prod $ parseComplete g s)+   of Left failure -> error ("Parse failure: " ++ toString (error "non-character") (failureDescription s failure 3))+      Right [x] -> x  infixJoin :: String -> String -> String -> String infixJoin op a b = "(" <> a <> op <> b <> ")"
grammatical-parsers.cabal view
@@ -1,5 +1,5 @@ name:                grammatical-parsers-version:             0.4.1.2+version:             0.5 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@@ -32,21 +32,26 @@                        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.SortedMemoizing,-                       Text.Grampa.ContextFree.LeftRecursive+                       Text.Grampa.ContextFree.Memoizing,+                       Text.Grampa.ContextFree.SortedMemoizing,+                       Text.Grampa.ContextFree.SortedMemoizing.Transformer,+                       Text.Grampa.ContextFree.LeftRecursive,+                       Text.Grampa.ContextFree.LeftRecursive.Transformer   other-modules:       Text.Grampa.Class, Text.Grampa.Internal,                        Text.Grampa.PEG.Backtrack.Measured,                        Text.Grampa.PEG.Continued, Text.Grampa.PEG.Continued.Measured,                        Text.Grampa.ContextFree.Continued.Measured   default-language:    Haskell2010-  -- other-modules:   ghc-options:         -Wall   build-depends:       base >=4.9 && <5,+                       bytestring >= 0.10 && < 0.11,                        containers >= 0.4 && < 0.7,                        transformers >= 0.5 && < 0.6,-                       monoid-subclasses >=0.4 && <1.1,+                       monoid-subclasses >=1.0 && <1.1,                        parsers < 0.13,-                       rank2classes >= 1.0.2 && < 1.4+                       input-parsers < 0.2,+                       attoparsec >= 0.13 && < 0.14,+                       rank2classes >= 1.0.2 && < 1.5  executable             arithmetic   hs-source-dirs:      examples@@ -55,16 +60,26 @@   default-language:    Haskell2010   build-depends:       base >=4.9 && <5, containers >= 0.5.7.0 && < 0.7,                        parsers < 0.13,-                       rank2classes >= 1.0.2 && < 1.4, grammatical-parsers,-                       monoid-subclasses >=0.4 && <1.1+                       rank2classes >= 1.0.2 && < 1.5, grammatical-parsers,+                       monoid-subclasses >=1.0 && <1.1 +executable             boolean-transformations+  hs-source-dirs:      examples+  main-is:             BooleanTransformations.hs+  other-modules:       Boolean, Utilities+  default-language:    Haskell2010+  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.1+ 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.1, parsers < 0.13,-                     rank2classes >= 1.0.2 && < 1.4, grammatical-parsers,+                     rank2classes >= 1.0.2 && < 1.5, grammatical-parsers,                      QuickCheck >= 2 && < 3, checkers >= 0.4.6 && < 0.6, size-based < 0.2,                      testing-feat >= 1.1 && < 1.2,                      tasty >= 0.7, tasty-quickcheck >= 0.7@@ -87,8 +102,8 @@   type:              exitcode-stdio-1.0   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.4, grammatical-parsers,-                     monoid-subclasses >=0.4 && <1.1, parsers < 0.13,+  Build-Depends:     base >=4.9 && < 5, rank2classes >= 1.0.2 && < 1.5, grammatical-parsers,+                     monoid-subclasses >=1.0 && <1.1, 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
@@ -3,29 +3,37 @@ {-# LANGUAGE FlexibleContexts, KindSignatures, OverloadedStrings, RankNTypes, ScopedTypeVariables #-} module Text.Grampa (    -- * Parsing methods-   MultiParsing(..),-   offsetContext, offsetLineAndColumn, positionOffset, failureDescription, simply,+   failureDescription, simply,    -- * Types-   Grammar, GrammarBuilder, ParseResults, ParseFailure(..), Ambiguous(..), Position,+   Grammar, GrammarBuilder, ParseResults, ParseFailure(..), Expected(..), Ambiguous(..), Position,    -- * Parser combinators and primitives-   GrammarParsing(..), MonoidParsing(..), AmbiguousParsing(..), Lexical(..),+   DeterministicParsing(..), AmbiguousParsing(..),+   InputParsing(..), InputCharParsing(..), ConsumedInputParsing(..),+   MultiParsing(..), GrammarParsing(..),+   TokenParsing(..), LexicalParsing(..),    module Text.Parser.Char,    module Text.Parser.Combinators,-   module Text.Parser.LookAhead)+   module Text.Parser.LookAhead,+   module Text.Grampa.Combinators) where -import Data.List (intersperse)+import Data.List (intersperse, nub, sort) import Data.Monoid ((<>))-import qualified Data.Monoid.Factorial as Factorial-import Data.Monoid.Factorial (FactorialMonoid)+import Data.Monoid.Textual (TextualMonoid) import Data.String (IsString(fromString)) import Text.Parser.Char (CharParsing(char, notChar, anyChar)) import Text.Parser.Combinators (Parsing((<?>), notFollowedBy, skipMany, skipSome, unexpected)) import Text.Parser.LookAhead (LookAheadParsing(lookAhead))+import Text.Parser.Token (TokenParsing(..))+import Text.Parser.Input.Position (Position)+import qualified Text.Parser.Input.Position as Position+import Text.Grampa.Combinators (concatMany, concatSome)  import qualified Rank2-import Text.Grampa.Class (Lexical(..), MultiParsing(..), GrammarParsing(..), MonoidParsing(..), AmbiguousParsing(..),-                          Ambiguous(..), ParseResults, ParseFailure(..), Position, positionOffset)+import Text.Grampa.Class (MultiParsing(..), GrammarParsing(..),+                          InputParsing(..), InputCharParsing(..),+                          ConsumedInputParsing(..), DeterministicParsing(..), LexicalParsing(..),+                          AmbiguousParsing(..), Ambiguous(..), ParseResults, ParseFailure(..), Expected(..))  -- | A type synonym for a fixed grammar record type @g@ with a given parser type @p@ on input streams of type @s@ type Grammar (g  :: (* -> *) -> *) p s = g (p g s)@@ -44,10 +52,10 @@  -- | 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. (Eq s, IsString s, FactorialMonoid s) => s -> ParseFailure -> Int -> s+failureDescription :: forall s. (Ord s, TextualMonoid s) => s -> ParseFailure s -> Int -> s failureDescription input (ParseFailure pos expected) contextLineCount =-   offsetContext input pos contextLineCount-   <> "expected " <> oxfordComma (fromString <$> expected)+   Position.context input (Position.fromStart pos) contextLineCount+   <> "expected " <> oxfordComma (fromExpected <$> nub (sort expected))    where oxfordComma :: [s] -> s          oxfordComma [] = ""          oxfordComma [x] = x@@ -56,25 +64,5 @@          onLast _ [] = []          onLast f [x] = [f x]          onLast f (x:xs) = x : onLast f xs---- | Given the parser input, an offset within it, and desired number of context lines, returns a description of--- the offset position in English.-offsetContext :: (Eq s, IsString s, FactorialMonoid s) => s -> Int -> Int -> s-offsetContext input offset contextLineCount = -   foldMap (<> "\n") prevLines <> fromString (replicate column ' ') <> "^\n"-   <> "at line " <> fromString (show $ length allPrevLines) <> ", column " <> fromString (show $ column+1) <> "\n"-   where (allPrevLines, column) = offsetLineAndColumn input offset-         prevLines = reverse (take contextLineCount allPrevLines)---- | Given the full input and an offset within it, returns all the input lines up to and including the offset--- in reverse order, as well as the zero-based column number of the offset-offsetLineAndColumn :: (Eq s, IsString s, FactorialMonoid s) => s -> Int -> ([s], Int)-offsetLineAndColumn input pos = context [] pos (Factorial.split (== "\n") input)-  where context revLines restCount []-          | restCount > 0 = (["Error: the offset is beyond the input length"], -1)-          | otherwise = (revLines, restCount)-        context revLines restCount (next:rest)-          | restCount' < 0 = (next:revLines, restCount)-          | otherwise = context (next:revLines) restCount' rest-          where nextLength = Factorial.length next-                restCount' = restCount - nextLength - 1+         fromExpected (Expected s) = fromString s+         fromExpected (ExpectedInput s) = "string \"" <> s <> "\""
src/Text/Grampa/Class.hs view
@@ -1,9 +1,13 @@-{-# LANGUAGE AllowAmbiguousTypes, ConstraintKinds, DefaultSignatures, OverloadedStrings, RankNTypes,-             ScopedTypeVariables, TypeApplications, TypeFamilies, DeriveDataTypeable #-}-module Text.Grampa.Class (MultiParsing(..), GrammarParsing(..), AmbiguousParsing(..), MonoidParsing(..), Lexical(..),-                          ParseResults, ParseFailure(..), Ambiguous(..), Position, positionOffset, completeParser) where+{-# LANGUAGE AllowAmbiguousTypes, ConstraintKinds, DefaultSignatures, DeriveDataTypeable, DeriveFunctor,+             FlexibleContexts, FlexibleInstances, OverloadedStrings, RankNTypes, ScopedTypeVariables, TypeApplications,+             TypeFamilies, TypeSynonymInstances, UndecidableInstances #-}+module Text.Grampa.Class (MultiParsing(..), GrammarParsing(..),+                          AmbiguousParsing(..), DeterministicParsing(..), InputParsing(..), InputCharParsing(..),+                          ConsumedInputParsing(..), LexicalParsing(..), TailsParsing(..),+                          ParseResults, ParseFailure(..), Expected(..),+                          Ambiguous(..), completeParser) where -import Control.Applicative (Alternative(empty), liftA2, (<|>))+import Control.Applicative (Alternative(empty), liftA2) import Data.Char (isAlphaNum, isLetter, isSpace) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..))@@ -11,38 +15,33 @@ import Data.Data (Data) import Data.Typeable (Typeable) import Data.Monoid (Monoid(mempty, mappend))-import Data.Monoid.Cancellative (LeftReductiveMonoid) import qualified Data.Monoid.Null as Null import Data.Monoid.Null (MonoidNull)-import qualified Data.Monoid.Factorial as Factorial import Data.Monoid.Factorial (FactorialMonoid) import Data.Monoid.Textual (TextualMonoid) import Data.Semigroup (Semigroup((<>)))-import Text.Parser.Combinators (Parsing((<?>)), skipMany)-import Text.Parser.Char (CharParsing(char))-import GHC.Exts (Constraint)+import Text.Parser.Combinators (Parsing((<?>)))+import Text.Parser.Token (TokenParsing)+import Text.Parser.Deterministic (DeterministicParsing(..))+import Text.Parser.Input (ConsumedInputParsing(..), InputParsing(..), InputCharParsing(..))+import qualified Text.Parser.Char+import Data.Kind (Constraint)  import qualified Rank2 -type ParseResults = Either ParseFailure---- | A 'ParseFailure' contains the offset of the parse failure and the list of things expected at that offset.-data ParseFailure = ParseFailure Int [String] deriving (Eq, Show)+import Prelude hiding (takeWhile) --- | Opaque data type that represents an input position.-newtype Position s = Position{-  -- | The length of the input from the position to end.-  remainderLength :: Int}+type ParseResults s = Either (ParseFailure s) --- | Map the position into its offset from the beginning of the full input.-positionOffset :: FactorialMonoid s => s -> Position s -> Int-positionOffset wholeInput = (wholeLength -) . remainderLength-   where wholeLength = Factorial.length wholeInput-{-# INLINE positionOffset #-}+-- | A 'ParseFailure' contains the offset of the parse failure and the list of things expected at that offset.+data ParseFailure s = ParseFailure Int [Expected s] deriving (Eq, Show)+data Expected s = Expected String+                | ExpectedInput s+                deriving (Functor, Eq, Ord, Read, Show)  -- | An 'Ambiguous' parse result, produced by the 'ambiguous' combinator, contains a 'NonEmpty' list of -- alternative results.-newtype Ambiguous a = Ambiguous (NonEmpty a) deriving (Data, Eq, Ord, Show, Typeable)+newtype Ambiguous a = Ambiguous{getAmbiguous :: NonEmpty a} deriving (Data, Eq, Ord, Show, Typeable)  instance Show1 Ambiguous where    liftShowsPrec sp sl d (Ambiguous (h :| l)) t@@ -69,37 +68,43 @@    mempty = Ambiguous (mempty :| [])    Ambiguous xs `mappend` Ambiguous ys = Ambiguous (liftA2 mappend xs ys) -completeParser :: MonoidNull s => Compose ParseResults (Compose [] ((,) s)) r -> Compose ParseResults [] r+completeParser :: MonoidNull s => Compose (ParseResults s) (Compose [] ((,) s)) r -> Compose (ParseResults s) [] r completeParser (Compose (Left failure)) = Compose (Left failure) completeParser (Compose (Right (Compose results))) =    case filter (Null.null . fst) results-   of [] -> Compose (Left $ ParseFailure 0 ["complete parse"])+   of [] -> Compose (Left $ ParseFailure 0 [Expected "complete parse"])       completeResults -> Compose (Right $ snd <$> completeResults)  -- | Choose one of the instances of this class to parse with.-class MultiParsing m where+class InputParsing m => MultiParsing m where    -- | Some parser types produce a single result, others a list of results.    type ResultFunctor m :: * -> *    type GrammarConstraint m (g :: (* -> *) -> *) :: Constraint    type GrammarConstraint m g = Rank2.Functor g    -- | Given a rank-2 record of parsers and input, produce a record of parses of the complete input.-   parseComplete :: (GrammarConstraint m g, FactorialMonoid s) => g (m g s) -> s -> g (ResultFunctor m)+   parseComplete :: (ParserInput m ~ s, GrammarConstraint m g, Eq s, FactorialMonoid s) =>+                    g m -> s -> g (ResultFunctor m)    -- | Given a rank-2 record of parsers and input, produce a record of prefix parses paired with the remaining input    -- suffix.-   parsePrefix :: (GrammarConstraint m g, FactorialMonoid s) =>-                  g (m g s) -> s -> g (Compose (ResultFunctor m) ((,) s))+   parsePrefix :: (ParserInput m ~ s, GrammarConstraint m g, Eq s, FactorialMonoid s) =>+                  g m -> s -> g (Compose (ResultFunctor m) ((,) s))  -- | Parsers that belong to this class can memoize the parse results to avoid exponential performance complexity. class MultiParsing m => GrammarParsing m where-   type GrammarFunctor m :: ((* -> *) -> *) -> * -> * -> *+   -- | The record of grammar productions associated with the parser+   type ParserGrammar m :: (* -> *) -> *+   -- | For internal use by 'notTerminal'+   type GrammarFunctor m :: * -> *+   -- | Converts the intermediate to final parsing result.+   parsingResult :: ParserInput m -> GrammarFunctor m a -> ResultFunctor m (ParserInput m, a)    -- | Used to reference a grammar production, only necessary from outside the grammar itself-   nonTerminal :: GrammarConstraint m g => (g (GrammarFunctor m g s) -> GrammarFunctor m g s a) -> m g s a+   nonTerminal :: (g ~ ParserGrammar m, GrammarConstraint m g) => (g (GrammarFunctor m) -> GrammarFunctor m a) -> m a    -- | Construct a grammar whose every production refers to itself.-   selfReferring :: (GrammarConstraint m g, Rank2.Distributive g) => g (m g s)+   selfReferring :: (g ~ ParserGrammar m, GrammarConstraint m g, Rank2.Distributive g) => g m    -- | Convert a self-referring grammar function to a grammar.-   fixGrammar :: forall g s. (GrammarConstraint m g, Rank2.Distributive g) => (g (m g s) -> g (m g s)) -> g (m g s)+   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 g s a -> m g s a+   recursive :: m a -> m a     selfReferring = Rank2.cotraverse nonTerminal id    {-# INLINE selfReferring #-}@@ -107,137 +112,61 @@    {-# INLINE fixGrammar #-}    recursive = id --- | Methods for parsing monoidal inputs-class MonoidParsing m where-   -- | A parser that fails on any input and succeeds at its end.-   endOfInput :: FactorialMonoid s => m s ()-   -- | Always sucessful parser that returns the remaining input without consuming it.-   getInput :: FactorialMonoid s => m s s-   -- | Retrieve the 'Position' the parser has reached in the input source.-   getSourcePos :: FactorialMonoid s => m s (Position s)--   -- | A parser that accepts any single input atom.-   anyToken :: FactorialMonoid s => m s s-   -- | A parser that accepts an input atom only if it satisfies the given predicate.-   satisfy :: FactorialMonoid s => (s -> Bool) -> m s s-   -- | Specialization of 'satisfy' on 'TextualMonoid' inputs, accepting and returning an input character only if it-   -- satisfies the given predicate.-   satisfyChar :: TextualMonoid s => (Char -> Bool) -> m s Char-   -- | Specialization of 'satisfy' on 'TextualMonoid' inputs, accepting an input character only if it satisfies the-   -- given predicate, and returning the input atom that represents the character. A faster version of @singleton <$>-   -- satisfyChar p@ and of @satisfy (fromMaybe False p . characterPrefix)@.-   satisfyCharInput :: TextualMonoid s => (Char -> Bool) -> m s s-   -- | A parser that succeeds exactly when satisfy doesn't, equivalent to-   -- 'Text.Parser.Combinators.notFollowedBy' @. satisfy@-   notSatisfy :: FactorialMonoid s => (s -> Bool) -> m s ()-   -- | A parser that succeeds exactly when satisfyChar doesn't, equivalent to-   -- 'Text.Parser.Combinators.notFollowedBy' @. satisfyChar@-   notSatisfyChar :: TextualMonoid s => (Char -> Bool) -> m s ()--   -- | A stateful scanner. The predicate modifies a state argument, and each transformed state is passed to successive-   -- invocations of the predicate on each token of the input until one returns 'Nothing' or the input ends.-   ---   -- This parser does not fail.  It will return an empty string if the predicate returns 'Nothing' on the first-   -- character.-   ---   -- /Note/: Because this parser does not fail, do not use it with combinators such as 'many', because such parsers-   -- loop until a failure occurs.  Careless use will thus result in an infinite loop.-   scan :: FactorialMonoid t => s -> (s -> t -> Maybe s) -> m t t-   -- | Stateful scanner like `scanChars`, but specialized for 'TextualMonoid' inputs.-   scanChars :: TextualMonoid t => s -> (s -> Char -> Maybe s) -> m t t-   -- | A parser that consumes and returns the given prefix of the input.-   string :: (FactorialMonoid s, LeftReductiveMonoid s, Show s) => s -> m s s--   -- | A parser accepting the longest sequence of input atoms that match the given predicate; an optimized version of-   -- 'concatMany . satisfy'.-   ---   -- /Note/: Because this parser does not fail, do not use it with combinators such as 'many', because such parsers-   -- loop until a failure occurs.  Careless use will thus result in an infinite loop.-   takeWhile :: FactorialMonoid s => (s -> Bool) -> m s s-   -- | A parser accepting the longest non-empty sequence of input atoms that match the given predicate; an optimized-   -- version of 'concatSome . satisfy'.-   takeWhile1 :: FactorialMonoid s => (s -> Bool) -> m s s-   -- | Specialization of 'takeWhile' on 'TextualMonoid' inputs, accepting the longest sequence of input characters that-   -- match the given predicate; an optimized version of 'fmap fromString  . many . satisfyChar'.-   ---   -- /Note/: Because this parser does not fail, do not use it with combinators such as 'many', because such parsers-   -- loop until a failure occurs.  Careless use will thus result in an infinite loop.-   takeCharsWhile :: TextualMonoid s => (Char -> Bool) -> m s s-   -- | Specialization of 'takeWhile1' on 'TextualMonoid' inputs, accepting the longest sequence of input characters-   -- that match the given predicate; an optimized version of 'fmap fromString  . some . satisfyChar'.-   takeCharsWhile1 :: TextualMonoid s => (Char -> Bool) -> m s s-   -- | Zero or more argument occurrences like 'many', with concatenated monoidal results.-   concatMany :: Monoid a => m s a -> m s a--   default concatMany :: (Monoid a, Alternative (m s)) => m s a -> m s a-   concatMany p = go-      where go = mappend <$> p <*> go <|> pure mempty-   default getSourcePos :: (FactorialMonoid s, Functor (m s)) => m s (Position s)-   getSourcePos = Position . Factorial.length <$> getInput-   {-# INLINE concatMany #-}-   {-# INLINE getSourcePos #-}+class GrammarParsing m => TailsParsing m where+   -- | Parse the tails of the input together with memoized parse results+   parseTails :: GrammarConstraint m g => m r -> [(ParserInput m, g (GrammarFunctor m))] -> GrammarFunctor m r+   parseAllTails :: (GrammarConstraint m g, Rank2.Functor g) =>+                    g m -> [(ParserInput m, g (GrammarFunctor m))] -> [(ParserInput m, g (GrammarFunctor m))]+   parseAllTails _ [] = []+   parseAllTails final parsed@((s, _):_) = (s, gd):parsed+      where gd = Rank2.fmap (`parseTails` parsed) final  -- | Parsers that can produce alternative parses and collect them into an 'Ambiguous' node-class AmbiguousParsing m where+class Alternative m => AmbiguousParsing m where    -- | Collect all alternative parses of the same length into a 'NonEmpty' list of results.    ambiguous :: m a -> m (Ambiguous a) --- | If a grammar is 'Lexical', its parsers can instantiate the 'Text.Parser.Token.TokenParsing' class.-class Lexical (g :: (* -> *) -> *) where-   type LexicalConstraint (m :: ((* -> *) -> *) -> * -> * -> *) g s :: Constraint+-- | If a grammar is 'Lexical', its parsers can instantiate the 'TokenParsing' class.+class (DeterministicParsing m, InputCharParsing m, TokenParsing m) => LexicalParsing m where    -- | Always succeeds, consuming all white space and comments-   lexicalWhiteSpace :: LexicalConstraint m g s => m g s ()+   lexicalWhiteSpace :: m ()    -- | Consumes all whitespace and comments, failing if there are none-   someLexicalSpace :: LexicalConstraint m g s => m g s ()+   someLexicalSpace :: m ()    -- | Consumes a single comment, defaults to 'empty'-   lexicalComment :: LexicalConstraint m g s => m g s ()+   lexicalComment :: m ()    -- | Consumes a single semicolon and any trailing whitespace, returning the character |';'|. The method can be    -- overridden for automatic semicolon insertion, but if it succeeds on semicolon or white space input it must    -- consume it.-   lexicalSemicolon :: LexicalConstraint m g s => m g s Char+   lexicalSemicolon :: m Char    -- | Applies the argument parser and consumes the trailing 'lexicalWhitespace'-   lexicalToken :: LexicalConstraint m g s => m g s a -> m g s a+   lexicalToken :: m a -> m a    -- | Applies the argument parser, determines whether its result is a legal identifier, and consumes the trailing    -- 'lexicalWhitespace'-   identifierToken :: LexicalConstraint m g s => m g s s -> m g s s+   identifierToken :: m (ParserInput m) -> m (ParserInput m)    -- | Determines whether the given character can start an identifier token, allows only a letter or underscore by    -- default    isIdentifierStartChar :: Char -> Bool    -- | Determines whether the given character can be any part of an identifier token, also allows numbers    isIdentifierFollowChar :: Char -> Bool    -- | Parses a valid identifier and consumes the trailing 'lexicalWhitespace'-   identifier :: LexicalConstraint m g s => m g s s+   identifier :: m (ParserInput m)    -- | Parses the argument word whole, not followed by any identifier character, and consumes the trailing    -- 'lexicalWhitespace'-   keyword :: LexicalConstraint m g s => s -> m g s ()+   keyword :: ParserInput m -> m () -   type instance LexicalConstraint m g s = (Applicative (m g ()), Monad (m g s),-                                            CharParsing (m g s), MonoidParsing (m g),-                                            Show s, TextualMonoid s)-   default lexicalComment :: Alternative (m g s) => m g s ()-   default lexicalWhiteSpace :: (LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s)-                             => m g s ()-   default someLexicalSpace :: (LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s)-                            => m g s ()-   default lexicalSemicolon :: (LexicalConstraint m g s, CharParsing (m g s), MonoidParsing (m g), TextualMonoid s)-                            => m g s Char-   default lexicalToken :: (LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s)-                        => m g s a -> m g s a-   default identifierToken :: (LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s)-                           => m g s s -> m g s s-   default identifier :: (LexicalConstraint m g s, Monad (m g s), Alternative (m g s),-                          Parsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s s-   default keyword :: (LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), Show s, TextualMonoid s)-                   => s -> m g s ()-   lexicalWhiteSpace = takeCharsWhile isSpace *> skipMany (lexicalComment *> takeCharsWhile isSpace)-   someLexicalSpace = takeCharsWhile1 isSpace *> skipMany (lexicalComment *> takeCharsWhile isSpace)-                      <|> lexicalComment *> skipMany (takeCharsWhile isSpace *> lexicalComment)+   default identifier :: TextualMonoid (ParserInput m) => m (ParserInput m)+   default keyword :: (Show (ParserInput m), TextualMonoid (ParserInput m)) => ParserInput m -> m ()++   lexicalWhiteSpace = takeCharsWhile isSpace *> skipAll (lexicalComment *> takeCharsWhile isSpace)+   someLexicalSpace = takeCharsWhile1 isSpace *> (lexicalComment *> lexicalWhiteSpace <<|> pure ())+                      <<|> lexicalComment *> lexicalWhiteSpace+                      <?> "whitespace"    lexicalComment = empty-   lexicalSemicolon = lexicalToken (char ';')+   lexicalSemicolon = lexicalToken (Text.Parser.Char.char ';')    lexicalToken p = p <* lexicalWhiteSpace    isIdentifierStartChar c = isLetter c || c == '_'    isIdentifierFollowChar c = isAlphaNum c || c == '_'-   identifier = identifierToken (liftA2 mappend (satisfyCharInput (isIdentifierStartChar @g))-                                                (takeCharsWhile (isIdentifierFollowChar @g))) <?> "an identifier"+   identifier = identifierToken (liftA2 mappend (satisfyCharInput (isIdentifierStartChar @m))+                                                (takeCharsWhile (isIdentifierFollowChar @m))) <?> "an identifier"    identifierToken = lexicalToken-   keyword s = lexicalToken (string s *> notSatisfyChar (isIdentifierFollowChar @g)) <?> ("keyword " <> show s)+   keyword s = lexicalToken (string s *> notSatisfyChar (isIdentifierFollowChar @m)) <?> ("keyword " <> show s)
src/Text/Grampa/Combinators.hs view
@@ -1,23 +1,30 @@+{-# LANGUAGE TypeFamilies #-}+ module Text.Grampa.Combinators (moptional, concatMany, concatSome,                                 flag, count, upto,                                 delimiter, operator, keyword) where  import Control.Applicative(Applicative(..), Alternative(..))-import Data.Monoid.Cancellative (LeftReductiveMonoid)-import Data.Monoid (Monoid, (<>))+import Data.List.NonEmpty (fromList)+import Data.Monoid (Monoid) import Data.Monoid.Factorial (FactorialMonoid)+import Data.Semigroup (Semigroup(sconcat))+import Data.Semigroup.Cancellative (LeftReductive) -import Text.Grampa.Class (MonoidParsing(concatMany, string), -                          Lexical(LexicalConstraint, lexicalToken, keyword))+import Text.Grampa.Class (InputParsing(ParserInput, string), LexicalParsing(lexicalToken, keyword)) import Text.Parser.Combinators (Parsing((<?>)), count)  -- | Attempts to parse a monoidal value, if the argument parser fails returns 'mempty'.-moptional :: (Monoid x, Alternative p) => p x -> p x+moptional :: (Alternative p, Monoid a) => p a -> p a moptional p = p <|> pure mempty +-- | Zero or more argument occurrences like 'many', with concatenated monoidal results.+concatMany :: (Alternative p, Monoid a) => p a -> p a+concatMany p = mconcat <$> many p+ -- | One or more argument occurrences like 'some', with concatenated monoidal results.-concatSome :: (Monoid x, Applicative (p s), MonoidParsing p) => p s x -> p s x-concatSome p = (<>) <$> p <*> concatMany p+concatSome :: (Alternative p, Semigroup a) => p a -> p a+concatSome p = sconcat . fromList <$> some p  -- | Returns 'True' if the argument parser succeeds and 'False' otherwise. flag :: Alternative p => p a -> p Bool@@ -31,11 +38,9 @@    | otherwise = pure []  -- | Parses the given delimiter, such as a comma or a brace-delimiter :: (Show s, FactorialMonoid s, LeftReductiveMonoid s,-              Parsing (p g s), MonoidParsing (p g), Lexical g, LexicalConstraint p g s) => s -> p g s s+delimiter :: (Show s, FactorialMonoid s, LeftReductive s, s ~ ParserInput m, LexicalParsing m) => s -> m s delimiter s = lexicalToken (string s) <?> ("delimiter " <> show s)  -- | Parses the given operator symbol-operator :: (Show s, FactorialMonoid s, LeftReductiveMonoid s,-             Parsing (p g s), MonoidParsing (p g), Lexical g, LexicalConstraint p g s) => s -> p g s s+operator :: (Show s, FactorialMonoid s, LeftReductive s, s ~ ParserInput m, LexicalParsing m) => s -> m s operator s = lexicalToken (string s) <?> ("operator " <> show s)
src/Text/Grampa/ContextFree/Continued.hs view
@@ -14,10 +14,10 @@ import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString) -import qualified Data.Monoid.Cancellative as Cancellative import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Null as Null import qualified Data.Monoid.Textual as Textual+import qualified Data.Semigroup.Cancellative as Cancellative  import qualified Rank2 @@ -25,21 +25,20 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token-import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Grampa.Class (DeterministicParsing(..), InputParsing(..), InputCharParsing(..), MultiParsing(..),+                          ParseResults, ParseFailure(..), Expected(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,                                               parsedSuffix :: !s}-                                     | NoParse FailureInfo+                                     | NoParse (FailureInfo 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. newtype Parser (g :: (* -> *) -> *) s r =-   Parser{applyParser :: forall x. s -> (r -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x}+   Parser{applyParser :: forall x. s -> (r -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x} -instance Show1 (Result g s) where+instance Show s => Show1 (Result g s) where    liftShowsPrec showsPrecSub _showList prec Parsed{parsedPrefix= r} rest = "Parsed " ++ showsPrecSub prec r rest    liftShowsPrec _showsPrec _showList _prec (NoParse f) rest = "NoParse " ++ shows f rest @@ -55,18 +54,18 @@    pure a = Parser (\input success failure-> success a input failure)    (<*>) :: forall a b. Parser g s (a -> b) -> Parser g s a -> Parser g s b    Parser p <*> Parser q = Parser r where-      r :: forall x. s -> (b -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      r :: forall x. s -> (b -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x       r rest success failure = p rest (\f rest'-> q rest' (success . f)) failure    {-# INLINABLE (<*>) #-}  instance Factorial.FactorialMonoid s => Alternative (Parser g s) where-   empty = Parser (\rest _ failure-> failure $ FailureInfo (Factorial.length rest) ["empty"])+   empty = Parser (\rest _ failure-> failure $ FailureInfo (Factorial.length rest) [Expected "empty"])    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator alt :: forall g s a. Parser g s a -> Parser g s a -> Parser g s a Parser p `alt` Parser q = Parser r where-   r :: forall x. s -> (a -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+   r :: forall x. s -> (a -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x    r rest success failure = p rest success' failure'       where success' a rest' _ = success a rest' failure'             failure' f1 = q rest success (\f2 -> failure (f1 <> f2))@@ -75,7 +74,7 @@    return = pure    (>>=) :: forall a b. Parser g s a -> (a -> Parser g s b) -> Parser g s b    Parser p >>= f = Parser r where-      r :: forall x. s -> (b -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      r :: forall x. s -> (b -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x       r rest success failure = p rest (\a rest'-> applyParser (f a) rest' success) failure  instance Factorial.FactorialMonoid s => MonadPlus (Parser g s) where@@ -92,154 +91,147 @@ instance Factorial.FactorialMonoid s => Parsing (Parser g s) where    try :: forall a. Parser g s a -> Parser g s a    try (Parser p) = Parser q-      where q :: forall x. s -> (a -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success (failure . rewindFailure)                where rewindFailure (FailureInfo _pos _msgs) = FailureInfo (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 -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success (failure . replaceFailure)                where replaceFailure (FailureInfo pos msgs) =-                        FailureInfo pos (if pos == Factorial.length input then [msg] else msgs)+                        FailureInfo pos (if pos == Factorial.length input then [Expected msg] else msgs) -   eof = endOfInput-   unexpected msg = Parser (\t _ failure -> failure $ FailureInfo (Factorial.length t) [msg])+   eof = Parser p+      where p rest success failure+               | Null.null rest = success () rest failure+               | otherwise = failure (FailureInfo (Factorial.length rest) [Expected "end of input"])+   unexpected msg = Parser (\t _ failure -> failure $ FailureInfo (Factorial.length t) [Expected msg])    notFollowedBy (Parser p) = Parser q-      where q :: forall x. s -> (() -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (() -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success' failure'-               where success' _ _ _ = failure (FailureInfo (Factorial.length input) ["notFollowedBy"])+               where success' _ _ _ = failure (FailureInfo (Factorial.length input) [Expected "notFollowedBy"])                      failure' _ = success () input failure +instance FactorialMonoid s => DeterministicParsing (Parser g s) where+   (<<|>) :: forall a. Parser g s a -> Parser g s a -> Parser g s a+   Parser p <<|> Parser q = Parser r where+      r :: forall x. s -> (a -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+      r rest success failure = p rest success' failure'+         where success' a rest' _ = success a rest' failure+               failure' f1 = q rest success (\f2 -> failure (f1 <> f2))+   takeSome p = (:) <$> p <*> takeMany p+   takeMany p = takeSome p <<|> pure []+ instance Factorial.FactorialMonoid s => LookAheadParsing (Parser g s) where    lookAhead :: forall a. Parser g s a -> Parser g s a    lookAhead (Parser p) = Parser q-      where q :: forall x. s -> (a -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success' failure'                where success' a _ = success a input                      failure' f = failure f  instance (Show s, TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+   satisfy predicate = Parser p+      where p :: forall x. s -> (Char -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> success first suffix failure+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--instance MonoidParsing (Parser g) where-   endOfInput = Parser p-      where p rest success failure-               | Null.null rest = success () rest failure-               | otherwise = failure (FailureInfo (Factorial.length rest) ["endOfInput"])+instance (Cancellative.LeftReductive s, Factorial.FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p       where p rest success failure = success rest rest failure    anyToken = Parser p       where p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) -> success first suffix failure-                  _ -> failure (FailureInfo (Factorial.length rest) ["anyToken"])-   satisfy :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "anyToken"])    satisfy predicate = Parser p-      where p :: forall x. s -> (s -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) | predicate first -> success first suffix failure-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfy"])-   satisfyChar :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s Char-   satisfyChar predicate = Parser p-      where p :: forall x. s -> (Char -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> success first suffix failure-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfyChar"])-   satisfyCharInput :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s-   satisfyCharInput predicate = Parser p-      where p :: forall x. s -> (s -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> success (Factorial.primePrefix rest) suffix failure-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfyChar"])-   notSatisfy :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s ()+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "satisfy"])    notSatisfy predicate = Parser p-      where p :: forall x. s -> (() -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (() -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, _)-                     | predicate first -> failure (FailureInfo (Factorial.length rest) ["notSatisfy"])-                  _ -> success () rest failure-   notSatisfyChar :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s ()-   notSatisfyChar predicate = Parser p-      where p :: forall x. s -> (() -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.characterPrefix rest-               of Just first | predicate first-                               -> failure (FailureInfo (Factorial.length rest) ["notSatisfyChar"])+                     | predicate first -> failure (FailureInfo (Factorial.length rest) [Expected "notSatisfy"])                   _ -> success () rest failure-   scan :: forall t s. FactorialMonoid t => s -> (s -> t -> Maybe s) -> Parser g t t+   scan :: forall state. state -> (state -> s -> Maybe state) -> Parser g s s    scan s0 f = Parser (p s0)-      where p :: forall x. s -> t -> (t -> t -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. state -> s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p s rest success failure = success prefix suffix failure                where (prefix, suffix, _) = Factorial.spanMaybe' s f rest-   scanChars :: forall t s. TextualMonoid t => s -> (s -> Char -> Maybe s) -> Parser g t t-   scanChars s0 f = Parser (p s0)-      where p :: forall x. s -> t -> (t -> t -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            p s rest success failure = success prefix suffix failure-               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest-   takeWhile :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s+   take n = Parser p+      where p :: forall x. s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p rest success failure+              | (prefix, suffix) <- Factorial.splitAt n rest,+                Factorial.length prefix == n = success prefix suffix failure+              | otherwise = failure (FailureInfo (Factorial.length rest) [Expected $ "take " ++ show n])    takeWhile predicate = Parser p-      where p :: forall x. s -> (s -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure | (prefix, suffix) <- Factorial.span predicate rest = success prefix suffix failure-   takeWhile1 :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s    takeWhile1 predicate = Parser p-      where p :: forall x. s -> (s -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure                | (prefix, suffix) <- Factorial.span predicate rest =                     if Null.null prefix-                    then failure (FailureInfo (Factorial.length rest) ["takeWhile1"])+                    then failure (FailureInfo (Factorial.length rest) [Expected "takeWhile1"])                     else success prefix suffix failure-   takeCharsWhile :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s+   string s = Parser p where+      p :: forall x. s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+      p s' success failure+         | Just suffix <- Cancellative.stripPrefix s s' = success s suffix failure+         | otherwise = failure (FailureInfo (Factorial.length s') [ExpectedInput s])+   {-# INLINABLE string #-}++instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p :: forall x. s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> success (Factorial.primePrefix rest) suffix failure+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "satisfyChar"])+   notSatisfyChar predicate = Parser p+      where p :: forall x. s -> (() -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.characterPrefix rest+               of Just first | predicate first+                               -> failure (FailureInfo (Factorial.length rest) [Expected "notSatisfyChar"])+                  _ -> success () rest failure+   scanChars :: forall state. state -> (state -> Char -> Maybe state) -> Parser g s s+   scanChars s0 f = Parser (p s0)+      where p :: forall x. state -> s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p s rest success failure = success prefix suffix failure+               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest    takeCharsWhile predicate = Parser p-      where p :: forall x. s -> (s -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure                | (prefix, suffix) <- Textual.span_ False predicate rest = success prefix suffix failure-   takeCharsWhile1 :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s    takeCharsWhile1 predicate = Parser p-      where p :: forall x. s -> (s -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure-               | Null.null prefix = failure (FailureInfo (Factorial.length rest) ["takeCharsWhile1"])+               | Null.null prefix = failure (FailureInfo (Factorial.length rest) [Expected "takeCharsWhile1"])                | otherwise = success prefix suffix failure                where (prefix, suffix) = Textual.span_ False predicate rest-   string :: forall s. (Cancellative.LeftReductiveMonoid s, FactorialMonoid s, Show s) => s -> Parser g s s-   string s = Parser p where-      p :: forall x. s -> (s -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-      p s' success failure-         | Just suffix <- Cancellative.stripPrefix s s' = success s suffix failure-         | otherwise = failure (FailureInfo (Factorial.length s') ["string " ++ show s])-   concatMany :: forall s a. Monoid a => Parser g s a -> Parser g s a-   concatMany (Parser p) = Parser q-      where q :: forall x. s -> (a -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            q rest success failure = p rest success' (const $ success mempty rest failure)-               where success' prefix suffix failure' =-                        q suffix (success . mappend prefix) (const $ success prefix suffix failure')-   {-# INLINABLE string #-}  -- | Continuation-passing context-free parser -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Continued.'Parser' g s) -> s -> g 'ParseResults'+--                  g (Continued.'Parser' g s) -> s -> g ('ParseResults' s) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = ParseResults+instance (Cancellative.LeftReductive s, Factorial.FactorialMonoid s) => MultiParsing (Parser g s) where+   type ResultFunctor (Parser g s) = ParseResults s    -- | Returns an input prefix parse paired with the remaining input suffix.    parsePrefix g input = Rank2.fmap (Compose . (\p-> applyParser p input (\a rest _-> Right (rest, a)) (Left . fromFailure input))) g    parseComplete g input = Rank2.fmap (\p-> applyParser p input (const . const . Right) (Left . fromFailure input))-                                      (Rank2.fmap (<* endOfInput) g)+                                      (Rank2.fmap (<* eof) g) -fromFailure :: FactorialMonoid s => s -> FailureInfo -> ParseFailure+fromFailure :: (Eq s, FactorialMonoid s) => s -> FailureInfo s -> ParseFailure s fromFailure s (FailureInfo pos msgs) = ParseFailure (Factorial.length s - pos + 1) (nub msgs)
src/Text/Grampa/ContextFree/Continued/Measured.hs view
@@ -14,10 +14,10 @@ import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString) -import qualified Data.Monoid.Cancellative as Cancellative import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Null as Null import qualified Data.Monoid.Textual as Textual+import qualified Data.Semigroup.Cancellative as Cancellative  import qualified Rank2 @@ -25,21 +25,20 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token-import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Grampa.Class (DeterministicParsing(..), InputParsing(..), InputCharParsing(..), ConsumedInputParsing(..),+                          MultiParsing(..), ParseResults, ParseFailure(..), Expected(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,                                               parsedSuffix :: !s}-                                     | NoParse FailureInfo+                                     | NoParse (FailureInfo 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. newtype Parser (g :: (* -> *) -> *) s r =-   Parser{applyParser :: forall x. s -> (r -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x}+   Parser{applyParser :: forall x. s -> (r -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x} -instance Show1 (Result g s) where+instance Show s => Show1 (Result g s) where    liftShowsPrec showsPrecSub _showList prec Parsed{parsedPrefix= r} rest = "Parsed " ++ showsPrecSub prec r rest    liftShowsPrec _showsPrec _showList _prec (NoParse f) rest = "NoParse " ++ shows f rest @@ -55,18 +54,18 @@    pure a = Parser (\input success failure-> success a 0 input failure)    (<*>) :: forall a b. Parser g s (a -> b) -> Parser g s a -> Parser g s b    Parser p <*> Parser q = Parser r where-      r :: forall x. s -> (b -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      r :: forall x. s -> (b -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x       r rest success failure = p rest (\f len rest'-> q rest' (\a len'-> success (f a) $! len + len')) failure    {-# INLINABLE (<*>) #-}  instance Factorial.FactorialMonoid s => Alternative (Parser g s) where-   empty = Parser (\rest _ failure-> failure $ FailureInfo (Factorial.length rest) ["empty"])+   empty = Parser (\rest _ failure-> failure $ FailureInfo (Factorial.length rest) [Expected "empty"])    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator alt :: forall g s a. Parser g s a -> Parser g s a -> Parser g s a Parser p `alt` Parser q = Parser r where-   r :: forall x. s -> (a -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+   r :: forall x. s -> (a -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x    r rest success failure = p rest success' failure'       where success' a len rest' _ = success a len rest' failure'             failure' f1 = q rest success (\f2 -> failure (f1 <> f2))@@ -75,7 +74,7 @@    return = pure    (>>=) :: forall a b. Parser g s a -> (a -> Parser g s b) -> Parser g s b    Parser p >>= f = Parser r where-      r :: forall x. s -> (b -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      r :: forall x. s -> (b -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x       r rest success failure = p rest                                  (\a len rest'-> applyParser (f a) rest' $ \b len'-> success b $! len + len')                                  failure@@ -94,159 +93,157 @@ instance Factorial.FactorialMonoid s => Parsing (Parser g s) where    try :: forall a. Parser g s a -> Parser g s a    try (Parser p) = Parser q-      where q :: forall x. s -> (a -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success (failure . rewindFailure)                where rewindFailure (FailureInfo _pos _msgs) = FailureInfo (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 -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success (failure . replaceFailure)                where replaceFailure (FailureInfo pos msgs) =-                        FailureInfo pos (if pos == Factorial.length input then [msg] else msgs)-   eof = endOfInput-   unexpected msg = Parser (\t _ failure -> failure $ FailureInfo (Factorial.length t) [msg])+                        FailureInfo pos (if pos == Factorial.length input then [Expected msg] else msgs)+   eof = Parser p+      where p rest success failure+               | Null.null rest = success () 0 rest failure+               | otherwise = failure (FailureInfo (Factorial.length rest) [Expected "end of input"])+   unexpected msg = Parser (\t _ failure -> failure $ FailureInfo (Factorial.length t) [Expected msg])    notFollowedBy (Parser p) = Parser q-      where q :: forall x. s -> (() -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (() -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success' failure'-               where success' _ _ _ _ = failure (FailureInfo (Factorial.length input) ["notFollowedBy"])+               where success' _ _ _ _ = failure (FailureInfo (Factorial.length input) [Expected "notFollowedBy"])                      failure' _ = success () 0 input failure +instance Factorial.FactorialMonoid s => DeterministicParsing (Parser g s) where+   (<<|>) :: forall a. Parser g s a -> Parser g s a -> Parser g s a+   Parser p <<|> Parser q = Parser r where+      r :: forall x. s -> (a -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+      r rest success failure = p rest success' failure'+         where success' a len rest' _ = success a len rest' failure+               failure' f1 = q rest success (\f2 -> failure (f1 <> f2))+   takeSome p = (:) <$> p <*> takeMany p+   takeMany p = takeSome p <<|> pure []+ instance Factorial.FactorialMonoid s => LookAheadParsing (Parser g s) where    lookAhead :: forall a. Parser g s a -> Parser g s a    lookAhead (Parser p) = Parser q-      where q :: forall x. s -> (a -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success' failure'                where success' a _ _ = success a 0 input                      failure' f = failure f  instance (Show s, TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+   satisfy predicate = Parser p+      where p :: forall x. s -> (Char -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> success first 1 suffix failure+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--instance MonoidParsing (Parser g) where-   endOfInput = Parser p-      where p rest success failure-               | Null.null rest = success () 0 rest failure-               | otherwise = failure (FailureInfo (Factorial.length rest) ["endOfInput"])+instance (Cancellative.LeftReductive s, Factorial.FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p       where p rest success failure = success rest 0 rest failure    anyToken = Parser p       where p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) -> success first 1 suffix failure-                  _ -> failure (FailureInfo (Factorial.length rest) ["anyToken"])-   satisfy :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "anyToken"])    satisfy predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) | predicate first -> success first 1 suffix failure-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfy"])-   satisfyChar :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s Char-   satisfyChar predicate = Parser p-      where p :: forall x. s -> (Char -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> success first 1 suffix failure-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfyChar"])-   satisfyCharInput :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s-   satisfyCharInput predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> success (Factorial.primePrefix rest) 1 suffix failure-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfyChar"])-   notSatisfy :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s ()+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "satisfy"])    notSatisfy predicate = Parser p-      where p :: forall x. s -> (() -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (() -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, _)-                     | predicate first -> failure (FailureInfo (Factorial.length rest) ["notSatisfy"])-                  _ -> success () 0 rest failure-   notSatisfyChar :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s ()-   notSatisfyChar predicate = Parser p-      where p :: forall x. s -> (() -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.characterPrefix rest-               of Just first | predicate first-                               -> failure (FailureInfo (Factorial.length rest) ["notSatisfyChar"])+                     | predicate first -> failure (FailureInfo (Factorial.length rest) [Expected "notSatisfy"])                   _ -> success () 0 rest failure-   scan :: forall t s. FactorialMonoid t => s -> (s -> t -> Maybe s) -> Parser g t t+   scan :: forall state. state -> (state -> s -> Maybe state) -> Parser g s s    scan s0 f = Parser (p s0)-      where p :: forall x. s -> t -> (t -> Int -> t -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. state -> s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p s rest success failure = success prefix len suffix failure                where (prefix, suffix, _) = Factorial.spanMaybe' s f rest                      !len = Factorial.length prefix-   scanChars :: forall t s. TextualMonoid t => s -> (s -> Char -> Maybe s) -> Parser g t t-   scanChars s0 f = Parser (p s0)-      where p :: forall x. s -> t -> (t -> Int -> t -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            p s rest success failure = success prefix len suffix failure-               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest-                     !len = Factorial.length prefix-   takeWhile :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s+   take n = Parser p+      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p rest success failure+               | (prefix, suffix) <- Factorial.splitAt n rest,+                 len <- Factorial.length prefix, len == n = success prefix len suffix failure+               | otherwise = failure (FailureInfo (Factorial.length rest) [Expected $ "take " ++ show n])    takeWhile predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure                 | (prefix, suffix) <- Factorial.span predicate rest,                   !len <- Factorial.length prefix =                      success prefix len suffix failure-   takeWhile1 :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s    takeWhile1 predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure                | (prefix, suffix) <- Factorial.span predicate rest,                   !len <- Factorial.length prefix =                     if len == 0-                    then failure (FailureInfo (Factorial.length rest) ["takeWhile1"])+                    then failure (FailureInfo (Factorial.length rest) [Expected "takeWhile1"])                     else success prefix len suffix failure-   takeCharsWhile :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s+   string s = Parser p where+      p :: forall x. s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+      p s' success failure+         | Just suffix <- Cancellative.stripPrefix s s', !len <- Factorial.length s = success s len suffix failure+         | otherwise = failure (FailureInfo (Factorial.length s') [ExpectedInput s])+   {-# INLINABLE string #-}++instance (Cancellative.LeftReductive s, FactorialMonoid s) => ConsumedInputParsing (Parser g s) where+   match :: forall a. Parser g s a -> Parser g s (s, a)+   match (Parser p) = Parser q+      where q :: forall x. s -> ((s, a) -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            q rest success failure = p rest success' failure+               where success' r !len suffix failure' = success (Factorial.take len rest, r) len suffix failure'++instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> success (Factorial.primePrefix rest) 1 suffix failure+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "satisfyChar"])+   notSatisfyChar predicate = Parser p+      where p :: forall x. s -> (() -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.characterPrefix rest+               of Just first | predicate first+                               -> failure (FailureInfo (Factorial.length rest) [Expected "notSatisfyChar"])+                  _ -> success () 0 rest failure+   scanChars :: forall state. state -> (state -> Char -> Maybe state) -> Parser g s s+   scanChars s0 f = Parser (p s0)+      where p :: forall x. state -> s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x+            p s rest success failure = success prefix len suffix failure+               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest+                     !len = Factorial.length prefix    takeCharsWhile predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure                | (prefix, suffix) <- Textual.span_ False predicate rest,                   !len <- Factorial.length prefix = success prefix len suffix failure-   takeCharsWhile1 :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s    takeCharsWhile1 predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> Int -> s -> (FailureInfo s -> x) -> x) -> (FailureInfo s -> x) -> x             p rest success failure-               | Null.null prefix = failure (FailureInfo (Factorial.length rest) ["takeCharsWhile1"])+               | Null.null prefix = failure (FailureInfo (Factorial.length rest) [Expected "takeCharsWhile1"])                | otherwise = len `seq` success prefix len suffix failure                where (prefix, suffix) = Textual.span_ False predicate rest                      len = Factorial.length prefix-   string :: forall s. (Cancellative.LeftReductiveMonoid s, FactorialMonoid s, Show s) => s -> Parser g s s-   string s = Parser p where-      p :: forall x. s -> (s -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-      p s' success failure-         | Just suffix <- Cancellative.stripPrefix s s', !len <- Factorial.length s = success s len suffix failure-         | otherwise = failure (FailureInfo (Factorial.length s') ["string " ++ show s])-   concatMany :: forall s a. Monoid a => Parser g s a -> Parser g s a-   concatMany (Parser p) = Parser q-      where q :: forall x. s -> (a -> Int -> s -> (FailureInfo -> x) -> x) -> (FailureInfo -> x) -> x-            q rest success failure = p rest success' (const $ success mempty 0 rest failure)-               where success' prefix !len suffix failure' =-                        q suffix -                          (\prefix' !len'-> success (mappend prefix prefix') (len + len')) -                          (const $ success prefix len suffix failure')-   {-# INLINABLE string #-}  -- | Continuation-passing context-free parser that keeps track of the parsed prefix length -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Continued.'Parser' g s) -> s -> g 'ParseResults'+--                  g (Continued.'Parser' g s) -> s -> g ('ParseResults' s) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = ParseResults+instance (Cancellative.LeftReductive s, Factorial.FactorialMonoid s) => MultiParsing (Parser g s) where+   type ResultFunctor (Parser g s) = ParseResults s    -- | Returns an input prefix parse paired with the remaining input suffix.    parsePrefix g input = Rank2.fmap (Compose . (\p-> applyParser p input                                                                  (\a _ rest _-> Right (rest, a))@@ -255,7 +252,7 @@    parseComplete g input = Rank2.fmap (\p-> applyParser p input                                                         (const . const . const . Right)                                                         (Left . fromFailure input))-                                      (Rank2.fmap (<* endOfInput) g)+                                      (Rank2.fmap (<* eof) g) -fromFailure :: FactorialMonoid s => s -> FailureInfo -> ParseFailure+fromFailure :: (Eq s, FactorialMonoid s) => s -> FailureInfo s -> ParseFailure s fromFailure s (FailureInfo pos msgs) = ParseFailure (Factorial.length s - pos + 1) (nub msgs)
src/Text/Grampa/ContextFree/LeftRecursive.hs view
@@ -1,17 +1,18 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, InstanceSigs,-             RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeFamilies, TypeOperators, UndecidableInstances #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, GADTs, GeneralizedNewtypeDeriving, InstanceSigs,+             RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeFamilies, TypeOperators,+             UndecidableInstances #-} {-# OPTIONS -fno-full-laziness #-}-module Text.Grampa.ContextFree.LeftRecursive (Fixed, Parser, SeparatedParser(..),+module Text.Grampa.ContextFree.LeftRecursive (Fixed, Parser, SeparatedParser(..), FallibleWithExpectations(..),                                               longest, peg, terminalPEG,-                                              parseSeparated, separated, (<<|>))+                                              liftPositive, liftPure, mapPrimitive,+                                              parseSeparated, separated) where  import Control.Applicative-import Control.Monad (Monad(..), MonadPlus(..))+import Control.Monad (Monad(..), MonadPlus(..), void) import Control.Monad.Trans.State.Lazy (State, evalState, get, put)  import Data.Functor.Compose (Compose(..))-import Data.List.NonEmpty (NonEmpty((:|))) import Data.Maybe (isJust)  import Data.Semigroup (Semigroup(..))@@ -19,57 +20,63 @@ 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 qualified Text.Parser.Char+import qualified Text.Parser.Char as Char import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token as Token  import qualified Rank2-import Text.Grampa.Class (GrammarParsing(..), MonoidParsing(..), MultiParsing(..), AmbiguousParsing(..),-                          Lexical(..), Ambiguous(..), ParseResults)-import Text.Grampa.Internal (ResultList(..), ResultsOfLength(..), fromResultList)+import Text.Grampa.Class (GrammarParsing(..), InputParsing(..), InputCharParsing(..), MultiParsing(..),+                          AmbiguousParsing(..), Ambiguous(..),+                          ConsumedInputParsing(..), DeterministicParsing(..),+                          TailsParsing(parseTails, parseAllTails), Expected(..))+import Text.Grampa.Internal (ResultList(..), FailureInfo(..), AmbiguousAlternative(ambiguousOr)) import qualified Text.Grampa.ContextFree.SortedMemoizing as Memoizing import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack -import Prelude hiding (cycle, null, span, takeWhile)+import Prelude hiding (cycle, null, span, take, takeWhile)  type Parser = Fixed Memoizing.Parser -type ResultAppend g s = ResultList g s Rank2.~> ResultList g s Rank2.~> ResultList g s+type ResultAppend p (g :: (* -> *) -> *) s =+   GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s) Rank2.~> GrammarFunctor (p g s)  data Fixed p g s a =    Parser {       complete, direct, direct0, direct1, indirect :: p g s a,-      appendResults :: ResultList g s a -> ResultList g s a -> ResultList g s a,+      isAmbiguous :: Maybe (AmbiguityWitness a),       cyclicDescendants :: Rank2.Apply g => g (Const (ParserFlags g)) -> ParserFlags g}    | DirectParser {       complete, direct0, direct1 :: p g s a}    | PositiveDirectParser {       complete :: p g s a} -data SeparatedParser p g s a = FrontParser (p g s a)-                             | CycleParser {-                                  cycleParser  :: p g s a,-                                  backParser   :: p g s a,-                                  appendResultsArrow :: ResultAppend g s a,-                                  dependencies :: g (Const Bool)}-                             | BackParser {-                                  backParser :: p g s a}+data AmbiguityWitness a where+   AmbiguityWitness :: (a :~: Ambiguous b) -> AmbiguityWitness a +data SeparatedParser p (g :: (* -> *) -> *) s a = FrontParser (p g s a)+                                                | CycleParser {+                                                     cycleParser  :: p g s a,+                                                     backParser   :: p g s a,+                                                     appendResultsArrow :: ResultAppend p g s a,+                                                     dependencies :: g (Const Bool)}+                                                | BackParser {+                                                     backParser :: p g s a}+ data ParserFlags g = ParserFlags {    nullable :: Bool,    dependsOn :: g (Const Bool)}  deriving instance Show (g (Const Bool)) => Show (ParserFlags g) -data ParserFunctor g s a = ParserResultsFunctor {parserResults :: ResultList g s a}-                         | ParserFlagsFunctor {parserFlags :: ParserFlags g}+data ParserFunctor p g s a = ParserResultsFunctor {parserResults :: GrammarFunctor (p g s) a}+                           | ParserFlagsFunctor {parserFlags :: ParserFlags g}  newtype Union (g :: (* -> *) -> *) = Union{getUnion :: g (Const Bool)} @@ -83,6 +90,19 @@    mempty = Union (Rank2.cotraverse (Const . getConst) (Const False))    mappend (Union g1) (Union g2) = Union (Rank2.liftA2 union g1 g2) +mapPrimitive :: (p g s a -> p g s a) -> Fixed p g s a -> Fixed p g s a+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= isAmbiguous p,+                                   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{@@ -91,7 +111,9 @@    direct0= direct0 p',    direct1= direct1 p',    indirect= indirect p',-   appendResults= appendResults p',+   isAmbiguous= case p+                of Parser{isAmbiguous= a} -> a+                   _ -> Nothing,    cyclicDescendants= cyclicDescendants p'}    where p' = general' p @@ -101,7 +123,7 @@    direct0= empty,    direct1= complete p,    indirect= empty,-   appendResults= (<>),+   isAmbiguous= Nothing,    cyclicDescendants= \cd-> ParserFlags False (const (Const False) Rank2.<$> cd)} general' p@DirectParser{} = Parser{    complete= complete p,@@ -109,7 +131,7 @@    direct0= direct0 p,    direct1= direct1 p,    indirect= empty,-   appendResults= (<>),+   isAmbiguous= Nothing,    cyclicDescendants= \cd-> ParserFlags True (const (Const False) Rank2.<$> cd)} general' p@Parser{} = p @@ -117,35 +139,50 @@ -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Apply' g, "Rank2".'Rank2.Traversable' g, 'FactorialMonoid' s) =>---                  g (LeftRecursive.'Fixed g s) -> s -> g ('Compose' 'ParseResults' [])+--                  g (LeftRecursive.'Fixed g s) -> s -> g ('Compose' ('ParseResults' s) []) -- @-instance MultiParsing (Fixed Memoizing.Parser) where-   type GrammarConstraint (Fixed Memoizing.Parser) g = (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g)-   type ResultFunctor (Fixed Memoizing.Parser) = Compose ParseResults []-   parsePrefix :: (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g, FactorialMonoid s) =>-                  g (Parser g s) -> s -> g (Compose (Compose ParseResults []) ((,) s))-   parsePrefix g input = Rank2.fmap (Compose . Compose . fromResultList input)+instance (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), GrammarFunctor (p g s) ~ rl s, FallibleWithExpectations rl,+          AmbiguousAlternative (GrammarFunctor (p g s))) =>+         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 :: (FactorialMonoid s, Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g) =>-                    g (Parser g s) -> s -> g (Compose ParseResults [])-   parseComplete g = \input-> let close = Rank2.fmap (<* endOfInput) selfReferring-                              in Rank2.fmap ((snd <$>) . Compose . fromResultList input)-                                            (snd $ head $ Memoizing.reparseTails close $ parseSeparated g' input)+   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 #-} -instance GrammarParsing (Fixed Memoizing.Parser) where-   type GrammarFunctor (Fixed Memoizing.Parser) = ParserFunctor-   nonTerminal :: forall g s a. (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g)-                  => (g (ParserFunctor g s) -> ParserFunctor g s a) -> Parser g s a+instance (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), GrammarFunctor (p g s) ~ rl s, FallibleWithExpectations rl,+          AmbiguousAlternative (GrammarFunctor (p g s))) =>+         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,-      appendResults= (<>),+      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@@ -177,7 +214,7 @@       direct0= fmap f (direct0 p),       direct1= fmap f (direct1 p),       indirect= fmap f (indirect p),-      appendResults= (<>)}+      isAmbiguous= Nothing}    {-# INLINABLE fmap #-}  instance Alternative (p g s) => Applicative (Fixed p g s) where@@ -198,7 +235,7 @@       direct0= direct0 p' <*> direct0 q,       direct1= direct0 p' <*> direct1 q <|> direct1 p' <*> complete q,       indirect= direct0 p' <*> indirect q <|> indirect p' <*> complete q,-      appendResults= (<>),+      isAmbiguous= Nothing,       cyclicDescendants= \deps-> let            pcd@(ParserFlags pn pd) = cyclicDescendants p' deps            ParserFlags qn qd = cyclicDescendants q deps@@ -212,7 +249,7 @@       direct0= direct0 p' <*> direct0 q',       direct1= direct0 p' <*> direct1 q' <|> direct1 p' <*> complete q',       indirect= indirect p' <*> complete q',-      appendResults= (<>),+      isAmbiguous= Nothing,       cyclicDescendants= \deps-> let            pcd@(ParserFlags pn pd) = cyclicDescendants p' deps            ParserFlags qn qd = cyclicDescendants q' deps@@ -244,7 +281,7 @@                     direct0= direct0 p' <|> direct0 q',                     direct1= direct1 p' <|> direct1 q',                     indirect= indirect p' <|> indirect q',-                    appendResults= (<>),+                    isAmbiguous= Nothing,                     cyclicDescendants= \deps-> let                          ParserFlags pn pd = cyclicDescendants p' deps                          ParserFlags qn qd = cyclicDescendants q' deps@@ -265,7 +302,7 @@       direct0= d0,       direct1= d1,       indirect= (:) <$> indirect p <*> mcp,-      appendResults= (<>),+      isAmbiguous= Nothing,       cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}       where d0 = pure [] <|> (:[]) <$> direct0 p             d1 = (:) <$> direct1 p <*> mcp@@ -281,7 +318,7 @@       direct0= d0,       direct1= d1,       indirect= (:) <$> indirect p <*> many (complete p),-      appendResults= (<>),+      isAmbiguous= Nothing,       cyclicDescendants= cyclicDescendants p}       where d0 = (:[]) <$> direct0 p             d1= (:) <$> direct1 p <*> many (complete p)@@ -289,29 +326,6 @@    {-# INLINABLE many #-}    {-# INLINABLE some #-} -infixl 3 <<|>-(<<|>) :: Parser g s a -> Parser g s a -> Parser g s a-p@DirectParser{} <<|> q@PositiveDirectParser{} = DirectParser{-   complete= complete p Memoizing.<<|> complete q,-   direct0 = direct0 p,-   direct1= direct1 p Memoizing.<<|> complete q}-p@DirectParser{} <<|> q@DirectParser{} = DirectParser{-   complete= complete p Memoizing.<<|> complete q,-   direct0 = direct0 p Memoizing.<<|> direct0 q,-   direct1= direct1 p Memoizing.<<|> direct1 q}-p <<|> q = Parser{complete= complete p' Memoizing.<<|> complete q',-                 direct= direct p' Memoizing.<<|> direct q',-                 direct0= direct0 p' Memoizing.<<|> direct0 q',-                 direct1= direct1 p' Memoizing.<<|> direct1 q',-                 indirect= indirect p' Memoizing.<<|> indirect q',-                 appendResults= (<>),-                 cyclicDescendants= \deps-> let-                         ParserFlags pn pd = cyclicDescendants p' deps-                         ParserFlags qn qd = cyclicDescendants q' deps-                      in ParserFlags (pn || qn) (Rank2.liftA2 union pd qd)}-   where p'@Parser{} = general p-         q'@Parser{} = general q- union :: Const Bool x -> Const Bool x -> Const Bool x union (Const False) d = d union (Const True) _ = Const True@@ -326,7 +340,7 @@       direct0= d0,       direct1= d1,       indirect= direct0 p >>= indirect . general' . cont,-      appendResults= (<>),+      isAmbiguous= Nothing,       cyclicDescendants= \cd-> (ParserFlags True $ Rank2.fmap (const $ Const True) cd)}       where d0 = direct0 p >>= direct0 . general' . cont             d1 = (direct0 p >>= direct1 . general' . cont) <|> (direct1 p >>= complete . cont)@@ -336,7 +350,7 @@       direct0= d0,       direct1= d1,       indirect= (indirect p >>= complete . cont) <|> (direct0 p >>= indirect . general' . cont),-      appendResults= (<>),+      isAmbiguous= Nothing,       cyclicDescendants= \cd->          let pcd@(ParserFlags pn _) = cyclicDescendants p' cd          in if pn@@ -357,18 +371,26 @@    mempty = pure mempty    mappend = liftA2 mappend -primitive :: String -> p g s a -> p g s a -> p g s a -> Fixed p g s a-primitive _name d0 d1 d = DirectParser{complete= d,-                                       direct0= d0,-                                       direct1= d1}+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 #-} -positivePrimitive :: String -> p g s a -> Fixed p g s a-positivePrimitive _name p = PositiveDirectParser{complete= p}-{-# INLINE positivePrimitive #-}+-- | 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 #-} -instance (Parsing (p g s), MonoidParsing (Fixed p g)) => Parsing (Fixed p g s) where-   eof = primitive "eof" eof empty eof+-- | 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),@@ -404,13 +426,73 @@       direct= notFollowedBy (direct p),       direct0= notFollowedBy (direct p),       direct1= empty,-      appendResults= (<>),+      isAmbiguous= Nothing,       indirect= notFollowedBy (indirect p),       cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}-   unexpected msg = positivePrimitive "unexpected" (unexpected msg)-   skipMany p = concatMany (() <$ p)+   unexpected msg = liftPositive (unexpected msg) -instance (LookAheadParsing (p g s), MonoidParsing (Fixed p g)) => LookAheadParsing (Fixed p g s) where+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' <<|> 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) (Rank2.liftA2 union 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 (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),@@ -424,135 +506,64 @@       direct= lookAhead (direct p),       direct0= lookAhead (direct p),       direct1= empty,-      appendResults= appendResults p,+      isAmbiguous= isAmbiguous p,       indirect= lookAhead (indirect p),       cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}} -instance MonoidParsing (Fixed Memoizing.Parser g) where-   endOfInput = primitive "endOfInput" endOfInput empty endOfInput-   getInput = primitive "getInput" getInput empty getInput-   anyToken = positivePrimitive "anyToken" anyToken-   satisfy predicate = positivePrimitive "satisfy" (satisfy predicate)-   satisfyChar predicate = positivePrimitive "satisfyChar" (satisfyChar predicate)-   satisfyCharInput predicate = positivePrimitive "satisfyCharInput" (satisfyCharInput predicate)-   notSatisfy predicate = primitive "notSatisfy" (notSatisfy predicate) empty (notSatisfy predicate)-   notSatisfyChar predicate = primitive "notSatisfyChar" (notSatisfyChar predicate) empty (notSatisfyChar predicate)-   scan s0 f = primitive "scan" (mempty <$ notSatisfy test) (lookAhead (satisfy test) *> p) p+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-   scanChars s0 f = primitive "scanChars" (mempty <$ notSatisfyChar test) (lookAhead (satisfyChar test) *> p) p-      where p = scanChars s0 f-            test = isJust . f s0    string s-      | null s = primitive ("(string " ++ shows s ")") (string s) empty (string s)-      | otherwise = positivePrimitive ("(string " ++ shows s ")") (string s)-   takeWhile predicate = primitive "takeWhile" (mempty <$ notSatisfy predicate)+      | 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 = positivePrimitive "takeWhile1" (takeWhile1 predicate)-   takeCharsWhile predicate = primitive "takeCharsWhile" (mempty <$ notSatisfyChar predicate)-                                                         (takeCharsWhile1 predicate) (takeCharsWhile predicate)-   takeCharsWhile1 predicate = positivePrimitive "takeCharsWhile1" (takeCharsWhile1 predicate)-   concatMany p@PositiveDirectParser{} = DirectParser{-      complete= cmp,-      direct0= d0,-      direct1= d1}-      where d0 = pure mempty-            d1 = mappend <$> complete p <*> cmp-            cmp = concatMany (complete p)-   concatMany p@DirectParser{} = DirectParser{-      complete= cmp,-      direct0= d0,-      direct1= d1}-      where d0 = pure mempty <|> direct0 p-            d1 = mappend <$> direct1 p <*> cmp-            cmp = concatMany (complete p)-   concatMany p@Parser{} = Parser{-      complete= cmp,-      direct= d0 <|> d1,-      direct0= d0,-      direct1= d1,-      indirect= mappend <$> indirect p <*> cmp,-      appendResults= mappend,-      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}-      where d0 = pure mempty <|> direct0 p-            d1 = mappend <$> direct1 p <*> cmp-            cmp = concatMany (complete p)+   takeWhile1 predicate = liftPositive (takeWhile1 predicate)    {-# INLINABLE string #-}-   {-# INLINABLE concatMany #-} -instance MonoidParsing (Fixed Backtrack.Parser g) where-   endOfInput = primitive "endOfInput" endOfInput empty endOfInput-   getInput = primitive "getInput" getInput empty getInput-   anyToken = positivePrimitive "anyToken" anyToken-   satisfy predicate = positivePrimitive "satisfy" (satisfy predicate)-   satisfyChar predicate = positivePrimitive "satisfyChar" (satisfyChar predicate)-   satisfyCharInput predicate = positivePrimitive "satisfyCharInput" (satisfyCharInput predicate)-   notSatisfy predicate = primitive "notSatisfy" (notSatisfy predicate) empty (notSatisfy predicate)-   notSatisfyChar predicate = primitive "notSatisfyChar" (notSatisfyChar predicate) empty (notSatisfyChar predicate)-   scan s0 f = primitive "scan" (mempty <$ notSatisfy test) (lookAhead (satisfy test) *> p) p-      where p = scan s0 f-            test = isJust . f s0-   scanChars s0 f = primitive "scanChars" (mempty <$ notSatisfyChar test) (lookAhead (satisfyChar test) *> p) p+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-   string s-      | null s = primitive ("(string " ++ shows s ")") (string s) empty (string s)-      | otherwise = positivePrimitive ("(string " ++ shows s ")") (string s)-   takeWhile predicate = primitive "takeWhile" (mempty <$ notSatisfy predicate)-                                               (takeWhile1 predicate) (takeWhile predicate)-   takeWhile1 predicate = positivePrimitive "takeWhile1" (takeWhile1 predicate)-   takeCharsWhile predicate = primitive "takeCharsWhile" (mempty <$ notSatisfyChar predicate)-                                                         (takeCharsWhile1 predicate) (takeCharsWhile predicate)-   takeCharsWhile1 predicate = positivePrimitive "takeCharsWhile1" (takeCharsWhile1 predicate)-   concatMany p@PositiveDirectParser{} = DirectParser{-      complete= cmp,-      direct0= d0,-      direct1= d1}-      where d0 = pure mempty-            d1 = mappend <$> complete p <*> cmp-            cmp = concatMany (complete p)-   concatMany p@DirectParser{} = DirectParser{-      complete= cmp,-      direct0= d0,-      direct1= d1}-      where d0 = pure mempty `Backtrack.alt` direct0 p-            d1 = mappend <$> direct1 p <*> cmp-            cmp = concatMany (complete p)-   concatMany p@Parser{} = Parser{-      complete= cmp,-      direct= d0 `Backtrack.alt` d1,-      direct0= d0,-      direct1= d1,-      indirect= mappend <$> indirect p <*> cmp,-      appendResults= mappend,-      cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}-      where d0 = pure mempty `Backtrack.alt` direct0 p-            d1 = mappend <$> direct1 p <*> cmp-            cmp = concatMany (complete p)-   {-# INLINABLE string #-}-   {-# INLINABLE concatMany #-}+   takeCharsWhile predicate = primitive (mempty <$ notSatisfyChar predicate)+                                        (takeCharsWhile1 predicate) (takeCharsWhile predicate)+   takeCharsWhile1 predicate = liftPositive (takeCharsWhile1 predicate) -instance (Parsing (p g s), MonoidParsing (Fixed p g), Show s, TextualMonoid s) => CharParsing (Fixed p g s) where-   satisfy = satisfyChar+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)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint (Fixed Backtrack.Parser) g s, Show s, TextualMonoid s) =>-         TokenParsing (Fixed Backtrack.Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--instance (Lexical g, LexicalConstraint (Fixed Memoizing.Parser) g s, Show s, TextualMonoid s) =>-         TokenParsing (Fixed Memoizing.Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--instance AmbiguousParsing (Fixed Memoizing.Parser g s) where+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),@@ -562,18 +573,8 @@                                  direct0=  ambiguous (direct0 p),                                  direct1=  ambiguous (direct1 p),                                  indirect= ambiguous (indirect p),-                                 appendResults= appendAmbiguous,+                                 isAmbiguous= Just (AmbiguityWitness Refl),                                  cyclicDescendants= cyclicDescendants p}-      where appendAmbiguous (ResultList rl1 f1) (ResultList rl2 f2) = ResultList (join rl1 rl2) (f1 <> f2)-            join [] rl = rl-            join rl [] = rl-            join rl1'@(rol1@(ResultsOfLength l1 s1 r1) : rest1) rl2'@(rol2@(ResultsOfLength l2 _ r2) : rest2)-               | l1 < l2 = rol1 : join rest1 rl2'-               | l1 > l2 = rol2 : join rl1' rest2-               | Ambiguous ar1 :| [] <- r1,-                 Ambiguous ar2 :| [] <- r2 =-                    ResultsOfLength l1 s1 (Ambiguous (ar1 <> ar2) :| []) : join rest1 rest2-               | otherwise = error "Ambiguous results should be grouped as a single value"    {-# INLINABLE ambiguous #-}  -- | Turns a context-free parser into a backtracking PEG parser that consumes the longest possible prefix of the list@@ -588,7 +589,7 @@                             direct0=  Memoizing.longest (direct0 p),                             direct1=  Memoizing.longest (direct1 p),                             indirect=  Memoizing.longest (indirect p),-                            appendResults= (<>),+                            isAmbiguous= Nothing,                             cyclicDescendants= cyclicDescendants p}  -- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest'@@ -602,7 +603,7 @@                         direct0=  Memoizing.peg (direct0 p),                         direct1=  Memoizing.peg (direct1 p),                         indirect=  Memoizing.peg (indirect p),-                        appendResults= (<>),+                        isAmbiguous= Nothing,                         cyclicDescendants= cyclicDescendants p}  -- | Turns a backtracking PEG parser into a context-free parser@@ -616,30 +617,39 @@                                 direct0=  Memoizing.terminalPEG (direct0 p),                                 direct1=  Memoizing.terminalPEG (direct1 p),                                 indirect=  Memoizing.terminalPEG (indirect p),-                                appendResults= (<>),+                                isAmbiguous= Nothing,                                 cyclicDescendants= cyclicDescendants p} -parseRecursive :: forall g s. (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g, FactorialMonoid s) =>-                  g (Parser g s) -> s -> [(s, g (ResultList g s))]+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, FallibleWithExpectations rl,+                                    AmbiguousAlternative (GrammarFunctor (p g s))) =>+                  g (Fixed p g s) -> s -> [(s, g (GrammarFunctor (p g s)))] parseRecursive = parseSeparated . separated {-# INLINE parseRecursive #-} -separated :: forall g s. (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g) =>-             g (Parser g s) -> g (SeparatedParser Memoizing.Parser g s)+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 (g (Const Bool)))          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 (g (Const Bool)) a -> Parser g s a-                    -> SeparatedParser Memoizing.Parser g s a+         reseparate :: forall a. Const Bool a -> Const Bool a -> Const (g (Const Bool)) a -> Fixed p g s a+                    -> SeparatedParser p g s a          reseparate (Const circular) (Const follower) (Const deps) p             | circular || leader && follower =-              CycleParser (indirect p) (direct p) (Rank2.Arrow (Rank2.Arrow . appendResults p)) deps+              CycleParser (indirect p) (direct p) (Rank2.Arrow (Rank2.Arrow . appendResults (isAmbiguous p))) deps             | follower = BackParser (complete p)             | otherwise = FrontParser (complete p)             where leader = getAny (Rank2.foldMap (Any . getConst) $ Rank2.liftA2 intersection circulars deps)+         appendResults (Just (AmbiguityWitness Refl)) = ambiguousOr+         appendResults Nothing = (<|>)          descendants = Rank2.fmap (Const . dependsOn . getConst) cyclicDescendantses          cyclicDescendantses = fixDescendants (Rank2.fmap (Const . cyclicDescendants . general) g)          circulars = Rank2.liftA2 leftRecursive bits cyclicDescendantses@@ -684,37 +694,40 @@ -- | Parse the given input using a context-free grammar separated into two parts: the first specifying all the -- left-recursive productions, the second all others. The first function argument specifies the left-recursive -- dependencies among the grammar productions.-parseSeparated :: forall g s. (Rank2.Apply g, Rank2.Foldable g, FactorialMonoid s) =>-                  g (SeparatedParser Memoizing.Parser g s) -> s -> [(s, g (ResultList g s))]+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, FallibleWithExpectations 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) . Memoizing.applyParser) directs+                  d      = Rank2.fmap (($ (s,d):parsedTail) . parseTails) directs                   d'     = fixRecursive s parsedTail d                   d''    = Rank2.liftA2 f parsers d'-                  f :: forall a. SeparatedParser Memoizing.Parser g s a -> ResultList g s a -> ResultList g s a-                  f (FrontParser p) _ = Memoizing.applyParser p ((s,d''):parsedTail)+                  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 (ResultList g s))] -> g (ResultList g s) -> g (ResultList g s)-         whileAnyContinues :: (g (ResultList g s) -> g (ResultList g s))-                           -> (g (ResultList g s) -> g (ResultList g s))-                           -> g (ResultList g s) -> g (ResultList g s) -> g (ResultList g s)-         recurseTotal :: s -> g (ResultList g s Rank2.~> ResultList g s) -> [(s, g (ResultList g s))]-                      -> g (ResultList g s)-                      -> g (ResultList g s)-         recurseMarginal :: s -> [(s, g (ResultList g s))]-                      -> g (ResultList g s)-                      -> g (ResultList g s)+         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 (g (Const Bool))))-         maybeDependency :: SeparatedParser Memoizing.Parser g s r -> Const (Maybe (g (Const Bool))) r-         appends :: g (ResultAppend g s)-         parserAppend :: SeparatedParser Memoizing.Parser g s r -> ResultAppend g s r+         maybeDependency :: SeparatedParser p g s r -> Const (Maybe (g (Const Bool))) 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 . (<>))+         parserAppend _ = Rank2.Arrow (Rank2.Arrow . const)          maybeDependencies = Rank2.fmap maybeDependency parsers          maybeDependency p@CycleParser{} = Const (Just $ dependencies p)          maybeDependency _ = Const Nothing@@ -727,30 +740,42 @@          whileAnyContinues ft fm total marginal =             Rank2.liftA3 choiceWhile maybeDependencies total (whileAnyContinues ft fm (ft total) (fm marginal))             where choiceWhile :: Const (Maybe (g (Const Bool))) x-                              -> ResultList g s x -> ResultList g s x-                              -> ResultList g s x+                              -> GrammarFunctor (p g s) x -> GrammarFunctor (p g s) x+                              -> GrammarFunctor (p g s) x                   choiceWhile (Const Nothing) t _ = t                   choiceWhile (Const (Just deps)) t t'                      | getAny (Rank2.foldMap (Any . getConst) (Rank2.liftA2 combine deps marginal)) = t'-                     | ResultList [] (Memoizing.FailureInfo _ expected) <- t =-                        let ResultList _ (Memoizing.FailureInfo pos expected') =-                               if getAny (Rank2.foldMap (Any . getConst) $-                                          Rank2.liftA2 (combineFailures expected) deps marginal)-                                  then t' else t-                        in ResultList [] (Memoizing.FailureInfo pos expected')-                     | otherwise = t-                     where combine :: Const Bool x -> ResultList g s x -> Const Bool x-                           combineFailures :: [String] -> Const Bool x -> ResultList g s x -> Const Bool x+                     | hasSuccess t = t+                     | otherwise =+                        let expected = expectations t+                            FailureInfo pos expected' =+                               failureOf (if getAny (Rank2.foldMap (Any . getConst) $+                                                     Rank2.liftA2 (combineFailures expected) deps marginal)+                                          then t' else t)+                        in failWith (FailureInfo pos expected')+                     where combine :: Const Bool x -> GrammarFunctor (p g s) x -> Const Bool x+                           combineFailures :: [Expected s] -> Const Bool x -> GrammarFunctor (p g s) x -> Const Bool x                            combine (Const False) _ = Const False-                           combine (Const True) (ResultList [] _) = Const False-                           combine (Const True) _ = Const True+                           combine (Const True) results = Const (hasSuccess results)                            combineFailures _ (Const False) _ = Const False-                           combineFailures expected (Const True) (ResultList _ (Memoizing.FailureInfo _ expected'))-                              = Const (any (`notElem` expected) expected')+                           combineFailures expected (Const True) rl = Const (any (`notElem` expected) $ expectations rl)           recurseTotal s initialAppends parsedTail total = Rank2.liftA2 reparse initialAppends indirects-            where reparse :: (ResultList g s Rank2.~> ResultList g s) a -> Memoizing.Parser g s a -> ResultList g s a-                  reparse append p = Rank2.apply append (Memoizing.applyParser p $ (s, total) : parsedTail)+            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)          recurseMarginal s parsedTail marginal =-            flip Memoizing.applyParser ((s, marginal) : parsedTail) Rank2.<$> indirects+            flip parseTails ((s, marginal) : parsedTail) Rank2.<$> indirects {-# NOINLINE parseSeparated #-}++class FallibleWithExpectations f where+   hasSuccess   :: f s a -> Bool+   failureOf    :: f s a -> FailureInfo s+   failWith     :: FailureInfo s -> f s a+   expectations :: f s a -> [Expected s]++instance FallibleWithExpectations (ResultList g) where+   hasSuccess (ResultList [] _) = False+   hasSuccess _ = True+   failureOf (ResultList _ failure) = failure+   failWith = ResultList []+   expectations (ResultList _ (FailureInfo _ expected)) = expected
+ src/Text/Grampa/ContextFree/LeftRecursive/Transformer.hs view
@@ -0,0 +1,26 @@+module Text.Grampa.ContextFree.LeftRecursive.Transformer (ParserT, SeparatedParser(..),+                                                          lift, liftPositive, tmap,+                                                          parseSeparated, separated)+where++import Text.Grampa.ContextFree.LeftRecursive (Fixed, SeparatedParser(..), FallibleWithExpectations(..),+                                              liftPositive, liftPure, mapPrimitive, parseSeparated, separated)+import qualified Text.Grampa.ContextFree.SortedMemoizing.Transformer as Transformer+import Text.Grampa.ContextFree.SortedMemoizing.Transformer (ResultListT(ResultList), FailureInfo(FailureInfo))++type ParserT m = Fixed (Transformer.ParserT m)++-- | Lift a parse-free computation into the parser.+lift :: Applicative m => m a -> ParserT m g s a+lift = liftPure . Transformer.lift++-- | Modify the computation carried by the parser.+tmap :: (m a -> m a) -> ParserT m g s a -> ParserT m g s a+tmap = mapPrimitive . Transformer.tmap++instance FallibleWithExpectations (ResultListT m g) where+   hasSuccess (ResultList [] _) = False+   hasSuccess _ = True+   failureOf (ResultList _ failure) = failure+   failWith = ResultList []+   expectations (ResultList _ (FailureInfo _ expected)) = expected
src/Text/Grampa/ContextFree/Memoizing.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE FlexibleContexts, GeneralizedNewtypeDeriving, InstanceSigs,              RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-}-module Text.Grampa.ContextFree.Memoizing (FailureInfo(..), ResultList(..), Parser(..), BinTree(..), (<<|>),+module Text.Grampa.ContextFree.Memoizing (FailureInfo(..), ResultList(..), Parser(..), BinTree(..),                                           fromResultList, reparseTails, longest, peg, terminalPEG) where @@ -11,27 +11,26 @@ import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (genericLength, maximumBy, nub)-import Data.Semigroup (Semigroup(..)) import Data.Monoid (Monoid(mappend, mempty))-import Data.Monoid.Cancellative (isPrefixOf) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid, length, splitPrimePrefix) import Data.Monoid.Textual (TextualMonoid) import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Textual as Textual+import Data.Semigroup (Semigroup((<>)))+import Data.Semigroup.Cancellative (LeftReductive(isPrefixOf)) import Data.String (fromString)  import qualified Text.Parser.Char import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token  import qualified Rank2 -import Text.Grampa.Class (Lexical(..), GrammarParsing(..), MonoidParsing(..), MultiParsing(..), -                          ParseResults, ParseFailure(..))+import Text.Grampa.Class (GrammarParsing(..), MultiParsing(..),+                          DeterministicParsing(..), InputParsing(..), InputCharParsing(..),+                          TailsParsing(parseTails), ParseResults, ParseFailure(..), Expected(..)) import Text.Grampa.Internal (BinTree(..), FailureInfo(..)) import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack @@ -41,17 +40,17 @@ -- 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 #-} !FailureInfo+data ResultList g s r = ResultList !(BinTree (ResultInfo g s r)) {-# UNPACK #-} !(FailureInfo s) data ResultInfo g s r = ResultInfo !Int ![(s, g (ResultList g s))] !r -instance Show r => Show (ResultList g s r) where+instance (Show s, Show r) => Show (ResultList g s r) where    show (ResultList l f) = "ResultList (" ++ shows l (") (" ++ shows f ")") -instance Show1 (ResultList g s) where+instance Show s => Show1 (ResultList g s) where    liftShowsPrec _sp showList _prec (ResultList l f) rest = "ResultList " ++ showList (simplify <$> toList l) (shows f rest)       where simplify (ResultInfo _ _ r) = r -instance Show r => Show (ResultInfo g s r) where+instance (Show s, Show r) => Show (ResultInfo g s r) where    show (ResultInfo l _ r) = "(ResultInfo @" ++ show l ++ " " ++ shows r ")"  instance Functor (ResultInfo g s) where@@ -83,18 +82,11 @@    {-# INLINABLE (<*>) #-}  instance Alternative (Parser g i) where-   empty = Parser (\rest-> ResultList mempty $ FailureInfo (genericLength rest) ["empty"])+   empty = Parser (\rest-> ResultList mempty $ FailureInfo (genericLength rest) [Expected "empty"])    Parser p <|> Parser q = Parser r where       r rest = p rest <> q rest    {-# INLINABLE (<|>) #-} -infixl 3 <<|>-(<<|>) :: Parser g s a -> Parser g s a -> Parser g s a-Parser p <<|> Parser q = Parser r where-   r rest = case p rest-            of rl@(ResultList EmptyTree _failure) -> rl <> q rest-               rl -> rl- instance Monad (Parser g i) where    return = pure    Parser p >>= f = Parser q where@@ -115,32 +107,38 @@    mempty = pure mempty    mappend = liftA2 mappend -instance GrammarParsing Parser where-   type GrammarFunctor Parser = ResultList+instance (Eq s, LeftReductive s, FactorialMonoid s) => GrammarParsing (Parser g s) where+   type ParserGrammar (Parser g s) = g+   type GrammarFunctor (Parser g s) = ResultList g s+   parsingResult s = Compose . fromResultList s    nonTerminal f = Parser p where       p ((_, d) : _) = f d-      p _ = ResultList mempty (FailureInfo 0 ["NonTerminal at endOfInput"])+      p _ = ResultList mempty (FailureInfo 0 [Expected "NonTerminal at endOfInput"])    {-# INLINE nonTerminal #-} +instance (Eq s, LeftReductive s, FactorialMonoid s) => TailsParsing (Parser g s) where+   parseTails = applyParser+ -- | Memoizing parser guarantees O(n²) performance for grammars with unambiguous productions, but provides no left -- recursion support. -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Memoizing.'Parser' g s) -> s -> g ('Compose' 'ParseResults' [])+--                  g (Memoizing.'Parser' g s) -> s -> g ('Compose' ('ParseResults' s) []) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = Compose ParseResults []+instance (LeftReductive s, FactorialMonoid s) => MultiParsing (Parser g s) where+   type GrammarConstraint (Parser g s) g' = (g ~ g', Rank2.Functor g)+   type ResultFunctor (Parser g s) = Compose (ParseResults s) []    -- | Returns the list of all possible input prefix parses paired with the remaining input suffix.-   parsePrefix g input = Rank2.fmap (Compose . Compose . fromResultList input) (snd $ head $ parseTails g input)-   parseComplete :: forall g s. (Rank2.Functor g, FactorialMonoid s) =>-                    g (Parser g s) -> s -> g (Compose ParseResults [])+   parsePrefix g input = Rank2.fmap (Compose . Compose . fromResultList input) (snd $ head $ parseGrammarTails g input)+   parseComplete :: (Rank2.Functor g, Eq s, FactorialMonoid s) =>+                    g (Parser g s) -> s -> g (Compose (ParseResults s) [])    parseComplete g input = Rank2.fmap ((snd <$>) . Compose . fromResultList input)-                              (snd $ head $ reparseTails close $ parseTails g input)-      where close = Rank2.fmap (<* endOfInput) g+                              (snd $ head $ reparseTails close $ parseGrammarTails g input)+      where close = Rank2.fmap (<* eof) g -parseTails :: (Rank2.Functor g, FactorialMonoid s) => g (Parser g s) -> s -> [(s, g (ResultList g s))]-parseTails g input = foldr parseTail [] (Factorial.tails input)+parseGrammarTails :: (Rank2.Functor g, FactorialMonoid s) => g (Parser g s) -> s -> [(s, g (ResultList g s))]+parseGrammarTails g input = foldr parseTail [] (Factorial.tails input)    where parseTail s parsedTail = parsed             where parsed = (s,d):parsedTail                   d      = Rank2.fmap (($ parsed) . applyParser) g@@ -150,44 +148,33 @@ reparseTails final parsed@((s, _):_) = (s, gd):parsed    where gd = Rank2.fmap (`applyParser` parsed) final -instance MonoidParsing (Parser g) where-   endOfInput = eof+instance (LeftReductive s, FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p       where p rest@((s, _):_) = ResultList (Leaf $ ResultInfo 0 rest s) mempty             p [] = ResultList (Leaf $ ResultInfo 0 [] mempty) mempty    anyToken = Parser p       where p rest@((s, _):t) = case splitPrimePrefix s                                 of Just (first, _) -> ResultList (Leaf $ ResultInfo 1 t first) mempty-                                   _ -> ResultList mempty (FailureInfo (genericLength rest) ["anyToken"])-            p [] = ResultList mempty (FailureInfo 0 ["anyToken"])+                                   _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "anyToken"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "anyToken"])    satisfy predicate = Parser p       where p rest@((s, _):t) =                case splitPrimePrefix s                of Just (first, _) | predicate first -> ResultList (Leaf $ ResultInfo 1 t first) mempty-                  _ -> ResultList mempty (FailureInfo (genericLength rest) ["satisfy"])-            p [] = ResultList mempty (FailureInfo 0 ["satisfy"])-   satisfyChar predicate = Parser p-      where p rest@((s, _):t) =-               case Textual.characterPrefix s-               of Just first | predicate first -> ResultList (Leaf $ ResultInfo 1 t first) mempty-                  _ -> ResultList mempty (FailureInfo (genericLength rest) ["satisfyChar"])-            p [] = ResultList mempty (FailureInfo 0 ["satisfyChar"])-   satisfyCharInput predicate = Parser p-      where p rest@((s, _):t) =-               case Textual.characterPrefix s-               of Just first | predicate first -> ResultList (Leaf $ ResultInfo 1 t $ Factorial.primePrefix s) mempty-                  _ -> ResultList mempty (FailureInfo (genericLength rest) ["satisfyCharInput"])-            p [] = ResultList mempty (FailureInfo 0 ["satisfyCharInput"])+                  _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "satisfy"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "satisfy"])    scan s0 f = Parser (p s0)       where p s rest@((i, _) : _) = ResultList (Leaf $ ResultInfo l (drop l rest) prefix) mempty                where (prefix, _, _) = Factorial.spanMaybe' s f i                      l = Factorial.length prefix             p _ [] = ResultList (Leaf $ ResultInfo 0 [] mempty) mempty-   scanChars s0 f = Parser (p s0)-      where p s rest@((i, _) : _) = ResultList (Leaf $ ResultInfo l (drop l rest) prefix) mempty-               where (prefix, _, _) = Textual.spanMaybe_' s f i-                     l = Factorial.length prefix-            p _ [] = ResultList (Leaf $ ResultInfo 0 [] mempty) mempty+   take 0 = mempty+   take n = Parser p+      where p rest@((s, _) : _)+               | x <- Factorial.take n s, l <- Factorial.length x, l == n =+                    ResultList (Leaf $ ResultInfo l (drop l rest) x) mempty+            p rest = ResultList mempty (FailureInfo (genericLength rest) [Expected $ "take " ++ show n])    takeWhile predicate = Parser p       where p rest@((s, _) : _)                | x <- Factorial.takeWhile predicate s, l <- Factorial.length x =@@ -197,7 +184,31 @@       where p rest@((s, _) : _)                | x <- Factorial.takeWhile predicate s, l <- Factorial.length x, l > 0 =                     ResultList (Leaf $ ResultInfo l (drop l rest) x) mempty-            p rest = ResultList mempty (FailureInfo (genericLength rest) ["takeWhile1"])+            p rest = ResultList mempty (FailureInfo (genericLength rest) [Expected "takeWhile1"])+   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 (FailureInfo (genericLength rest) [ExpectedInput s])+      l = Factorial.length s+   notSatisfy predicate = Parser p+      where p rest@((s, _):_)+               | Just (first, _) <- splitPrimePrefix s, +                 predicate first = ResultList mempty (FailureInfo (genericLength rest) [Expected "notSatisfy"])+            p rest = ResultList (Leaf $ ResultInfo 0 rest ()) mempty+   {-# INLINABLE string #-}++instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p rest@((s, _):t) =+               case Textual.characterPrefix s+               of Just first | predicate first -> ResultList (Leaf $ ResultInfo 1 t $ Factorial.primePrefix s) mempty+                  _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "satisfyCharInput"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "satisfyCharInput"])+   scanChars s0 f = Parser (p s0)+      where p s rest@((i, _) : _) = ResultList (Leaf $ ResultInfo l (drop l rest) prefix) mempty+               where (prefix, _, _) = Textual.spanMaybe_' s f i+                     l = Factorial.length prefix+            p _ [] = ResultList (Leaf $ ResultInfo 0 [] mempty) mempty    takeCharsWhile predicate = Parser p       where p rest@((s, _) : _)                | x <- Textual.takeWhile_ False predicate s, l <- Factorial.length x =@@ -207,23 +218,12 @@       where p rest@((s, _) : _)                | x <- Textual.takeWhile_ False predicate s, l <- Factorial.length x, l > 0 =                     ResultList (Leaf $ ResultInfo l (drop l rest) x) mempty-            p rest = ResultList mempty (FailureInfo (genericLength rest) ["takeCharsWhile1"])-   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 (FailureInfo (genericLength rest) ["string " ++ show s])-      l = Factorial.length s-   notSatisfy predicate = Parser p-      where p rest@((s, _):_)-               | Just (first, _) <- splitPrimePrefix s, -                 predicate first = ResultList mempty (FailureInfo (genericLength rest) ["notSatisfy"])-            p rest = ResultList (Leaf $ ResultInfo 0 rest ()) mempty+            p rest = ResultList mempty (FailureInfo (genericLength rest) [Expected "takeCharsWhile1"])    notSatisfyChar predicate = Parser p       where p rest@((s, _):_)                | Just first <- Textual.characterPrefix s, -                 predicate first = ResultList mempty (FailureInfo (genericLength rest) ["notSatisfyChar"])+                 predicate first = ResultList mempty (FailureInfo (genericLength rest) [Expected "notSatisfyChar"])             p rest = ResultList (Leaf $ ResultInfo 0 rest ()) mempty-   {-# INLINABLE string #-}  instance MonoidNull s => Parsing (Parser g s) where    try (Parser p) = Parser q@@ -233,41 +233,54 @@    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)                where replaceFailure (ResultList EmptyTree (FailureInfo pos msgs)) =-                        ResultList EmptyTree (FailureInfo pos $ if pos == genericLength rest then [msg] else msgs)+                        ResultList EmptyTree (FailureInfo pos $ if pos == genericLength rest then [Expected msg] else msgs)                      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 (FailureInfo (genericLength t) ["notFollowedBy"])+            rewind t ResultList{} = ResultList mempty (FailureInfo (genericLength t) [Expected "notFollowedBy"])    skipMany p = go       where go = pure () <|> p *> go-   unexpected msg = Parser (\t-> ResultList mempty $ FailureInfo (genericLength t) [msg])+   unexpected msg = Parser (\t-> ResultList mempty $ FailureInfo (genericLength t) [Expected msg])    eof = Parser f       where f rest@((s, _):_)                | null s = ResultList (Leaf $ ResultInfo 0 rest ()) mempty-               | otherwise = ResultList mempty (FailureInfo (genericLength rest) ["endOfInput"])+               | otherwise = ResultList mempty (FailureInfo (genericLength rest) [Expected "endOfInput"])             f [] = ResultList (Leaf $ ResultInfo 0 [] ()) mempty +instance MonoidNull s => DeterministicParsing (Parser g s) where+   Parser p <<|> Parser q = Parser r where+      r rest = case p rest+               of rl@(ResultList EmptyTree _failure) -> rl <> q rest+                  rl -> rl+   takeSome p = (:) <$> p <*> takeMany p+   takeMany (Parser p) = Parser (q 0 id) where+      q len acc rest = case p rest+                       of ResultList EmptyTree _failure -> ResultList (Leaf $ ResultInfo len rest (acc [])) mempty+                          ResultList rl _ -> foldMap continue rl+         where continue (ResultInfo len' rest' result) = q (len + len') (acc . (result:)) rest'+   skipAll (Parser p) = Parser (q 0) where+      q len rest = case p rest+                   of ResultList EmptyTree _failure -> ResultList (Leaf $ ResultInfo len rest ()) mempty+                      ResultList rl _failure -> foldMap continue rl+         where continue (ResultInfo len' rest' _) = q (len + len') rest'+ instance MonoidNull s => LookAheadParsing (Parser g s) where    lookAhead (Parser p) = Parser (\input-> rewind input (p input))       where rewind t (ResultList rl failure) = ResultList (rewindInput t <$> rl) failure             rewindInput t (ResultInfo _ _ r) = ResultInfo 0 t r  instance (Show s, TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+   satisfy predicate = Parser p+      where p rest@((s, _):t) =+               case Textual.characterPrefix s+               of Just first | predicate first -> ResultList (Leaf $ ResultInfo 1 t first) mempty+                  _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "Char.satisfy"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--fromResultList :: FactorialMonoid s => s -> ResultList g s r -> ParseResults [(s, r)]-fromResultList s (ResultList EmptyTree (FailureInfo pos msgs)) =-   Left (ParseFailure (length s - pos + 1) (nub msgs))+fromResultList :: (Eq s, FactorialMonoid s) => s -> ResultList g s r -> ParseResults s [(s, r)]+fromResultList s (ResultList EmptyTree (FailureInfo pos msgs)) = Left (ParseFailure (length s - pos + 1) (nub msgs)) fromResultList _ (ResultList rl _failure) = Right (f <$> toList rl)    where f (ResultInfo _ ((s, _):_) r) = (s, r)          f (ResultInfo _ [] r) = (mempty, r)@@ -277,17 +290,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 EmptyTree failure -> Backtrack.NoParse failure+            of ResultList EmptyTree (FailureInfo pos expected) -> Backtrack.NoParse (FailureInfo pos $ map message expected)                ResultList rs _ -> parsed (maximumBy (compare `on` resultLength) rs)    resultLength (ResultInfo l _ _) = l    parsed (ResultInfo l s r) = Backtrack.Parsed l r s+   message (Expected msg) = Expected msg+   message (ExpectedInput s) = ExpectedInput [(s, error "longest")]  -- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest' peg :: 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 failure -> ResultList mempty failure+               Backtrack.NoParse (FailureInfo pos expected) -> ResultList mempty (FailureInfo pos ((fst . head <$>) <$> expected))  -- | Turns a backtracking PEG parser into a context-free parser terminalPEG :: Monoid s => Backtrack.Parser g s a -> Parser g s a
src/Text/Grampa/ContextFree/Parallel.hs view
@@ -10,11 +10,11 @@ import Data.Functor.Compose (Compose(..)) import Data.List (nub) import Data.Semigroup (Semigroup(..))+import qualified Data.Semigroup.Cancellative as Cancellative import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid) import Data.Monoid.Textual (TextualMonoid)-import qualified Data.Monoid.Cancellative as Cancellative import qualified Data.Monoid.Null as Null import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Textual as Textual@@ -24,13 +24,12 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token  import qualified Rank2 -import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))-import Text.Grampa.Internal (BinTree(..))+import Text.Grampa.Class (DeterministicParsing(..), InputParsing(..), InputCharParsing(..), MultiParsing(..),+                          ParseResults, ParseFailure(..), Expected(..))+import Text.Grampa.Internal (BinTree(..), FailureInfo(..), noFailure)  import Prelude hiding (iterate, null, showList, span, takeWhile) @@ -38,14 +37,13 @@ -- support. newtype Parser (g :: (* -> *) -> *) s r = Parser{applyParser :: s -> ResultList s r} -data ResultList s r = ResultList !(BinTree (ResultInfo s r)) {-# UNPACK #-} !FailureInfo+data ResultList s r = ResultList !(BinTree (ResultInfo s r)) {-# UNPACK #-} !(FailureInfo s) data ResultInfo s r = ResultInfo !s !r-data FailureInfo = FailureInfo Int [String] deriving (Eq, Show)  instance (Show s, Show r) => Show (ResultList s r) where    show (ResultList l f) = "ResultList (" ++ shows l (") (" ++ shows f ")") -instance Show1 (ResultList s) where+instance Show s => Show1 (ResultList s) where    liftShowsPrec _sp showList _prec (ResultList l f) rest = "ResultList " ++ showList (simplify <$> toList l) (shows f rest)       where simplify (ResultInfo _ r) = r @@ -62,24 +60,14 @@    ResultList rl1 f1 <> ResultList rl2 f2 = ResultList (rl1 <> rl2) (f1 <> f2)  instance Monoid (ResultList s r) where-   mempty = ResultList mempty mempty-   mappend = (<>)--instance Semigroup FailureInfo where-   FailureInfo pos1 exp1 <> FailureInfo pos2 exp2 = FailureInfo pos' exp'-      where (pos', exp') | pos1 < pos2 = (pos1, exp1)-                         | pos1 > pos2 = (pos2, exp2)-                         | otherwise = (pos1, exp1 <> exp2)--instance Monoid FailureInfo where-   mempty = FailureInfo maxBound []+   mempty = ResultList mempty noFailure    mappend = (<>)  instance Functor (Parser g s) where    fmap f (Parser p) = Parser (fmap f . p)  instance Applicative (Parser g s) where-   pure a = Parser (\rest-> ResultList (Leaf $ ResultInfo rest a) mempty)+   pure a = Parser (\rest-> ResultList (Leaf $ ResultInfo rest a) noFailure)    Parser p <*> Parser q = Parser r where       r rest = case p rest                of ResultList results failure -> ResultList mempty failure <> foldMap continue results@@ -87,7 +75,7 @@   instance FactorialMonoid s => Alternative (Parser g s) where-   empty = Parser (\s-> ResultList mempty $ FailureInfo (Factorial.length s) ["empty"])+   empty = Parser (\s-> ResultList mempty $ FailureInfo (Factorial.length s) [Expected "empty"])    Parser p <|> Parser q = Parser r where       r rest = p rest <> q rest @@ -112,80 +100,78 @@ -- | Parallel parser produces a list of all possible parses. -- -- @--- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Parallel.'Parser' g s) -> s -> g ('Compose' 'ParseResults' [])+-- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, Eq s, 'FactorialMonoid' s) =>+--                  g (Parallel.'Parser' g s) -> s -> g ('Compose' ('ParseResults' s) []) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = Compose ParseResults []+instance (Cancellative.LeftReductive s, FactorialMonoid s) => MultiParsing (Parser g s) where+   type ResultFunctor (Parser g s) = Compose (ParseResults s) []    -- | Returns the list of all possible input prefix parses paired with the remaining input suffix.    parsePrefix g input = Rank2.fmap (Compose . Compose . fromResultList input . (`applyParser` input)) g    -- | Returns the list of all possible parses of complete input.-   parseComplete :: forall g s. (Rank2.Functor g, FactorialMonoid s) =>-                    g (Parser g s) -> s -> g (Compose ParseResults [])-   parseComplete g input = Rank2.fmap ((snd <$>) . getCompose) (parsePrefix (Rank2.fmap (<* endOfInput) g) input)+   parseComplete :: (Rank2.Functor g', Eq s, FactorialMonoid s) =>+                    g' (Parser g s) -> s -> g' (Compose (ParseResults s) [])+   parseComplete g input = Rank2.fmap ((snd <$>) . getCompose) (parsePrefix (Rank2.fmap (<* eof) g) input) -instance MonoidParsing (Parser g) where-   endOfInput = Parser f-      where f s | null s = ResultList (Leaf $ ResultInfo s ()) mempty-                | otherwise = ResultList mempty (FailureInfo (Factorial.length s) ["endOfInput"])+instance (Cancellative.LeftReductive s, FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p-      where p s = ResultList (Leaf $ ResultInfo s s) mempty+      where p s = ResultList (Leaf $ ResultInfo s s) noFailure    anyToken = Parser p       where p s = case Factorial.splitPrimePrefix s-                  of Just (first, rest) -> ResultList (Leaf $ ResultInfo rest first) mempty-                     _ -> ResultList mempty (FailureInfo (Factorial.length s) ["anyToken"])+                  of Just (first, rest) -> ResultList (Leaf $ ResultInfo rest first) noFailure+                     _ -> ResultList mempty (FailureInfo (Factorial.length s) [Expected "anyToken"])    satisfy predicate = Parser p       where p s = case Factorial.splitPrimePrefix s-                  of Just (first, rest) | predicate first -> ResultList (Leaf $ ResultInfo rest first) mempty-                     _ -> ResultList mempty (FailureInfo (Factorial.length s) ["satisfy"])-   satisfyChar predicate = Parser p-      where p s =-               case Textual.splitCharacterPrefix s-               of Just (first, rest) | predicate first -> ResultList (Leaf $ ResultInfo rest first) mempty-                  _ -> ResultList mempty (FailureInfo (Factorial.length s) ["satisfyChar"])-   satisfyCharInput predicate = Parser p-      where p s =-               case Textual.splitCharacterPrefix s-               of Just (first, rest) | predicate first -> ResultList (Leaf $ ResultInfo rest $ Factorial.primePrefix s) mempty-                  _ -> ResultList mempty (FailureInfo (Factorial.length s) ["satisfyChar"])+                  of Just (first, rest) | predicate first -> ResultList (Leaf $ ResultInfo rest first) noFailure+                     _ -> ResultList mempty (FailureInfo (Factorial.length s) [Expected "satisfy"])    notSatisfy predicate = Parser p       where p s = case Factorial.splitPrimePrefix s                   of Just (first, _) -                        | predicate first -> ResultList mempty (FailureInfo (Factorial.length s) ["notSatisfy"])-                     _ -> ResultList (Leaf $ ResultInfo s ()) mempty-   notSatisfyChar predicate = Parser p-      where p s = case Textual.characterPrefix s-                  of Just first -                        | predicate first -> ResultList mempty (FailureInfo (Factorial.length s) ["notSatisfyChar"])-                     _ -> ResultList (Leaf $ ResultInfo s ()) mempty+                        | predicate first -> ResultList mempty (FailureInfo (Factorial.length s) [Expected "notSatisfy"])+                     _ -> ResultList (Leaf $ ResultInfo s ()) noFailure    scan s0 f = Parser (p s0)-      where p s i = ResultList (Leaf $ ResultInfo suffix prefix) mempty+      where p s i = ResultList (Leaf $ ResultInfo suffix prefix) noFailure                where (prefix, suffix, _) = Factorial.spanMaybe' s f i-   scanChars s0 f = Parser (p s0)-      where p s i = ResultList (Leaf $ ResultInfo suffix prefix) mempty-               where (prefix, suffix, _) = Textual.spanMaybe_' s f i+   take n = Parser p+      where p s+              | (prefix, suffix) <- Factorial.splitAt n s,+                Factorial.length prefix == n = ResultList (Leaf $ ResultInfo suffix prefix) noFailure+              | otherwise = ResultList mempty (FailureInfo (Factorial.length s) [Expected $ "take " ++ show n])    takeWhile predicate = Parser p-      where p s | (prefix, suffix) <- Factorial.span predicate s = ResultList (Leaf $ ResultInfo suffix prefix) mempty+      where p s = ResultList (Leaf $ ResultInfo suffix prefix) noFailure+              where (prefix, suffix) = Factorial.span predicate s    takeWhile1 predicate = Parser p       where p s | (prefix, suffix) <- Factorial.span predicate s =                 if Null.null prefix-               then ResultList mempty (FailureInfo (Factorial.length s) ["takeWhile1"])-               else ResultList (Leaf $ ResultInfo suffix prefix) mempty+               then ResultList mempty (FailureInfo (Factorial.length s) [Expected "takeWhile1"])+               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 (FailureInfo (Factorial.length s') [ExpectedInput s])++instance TextualMonoid s => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p s =+               case Textual.splitCharacterPrefix s+               of Just (first, rest)+                     | predicate first -> ResultList (Leaf $ ResultInfo rest $ Factorial.primePrefix s) noFailure+                  _ -> ResultList mempty (FailureInfo (Factorial.length s) [Expected "satisfyCharInput"])+   notSatisfyChar predicate = Parser p+      where p s = case Textual.characterPrefix s+                  of Just first +                        | predicate first -> ResultList mempty (FailureInfo (Factorial.length s) [Expected "notSatisfyChar"])+                     _ -> ResultList (Leaf $ ResultInfo s ()) noFailure+   scanChars s0 f = Parser (p s0)+      where p s i = ResultList (Leaf $ ResultInfo suffix prefix) noFailure+               where (prefix, suffix, _) = Textual.spanMaybe_' s f i    takeCharsWhile predicate = Parser p       where p s | (prefix, suffix) <- Textual.span_ False predicate s = -               ResultList (Leaf $ ResultInfo suffix prefix) mempty+               ResultList (Leaf $ ResultInfo suffix prefix) noFailure    takeCharsWhile1 predicate = Parser p       where p s | (prefix, suffix) <- Textual.span_ False predicate s =                if null prefix-               then ResultList mempty (FailureInfo (Factorial.length s) ["takeCharsWhile1"])-               else ResultList (Leaf $ ResultInfo suffix prefix) mempty-   string s = Parser p where-      p s' | Just suffix <- Cancellative.stripPrefix s s' = ResultList (Leaf $ ResultInfo suffix s) mempty-           | otherwise = ResultList mempty (FailureInfo (Factorial.length s') ["string " ++ show s])-   concatMany (Parser p) = Parser q-      where q s = ResultList (Leaf $ ResultInfo s mempty) failure <> foldMap continue rs-               where ResultList rs failure = p s-            continue (ResultInfo suffix prefix) = mappend prefix <$> q suffix+               then ResultList mempty (FailureInfo (Factorial.length s) [Expected "takeCharsWhile1"])+               else ResultList (Leaf $ ResultInfo suffix prefix) noFailure  instance FactorialMonoid s => Parsing (Parser g s) where    try (Parser p) = Parser q@@ -196,35 +182,50 @@       where q rest = replaceFailure (p rest)                where replaceFailure (ResultList EmptyTree (FailureInfo pos msgs)) =                         ResultList EmptyTree (FailureInfo pos $-                                              if pos == Factorial.length rest then [msg] else msgs)+                                              if pos == Factorial.length rest then [Expected msg] else msgs)                      replaceFailure rl = rl    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))-      where rewind t (ResultList EmptyTree _) = ResultList (Leaf $ ResultInfo t ()) mempty-            rewind t ResultList{} = ResultList mempty (FailureInfo (Factorial.length t) ["notFollowedBy"])+      where rewind t (ResultList EmptyTree _) = ResultList (Leaf $ ResultInfo t ()) noFailure+            rewind t ResultList{} = ResultList mempty (FailureInfo (Factorial.length t) [Expected "notFollowedBy"])    skipMany p = go-      where go = pure () <|> p *> go-   unexpected msg = Parser (\t-> ResultList mempty $ FailureInfo (Factorial.length t) [msg])-   eof = endOfInput+      where go = pure () <|> try p *> go+   unexpected msg = Parser (\t-> ResultList mempty $ FailureInfo (Factorial.length t) [Expected msg])+   eof = Parser f+      where f s | null s = ResultList (Leaf $ ResultInfo s ()) noFailure+                | otherwise = ResultList mempty (FailureInfo (Factorial.length s) [Expected "end of input"]) +instance FactorialMonoid s => DeterministicParsing (Parser g s) where+   Parser p <<|> Parser q = Parser r where+      r rest = case p rest+               of rl@(ResultList EmptyTree _failure) -> rl <> q rest+                  rl -> rl+   takeSome p = (:) <$> p <*> takeMany p+   takeMany (Parser p) = Parser (q id) where+      q acc rest = case p rest+                   of ResultList EmptyTree _failure -> ResultList (Leaf $ ResultInfo rest (acc [])) mempty+                      ResultList rl _ -> foldMap continue rl+         where continue (ResultInfo rest' result) = q (acc . (result:)) rest'+   skipAll (Parser p) = Parser q where+      q rest = case p rest+               of ResultList EmptyTree _failure -> ResultList (Leaf $ ResultInfo rest ()) mempty+                  ResultList rl _failure -> foldMap continue rl+         where continue (ResultInfo rest' _) = q rest'+ instance FactorialMonoid s => LookAheadParsing (Parser g s) where    lookAhead (Parser p) = Parser (\input-> rewind input (p input))       where rewind t (ResultList rl failure) = ResultList (rewindInput t <$> rl) failure             rewindInput t (ResultInfo _ r) = ResultInfo t r -instance (Show s, TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+instance TextualMonoid s => CharParsing (Parser g s) where+   satisfy predicate = Parser p+      where p s =+               case Textual.splitCharacterPrefix s+               of Just (first, rest) | predicate first -> ResultList (Leaf $ ResultInfo rest first) noFailure+                  _ -> ResultList mempty (FailureInfo (Factorial.length s) [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--fromResultList :: FactorialMonoid s => s -> ResultList s r -> ParseResults [(s, r)]+fromResultList :: (Eq s, FactorialMonoid s) => s -> ResultList s r -> ParseResults s [(s, r)] fromResultList s (ResultList EmptyTree (FailureInfo pos msgs)) =     Left (ParseFailure (Factorial.length s - pos) (nub msgs)) fromResultList _ (ResultList rl _failure) = Right (f <$> toList rl)
src/Text/Grampa/ContextFree/SortedMemoizing.hs view
@@ -1,8 +1,8 @@-{-# LANGUAGE FlexibleContexts, GeneralizedNewtypeDeriving, InstanceSigs,+{-# LANGUAGE BangPatterns, FlexibleContexts, GeneralizedNewtypeDeriving, InstanceSigs,              RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-} module Text.Grampa.ContextFree.SortedMemoizing -       (FailureInfo(..), ResultList(..), Parser(..), (<<|>),-        reparseTails, longest, peg, terminalPEG)+       (FailureInfo(..), ResultList(..), Parser(..),+        longest, peg, terminalPEG) where  import Control.Applicative@@ -10,28 +10,27 @@ import Data.Functor.Compose (Compose(..)) import Data.List (genericLength) import Data.List.NonEmpty (NonEmpty((:|)))-import Data.Semigroup (Semigroup(..)) import Data.Monoid (Monoid(mappend, mempty))-import Data.Monoid.Cancellative (isPrefixOf) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid, splitPrimePrefix) import Data.Monoid.Textual (TextualMonoid) import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Textual as Textual import Data.Semigroup (Semigroup((<>)))+import Data.Semigroup.Cancellative (LeftReductive(isPrefixOf)) import Data.String (fromString)  import qualified Text.Parser.Char import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token  import qualified Rank2 -import Text.Grampa.Class (Lexical(..), GrammarParsing(..), MonoidParsing(..), MultiParsing(..), AmbiguousParsing(..),-                          Ambiguous(Ambiguous), ParseResults)+import Text.Grampa.Class (GrammarParsing(..), InputParsing(..), InputCharParsing(..), MultiParsing(..),+                          AmbiguousParsing(..), Ambiguous(Ambiguous),+                          ConsumedInputParsing(..), DeterministicParsing(..),+                          TailsParsing(parseTails, parseAllTails), ParseResults, Expected(..)) import Text.Grampa.Internal (FailureInfo(..), ResultList(..), ResultsOfLength(..), fromResultList) import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack @@ -63,13 +62,6 @@    {-# INLINE (<|>) #-}    {-# INLINABLE empty #-} -infixl 3 <<|>-(<<|>) :: Parser g s a -> Parser g s a -> Parser g s a-Parser p <<|> Parser q = Parser r where-   r rest = case p rest-            of rl@(ResultList [] _failure) -> rl <> q rest-               rl -> rl- instance Monad (Parser g i) where    return = pure    (>>) = (*>)@@ -91,79 +83,70 @@    mempty = pure mempty    mappend = liftA2 mappend -instance GrammarParsing Parser where-   type GrammarFunctor Parser = ResultList+instance (Eq s, LeftReductive s, FactorialMonoid s) => GrammarParsing (Parser g s) where+   type ParserGrammar (Parser g s) = g+   type GrammarFunctor (Parser g s) = ResultList g s+   parsingResult s = Compose . fromResultList s+   nonTerminal :: (Rank2.Functor g, ParserInput (Parser g s) ~ s) => (g (ResultList g s) -> ResultList g s a) -> Parser g s a    nonTerminal f = Parser p where       p ((_, d) : _) = f d-      p _ = ResultList mempty (FailureInfo 0 ["NonTerminal at endOfInput"])+      p _ = ResultList mempty (FailureInfo 0 [Expected "NonTerminal at endOfInput"])    {-# INLINE nonTerminal #-} +instance (Eq s, LeftReductive s, FactorialMonoid s) => TailsParsing (Parser g s) where+   parseTails = applyParser+ -- | Memoizing parser guarantees O(n²) performance for grammars with unambiguous productions, but provides no left -- recursion support. -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Memoizing.'Parser' g s) -> s -> g ('Compose' 'ParseResults' [])+--                  g (Memoizing.'Parser' g s) -> s -> g ('Compose' ('ParseResults' s) []) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = Compose ParseResults []+instance (LeftReductive s, FactorialMonoid s) => MultiParsing (Parser g s) where+   type GrammarConstraint (Parser g s) g' = (g ~ g', Rank2.Functor g)+   type ResultFunctor (Parser g s) = Compose (ParseResults s) []    -- | Returns the list of all possible input prefix parses paired with the remaining input suffix.-   parsePrefix g input = Rank2.fmap (Compose . Compose . fromResultList input) (snd $ head $ parseTails g input)-   parseComplete :: forall g s. (Rank2.Functor g, FactorialMonoid s) =>-                    g (Parser g s) -> s -> g (Compose ParseResults [])+   parsePrefix g input = Rank2.fmap (Compose . Compose . fromResultList input) (snd $ head $ parseGrammarTails g input)+   parseComplete :: (ParserInput (Parser g s) ~ s, Rank2.Functor g, Eq s, FactorialMonoid s) =>+                    g (Parser g s) -> s -> g (Compose (ParseResults s) [])    parseComplete g input = Rank2.fmap ((snd <$>) . Compose . fromResultList input)-                              (snd $ head $ reparseTails close $ parseTails g input)-      where close = Rank2.fmap (<* endOfInput) g+                              (snd $ head $ parseAllTails close $ parseGrammarTails g input)+      where close = Rank2.fmap (<* eof) g -parseTails :: (Rank2.Functor g, FactorialMonoid s) => g (Parser g s) -> s -> [(s, g (ResultList g s))]-parseTails g input = foldr parseTail [] (Factorial.tails input)+parseGrammarTails :: (Rank2.Functor g, FactorialMonoid s) => g (Parser g s) -> s -> [(s, g (ResultList g s))]+parseGrammarTails g input = foldr parseTail [] (Factorial.tails input)    where parseTail s parsedTail = parsed             where parsed = (s,d):parsedTail                   d      = Rank2.fmap (($ parsed) . applyParser) g -reparseTails :: Rank2.Functor g => g (Parser g s) -> [(s, g (ResultList g s))] -> [(s, g (ResultList g s))]-reparseTails _ [] = []-reparseTails final parsed@((s, _):_) = (s, gd):parsed-   where gd = Rank2.fmap (`applyParser` parsed) final--instance MonoidParsing (Parser g) where-   endOfInput = eof+instance (LeftReductive s, FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p       where p rest@((s, _):_) = ResultList [ResultsOfLength 0 rest (s:|[])] mempty             p [] = ResultList [ResultsOfLength 0 [] (mempty:|[])] mempty    anyToken = Parser p       where p rest@((s, _):t) = case splitPrimePrefix s                                 of Just (first, _) -> ResultList [ResultsOfLength 1 t (first:|[])] mempty-                                   _ -> ResultList mempty (FailureInfo (genericLength rest) ["anyToken"])-            p [] = ResultList mempty (FailureInfo 0 ["anyToken"])+                                   _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "anyToken"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "anyToken"])    satisfy predicate = Parser p       where p rest@((s, _):t) =                case splitPrimePrefix s                of Just (first, _) | predicate first -> ResultList [ResultsOfLength 1 t (first:|[])] mempty-                  _ -> ResultList mempty (FailureInfo (genericLength rest) ["satisfy"])-            p [] = ResultList mempty (FailureInfo 0 ["satisfy"])-   satisfyChar predicate = Parser p-      where p rest@((s, _):t) =-               case Textual.characterPrefix s-               of Just first | predicate first -> ResultList [ResultsOfLength 1 t (first:|[])] mempty-                  _ -> ResultList mempty (FailureInfo (genericLength rest) ["satisfyChar"])-            p [] = ResultList mempty (FailureInfo 0 ["satisfyChar"])-   satisfyCharInput predicate = Parser p-      where p rest@((s, _):t) =-               case Textual.characterPrefix s-               of Just first | predicate first -> ResultList [ResultsOfLength 1 t (Factorial.primePrefix s:|[])] mempty-                  _ -> ResultList mempty (FailureInfo (genericLength rest) ["satisfyCharInput"])-            p [] = ResultList mempty (FailureInfo 0 ["satisfyCharInput"])+                  _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "satisfy"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "satisfy"])    scan s0 f = Parser (p s0)       where p s rest@((i, _) : _) = ResultList [ResultsOfLength l (drop l rest) (prefix:|[])] mempty                where (prefix, _, _) = Factorial.spanMaybe' s f i                      l = Factorial.length prefix             p _ [] = ResultList [ResultsOfLength 0 [] (mempty:|[])] mempty-   scanChars s0 f = Parser (p s0)-      where p s rest@((i, _) : _) = ResultList [ResultsOfLength l (drop l rest) (prefix:|[])] mempty-               where (prefix, _, _) = Textual.spanMaybe_' s f i-                     l = Factorial.length prefix-            p _ [] = ResultList [ResultsOfLength 0 [] (mempty:|[])] mempty+   take 0 = mempty+   take n = Parser p+      where p rest@((s, _) : _)+               | x <- Factorial.take n s, l <- Factorial.length x, l == n =+                    ResultList [ResultsOfLength l (drop l rest) (x:|[])] mempty+            p rest = ResultList mempty (FailureInfo (genericLength rest) [Expected $ "take " ++ show n])    takeWhile predicate = Parser p       where p rest@((s, _) : _)                | x <- Factorial.takeWhile predicate s, l <- Factorial.length x =@@ -173,7 +156,31 @@       where p rest@((s, _) : _)                | x <- Factorial.takeWhile predicate s, l <- Factorial.length x, l > 0 =                     ResultList [ResultsOfLength l (drop l rest) (x:|[])] mempty-            p rest = ResultList mempty (FailureInfo (genericLength rest) ["takeWhile1"])+            p rest = ResultList mempty (FailureInfo (genericLength rest) [Expected "takeWhile1"])+   string s = Parser p where+      p rest@((s', _) : _)+         | s `isPrefixOf` s' = ResultList [ResultsOfLength l (Factorial.drop l rest) (s:|[])] mempty+      p rest = ResultList mempty (FailureInfo (genericLength rest) [ExpectedInput s])+      l = Factorial.length s+   notSatisfy predicate = Parser p+      where p rest@((s, _):_)+               | Just (first, _) <- splitPrimePrefix s, +                 predicate first = ResultList mempty (FailureInfo (genericLength rest) [Expected "notSatisfy"])+            p rest = ResultList [ResultsOfLength 0 rest (():|[])] mempty+   {-# INLINABLE string #-}++instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p rest@((s, _):t) =+               case Textual.characterPrefix s+               of Just first | predicate first -> ResultList [ResultsOfLength 1 t (Factorial.primePrefix s:|[])] mempty+                  _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "satisfyCharInput"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "satisfyCharInput"])+   scanChars s0 f = Parser (p s0)+      where p s rest@((i, _) : _) = ResultList [ResultsOfLength l (drop l rest) (prefix:|[])] mempty+               where (prefix, _, _) = Textual.spanMaybe_' s f i+                     l = Factorial.length prefix+            p _ [] = ResultList [ResultsOfLength 0 [] (mempty:|[])] mempty    takeCharsWhile predicate = Parser p       where p rest@((s, _) : _)                | x <- Textual.takeWhile_ False predicate s, l <- Factorial.length x =@@ -183,24 +190,20 @@       where p rest@((s, _) : _)                | x <- Textual.takeWhile_ False predicate s, l <- Factorial.length x, l > 0 =                     ResultList [ResultsOfLength l (drop l rest) (x:|[])] mempty-            p rest = ResultList mempty (FailureInfo (genericLength rest) ["takeCharsWhile1"])-   string s = Parser p where-      p rest@((s', _) : _)-         | s `isPrefixOf` s' = ResultList [ResultsOfLength l (Factorial.drop l rest) (s:|[])] mempty-      p rest = ResultList mempty (FailureInfo (genericLength rest) ["string " ++ show s])-      l = Factorial.length s-   notSatisfy predicate = Parser p-      where p rest@((s, _):_)-               | Just (first, _) <- splitPrimePrefix s, -                 predicate first = ResultList mempty (FailureInfo (genericLength rest) ["notSatisfy"])-            p rest = ResultList [ResultsOfLength 0 rest (():|[])] mempty+            p rest = ResultList mempty (FailureInfo (genericLength rest) [Expected "takeCharsWhile1"])    notSatisfyChar predicate = Parser p       where p rest@((s, _):_)                | Just first <- Textual.characterPrefix s, -                 predicate first = ResultList mempty (FailureInfo (genericLength rest) ["notSatisfyChar"])+                 predicate first = ResultList mempty (FailureInfo (genericLength rest) [Expected "notSatisfyChar"])             p rest = ResultList [ResultsOfLength 0 rest (():|[])] mempty-   {-# INLINABLE string #-} +instance (LeftReductive s, FactorialMonoid s) => ConsumedInputParsing (Parser g s) where+   match (Parser p) = Parser q+      where q [] = addConsumed mempty (p [])+            q rest@((s, _) : _) = addConsumed s (p rest)+            addConsumed input (ResultList rl failure) = ResultList (add1 <$> rl) failure+               where add1 (ResultsOfLength l t rs) = ResultsOfLength l t ((,) (Factorial.take l input) <$> rs)+ instance MonoidNull s => Parsing (Parser g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)@@ -209,20 +212,37 @@    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)                where replaceFailure (ResultList [] (FailureInfo pos msgs)) =-                        ResultList [] (FailureInfo pos $ if pos == genericLength rest then [msg] else msgs)+                        ResultList [] (FailureInfo pos $ if pos == genericLength rest then [Expected msg] else msgs)                      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 (FailureInfo (genericLength t) ["notFollowedBy"])+            rewind t ResultList{} = ResultList mempty (FailureInfo (genericLength t) [Expected "notFollowedBy"])    skipMany p = go-      where go = pure () <|> p *> go-   unexpected msg = Parser (\t-> ResultList mempty $ FailureInfo (genericLength t) [msg])+      where go = pure () <|> try p *> go+   unexpected msg = Parser (\t-> ResultList mempty $ FailureInfo (genericLength t) [Expected msg])    eof = Parser f       where f rest@((s, _):_)                | null s = ResultList [ResultsOfLength 0 rest (():|[])] mempty-               | otherwise = ResultList mempty (FailureInfo (genericLength rest) ["endOfInput"])+               | otherwise = ResultList mempty (FailureInfo (genericLength rest) [Expected "end of input"])             f [] = ResultList [ResultsOfLength 0 [] (():|[])] mempty +instance MonoidNull s => DeterministicParsing (Parser g s) where+   Parser p <<|> Parser q = Parser r where+      r rest = case p rest+               of rl@(ResultList [] _failure) -> rl <> q rest+                  rl -> rl+   takeSome p = (:) <$> p <*> takeMany p+   takeMany (Parser p) = Parser (q 0 id) where+      q !len acc rest = case p rest+                        of ResultList [] _failure -> ResultList [ResultsOfLength len rest (acc [] :| [])] mempty+                           ResultList rl _ -> foldMap continue rl+         where continue (ResultsOfLength len' rest' results) = foldMap (\r-> q (len + len') (acc . (r:)) rest') results+   skipAll (Parser p) = Parser (q 0) where+      q !len rest = case p rest+                    of ResultList [] _failure -> ResultList [ResultsOfLength len rest (():|[])] mempty+                       ResultList rl _failure -> foldMap continue rl+         where continue (ResultsOfLength len' rest' _) = q (len + len') rest'+ instance MonoidNull s => LookAheadParsing (Parser g s) where    lookAhead (Parser p) = Parser (\input-> rewind input (p input))       where rewind _ rl@(ResultList [] _) = rl@@ -230,18 +250,15 @@             results (ResultsOfLength _ _ r) = r  instance (Show s, TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+   satisfy predicate = Parser p+      where p rest@((s, _):t) =+               case Textual.characterPrefix s+               of Just first | predicate first -> ResultList [ResultsOfLength 1 t (first:|[])] mempty+                  _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "Char.satisfy"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken- instance AmbiguousParsing (Parser g s) where    ambiguous (Parser p) = Parser q       where q rest | ResultList rs failure <- p rest = ResultList (groupByLength <$> rs) failure@@ -252,16 +269,18 @@ 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 [] failure -> Backtrack.NoParse failure+            of ResultList [] (FailureInfo pos expected) -> Backtrack.NoParse (FailureInfo pos $ map message expected)                ResultList rs _ -> parsed (last rs)    parsed (ResultsOfLength l s (r:|_)) = Backtrack.Parsed l r s+   message (Expected msg) = Expected msg+   message (ExpectedInput s) = ExpectedInput [(s, error "longest")]  -- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest' peg :: 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 failure -> ResultList mempty failure+               Backtrack.NoParse (FailureInfo pos expected) -> ResultList mempty (FailureInfo pos ((fst . head <$>) <$> expected))  -- | Turns a backtracking PEG parser into a context-free parser terminalPEG :: Monoid s => Backtrack.Parser g s a -> Parser g s a
+ src/Text/Grampa/ContextFree/SortedMemoizing/Transformer.hs view
@@ -0,0 +1,395 @@+{-# LANGUAGE BangPatterns, FlexibleContexts, GeneralizedNewtypeDeriving, InstanceSigs,+             RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-}+module Text.Grampa.ContextFree.SortedMemoizing.Transformer+       (FailureInfo(..), ResultListT(..), ParserT(..), (<<|>),+        lift, tmap, longest, peg, terminalPEG)+where++import Control.Applicative+import Control.Monad (MonadPlus(..), join, void)+import Data.Function (on)+import Data.Functor.Compose (Compose(..))+import Data.Functor.Identity (Identity(..))+import Data.List (genericLength, nub)+import Data.List.NonEmpty (NonEmpty((:|)), groupBy, fromList, toList)+import Data.Monoid.Null (MonoidNull(null))+import Data.Monoid.Factorial (FactorialMonoid, splitPrimePrefix)+import Data.Monoid.Textual (TextualMonoid)+import qualified Data.Monoid.Factorial as Factorial+import qualified Data.Monoid.Textual as Textual+import Data.Semigroup.Cancellative (LeftReductive(isPrefixOf))+import Data.String (fromString)++import qualified Text.Parser.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(..),+                          ConsumedInputParsing(..), DeterministicParsing(..),+                          AmbiguousParsing(..), Ambiguous(Ambiguous),+                          TailsParsing(..), ParseResults, ParseFailure(..), Expected(..))+import Text.Grampa.Internal (FailureInfo(..), AmbiguousAlternative(..))+import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack++import Prelude hiding (iterate, length, null, showList, span, takeWhile)++-- | Parser for a context-free grammar with packrat-like sharing that carries a monadic computation as part of the+-- parse result.+newtype ParserT m g s r = Parser{applyParser :: [(s, g (ResultListT m g s))] -> ResultListT m g s r}++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  :: !(FailureInfo s)}++singleResult :: Applicative m => 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++instance Functor m => Functor (ParserT m g s) where+   fmap f (Parser p) = Parser (fmap f . p)+   {-# INLINE fmap #-}++instance Applicative m => Applicative (ParserT m g s) where+   pure a = Parser (\rest-> singleResult 0 rest a)+   Parser p <*> Parser q = Parser r where+      r rest = case p rest+               of ResultList results failure -> ResultList mempty failure <> foldMap continue results+      continue (ResultsOfLengthT (ROL l rest' fs)) = foldMap (continue' l $ q rest') fs+      continue' l (ResultList rs failure) f = ResultList (adjust l f <$> rs) failure+      adjust l f (ResultsOfLengthT (ROL l' rest' as)) = ResultsOfLengthT (ROL (l+l') rest' ((f <*>) <$> as))+   {-# INLINABLE pure #-}+   {-# INLINABLE (<*>) #-}++instance Applicative m => Alternative (ParserT m g s) where+   empty = Parser (\rest-> ResultList mempty $ FailureInfo (genericLength rest) [])+   Parser p <|> Parser q = Parser r where+      r rest = p rest <> q rest+   {-# INLINE (<|>) #-}+   {-# INLINABLE empty #-}++instance (Monad m, Traversable m) => Monad (ParserT m g s) where+   return = pure+   (>>) = (*>)+   Parser p >>= f = Parser q where+      q rest = case p rest+               of ResultList results failure -> ResultList mempty failure <> foldMap continue results+      continue (ResultsOfLengthT (ROL l rest' rs)) = foldMap (continue' l . flip applyParser rest' . rejoin . fmap f) rs+      continue' l (ResultList rs failure) = ResultList (adjust l <$> rs) failure+      adjust l (ResultsOfLengthT (ROL l' rest' rs)) = ResultsOfLengthT (ROL (l+l') rest' rs)+      rejoin :: forall a. m (ParserT m g s a) -> ParserT m g s a+      rejoinResults :: forall a. m (ResultListT m g s a) -> ResultListT m g s a+      rejoinResultsOfLengthT :: forall a. m (ResultsOfLengthT m g s a) -> ResultsOfLengthT m g s a+      rejoin m = Parser (\rest-> rejoinResults $ flip applyParser rest <$> m)+      rejoinResults m = ResultList (fmap rejoinResultsOfLengthT $ sequence $ resultSuccesses <$> m) (foldMap resultFailures m)+      rejoinResultsOfLengthT m = ResultsOfLengthT (join <$> traverse getResultsOfLength m)++instance (Foldable m, Monad m, Traversable m) => MonadPlus (ParserT m g s) where+   mzero = empty+   mplus = (<|>)++-- | Lift a parse-free computation into the parser.+lift :: m a -> ParserT m g s a+lift m = Parser (\rest-> ResultList [ResultsOfLengthT $ ROL 0 rest (m:|[])] mempty)++-- | Modify the computation carried by the parser.+tmap :: (m a -> m b) -> ParserT m g s a -> ParserT m g s b+tmap f (Parser p) = Parser (mapResultList f . p)++mapResultList :: (m a -> m b) -> ResultListT m g s a -> ResultListT m g s b+mapResultList f (ResultList successes failures) = ResultList (mapResults f <$> successes) failures++mapResults :: (m a -> m b) -> ResultsOfLengthT m g s a -> ResultsOfLengthT m g s b+mapResults f (ResultsOfLengthT rol) = ResultsOfLengthT (f <$> rol)++instance (Applicative m, Semigroup x) => Semigroup (ParserT m g s x) where+   (<>) = liftA2 (<>)++instance (Applicative m, Monoid x) => Monoid (ParserT m g s x) where+   mempty = pure mempty+   mappend = liftA2 mappend++-- | Memoizing parser guarantees O(n²) performance for grammars with unambiguous productions, but provides no left+-- recursion support.+--+-- @+-- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>+--                  g (Memoizing.'Parser' g s) -> s -> g ('Compose' ('ParseResults' s) [])+-- @+instance (Applicative m, LeftReductive s, FactorialMonoid s) => MultiParsing (ParserT m g s) where+   type GrammarConstraint (ParserT m g s) g' = (g ~ g', Rank2.Functor g)+   type ResultFunctor (ParserT m g s) = Compose (Compose (ParseResults s) []) m+   -- | Returns the list of all possible input prefix parses paired with the remaining input suffix.+   parsePrefix g input = Rank2.fmap (Compose . Compose . Compose . fmap (fmap sequenceA) . fromResultList input)+                                    (snd $ head $ parseGrammarTails g input)+   parseComplete :: (ParserInput (ParserT m g s) ~ s, Rank2.Functor g, Eq s, FactorialMonoid s) =>+                    g (ParserT m g s) -> s -> g (Compose (Compose (ParseResults s) []) m)+   parseComplete g input = Rank2.fmap (Compose . fmap snd . Compose . fromResultList input)+                              (snd $ head $ parseAllTails close $ parseGrammarTails g input)+      where close = Rank2.fmap (<* eof) g++instance (Applicative m, Eq s, LeftReductive s, FactorialMonoid s, Rank2.Functor g) =>+         GrammarParsing (ParserT m g s) where+   type ParserGrammar (ParserT m g s) = g+   type GrammarFunctor (ParserT m g s) = ResultListT m g s+   parsingResult s = Compose . Compose . fmap (fmap sequenceA) . fromResultList s+   nonTerminal :: (ParserInput (ParserT m g s) ~ s) => (g (ResultListT m g s) -> ResultListT m g s a) -> ParserT m g s a+   nonTerminal f = Parser p where+      p ((_, d) : _) = f d+      p _ = ResultList mempty (FailureInfo 0 [Expected "NonTerminal at endOfInput"])+   {-# INLINE nonTerminal #-}++instance (Applicative m, Eq s, LeftReductive s, FactorialMonoid s, Rank2.Functor g) =>+         TailsParsing (ParserT m g s) where+   parseTails = applyParser++parseGrammarTails :: (Rank2.Functor g, FactorialMonoid s) => g (ParserT m g s) -> s -> [(s, g (ResultListT m g s))]+parseGrammarTails g input = foldr parseTail [] (Factorial.tails input)+   where parseTail s parsedTail = parsed+            where parsed = (s,d):parsedTail+                  d      = Rank2.fmap (($ parsed) . applyParser) g++instance (Applicative m, LeftReductive s, FactorialMonoid s) => InputParsing (ParserT m g s) where+   type ParserInput (ParserT m g s) = s+   getInput = Parser p+      where p rest@((s, _):_) = singleResult 0 rest s+            p [] = singleResult 0 [] mempty+   anyToken = Parser p+      where p rest@((s, _):t) = case splitPrimePrefix s+                                of Just (first, _) -> singleResult 1 t first+                                   _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "anyToken"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "anyToken"])+   satisfy predicate = Parser p+      where p rest@((s, _):t) =+               case splitPrimePrefix s+               of Just (first, _) | predicate first -> singleResult 1 t first+                  _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "satisfy"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "satisfy"])+   scan s0 f = Parser (p s0)+      where p s rest@((i, _) : _) = singleResult l (drop l rest) prefix+               where (prefix, _, _) = Factorial.spanMaybe' s f i+                     l = Factorial.length prefix+            p _ [] = singleResult 0 [] mempty+   takeWhile predicate = Parser p+      where p rest@((s, _) : _)+               | x <- Factorial.takeWhile predicate s, l <- Factorial.length x =+                    singleResult l (drop l rest) x+            p [] = singleResult 0 [] mempty+   take 0 = mempty+   take n = Parser p+      where p rest@((s, _) : _)+               | x <- Factorial.take n s, l <- Factorial.length x, l == n =+                    singleResult l (drop l rest) x+            p rest = ResultList mempty (FailureInfo (genericLength rest) [Expected $ "take " ++ show n])+   takeWhile1 predicate = Parser p+      where p rest@((s, _) : _)+               | x <- Factorial.takeWhile predicate s, l <- Factorial.length x, l > 0 =+                    singleResult l (drop l rest) x+            p rest = ResultList mempty (FailureInfo (genericLength rest) [Expected "takeWhile1"])+   string s = Parser p where+      p rest@((s', _) : _)+         | s `isPrefixOf` s' = singleResult l (drop l rest) s+      p rest = ResultList mempty (FailureInfo (genericLength rest) [ExpectedInput s])+      l = Factorial.length s+   notSatisfy predicate = Parser p+      where p rest@((s, _):_)+               | Just (first, _) <- splitPrimePrefix s, +                 predicate first = ResultList mempty (FailureInfo (genericLength rest) [Expected "notSatisfy"])+            p rest = singleResult 0 rest ()+   {-# INLINABLE string #-}++instance (Applicative m, Show s, TextualMonoid s) => InputCharParsing (ParserT m g s) where+   satisfyCharInput predicate = Parser p+      where p rest@((s, _):t) =+               case Textual.characterPrefix s+               of Just first+                     | predicate first -> singleResult 1 t (Factorial.primePrefix s)+                  _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "satisfyCharInput"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "satisfyCharInput"])+   scanChars s0 f = Parser (p s0)+      where p s rest@((i, _) : _) = singleResult l (drop l rest) prefix+               where (prefix, _, _) = Textual.spanMaybe_' s f i+                     l = Factorial.length prefix+            p _ [] = singleResult 0 [] mempty+   takeCharsWhile predicate = Parser p+      where p rest@((s, _) : _)+               | x <- Textual.takeWhile_ False predicate s, l <- Factorial.length x =+                    singleResult l (drop l rest) x+            p [] = singleResult 0 [] mempty+   takeCharsWhile1 predicate = Parser p+      where p rest@((s, _) : _)+               | x <- Textual.takeWhile_ False predicate s, l <- Factorial.length x, l > 0 =+                    singleResult l (drop l rest) x+            p rest = ResultList mempty (FailureInfo (genericLength rest) [Expected "takeCharsWhile1"])+   notSatisfyChar predicate = Parser p+      where p rest@((s, _):_)+               | Just first <- Textual.characterPrefix s, +                 predicate first = ResultList mempty (FailureInfo (genericLength rest) [Expected "notSatisfyChar"])+            p rest = singleResult 0 rest ()++instance (Applicative m, LeftReductive s, FactorialMonoid s) => ConsumedInputParsing (ParserT m g s) where+   match (Parser p) = Parser q+      where q [] = addConsumed mempty (p [])+            q rest@((s, _) : _) = addConsumed s (p rest)+            addConsumed input (ResultList rl failure) = ResultList (add1 <$> rl) failure+               where add1 (ResultsOfLengthT (ROL l t rs)) =+                        ResultsOfLengthT (ROL l t $ ((,) (Factorial.take l input) <$>) <$> rs)++instance (Applicative m, MonoidNull s) => Parsing (ParserT m g s) where+   try (Parser p) = Parser q+      where q rest = rewindFailure (p rest)+               where rewindFailure (ResultList rl (FailureInfo _pos _msgs)) =+                        ResultList rl (FailureInfo (genericLength rest) [])+   Parser p <?> msg  = Parser q+      where q rest = replaceFailure (p rest)+               where replaceFailure (ResultList [] (FailureInfo pos msgs)) =+                        ResultList [] (FailureInfo pos $ if pos == genericLength rest then [Expected msg] else msgs)+                     replaceFailure rl = rl+   notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))+      where rewind t (ResultList [] _) = singleResult 0 t ()+            rewind t ResultList{} = ResultList mempty (FailureInfo (genericLength t) [Expected "notFollowedBy"])+   skipMany p = go+      where go = pure () <|> try p *> go+   unexpected msg = Parser (\t-> ResultList mempty $ FailureInfo (genericLength t) [Expected msg])+   eof = Parser f+      where f rest@((s, _):_)+               | null s = singleResult 0 rest ()+               | otherwise = ResultList mempty (FailureInfo (genericLength rest) [Expected "end of input"])+            f [] = singleResult 0 [] ()++instance (Applicative m, MonoidNull s) => DeterministicParsing (ParserT m g s) where+   Parser p <<|> Parser q = Parser r where+      r rest = case p rest+               of rl@(ResultList [] _failure) -> rl <> q rest+                  rl -> rl+   takeSome p = (:) <$> p <*> takeMany p+   takeMany (Parser p) = Parser (q 0 (pure id)) where+      q !len acc rest = case p rest+                        of ResultList [] _failure+                              -> ResultList [ResultsOfLengthT $ ROL len rest (fmap ($ []) acc :| [])] mempty+                           ResultList rl _ -> foldMap continue rl+         where continue (ResultsOfLengthT (ROL len' rest' results)) =+                  foldMap (\r-> q (len + len') (liftA2 (.) acc ((:) <$> r)) rest') results+   skipAll (Parser p) = Parser (q 0) where+      q !len rest = case p rest+                    of ResultList [] _failure -> singleResult len rest ()+                       ResultList rl _failure -> foldMap continue rl+         where continue (ResultsOfLengthT (ROL len' rest' _)) = q (len + len') rest'++instance (Applicative m, MonoidNull s) => LookAheadParsing (ParserT m g s) where+   lookAhead (Parser p) = Parser (\input-> rewind input (p input))+      where rewind _ rl@(ResultList [] _) = rl+            rewind t (ResultList rl failure) =+               ResultList [ResultsOfLengthT $ ROL 0 t $ foldr1 (<>) (results <$> rl)] failure+            results (ResultsOfLengthT (ROL _ _ r)) = r++instance (Applicative m, Show s, TextualMonoid s) => CharParsing (ParserT m g s) where+   satisfy predicate = Parser p+      where p rest@((s, _):t) =+               case Textual.characterPrefix s+               of Just first | predicate first -> singleResult 1 t first+                  _ -> ResultList mempty (FailureInfo (genericLength rest) [Expected "Char.satisfy"])+            p [] = ResultList mempty (FailureInfo 0 [Expected "Char.satisfy"])+   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 (Applicative m, Eq (m ())) => AmbiguousParsing (ParserT m g s) where+   ambiguous (Parser p) = Parser q+      where q rest | ResultList rs failure <- p rest = ResultList (groupByLength <$> rs) failure+            groupByLength :: ResultsOfLengthT m g s r -> ResultsOfLengthT m g s (Ambiguous r)+            groupByLength (ResultsOfLengthT (ROL l rest rs)) =+               ResultsOfLengthT (ROL l rest $ (Ambiguous <$>) <$> fromList (sequenceA <$> groupBy ((==) `on` void) rs))++-- | 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 :: 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 [] (FailureInfo pos expected) -> Backtrack.NoParse (FailureInfo pos $ map message expected)+               ResultList rs _ -> parsed (last rs)+   parsed (ResultsOfLengthT (ROL l s (Identity r:|_))) = Backtrack.Parsed l r s+   message (Expected msg) = Expected msg+   message (ExpectedInput s) = ExpectedInput [(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 => 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 (FailureInfo pos expected) ->+                  ResultList mempty (FailureInfo pos ((fst . head <$>) <$> expected))++-- | Turns a backtracking PEG parser into a context-free parser+terminalPEG :: (Applicative m, Monoid s) => Backtrack.Parser g s a -> ParserT m g s a+terminalPEG p = Parser q where+   q [] = case Backtrack.applyParser p mempty+            of Backtrack.Parsed l result _ -> singleResult l [] result+               Backtrack.NoParse failure -> ResultList mempty failure+   q rest@((s, _):_) = case Backtrack.applyParser p s+                       of Backtrack.Parsed l result _ -> singleResult l (drop l rest) result+                          Backtrack.NoParse failure -> ResultList mempty failure++fromResultList :: (Functor m, Eq s, FactorialMonoid s) => s -> ResultListT m g s r -> ParseResults s [(s, m r)]+fromResultList s (ResultList [] (FailureInfo pos msgs)) =+   Left (ParseFailure (Factorial.length s - pos + 1) (nub msgs))+fromResultList _ (ResultList rl _failure) = Right (foldMap f rl)+   where f (ResultsOfLengthT (ROL _ ((s, _):_) r)) = (,) s <$> toList r+         f (ResultsOfLengthT (ROL _ [] r)) = (,) mempty <$> toList r+{-# INLINABLE fromResultList #-}++instance Functor (ResultsOfLength m g s) where+   fmap f (ROL l t a) = ROL l t (f <$> a)+   {-# INLINE fmap #-}++instance Functor m => Functor (ResultsOfLengthT m g s) where+   fmap f (ResultsOfLengthT rol) = ResultsOfLengthT (fmap f <$> rol)+   {-# INLINE fmap #-}++instance Functor m => Functor (ResultListT m g s) where+   fmap f (ResultList l failure) = ResultList ((f <$>) <$> l) failure+   {-# INLINE fmap #-}++instance Applicative m => Applicative (ResultsOfLength m g s) where+   pure = ROL 0 mempty . pure+   ROL l1 _ fs <*> ROL l2 t2 xs = ROL (l1 + l2) t2 (fs <*> xs)+   {-# INLINE pure #-}+   {-# INLINE (<*>) #-}++instance Applicative m => Applicative (ResultsOfLengthT m g s) where+   pure = ResultsOfLengthT . pure . pure+   ResultsOfLengthT rol1 <*> ResultsOfLengthT rol2 = ResultsOfLengthT (liftA2 (<*>) rol1 rol2)++instance Applicative m => Applicative (ResultListT m g s) where+   pure a = ResultList [pure a] mempty+   ResultList rl1 f1 <*> ResultList rl2 f2 = ResultList ((<*>) <$> rl1 <*> rl2) (f1 <> f2)++instance Applicative m => Alternative (ResultListT m g s) where+   empty = ResultList mempty mempty+   (<|>) = (<>)++instance Applicative m => AmbiguousAlternative (ResultListT m g s) where+   ambiguousOr (ResultList rl1 f1) (ResultList rl2 f2) = ResultList (merge rl1 rl2) (f1 <> f2)+      where merge [] rl = rl+            merge rl [] = rl+            merge rl1'@(rol1@(ResultsOfLengthT (ROL l1 s1 r1)) : rest1)+                  rl2'@(rol2@(ResultsOfLengthT (ROL l2 _ r2)) : rest2)+               | l1 < l2 = rol1 : merge rest1 rl2'+               | l1 > l2 = rol2 : merge rl1' rest2+               | otherwise = ResultsOfLengthT (ROL l1 s1 $ liftA2 (liftA2 collect) r1 r2) : merge rest1 rest2+            collect (Ambiguous xs) (Ambiguous ys) = Ambiguous (xs <> ys)++instance Semigroup (ResultListT m g s r) where+   ResultList rl1 f1 <> ResultList rl2 f2 = ResultList (merge rl1 rl2) (f1 <> f2)+      where merge [] rl = rl+            merge rl [] = rl+            merge rl1'@(rol1@(ResultsOfLengthT (ROL l1 s1 r1)) : rest1)+                 rl2'@(rol2@(ResultsOfLengthT (ROL l2 _ r2)) : rest2)+               | l1 < l2 = rol1 : merge rest1 rl2'+               | l1 > l2 = rol2 : merge rl1' rest2+               | otherwise = ResultsOfLengthT (ROL l1 s1 (r1 <> r2)) : merge rest1 rest2++instance Monoid (ResultListT m g s r) where+   mempty = ResultList mempty mempty+   mappend = (<>)
src/Text/Grampa/Internal.hs view
@@ -1,5 +1,10 @@-module Text.Grampa.Internal (BinTree(..), FailureInfo(..), ResultList(..), ResultsOfLength(..), fromResultList) where+{-# LANGUAGE FlexibleInstances, RankNTypes #-} +module Text.Grampa.Internal (BinTree(..), FailureInfo(..), ResultList(..), ResultsOfLength(..),+                             AmbiguousAlternative(..),+                             fromResultList, noFailure) where++import Control.Applicative (Applicative(..), Alternative(..)) import Data.Foldable (toList) import Data.Functor.Classes (Show1(..)) import Data.List.NonEmpty (NonEmpty)@@ -9,22 +14,22 @@  import Data.Monoid.Factorial (FactorialMonoid, length) -import Text.Grampa.Class (ParseFailure(..), ParseResults)+import Text.Grampa.Class (Ambiguous(..), Expected(..), ParseFailure(..), ParseResults)  import Prelude hiding (length, showList) -data FailureInfo = FailureInfo Int [String] deriving (Eq, Show)+data FailureInfo s = FailureInfo Int [Expected s] deriving (Eq, Show)  data ResultsOfLength g s r = ResultsOfLength !Int ![(s, g (ResultList g s))] !(NonEmpty r) -data ResultList g s r = ResultList ![ResultsOfLength g s r] !FailureInfo+data ResultList g s r = ResultList ![ResultsOfLength g s r] !(FailureInfo s)  data BinTree a = Fork !(BinTree a) !(BinTree a)                | Leaf !a                | EmptyTree                deriving (Show) -fromResultList :: FactorialMonoid s => s -> ResultList g s r -> ParseResults [(s, r)]+fromResultList :: (Eq s, FactorialMonoid s) => s -> ResultList g s r -> ParseResults s [(s, r)] fromResultList s (ResultList [] (FailureInfo pos msgs)) =    Left (ParseFailure (length s - pos + 1) (nub msgs)) fromResultList _ (ResultList rl _failure) = Right (foldMap f rl)@@ -32,26 +37,23 @@          f (ResultsOfLength _ [] r) = (,) mempty <$> toList r {-# INLINABLE fromResultList #-} -instance Semigroup FailureInfo where+noFailure :: FailureInfo s+noFailure = FailureInfo maxBound []++instance Semigroup (FailureInfo s) where    FailureInfo pos1 exp1 <> FailureInfo pos2 exp2 = FailureInfo pos' exp'       where (pos', exp') | pos1 < pos2 = (pos1, exp1)                          | pos1 > pos2 = (pos2, exp2)-                         | otherwise = (pos1, merge exp1 exp2)-            merge [] exps = exps-            merge exps [] = exps-            merge xs@(x:xs') ys@(y:ys')-               | x < y = x : merge xs' ys-               | x > y = y : merge xs ys'-               | otherwise = x : merge xs' ys'+                         | otherwise = (pos1, exp1 <> exp2) -instance Monoid FailureInfo where+instance Monoid (FailureInfo s) where    mempty = FailureInfo maxBound []    mappend = (<>) -instance Show r => Show (ResultList g s r) where+instance (Show s, Show r) => Show (ResultList g s r) where    show (ResultList l f) = "ResultList (" ++ shows l (") (" ++ shows f ")") -instance Show1 (ResultList g s) where+instance Show s => Show1 (ResultList g s) where    liftShowsPrec _sp showList _prec (ResultList rol f) rest =        "ResultList " ++ shows (simplify <$> toList rol) (shows f rest)       where simplify (ResultsOfLength l _ r) = "ResultsOfLength " <> show l <> " _ " <> showList (toList r) ""@@ -67,14 +69,39 @@    fmap f (ResultList l failure) = ResultList ((f <$>) <$> l) failure    {-# INLINE fmap #-} +instance Applicative (ResultsOfLength g s) where+   pure = ResultsOfLength 0 mempty . pure+   ResultsOfLength l1 _ fs <*> ResultsOfLength l2 t2 xs = ResultsOfLength (l1 + l2) t2 (fs <*> xs)++instance Applicative (ResultList g s) where+   pure a = ResultList [pure a] mempty+   ResultList rl1 f1 <*> ResultList rl2 f2 = ResultList ((<*>) <$> rl1 <*> rl2) (f1 <> f2)++instance Alternative (ResultList g s) where+   empty = ResultList mempty mempty+   (<|>) = (<>)+ instance Semigroup (ResultList g s r) where-   ResultList rl1 f1 <> ResultList rl2 f2 = ResultList (join rl1 rl2) (f1 <> f2)-      where join [] rl = rl-            join rl [] = rl-            join rl1'@(rol1@(ResultsOfLength l1 s1 r1) : rest1) rl2'@(rol2@(ResultsOfLength l2 _ r2) : rest2)-               | l1 < l2 = rol1 : join rest1 rl2'-               | l1 > l2 = rol2 : join rl1' rest2-               | otherwise = ResultsOfLength l1 s1 (r1 <> r2) : join rest1 rest2+   ResultList rl1 f1 <> ResultList rl2 f2 = ResultList (merge rl1 rl2) (f1 <> f2)+      where merge [] rl = rl+            merge rl [] = rl+            merge rl1'@(rol1@(ResultsOfLength l1 s1 r1) : rest1) rl2'@(rol2@(ResultsOfLength l2 _ r2) : rest2)+               | l1 < l2 = rol1 : merge rest1 rl2'+               | l1 > l2 = rol2 : merge rl1' rest2+               | otherwise = ResultsOfLength l1 s1 (r1 <> r2) : merge rest1 rest2++instance AmbiguousAlternative (ResultList g s) where+   ambiguousOr (ResultList rl1 f1) (ResultList rl2 f2) = ResultList (merge rl1 rl2) (f1 <> f2)+      where merge [] rl = rl+            merge rl [] = rl+            merge rl1'@(rol1@(ResultsOfLength l1 s1 r1) : rest1) rl2'@(rol2@(ResultsOfLength l2 _ r2) : rest2)+               | l1 < l2 = rol1 : merge rest1 rl2'+               | l1 > l2 = rol2 : merge rl1' rest2+               | otherwise = ResultsOfLength l1 s1 (liftA2 collect r1 r2) : merge rest1 rest2+            collect (Ambiguous xs) (Ambiguous ys) = Ambiguous (xs <> ys)++class Alternative f => AmbiguousAlternative f where+   ambiguousOr :: f (Ambiguous a) -> f (Ambiguous a) -> f (Ambiguous a)  instance Monoid (ResultList g s r) where    mempty = ResultList mempty mempty
src/Text/Grampa/PEG/Backtrack.hs view
@@ -14,10 +14,10 @@ import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString) -import qualified Data.Monoid.Cancellative as Cancellative import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Null as Null import qualified Data.Monoid.Textual as Textual+import qualified Data.Semigroup.Cancellative as Cancellative  import qualified Rank2 @@ -25,20 +25,19 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token-import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Grampa.Class (DeterministicParsing(..), InputParsing(..), InputCharParsing(..), MultiParsing(..),+                          ParseResults, ParseFailure(..), Expected(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,                                               parsedSuffix :: !s}-                                     | NoParse FailureInfo+                                     | NoParse (FailureInfo s)  -- | Parser type for Parsing Expression Grammars that uses a backtracking algorithm, fast for grammars in LL(1) class -- but with potentially exponential performance for longer ambiguous prefixes. newtype Parser g s r = Parser{applyParser :: s -> Result g s r} -instance Show1 (Result g s) where+instance Show s => Show1 (Result g s) where    liftShowsPrec showsPrecSub _showList prec Parsed{parsedPrefix= r} rest = "Parsed " ++ showsPrecSub prec r rest    liftShowsPrec _showsPrec _showList _prec (NoParse f) rest = "NoParse " ++ shows f rest @@ -59,7 +58,7 @@    {-# INLINABLE (<*>) #-}  instance Factorial.FactorialMonoid s => Alternative (Parser g s) where-   empty = Parser (\rest-> NoParse $ FailureInfo (Factorial.length rest) ["empty"])+   empty = Parser (\rest-> NoParse $ FailureInfo (Factorial.length rest) [Expected "empty"])    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator@@ -96,113 +95,112 @@    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)                where replaceFailure (NoParse (FailureInfo pos msgs)) =-                        NoParse (FailureInfo pos $ if pos == Factorial.length rest then [msg] else msgs)+                        NoParse (FailureInfo pos $ if pos == Factorial.length rest then [Expected msg] else msgs)                      replaceFailure parsed = parsed-   eof = endOfInput-   unexpected msg = Parser (\t-> NoParse $ FailureInfo (Factorial.length t) [msg])+   eof = Parser p+      where p rest+               | Null.null rest = Parsed () rest+               | otherwise = NoParse (FailureInfo (Factorial.length rest) [Expected "end of input"])+   unexpected msg = Parser (\t-> NoParse $ FailureInfo (Factorial.length t) [Expected msg])    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))-      where rewind t Parsed{} = NoParse (FailureInfo (Factorial.length t) ["notFollowedBy"])+      where rewind t Parsed{} = NoParse (FailureInfo (Factorial.length t) [Expected "notFollowedBy"])             rewind t NoParse{} = Parsed () t +-- | Every PEG parser is deterministic all the time.+instance FactorialMonoid s => DeterministicParsing (Parser g s) where+   (<<|>) = alt+   takeSome = some+   takeMany = many+   skipAll = skipMany+ instance Factorial.FactorialMonoid s => LookAheadParsing (Parser g s) where    lookAhead (Parser p) = Parser (\input-> rewind input (p input))       where rewind t (Parsed r _) = Parsed r t             rewind _ r@NoParse{} = r  instance (Show s, Textual.TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+   satisfy predicate = Parser p+      where p rest =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> Parsed first suffix+                  _ -> NoParse (FailureInfo (Factorial.length rest) [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--instance MonoidParsing (Parser g) where-   endOfInput = Parser p-      where p rest-               | Null.null rest = Parsed () rest-               | otherwise = NoParse (FailureInfo (Factorial.length rest) ["endOfInput"])+instance (Cancellative.LeftReductive s, FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p       where p rest = Parsed rest rest    anyToken = Parser p       where p rest = case Factorial.splitPrimePrefix rest                      of Just (first, suffix) -> Parsed first suffix-                        _ -> NoParse (FailureInfo (Factorial.length rest) ["anyToken"])+                        _ -> NoParse (FailureInfo (Factorial.length rest) [Expected "anyToken"])    satisfy predicate = Parser p       where p rest =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) | predicate first -> Parsed first suffix-                  _ -> NoParse (FailureInfo (Factorial.length rest) ["satisfy"])-   satisfyChar predicate = Parser p-      where p rest =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> Parsed first suffix-                  _ -> NoParse (FailureInfo (Factorial.length rest) ["satisfyChar"])-   satisfyCharInput predicate = Parser p-      where p rest =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> Parsed (Factorial.primePrefix rest) suffix-                  _ -> NoParse (FailureInfo (Factorial.length rest) ["satisfyChar"])+                  _ -> NoParse (FailureInfo (Factorial.length rest) [Expected "satisfy"])    notSatisfy predicate = Parser p       where p s = case Factorial.splitPrimePrefix s                   of Just (first, _) -                        | predicate first -> NoParse (FailureInfo (Factorial.length s) ["notSatisfy"])-                     _ -> Parsed () s-   notSatisfyChar predicate = Parser p-      where p s = case Textual.characterPrefix s-                  of Just first | predicate first -                                  -> NoParse (FailureInfo (Factorial.length s) ["notSatisfyChar"])+                        | predicate first -> NoParse (FailureInfo (Factorial.length s) [Expected "notSatisfy"])                      _ -> Parsed () s    scan s0 f = Parser (p s0)       where p s rest = Parsed prefix suffix                where (prefix, suffix, _) = Factorial.spanMaybe' s f rest-   scanChars s0 f = Parser (p s0)-      where p s rest = Parsed prefix suffix-               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest+   take n = Parser p+      where p rest+              | (prefix, suffix) <- Factorial.splitAt n rest, Factorial.length prefix == n = Parsed prefix suffix+              | otherwise = NoParse (FailureInfo (Factorial.length rest) [Expected $ "take " ++ show n])    takeWhile predicate = Parser p       where p rest | (prefix, suffix) <- Factorial.span predicate rest = Parsed prefix suffix    takeWhile1 predicate = Parser p       where p rest | (prefix, suffix) <- Factorial.span predicate rest =                         if Null.null prefix-                        then NoParse (FailureInfo (Factorial.length rest) ["takeWhile1"])+                        then NoParse (FailureInfo (Factorial.length rest) [Expected "takeWhile1"])                         else Parsed prefix suffix+   string s = Parser p where+      p s' | Just suffix <- Cancellative.stripPrefix s s' = Parsed s suffix+           | otherwise = NoParse (FailureInfo (Factorial.length s') [ExpectedInput s])+   {-# INLINABLE string #-}++instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p rest =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> Parsed (Factorial.primePrefix rest) suffix+                  _ -> NoParse (FailureInfo (Factorial.length rest) [Expected "satisfyCharInput"])+   notSatisfyChar predicate = Parser p+      where p s = case Textual.characterPrefix s+                  of Just first | predicate first +                                  -> NoParse (FailureInfo (Factorial.length s) [Expected "notSatisfyChar"])+                     _ -> Parsed () s+   scanChars s0 f = Parser (p s0)+      where p s rest = Parsed prefix suffix+               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest    takeCharsWhile predicate = Parser p       where p rest | (prefix, suffix) <- Textual.span_ False predicate rest = Parsed prefix suffix    takeCharsWhile1 predicate = Parser p       where p rest | (prefix, suffix) <- Textual.span_ False predicate rest =                      if Null.null prefix-                     then NoParse (FailureInfo (Factorial.length rest) ["takeCharsWhile1"])+                     then NoParse (FailureInfo (Factorial.length rest) [Expected "takeCharsWhile1"])                      else Parsed prefix suffix-   string s = Parser p where-      p s' | Just suffix <- Cancellative.stripPrefix s s' = Parsed s suffix-           | otherwise = NoParse (FailureInfo (Factorial.length s') ["string " ++ show s])-   concatMany (Parser p) = Parser q-      where q rest = case p rest-                     of Parsed prefix suffix -> let Parsed prefix' suffix' = q suffix-                                                in Parsed (mappend prefix prefix') suffix'-                        NoParse{} -> Parsed mempty rest-   {-# INLINABLE string #-}  -- | Backtracking PEG parser -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Backtrack.'Parser' g s) -> s -> g 'ParseResults'+--                  g (Backtrack.'Parser' g s) -> s -> g ('ParseResults' s) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = ParseResults+instance (Cancellative.LeftReductive s, Factorial.FactorialMonoid s) => MultiParsing (Parser g s) where+   type ResultFunctor (Parser g s) = ParseResults s    {-# NOINLINE parsePrefix #-}    -- | Returns an input prefix parse paired with the remaining input suffix.    parsePrefix g input = Rank2.fmap (Compose . fromResult input . (`applyParser` input)) g    parseComplete g input = Rank2.fmap ((snd <$>) . fromResult input . (`applyParser` input))-                                      (Rank2.fmap (<* endOfInput) g)+                                      (Rank2.fmap (<* eof) g) -fromResult :: FactorialMonoid s => s -> Result g s r -> ParseResults (s, r)+fromResult :: (Eq s, FactorialMonoid s) => s -> Result g s r -> ParseResults s (s, r) fromResult s (NoParse (FailureInfo pos msgs)) =    Left (ParseFailure (Factorial.length s - pos + 1) (nub msgs)) fromResult _ (Parsed prefix suffix) = Right (suffix, prefix)
src/Text/Grampa/PEG/Backtrack/Measured.hs view
@@ -14,10 +14,10 @@ import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString) -import qualified Data.Monoid.Cancellative as Cancellative import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Null as Null import qualified Data.Monoid.Textual as Textual+import qualified Data.Semigroup.Cancellative as Cancellative  import qualified Rank2 @@ -25,21 +25,20 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token-import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Grampa.Class (DeterministicParsing(..), InputParsing(..), InputCharParsing(..), ConsumedInputParsing(..),+                          MultiParsing(..), ParseResults, ParseFailure(..), Expected(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedLength :: !Int,                                               parsedResult :: !v,                                               parsedSuffix :: !s}-                                     | NoParse FailureInfo+                                     | NoParse (FailureInfo s)  -- | Parser type for Parsing Expression Grammars that uses a backtracking algorithm, fast for grammars in LL(1) class -- but with potentially exponential performance for longer ambiguous prefixes. newtype Parser g s r = Parser{applyParser :: s -> Result g s r} -instance Show1 (Result g s) where+instance Show s => Show1 (Result g s) where    liftShowsPrec showsPrecSub _showList prec Parsed{parsedResult= r} rest = "Parsed " ++ showsPrecSub prec r rest    liftShowsPrec _showsPrec _showList _prec (NoParse f) rest = "NoParse " ++ shows f rest @@ -61,8 +60,8 @@                   NoParse failure -> NoParse failure    {-# INLINABLE (<*>) #-} -instance Factorial.FactorialMonoid s => Alternative (Parser g s) where-   empty = Parser (\rest-> NoParse $ FailureInfo (Factorial.length rest) ["empty"])+instance FactorialMonoid s => Alternative (Parser g s) where+   empty = Parser (\rest-> NoParse $ FailureInfo (Factorial.length rest) [Expected "empty"])    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator@@ -81,7 +80,7 @@                                          NoParse failure -> NoParse failure                   NoParse failure -> NoParse failure -instance Factorial.FactorialMonoid s => MonadPlus (Parser g s) where+instance FactorialMonoid s => MonadPlus (Parser g s) where    mzero = empty    mplus = (<|>) @@ -92,7 +91,7 @@    mempty = pure mempty    mappend = liftA2 mappend -instance Factorial.FactorialMonoid s => Parsing (Parser g s) where+instance FactorialMonoid s => Parsing (Parser g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)                where rewindFailure (NoParse (FailureInfo _pos _msgs)) =@@ -101,116 +100,121 @@    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)                where replaceFailure (NoParse (FailureInfo pos msgs)) =-                        NoParse (FailureInfo pos $ if pos == Factorial.length rest then [msg] else msgs)+                        NoParse (FailureInfo pos $ if pos == Factorial.length rest then [Expected msg] else msgs)                      replaceFailure parsed = parsed-   eof = endOfInput-   unexpected msg = Parser (\t-> NoParse $ FailureInfo (Factorial.length t) [msg])+   eof = Parser p+      where p rest+               | Null.null rest = Parsed 0 () rest+               | otherwise = NoParse (FailureInfo (Factorial.length rest) [Expected "end of input"])+   unexpected msg = Parser (\t-> NoParse $ FailureInfo (Factorial.length t) [Expected msg])    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))-      where rewind t Parsed{} = NoParse (FailureInfo (Factorial.length t) ["notFollowedBy"])+      where rewind t Parsed{} = NoParse (FailureInfo (Factorial.length t) [Expected "notFollowedBy"])             rewind t NoParse{} = Parsed 0 () t -instance Factorial.FactorialMonoid s => LookAheadParsing (Parser g s) where+-- | Every PEG parser is deterministic all the time.+instance FactorialMonoid s => DeterministicParsing (Parser g s) where+   (<<|>) = alt+   takeSome = some+   takeMany = many+   skipAll = skipMany++instance FactorialMonoid s => LookAheadParsing (Parser g s) where    lookAhead (Parser p) = Parser (\input-> rewind input (p input))       where rewind t (Parsed _ r _) = Parsed 0 r t             rewind _ r@NoParse{} = r  instance (Show s, Textual.TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+   satisfy predicate = Parser p+      where p rest =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> Parsed 1 first suffix+                  _ -> NoParse (FailureInfo (Factorial.length rest) [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--instance MonoidParsing (Parser g) where-   endOfInput = Parser p-      where p rest-               | Null.null rest = Parsed 0 () rest-               | otherwise = NoParse (FailureInfo (Factorial.length rest) ["endOfInput"])+instance (Cancellative.LeftReductive s, FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p       where p rest = Parsed 0 rest rest    anyToken = Parser p       where p rest = case Factorial.splitPrimePrefix rest                      of Just (first, suffix) -> Parsed 1 first suffix-                        _ -> NoParse (FailureInfo (Factorial.length rest) ["anyToken"])+                        _ -> NoParse (FailureInfo (Factorial.length rest) [Expected "anyToken"])    satisfy predicate = Parser p       where p rest =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) | predicate first -> Parsed 1 first suffix-                  _ -> NoParse (FailureInfo (Factorial.length rest) ["satisfy"])-   satisfyChar predicate = Parser p-      where p rest =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> Parsed 1 first suffix-                  _ -> NoParse (FailureInfo (Factorial.length rest) ["satisfyChar"])-   satisfyCharInput predicate = Parser p-      where p rest =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> Parsed 1 (Factorial.primePrefix rest) suffix-                  _ -> NoParse (FailureInfo (Factorial.length rest) ["satisfyChar"])+                  _ -> NoParse (FailureInfo (Factorial.length rest) [Expected "satisfy"])    notSatisfy predicate = Parser p       where p s = case Factorial.splitPrimePrefix s                   of Just (first, _) -                        | predicate first -> NoParse (FailureInfo (Factorial.length s) ["notSatisfy"])-                     _ -> Parsed 0 () s-   notSatisfyChar predicate = Parser p-      where p s = case Textual.characterPrefix s-                  of Just first | predicate first -                                  -> NoParse (FailureInfo (Factorial.length s) ["notSatisfyChar"])+                        | predicate first -> NoParse (FailureInfo (Factorial.length s) [Expected "notSatisfy"])                      _ -> Parsed 0 () s    scan s0 f = Parser (p s0)       where p s rest = Parsed (Factorial.length prefix) prefix suffix                where (prefix, suffix, _) = Factorial.spanMaybe' s f rest-   scanChars s0 f = Parser (p s0)-      where p s rest = Parsed (Factorial.length prefix) prefix suffix-               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest+   take n = Parser p+      where p rest+              | (prefix, suffix) <- Factorial.splitAt n rest, Factorial.length prefix == n = Parsed n prefix suffix+              | otherwise = NoParse (FailureInfo (Factorial.length rest) [Expected $ "take " ++ show n])    takeWhile predicate = Parser p       where p rest | (prefix, suffix) <- Factorial.span predicate rest =                Parsed (Factorial.length prefix) prefix suffix    takeWhile1 predicate = Parser p       where p rest | (prefix, suffix) <- Factorial.span predicate rest =                         if Null.null prefix-                        then NoParse (FailureInfo (Factorial.length rest) ["takeWhile1"])+                        then NoParse (FailureInfo (Factorial.length rest) [Expected "takeWhile1"])                         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 (FailureInfo (Factorial.length s') [ExpectedInput s])+      l = Factorial.length s+   {-# INLINABLE string #-}++instance (Cancellative.LeftReductive s, FactorialMonoid s) => ConsumedInputParsing (Parser g s) where+   match (Parser p) = Parser q+      where q rest = case p rest+                     of Parsed l prefix suffix -> Parsed l (Factorial.take l rest, prefix) suffix+                        NoParse failure -> NoParse failure++instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p rest =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> Parsed 1 (Factorial.primePrefix rest) suffix+                  _ -> NoParse (FailureInfo (Factorial.length rest) [Expected "satisfyChar"])+   notSatisfyChar predicate = Parser p+      where p s = case Textual.characterPrefix s+                  of Just first | predicate first +                                  -> NoParse (FailureInfo (Factorial.length s) [Expected "notSatisfyChar"])+                     _ -> Parsed 0 () s+   scanChars s0 f = Parser (p s0)+      where p s rest = Parsed (Factorial.length prefix) prefix suffix+               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest    takeCharsWhile predicate = Parser p       where p rest | (prefix, suffix) <- Textual.span_ False predicate rest =                 Parsed (Factorial.length prefix) prefix suffix    takeCharsWhile1 predicate = Parser p       where p rest | (prefix, suffix) <- Textual.span_ False predicate rest =                      if Null.null prefix-                     then NoParse (FailureInfo (Factorial.length rest) ["takeCharsWhile1"])+                     then NoParse (FailureInfo (Factorial.length rest) [Expected "takeCharsWhile1"])                      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 (FailureInfo (Factorial.length s') ["string " ++ show s])-      l = Factorial.length s-   concatMany (Parser p) = Parser q-      where q rest = case p rest-                     of Parsed l prefix suffix -> let Parsed l' prefix' suffix' = q suffix-                                                  in Parsed (l+l') (mappend prefix prefix') suffix'-                        NoParse{} -> Parsed 0 mempty rest-   {-# INLINABLE string #-}  -- | Backtracking PEG parser -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Backtrack.'Parser' g s) -> s -> g 'ParseResults'+--                  g (Backtrack.'Parser' g s) -> s -> g ('ParseResults' s) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = ParseResults+instance (Cancellative.LeftReductive s, Factorial.FactorialMonoid s) => MultiParsing (Parser g s) where+   type ResultFunctor (Parser g s) = ParseResults s    {-# NOINLINE parsePrefix #-}    -- | Returns an input prefix parse paired with the remaining input suffix.    parsePrefix g input = Rank2.fmap (Compose . fromResult input . (`applyParser` input)) g    parseComplete g input = Rank2.fmap ((snd <$>) . fromResult input . (`applyParser` input))-                                      (Rank2.fmap (<* endOfInput) g)+                                      (Rank2.fmap (<* eof) g) -fromResult :: FactorialMonoid s => s -> Result g s r -> ParseResults (s, r)+fromResult :: (Eq s, FactorialMonoid s) => s -> Result g s r -> ParseResults s (s, r) fromResult s (NoParse (FailureInfo pos msgs)) =    Left (ParseFailure (Factorial.length s - pos + 1) (nub msgs)) fromResult _ (Parsed _ prefix suffix) = Right (suffix, prefix)
src/Text/Grampa/PEG/Continued.hs view
@@ -8,13 +8,13 @@ import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (nub)-import Data.Semigroup (Semigroup(..))+import Data.Semigroup (Semigroup((<>)))+import Data.Semigroup.Cancellative (LeftReductive(stripPrefix)) import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Factorial(FactorialMonoid) import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString) -import qualified Data.Monoid.Cancellative as Cancellative import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Null as Null import qualified Data.Monoid.Textual as Textual@@ -25,21 +25,20 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token-import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Grampa.Class (DeterministicParsing(..), InputParsing(..), InputCharParsing(..), MultiParsing(..),+                          ParseResults, ParseFailure(..), Expected(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,                                               parsedSuffix :: !s}-                                     | NoParse FailureInfo+                                     | NoParse (FailureInfo 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. newtype Parser (g :: (* -> *) -> *) s r =-   Parser{applyParser :: forall x. s -> (r -> s -> x) -> (FailureInfo -> x) -> x}+   Parser{applyParser :: forall x. s -> (r -> s -> x) -> (FailureInfo s -> x) -> x} -instance Show1 (Result g s) where+instance Show s => Show1 (Result g s) where    liftShowsPrec showsPrecSub _showList prec Parsed{parsedPrefix= r} rest = "Parsed " ++ showsPrecSub prec r rest    liftShowsPrec _showsPrec _showList _prec (NoParse f) rest = "NoParse " ++ shows f rest @@ -55,28 +54,28 @@    pure a = Parser (\input success _-> success a input)    (<*>) :: forall a b. Parser g s (a -> b) -> Parser g s a -> Parser g s b    Parser p <*> Parser q = Parser r where-      r :: forall x. s -> (b -> s -> x) -> (FailureInfo -> x) -> x+      r :: forall x. s -> (b -> s -> x) -> (FailureInfo s -> x) -> x       r rest success failure = p rest (\f rest'-> q rest' (success . f) failure) failure    {-# INLINABLE (<*>) #-} -instance Factorial.FactorialMonoid s => Alternative (Parser g s) where-   empty = Parser (\rest _ failure-> failure $ FailureInfo (Factorial.length rest) ["empty"])+instance FactorialMonoid s => Alternative (Parser g s) where+   empty = Parser (\rest _ failure-> failure $ FailureInfo (Factorial.length rest) [Expected "empty"])    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator alt :: forall g s a. Parser g s a -> Parser g s a -> Parser g s a Parser p `alt` Parser q = Parser r where-   r :: forall x. s -> (a -> s -> x) -> (FailureInfo -> x) -> x+   r :: forall x. s -> (a -> s -> x) -> (FailureInfo s -> x) -> x    r rest success failure = p rest success (\f1-> q rest success $ \f2 -> failure (f1 <> f2))  instance Monad (Parser g s) where    return = pure    (>>=) :: forall a b. Parser g s a -> (a -> Parser g s b) -> Parser g s b    Parser p >>= f = Parser r where-      r :: forall x. s -> (b -> s -> x) -> (FailureInfo -> x) -> x+      r :: forall x. s -> (b -> s -> x) -> (FailureInfo s -> x) -> x       r rest success failure = p rest (\a rest'-> applyParser (f a) rest' success failure) failure -instance Factorial.FactorialMonoid s => MonadPlus (Parser g s) where+instance FactorialMonoid s => MonadPlus (Parser g s) where    mzero = empty    mplus = (<|>) @@ -87,155 +86,144 @@    mempty = pure mempty    mappend = liftA2 mappend -instance Factorial.FactorialMonoid s => Parsing (Parser g s) where+instance FactorialMonoid s => Parsing (Parser g s) where    try :: forall a. Parser g s a -> Parser g s a    try (Parser p) = Parser q-      where q :: forall x. s -> (a -> s -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> s -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success (failure . rewindFailure)                where rewindFailure (FailureInfo _pos _msgs) = FailureInfo (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) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> s -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success (failure . replaceFailure)                where replaceFailure (FailureInfo pos msgs) =-                        FailureInfo pos (if pos == Factorial.length input then [msg] else msgs)-   eof = endOfInput-   unexpected msg = Parser (\t _ failure -> failure $ FailureInfo (Factorial.length t) [msg])+                        FailureInfo pos (if pos == Factorial.length input then [Expected msg] else msgs)+   eof = Parser p+      where p rest success failure+               | Null.null rest = success () rest+               | otherwise = failure (FailureInfo (Factorial.length rest) [Expected "end of input"])+   unexpected msg = Parser (\t _ failure -> failure $ FailureInfo (Factorial.length t) [Expected msg])    notFollowedBy (Parser p) = Parser q-      where q :: forall x. s -> (() -> s -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (() -> s -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success' failure'-               where success' _ _ = failure (FailureInfo (Factorial.length input) ["notFollowedBy"])+               where success' _ _ = failure (FailureInfo (Factorial.length input) [Expected "notFollowedBy"])                      failure' _ = success () input -instance Factorial.FactorialMonoid s => LookAheadParsing (Parser g s) where+-- | Every PEG parser is deterministic all the time.+instance FactorialMonoid s => DeterministicParsing (Parser g s) where+   (<<|>) = alt+   takeSome = some+   takeMany = many+   skipAll = skipMany++instance FactorialMonoid s => LookAheadParsing (Parser g s) where    lookAhead :: forall a. Parser g s a -> Parser g s a    lookAhead (Parser p) = Parser q-      where q :: forall x. s -> (a -> s -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> s -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success' failure'                where success' a _ = success a input                      failure' f = failure f  instance (Show s, TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+   satisfy predicate = Parser p+      where p :: forall x. s -> (Char -> s -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> success first suffix+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--instance MonoidParsing (Parser g) where-   endOfInput = Parser p-      where p rest success failure-               | Null.null rest = success () rest-               | otherwise = failure (FailureInfo (Factorial.length rest) ["endOfInput"])+instance (LeftReductive s, FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p       where p rest success _ = success rest rest    anyToken = Parser p       where p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) -> success first suffix-                  _ -> failure (FailureInfo (Factorial.length rest) ["anyToken"])-   satisfy :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "anyToken"])    satisfy predicate = Parser p-      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo s -> x) -> x             p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) | predicate first -> success first suffix-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfy"])-   satisfyChar :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s Char-   satisfyChar predicate = Parser p-      where p :: forall x. s -> (Char -> s -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> success first suffix-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfyChar"])-   satisfyCharInput :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s-   satisfyCharInput predicate = Parser p-      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> success (Factorial.primePrefix rest) suffix-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfyChar"])-   notSatisfy :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s ()+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "satisfy"])    notSatisfy predicate = Parser p-      where p :: forall x. s -> (() -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (() -> s -> x) -> (FailureInfo s -> x) -> x             p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, _)-                     | predicate first -> failure (FailureInfo (Factorial.length rest) ["notSatisfy"])-                  _ -> success () rest-   notSatisfyChar :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s ()-   notSatisfyChar predicate = Parser p-      where p :: forall x. s -> (() -> s -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.characterPrefix rest-               of Just first | predicate first-                               -> failure (FailureInfo (Factorial.length rest) ["notSatisfyChar"])+                     | predicate first -> failure (FailureInfo (Factorial.length rest) [Expected "notSatisfy"])                   _ -> success () rest-   scan :: forall t s. FactorialMonoid t => s -> (s -> t -> Maybe s) -> Parser g t t+   scan :: forall state. state -> (state -> s -> Maybe state) -> Parser g s s    scan s0 f = Parser (p s0)-      where p :: forall x. s -> t -> (t -> t -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. state -> s -> (s -> s -> x) -> (FailureInfo s -> x) -> x             p s rest success _ = success prefix suffix                where (prefix, suffix, _) = Factorial.spanMaybe' s f rest-   scanChars :: forall t s. TextualMonoid t => s -> (s -> Char -> Maybe s) -> Parser g t t-   scanChars s0 f = Parser (p s0)-      where p :: forall x. s -> t -> (t -> t -> x) -> (FailureInfo -> x) -> x-            p s rest success _ = success prefix suffix-               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest-   takeWhile :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s+   take n = Parser p+      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo s -> x) -> x+            p rest success _+               | (prefix, suffix) <- Factorial.splitAt n rest, Factorial.length prefix == n = success prefix suffix+            p rest _ failure = failure (FailureInfo (Factorial.length rest) [Expected $ "take" ++ show n])    takeWhile predicate = Parser p-      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo s -> x) -> x             p rest success _ | (prefix, suffix) <- Factorial.span predicate rest = success prefix suffix-   takeWhile1 :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s    takeWhile1 predicate = Parser p-      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo s -> x) -> x             p rest success failure                | (prefix, suffix) <- Factorial.span predicate rest =                     if Null.null prefix-                    then failure (FailureInfo (Factorial.length rest) ["takeWhile1"])+                    then failure (FailureInfo (Factorial.length rest) [Expected "takeWhile1"])                     else success prefix suffix-   takeCharsWhile :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s+   string s = Parser p where+      p :: forall x. s -> (s -> s -> x) -> (FailureInfo s -> x) -> x+      p s' success failure+         | Just suffix <- stripPrefix s s' = success s suffix+         | otherwise = failure (FailureInfo (Factorial.length s') [ExpectedInput s])+   {-# INLINABLE string #-}++instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> success (Factorial.primePrefix rest) suffix+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "satisfyChar"])+   notSatisfyChar predicate = Parser p+      where p :: forall x. s -> (() -> s -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.characterPrefix rest+               of Just first | predicate first+                               -> failure (FailureInfo (Factorial.length rest) [Expected "notSatisfyChar"])+                  _ -> success () rest+   scanChars :: forall state. state -> (state -> Char -> Maybe state) -> Parser g s s+   scanChars s0 f = Parser (p s0)+      where p :: forall x. state -> s -> (s -> s -> x) -> (FailureInfo s -> x) -> x+            p s rest success _ = success prefix suffix+               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest    takeCharsWhile predicate = Parser p-      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo s -> x) -> x             p rest success _ | (prefix, suffix) <- Textual.span_ False predicate rest = success prefix suffix-   takeCharsWhile1 :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s    takeCharsWhile1 predicate = Parser p-      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> s -> x) -> (FailureInfo s -> x) -> x             p rest success failure-               | Null.null prefix = failure (FailureInfo (Factorial.length rest) ["takeCharsWhile1"])+               | Null.null prefix = failure (FailureInfo (Factorial.length rest) [Expected "takeCharsWhile1"])                | otherwise = success prefix suffix                where (prefix, suffix) = Textual.span_ False predicate rest-   string :: forall s. (Cancellative.LeftReductiveMonoid s, FactorialMonoid s, Show s) => s -> Parser g s s-   string s = Parser p where-      p :: forall x. s -> (s -> s -> x) -> (FailureInfo -> x) -> x-      p s' success failure-         | Just suffix <- Cancellative.stripPrefix s s' = success s suffix-         | otherwise = failure (FailureInfo (Factorial.length s') ["string " ++ show s])-   concatMany :: forall s a. Monoid a => Parser g s a -> Parser g s a-   concatMany (Parser p) = Parser q-      where q :: forall x. s -> (a -> s -> x) -> (FailureInfo -> x) -> x-            q rest success _ = p rest success' failure-               where success' prefix suffix = q suffix (success . mappend prefix) (const $ success prefix suffix)-                     failure _ = success mempty rest-   {-# INLINABLE string #-}  -- | Continuation-passing PEG parser -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Continued.'Parser' g s) -> s -> g 'ParseResults'+--                  g (Continued.'Parser' g s) -> s -> g ('ParseResults' s) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = ParseResults+instance (LeftReductive s, FactorialMonoid s) => MultiParsing (Parser g s) where+   type ResultFunctor (Parser g s) = ParseResults s    -- | Returns an input prefix parse paired with the remaining input suffix.    parsePrefix g input = Rank2.fmap (Compose . (\p-> applyParser p input (flip $ curry Right) (Left . fromFailure input))) g    parseComplete g input = Rank2.fmap (\p-> applyParser p input (const . Right) (Left . fromFailure input))-                                      (Rank2.fmap (<* endOfInput) g)+                                      (Rank2.fmap (<* eof) g) -fromFailure :: FactorialMonoid s => s -> FailureInfo -> ParseFailure+fromFailure :: (Eq s, FactorialMonoid s) => s -> FailureInfo s -> ParseFailure s fromFailure s (FailureInfo pos msgs) = ParseFailure (Factorial.length s - pos + 1) (nub msgs)
src/Text/Grampa/PEG/Continued/Measured.hs view
@@ -14,33 +14,32 @@ import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString) -import qualified Data.Monoid.Cancellative as Cancellative+import Data.Semigroup.Cancellative (LeftReductive(stripPrefix)) import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Null as Null import qualified Data.Monoid.Textual as Textual  import qualified Rank2 -import qualified Text.Parser.Char+import qualified Text.Parser.Char as Char import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token-import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Grampa.Class (DeterministicParsing(..), InputParsing(..), InputCharParsing(..), ConsumedInputParsing(..),+                          MultiParsing(..), ParseResults, ParseFailure(..), Expected(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,                                               parsedSuffix :: !s}-                                     | NoParse FailureInfo+                                     | NoParse (FailureInfo s)  -- | Parser type for Parsing Expression Grammars that uses a continuation-passing algorithm and keeps track of the -- parsed prefix length, fast for grammars in LL(1) class but with potentially exponential performance for longer -- ambiguous prefixes. newtype Parser (g :: (* -> *) -> *) s r =-   Parser{applyParser :: forall x. s -> (r -> Int -> s -> x) -> (FailureInfo -> x) -> x}+   Parser{applyParser :: forall x. s -> (r -> Int -> s -> x) -> (FailureInfo s -> x) -> x} -instance Show1 (Result g s) where+instance Show s => Show1 (Result g s) where    liftShowsPrec showsPrecSub _showList prec Parsed{parsedPrefix= r} rest = "Parsed " ++ showsPrecSub prec r rest    liftShowsPrec _showsPrec _showList _prec (NoParse f) rest = "NoParse " ++ shows f rest @@ -56,30 +55,30 @@    pure a = Parser (\input success _-> success a 0 input)    (<*>) :: forall a b. Parser g s (a -> b) -> Parser g s a -> Parser g s b    Parser p <*> Parser q = Parser r where-      r :: forall x. s -> (b -> Int -> s -> x) -> (FailureInfo -> x) -> x+      r :: forall x. s -> (b -> Int -> s -> x) -> (FailureInfo s -> x) -> x       r rest success failure = p rest (\f len rest'-> q rest' (\a len'-> success (f a) $! len + len') failure) failure    {-# INLINABLE (<*>) #-} -instance Factorial.FactorialMonoid s => Alternative (Parser g s) where-   empty = Parser (\rest _ failure-> failure $ FailureInfo (Factorial.length rest) ["empty"])+instance FactorialMonoid s => Alternative (Parser g s) where+   empty = Parser (\rest _ failure-> failure $ FailureInfo (Factorial.length rest) [Expected "empty"])    (<|>) = alt  -- | A named and unconstrained version of the '<|>' operator alt :: forall g s a. Parser g s a -> Parser g s a -> Parser g s a Parser p `alt` Parser q = Parser r where-   r :: forall x. s -> (a -> Int -> s -> x) -> (FailureInfo -> x) -> x+   r :: forall x. s -> (a -> Int -> s -> x) -> (FailureInfo s -> x) -> x    r rest success failure = p rest success (\f1-> q rest success $ \f2 -> failure (f1 <> f2))  instance Monad (Parser g s) where    return = pure    (>>=) :: forall a b. Parser g s a -> (a -> Parser g s b) -> Parser g s b    Parser p >>= f = Parser r where-      r :: forall x. s -> (b -> Int -> s -> x) -> (FailureInfo -> x) -> x+      r :: forall x. s -> (b -> Int -> s -> x) -> (FailureInfo s -> x) -> x       r rest success failure = p rest                                   (\a len rest'-> applyParser (f a) rest' (\b len'-> success b $! len + len') failure)                                  failure -instance Factorial.FactorialMonoid s => MonadPlus (Parser g s) where+instance FactorialMonoid s => MonadPlus (Parser g s) where    mzero = empty    mplus = (<|>) @@ -90,166 +89,161 @@    mempty = pure mempty    mappend = liftA2 mappend -instance Factorial.FactorialMonoid s => Parsing (Parser g s) where+instance FactorialMonoid s => Parsing (Parser g s) where    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) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> Int -> s -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success (failure . rewindFailure)                where rewindFailure (FailureInfo _pos _msgs) = FailureInfo (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) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> Int -> s -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success (failure . replaceFailure)                where replaceFailure (FailureInfo pos msgs) =-                        FailureInfo pos (if pos == Factorial.length input then [msg] else msgs)-   eof = endOfInput-   unexpected msg = Parser (\t _ failure -> failure $ FailureInfo (Factorial.length t) [msg])+                        FailureInfo pos (if pos == Factorial.length input then [Expected msg] else msgs)+   eof = Parser p+      where p rest success failure+               | Null.null rest = success () 0 rest+               | otherwise = failure (FailureInfo (Factorial.length rest) [Expected "end of input"])+   unexpected msg = Parser (\t _ failure -> failure $ FailureInfo (Factorial.length t) [Expected msg])    notFollowedBy (Parser p) = Parser q-      where q :: forall x. s -> (() -> Int -> s -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (() -> Int -> s -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success' failure'-               where success' _ _ _ = failure (FailureInfo (Factorial.length input) ["notFollowedBy"])+               where success' _ _ _ = failure (FailureInfo (Factorial.length input) [Expected "notFollowedBy"])                      failure' _ = success () 0 input -instance Factorial.FactorialMonoid s => LookAheadParsing (Parser g s) where+-- | Every PEG parser is deterministic all the time.+instance FactorialMonoid s => DeterministicParsing (Parser g s) where+   (<<|>) = alt+   takeSome = some+   takeMany = many+   skipAll = skipMany++instance FactorialMonoid s => LookAheadParsing (Parser g s) where    lookAhead :: forall a. Parser g s a -> Parser g s a    lookAhead (Parser p) = Parser q-      where q :: forall x. s -> (a -> Int -> s -> x) -> (FailureInfo -> x) -> x+      where q :: forall x. s -> (a -> Int -> s -> x) -> (FailureInfo s -> x) -> x             q input success failure = p input success' failure'                where success' a _ _ = success a 0 input                      failure' f = failure f  instance (Show s, TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+   satisfy predicate = Parser p+      where p :: forall x. s -> (Char -> Int -> s -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> success first 1 suffix+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--instance MonoidParsing (Parser g) where-   endOfInput = Parser p-      where p rest success failure-               | Null.null rest = success () 0 rest-               | otherwise = failure (FailureInfo (Factorial.length rest) ["endOfInput"])+instance (LeftReductive s, FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p       where p rest success _ = success rest 0 rest    anyToken = Parser p       where p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) -> success first 1 suffix-                  _ -> failure (FailureInfo (Factorial.length rest) ["anyToken"])-   satisfy :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "anyToken"])    satisfy predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x             p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, suffix) | predicate first -> success first 1 suffix-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfy"])-   satisfyChar :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s Char-   satisfyChar predicate = Parser p-      where p :: forall x. s -> (Char -> Int -> s -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> success first 1 suffix-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfyChar"])-   satisfyCharInput :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s-   satisfyCharInput predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.splitCharacterPrefix rest-               of Just (first, suffix) | predicate first -> success (Factorial.primePrefix rest) 1 suffix-                  _ -> failure (FailureInfo (Factorial.length rest) ["satisfyChar"])-   notSatisfy :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s ()+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "satisfy"])    notSatisfy predicate = Parser p-      where p :: forall x. s -> (() -> Int -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (() -> Int -> s -> x) -> (FailureInfo s -> x) -> x             p rest success failure =                case Factorial.splitPrimePrefix rest                of Just (first, _)-                     | predicate first -> failure (FailureInfo (Factorial.length rest) ["notSatisfy"])-                  _ -> success () 0 rest-   notSatisfyChar :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s ()-   notSatisfyChar predicate = Parser p-      where p :: forall x. s -> (() -> Int -> s -> x) -> (FailureInfo -> x) -> x-            p rest success failure =-               case Textual.characterPrefix rest-               of Just first | predicate first-                               -> failure (FailureInfo (Factorial.length rest) ["notSatisfyChar"])+                     | predicate first -> failure (FailureInfo (Factorial.length rest) [Expected "notSatisfy"])                   _ -> success () 0 rest-   scan :: forall t s. FactorialMonoid t => s -> (s -> t -> Maybe s) -> Parser g t t+   scan :: forall state. state -> (state -> s -> Maybe state) -> Parser g s s    scan s0 f = Parser (p s0)-      where p :: forall x. s -> t -> (t -> Int -> t -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. state -> s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x             p s rest success _ = success prefix len suffix                where (prefix, suffix, _) = Factorial.spanMaybe' s f rest                      !len = Factorial.length prefix-   scanChars :: forall t s. TextualMonoid t => s -> (s -> Char -> Maybe s) -> Parser g t t-   scanChars s0 f = Parser (p s0)-      where p :: forall x. s -> t -> (t -> Int -> t -> x) -> (FailureInfo -> x) -> x-            p s rest success _ = success prefix len suffix-               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest-                     !len = Factorial.length prefix-   takeWhile :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s+   take n = Parser p+      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x+            p rest success _+               | (prefix, suffix) <- Factorial.splitAt n rest,+                 len <- Factorial.length prefix, len == n = success prefix len suffix+            p rest _ failure = failure (FailureInfo (Factorial.length rest) [Expected $ "take" ++ show n])    takeWhile predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x             p rest success _                 | (prefix, suffix) <- Factorial.span predicate rest,                   !len <- Factorial.length prefix = success prefix len suffix-   takeWhile1 :: forall s. FactorialMonoid s => (s -> Bool) -> Parser g s s    takeWhile1 predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x             p rest success failure                | (prefix, suffix) <- Factorial.span predicate rest,                   !len <- Factorial.length prefix =                     if len == 0-                    then failure (FailureInfo (Factorial.length rest) ["takeWhile1"])+                    then failure (FailureInfo (Factorial.length rest) [Expected "takeWhile1"])                     else success prefix len suffix-   takeCharsWhile :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s+   string s = Parser p where+      p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x+      p s' success failure+         | Just suffix <- stripPrefix s s', !len <- Factorial.length s = success s len suffix+         | otherwise = failure (FailureInfo (Factorial.length s') [ExpectedInput s])+   {-# INLINABLE string #-}++instance (LeftReductive s, FactorialMonoid s) => ConsumedInputParsing (Parser g s) where+   match :: forall a. Parser g s a -> Parser g s (s, a)+   match (Parser p) = Parser q+      where q :: forall x. s -> ((s, a) -> Int -> s -> x) -> (FailureInfo s -> x) -> x+            q rest success failure = p rest success' failure+               where success' r !len suffix = success (Factorial.take len rest, r) len suffix++instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.splitCharacterPrefix rest+               of Just (first, suffix) | predicate first -> success (Factorial.primePrefix rest) 1 suffix+                  _ -> failure (FailureInfo (Factorial.length rest) [Expected "satisfyCharInput"])+   notSatisfyChar predicate = Parser p+      where p :: forall x. s -> (() -> Int -> s -> x) -> (FailureInfo s -> x) -> x+            p rest success failure =+               case Textual.characterPrefix rest+               of Just first | predicate first+                               -> failure (FailureInfo (Factorial.length rest) [Expected "notSatisfyChar"])+                  _ -> success () 0 rest+   scanChars :: forall state. state -> (state -> Char -> Maybe state) -> Parser g s s+   scanChars s0 f = Parser (p s0)+      where p :: forall x. state -> s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x+            p s rest success _ = success prefix len suffix+               where (prefix, suffix, _) = Textual.spanMaybe_' s f rest+                     !len = Factorial.length prefix    takeCharsWhile predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo -> x) -> x-            p rest success _ +      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x+            p rest success _                | (prefix, suffix) <- Textual.span_ False predicate rest,                   !len <- Factorial.length prefix = success prefix len suffix-   takeCharsWhile1 :: forall s. TextualMonoid s => (Char -> Bool) -> Parser g s s    takeCharsWhile1 predicate = Parser p-      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo -> x) -> x+      where p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo s -> x) -> x             p rest success failure-               | Null.null prefix = failure (FailureInfo (Factorial.length rest) ["takeCharsWhile1"])+               | Null.null prefix = failure (FailureInfo (Factorial.length rest) [Expected "takeCharsWhile1"])                | otherwise = success prefix len suffix                where (prefix, suffix) = Textual.span_ False predicate rest                      !len = Factorial.length prefix-   string :: forall s. (Cancellative.LeftReductiveMonoid s, FactorialMonoid s, Show s) => s -> Parser g s s-   string s = Parser p where-      p :: forall x. s -> (s -> Int -> s -> x) -> (FailureInfo -> x) -> x-      p s' success failure-         | Just suffix <- Cancellative.stripPrefix s s', !len <- Factorial.length s = success s len suffix-         | otherwise = failure (FailureInfo (Factorial.length s') ["string " ++ show s])-   concatMany :: forall s a. Monoid a => Parser g s a -> Parser g s a-   concatMany (Parser p) = Parser q-      where q :: forall x. s -> (a -> Int -> s -> x) -> (FailureInfo -> x) -> x-            q rest success _ = p rest success' failure-               where success' prefix !len suffix = -                        q suffix (\prefix' !len'-> success (mappend prefix prefix') (len + len')) -                          (const $ success prefix len suffix)-                     failure _ = success mempty 0 rest-   {-# INLINABLE string #-}  -- | Continuation-passing PEG parser that keeps track of the parsed prefix length -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Continued.'Parser' g s) -> s -> g 'ParseResults'+--                  g (Continued.'Parser' g s) -> s -> g ('ParseResults' s) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = ParseResults+instance (LeftReductive s, FactorialMonoid s) => MultiParsing (Parser g s) where+   type ResultFunctor (Parser g s) = ParseResults s    -- | Returns an input prefix parse paired with the remaining input suffix.    parsePrefix g input = Rank2.fmap (Compose . (\p-> applyParser p input (\a _ rest-> Right (rest, a))                                                                   (Left . fromFailure input))) g    parseComplete g input = Rank2.fmap (\p-> applyParser p input (const . const . Right) (Left . fromFailure input))-                                      (Rank2.fmap (<* endOfInput) g)+                                      (Rank2.fmap (<* eof) g) -fromFailure :: FactorialMonoid s => s -> FailureInfo -> ParseFailure+fromFailure :: (Eq s, FactorialMonoid s) => s -> FailureInfo s -> ParseFailure s fromFailure s (FailureInfo pos msgs) = ParseFailure (Factorial.length s - pos + 1) (nub msgs)
src/Text/Grampa/PEG/Packrat.hs view
@@ -8,13 +8,13 @@ import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (genericLength, nub)-import Data.Semigroup (Semigroup(..)) import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Factorial(FactorialMonoid) import Data.Monoid.Textual(TextualMonoid)+import Data.Semigroup (Semigroup(..))+import Data.Semigroup.Cancellative (LeftReductive(isPrefixOf)) import Data.String (fromString) -import qualified Data.Monoid.Cancellative as Cancellative import qualified Data.Monoid.Factorial as Factorial import qualified Data.Monoid.Null as Null import qualified Data.Monoid.Textual as Textual@@ -25,22 +25,21 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing)-import qualified Text.Parser.Token-import Text.Grampa.Class (Lexical(..), GrammarParsing(..), MonoidParsing(..), MultiParsing(..), -                          ParseResults, ParseFailure(..))+import Text.Grampa.Class (DeterministicParsing(..), InputParsing(..), InputCharParsing(..),+                          GrammarParsing(..), MultiParsing(..),+                          TailsParsing(parseTails), ParseResults, ParseFailure(..), Expected(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result g s v = Parsed{parsedPrefix :: !v,                             parsedSuffix :: ![(s, g (Result g s))]}-                  | NoParse FailureInfo+                  | NoParse (FailureInfo 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 -- 'parse' function returns an input prefix parse paired with the remaining input suffix. newtype Parser g s r = Parser{applyParser :: [(s, g (Result g s))] -> Result g s r} -instance Show1 (Result g s) where+instance Show s => Show1 (Result g s) where    liftShowsPrec showsPrecSub _showList prec Parsed{parsedPrefix= r} rest = "Parsed " ++ showsPrecSub prec r rest    liftShowsPrec _showsPrec _showList _prec (NoParse f) rest = "NoParse " ++ shows f rest @@ -59,7 +58,7 @@                   NoParse failure -> NoParse failure  instance Alternative (Parser g s) where-   empty = Parser (\rest-> NoParse $ FailureInfo (genericLength rest) ["empty"])+   empty = Parser (\rest-> NoParse $ FailureInfo (genericLength rest) [Expected "empty"])    Parser p <|> Parser q = Parser r where       r rest = case p rest                of x@Parsed{} -> x@@ -83,7 +82,7 @@    mempty = pure mempty    mappend = liftA2 mappend -instance Factorial.FactorialMonoid s => Parsing (Parser g s) where+instance FactorialMonoid s => Parsing (Parser g s) where    try (Parser p) = Parser q       where q rest = rewindFailure (p rest)                where rewindFailure (NoParse (FailureInfo _pos _msgs)) = NoParse (FailureInfo (genericLength rest) [])@@ -91,96 +90,110 @@    Parser p <?> msg  = Parser q       where q rest = replaceFailure (p rest)                where replaceFailure (NoParse (FailureInfo pos msgs)) =-                        NoParse (FailureInfo pos $ if pos == genericLength rest then [msg] else msgs)+                        NoParse (FailureInfo pos $ if pos == genericLength rest then [Expected msg] else msgs)                      replaceFailure parsed = parsed-   eof = endOfInput-   unexpected msg = Parser (\t-> NoParse $ FailureInfo (genericLength t) [msg])+   eof = Parser p+      where p rest@((s, _) : _)+               | not (Null.null s) = NoParse (FailureInfo (genericLength rest) [Expected "end of input"])+            p rest = Parsed () rest+   unexpected msg = Parser (\t-> NoParse $ FailureInfo (genericLength t) [Expected msg])    notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))-      where rewind t Parsed{} = NoParse (FailureInfo (genericLength t) ["notFollowedBy"])+      where rewind t Parsed{} = NoParse (FailureInfo (genericLength t) [Expected "notFollowedBy"])             rewind t NoParse{} = Parsed () t -instance Factorial.FactorialMonoid s => LookAheadParsing (Parser g s) where+-- | Every PEG parser is deterministic all the time.+instance FactorialMonoid s => DeterministicParsing (Parser g s) where+   (<<|>) = (<|>)+   takeSome = some+   takeMany = many+   skipAll = skipMany++instance FactorialMonoid s => LookAheadParsing (Parser g s) where    lookAhead (Parser p) = Parser (\input-> rewind input (p input))       where rewind t (Parsed r _) = Parsed r t             rewind _ r@NoParse{} = r  instance (Show s, Textual.TextualMonoid s) => CharParsing (Parser g s) where-   satisfy = satisfyChar+   satisfy predicate = Parser p+      where p rest@((s, _):t) =+               case Textual.characterPrefix s+               of Just first | predicate first -> Parsed first t+                  _ -> NoParse (FailureInfo (genericLength rest) [Expected "Char.satisfy"])+            p [] = NoParse (FailureInfo 0 [Expected "Char.satisfy"])    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)-   char = satisfyChar . (==)-   notChar = satisfyChar . (/=)-   anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Lexical g, LexicalConstraint Parser g s, Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = someLexicalSpace-   semi = lexicalSemicolon-   token = lexicalToken--instance GrammarParsing Parser where-   type GrammarFunctor Parser = Result+instance (Eq s, LeftReductive s, FactorialMonoid s) => GrammarParsing (Parser g s) where+   type ParserGrammar (Parser g s) = g+   type GrammarFunctor (Parser g s) = Result g s+   parsingResult = fromResult    nonTerminal f = Parser p where       p ((_, d) : _) = f d-      p _ = NoParse (FailureInfo 0 ["NonTerminal at endOfInput"])+      p _ = NoParse (FailureInfo 0 [Expected "NonTerminal at endOfInput"]) -instance MonoidParsing (Parser g) where-   endOfInput = Parser p-      where p rest@((s, _) : _)-               | not (Null.null s) = NoParse (FailureInfo (genericLength rest) ["endOfInput"])-            p rest = Parsed () rest+instance (Eq s, LeftReductive s, FactorialMonoid s) => TailsParsing (Parser g s) where+   parseTails = applyParser++instance (LeftReductive s, FactorialMonoid s) => InputParsing (Parser g s) where+   type ParserInput (Parser g s) = s    getInput = Parser p       where p rest@((s, _):_) = Parsed s rest             p [] = Parsed mempty []    anyToken = Parser p       where p rest@((s, _):t) = case Factorial.splitPrimePrefix s                                 of Just (first, _) -> Parsed first t-                                   _ -> NoParse (FailureInfo (genericLength rest) ["anyToken"])-            p [] = NoParse (FailureInfo 0 ["anyToken"])+                                   _ -> NoParse (FailureInfo (genericLength rest) [Expected "anyToken"])+            p [] = NoParse (FailureInfo 0 [Expected "anyToken"])    satisfy predicate = Parser p       where p rest@((s, _):t) =                case Factorial.splitPrimePrefix s                of Just (first, _) | predicate first -> Parsed first t-                  _ -> NoParse (FailureInfo (genericLength rest) ["satisfy"])-            p [] = NoParse (FailureInfo 0 ["satisfy"])-   satisfyChar predicate = Parser p-      where p rest@((s, _):t) =-               case Textual.characterPrefix s-               of Just first | predicate first -> Parsed first t-                  _ -> NoParse (FailureInfo (genericLength rest) ["satisfyChar"])-            p [] = NoParse (FailureInfo 0 ["satisfyChar"])-   satisfyCharInput predicate = Parser p-      where p rest@((s, _):t) =-               case Textual.characterPrefix s-               of Just first | predicate first -> Parsed (Factorial.primePrefix s) t-                  _ -> NoParse (FailureInfo (genericLength rest) ["satisfyChar"])-            p [] = NoParse (FailureInfo 0 ["satisfyChar"])+                  _ -> NoParse (FailureInfo (genericLength rest) [Expected "satisfy"])+            p [] = NoParse (FailureInfo 0 [Expected "satisfy"])    notSatisfy predicate = Parser p       where p rest@((s, _):_)                | Just (first, _) <- Factorial.splitPrimePrefix s, -                 predicate first = NoParse (FailureInfo (genericLength rest) ["notSatisfy"])-            p rest = Parsed () rest-   notSatisfyChar predicate = Parser p-      where p rest@((s, _):_)-               | Just first <- Textual.characterPrefix s, -                 predicate first = NoParse (FailureInfo (genericLength rest) ["notSatisfyChar"])+                 predicate first = NoParse (FailureInfo (genericLength rest) [Expected "notSatisfy"])             p rest = Parsed () rest    scan s0 f = Parser (p s0)       where p s ((i, _):t) = Parsed prefix (drop (Factorial.length prefix - 1) t)                where (prefix, _, _) = Factorial.spanMaybe' s f i             p _ [] = Parsed mempty []-   scanChars s0 f = Parser (p s0)-      where p s ((i, _):t) = Parsed prefix (drop (Factorial.length prefix - 1) t)-               where (prefix, _, _) = Textual.spanMaybe_' s f i-            p _ [] = Parsed mempty []    takeWhile predicate = Parser p       where p rest@((s, _) : _)                | x <- Factorial.takeWhile predicate s = Parsed x (Factorial.drop (Factorial.length x) rest)             p [] = Parsed mempty []+   take n = Parser p+      where p rest@((s, _) : _)+               | x <- Factorial.take n s, Factorial.length x == n = Parsed x (drop n rest)+            p [] | n == 0 = Parsed mempty []+            p rest = NoParse (FailureInfo (genericLength rest) [Expected $ "take " ++ show n])    takeWhile1 predicate = Parser p       where p rest@((s, _) : _)                | x <- Factorial.takeWhile predicate s, not (Null.null x) =                     Parsed x (Factorial.drop (Factorial.length x) rest)-            p rest = NoParse (FailureInfo (genericLength rest) ["takeWhile1"])+            p rest = NoParse (FailureInfo (genericLength rest) [Expected "takeWhile1"])+   string s = Parser p where+      p rest@((s', _) : _)+         | s `isPrefixOf` s' = Parsed s (Factorial.drop (Factorial.length s) rest)+      p rest = NoParse (FailureInfo (genericLength rest) [ExpectedInput s])++instance (Show s, TextualMonoid s) => InputCharParsing (Parser g s) where+   satisfyCharInput predicate = Parser p+      where p rest@((s, _):t) =+               case Textual.characterPrefix s+               of Just first | predicate first -> Parsed (Factorial.primePrefix s) t+                  _ -> NoParse (FailureInfo (genericLength rest) [Expected "satisfyCharInput"])+            p [] = NoParse (FailureInfo 0 [Expected "satisfyCharInput"])+   notSatisfyChar predicate = Parser p+      where p rest@((s, _):_)+               | Just first <- Textual.characterPrefix s, +                 predicate first = NoParse (FailureInfo (genericLength rest) [Expected "notSatisfyChar"])+            p rest = Parsed () rest+   scanChars s0 f = Parser (p s0)+      where p s ((i, _):t) = Parsed prefix (drop (Factorial.length prefix - 1) t)+               where (prefix, _, _) = Textual.spanMaybe_' s f i+            p _ [] = Parsed mempty []    takeCharsWhile predicate = Parser p       where p rest@((s, _) : _)                | x <- Textual.takeWhile_ False predicate s =@@ -190,31 +203,25 @@       where p rest@((s, _) : _)                | x <- Textual.takeWhile_ False predicate s, not (Null.null x) =                     Parsed x (drop (Factorial.length x) rest)-            p rest = NoParse (FailureInfo (genericLength rest) ["takeCharsWhile1"])-   string s = Parser p where-      p rest@((s', _) : _)-         | Cancellative.isPrefixOf s s' = Parsed s (Factorial.drop (Factorial.length s) rest)-      p rest = NoParse (FailureInfo (genericLength rest) ["string " ++ show s])-   concatMany p = go-      where go = mappend <$> p <*> go <|> mempty-+            p rest = NoParse (FailureInfo (genericLength rest) [Expected "takeCharsWhile1"])  -- | Packrat parser -- -- @ -- 'parseComplete' :: ("Rank2".'Rank2.Functor' g, 'FactorialMonoid' s) =>---                  g (Packrat.'Parser' g s) -> s -> g 'ParseResults'+--                  g (Packrat.'Parser' g s) -> s -> g ('ParseResults' s) -- @-instance MultiParsing Parser where-   type ResultFunctor Parser = ParseResults+instance (LeftReductive s, FactorialMonoid s) => MultiParsing (Parser g s) where+   type ResultFunctor (Parser g s) = ParseResults s+   type GrammarConstraint (Parser g s) g' = (g ~ g', Rank2.Functor g)    {-# NOINLINE parsePrefix #-}-   parsePrefix g input = Rank2.fmap (Compose . fromResult input) (snd $ head $ parseTails g input)+   parsePrefix g input = Rank2.fmap (Compose . fromResult input) (snd $ head $ parseGrammarTails g input)    parseComplete g input = Rank2.fmap ((snd <$>) . fromResult input)-                                      (snd $ head $ reparseTails close $ parseTails g input)-      where close = Rank2.fmap (<* endOfInput) g+                                      (snd $ head $ reparseTails close $ parseGrammarTails g input)+      where close = Rank2.fmap (<* eof) g -parseTails :: (Rank2.Functor g, FactorialMonoid s) => g (Parser g s) -> s -> [(s, g (Result g s))]-parseTails g input = foldr parseTail [] (Factorial.tails input)+parseGrammarTails :: (Rank2.Functor g, FactorialMonoid s) => g (Parser g s) -> s -> [(s, g (Result g s))]+parseGrammarTails g input = foldr parseTail [] (Factorial.tails input)       where parseTail s parsedTail = parsed where                parsed = (s,d):parsedTail                d      = Rank2.fmap (($ parsed) . applyParser) g@@ -224,7 +231,7 @@ reparseTails final parsed@((s, _):_) = (s, gd):parsed    where gd = Rank2.fmap (`applyParser` parsed) final -fromResult :: FactorialMonoid s => s -> Result g s r -> ParseResults (s, r)+fromResult :: (Eq s, FactorialMonoid s) => s -> Result g s r -> ParseResults s (s, r) fromResult s (NoParse (FailureInfo pos msgs)) =    Left (ParseFailure (Factorial.length s - pos + 1) (nub msgs)) fromResult _ (Parsed prefix []) = Right (mempty, prefix)
test/Benchmark.hs view
@@ -13,6 +13,7 @@ import qualified Rank2 import qualified Rank2.TH +import Text.Parser.Combinators (eof) import Text.Grampa import Text.Grampa.ContextFree.Parallel (Parser) import qualified Arithmetic@@ -27,7 +28,7 @@  recursiveManyGrammar :: Recursive (Parser g String) -> Recursive (Parser g String) recursiveManyGrammar Recursive{..} = Recursive{-   start= rec <* endOfInput,+   start= rec <* eof,    rec= many (char ';') <* optional next,    next= string "END"} 
test/Doctest.hs view
@@ -1,7 +1,10 @@-import Build_doctests (flags, pkgs, module_sources)+import Build_doctests import Test.DocTest (doctest)  main :: IO () main = do     doctest (flags ++ pkgs ++ module_sources)+    doctest (flags_exe_arithmetic ++ pkgs_exe_arithmetic ++ module_sources_exe_arithmetic)+    doctest (flags_exe_boolean_transformations ++ pkgs_exe_boolean_transformations+             ++ module_sources_exe_boolean_transformations)     doctest (flags ++ pkgs ++ ["-pgmL", "markdown-unlit", "-isrc", "test/README.lhs"])
test/README.lhs view
@@ -89,9 +89,9 @@ -- >>> parseComplete grammar "1+2*3" -- Arithmetic{ --   sum=Compose (Right [7]),---   product=Compose (Left (ParseFailure 1 ["endOfInput"])),---   factor=Compose (Left (ParseFailure 1 ["endOfInput"])),---   number=Compose (Left (ParseFailure 1 ["endOfInput"]))}+--   product=Compose (Left (ParseFailure 1 [Expected "end of input"])),+--   factor=Compose (Left (ParseFailure 1 [Expected "end of input"])),+--   number=Compose (Left (ParseFailure 1 [Expected "end of input"]))} -- >>> parsePrefix grammar "1+2*3 apples" -- Arithmetic{ --   sum=Compose (Compose (Right [("+2*3 apples",1),("*3 apples",3),(" apples",7)])),
test/Test.hs view
@@ -1,5 +1,5 @@ {-# Language FlexibleContexts, FlexibleInstances, RankNTypes, RecordWildCards, -             ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, UndecidableInstances #-}+             ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TypeFamilies, UndecidableInstances #-} module Main where  import Control.Applicative (Applicative, Alternative, Const(..), pure, empty, many, optional, (<*>), (*>), (<|>))@@ -10,15 +10,16 @@ import Data.List.NonEmpty (NonEmpty((:|))) import Data.Semigroup (Semigroup, (<>)) import Data.Monoid (Monoid(..), Product(..))-import Data.Monoid.Cancellative (LeftReductiveMonoid, isPrefixOf) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid, factors) import Data.Monoid.Textual (TextualMonoid(toString))+import Data.Semigroup.Cancellative (LeftReductive, isPrefixOf) import Data.Typeable (Typeable) import Data.Word (Word8, Word64)  import Data.Functor.Compose (Compose(..))-import Text.Parser.Combinators (choice, sepBy1, skipMany)+import Text.Parser.Combinators (choice, eof, sepBy1, skipMany)+import qualified Text.Parser.Char as Char import Text.Parser.Token (whiteSpace)  import Control.Enumerable (Shareable, Sized, share)@@ -49,7 +50,8 @@                              next :: f String} deriving instance (Show (f String), Show (f [String])) => Show (Recursive f) -instance Lexical Recursive+instance TokenParsing (LeftRecursive.Parser Recursive String)+instance LexicalParsing (LeftRecursive.Parser Recursive String)  $(Rank2.TH.deriveAll ''Recursive) @@ -66,11 +68,11 @@           pure id <*> symbol "..." <?> "start",    rec= sepBy1 one (ignorable *> string "," <?> "comma") <?> "rec",    one= do ignorable-           identifier <- ((:) <$> satisfyChar isLetter <*> (toString (const "") <$> takeCharsWhile isLetter))+           identifier <- ((:) <$> Char.satisfy isLetter <*> (toString (const "") <$> takeCharsWhile isLetter))            guard (identifier /= "reserved")            pure id <*> pure identifier         <?> "one",-   next= string "--" *> (toString (const "") <$> takeCharsWhile (/= '\n') <* (void (char '\n') <|> endOfInput)) <?> "next"+   next= string "--" *> (toString (const "") <$> takeCharsWhile (/= '\n') <* (void (char '\n') <|> eof)) <?> "next"    }  symbol s = ignorable *> string s <* ignorable@@ -82,7 +84,7 @@  type Parser = Parallel.Parser -simpleParse :: FactorialMonoid s => Parallel.Parser (Rank2.Only r) s r -> s -> ParseResults [(s, r)]+simpleParse :: (Eq s, FactorialMonoid s, LeftReductive s) => Parallel.Parser (Rank2.Only r) s r -> s -> ParseResults s [(s, r)] simpleParse p input = getCompose . getCompose $ simply parsePrefix p input  tests = testGroup "Grampa" [@@ -123,7 +125,7 @@                                                      :| [Test.Ambiguous.Xy2                                                          (pure $ Test.Ambiguous.Xy1 "x" "") "y"]))]))],            testGroup "primitives"-             [testProperty "anyToken mempty" $ simpleParse anyToken "" == Left (ParseFailure 0 ["anyToken"]),+             [testProperty "anyToken mempty" $ simpleParse anyToken "" == Left (ParseFailure 0 [Expected "anyToken"]),               testProperty "anyToken list" $                 \(x::Word8) xs-> simpleParse anyToken (x:xs) == Right [(xs, [x])],               testProperty "satisfy success" $ \bools->@@ -133,10 +135,10 @@               testProperty "string success" $ \(xs::[Word8]) ys->                    simpleParse (string xs) (xs <> ys) == Right [(ys, xs)],               testProperty "string" $ \(xs::[Word8]) ys-> not (xs `isPrefixOf` ys)-                ==> simpleParse (string xs) ys == Left (ParseFailure 0 ["string " ++ show xs]),-              testProperty "endOfInput mempty" $ simpleParse endOfInput "" == Right [("", ())],-              testProperty "endOfInput failure" $ \s->-                   s /= "" ==> simpleParse endOfInput s == Left (ParseFailure 0 ["endOfInput"])],+                ==> simpleParse (string xs) ys == Left (ParseFailure 0 [ExpectedInput xs]),+              testProperty "eof mempty" $ simpleParse eof "" == Right [("", ())],+              testProperty "eof failure" $ \s->+                   s /= "" ==> simpleParse eof s == Left (ParseFailure 0 [Expected "end of input"])],            testGroup "lookAhead"              [testProperty "lookAhead" lookAheadP,               testProperty "lookAhead p *> p" lookAheadConsumeP,@@ -156,11 +158,16 @@               testBatch $ monadPlus parser2s],            testGroup "errors"              [testProperty "start" (Test.Examples.parseArithmetical ":4" -                                    === Left ":4\n^\nat line 1, column 1\nexpected digits, string \"(\", or string \"-\""),+                                    === Left (":4\n^\nat line 1, column 1\n" <>+                                              "expected digits, string \"(\", or string \"-\"")),+              testProperty "tabs" (Test.Examples.parseArithmetical "\t\t :4" +                                   === Left ("\t\t :4\n\t\t ^\nat line 1, column 4\n" <>+                                             "expected digits, string \"(\", or string \"-\"")),               testProperty "middle" (Test.Examples.parseArithmetical "4 - :3"                                      === Left "4 - :3\n    ^\nat line 1, column 5\nexpected digits or string \"(\""),               testProperty "middle line" (Test.Examples.parseArithmetical "4 -\n :3\n+ 2"-                                           === Left "4 -\n :3\n ^\nat line 2, column 2\nexpected digits or string \"(\""),+                                          === Left ("4 -\n :3\n ^\nat line 2, column 2\n" <>+                                                    "expected digits or string \"(\"")),               testProperty "missing" (Test.Examples.parseArithmetical "4 - "                                        === Left "4 - \n    ^\nat line 1, column 5\nexpected digits or string \"(\""),               testProperty "missing" (Test.Examples.parseArithmetical "4 -\n" @@ -209,14 +216,14 @@    mempty = DescribedParser "mempty" mempty    DescribedParser d1 p1 `mappend` DescribedParser d2 p2 = DescribedParser (d1 ++ " <> " ++ d2) (mappend p1 p2) -instance EqProp ParseFailure where+instance EqProp (ParseFailure s) where    ParseFailure pos1 msg1 =-= ParseFailure pos2 msg2 = property (pos1 == pos2) -instance (Ord r, Show r, EqProp r, Eq s, EqProp s, Show s, FactorialMonoid s, Arbitrary s) =>+instance (Ord r, Show r, EqProp r, Eq s, EqProp s, Show s, FactorialMonoid s, LeftReductive s, Arbitrary s) =>          EqProp (Parser (Rank2.Only r) s r) where    p1 =-= p2 = forAll arbitrary (\s-> (nub <$> simpleParse p1 s) =-= (nub <$> simpleParse p2 s)) -instance (FactorialMonoid s, Show s, EqProp s, Arbitrary s, Ord r, Show r, EqProp r, Typeable r) =>+instance (Eq s, FactorialMonoid s, LeftReductive s, Show s, EqProp s, Arbitrary s, Ord r, Show r, EqProp r, Typeable r) =>          EqProp (DescribedParser s r) where    DescribedParser _ p1 =-= DescribedParser _ p2 = forAll arbitrary $ \s->       simpleParse p1 s =-= simpleParse p2 s@@ -241,7 +248,7 @@    mzero = DescribedParser "mzero" mzero    DescribedParser d1 p1 `mplus` DescribedParser d2 p2 = DescribedParser (d1 ++ " `mplus` " ++ d2) (mplus p1 p2) -instance forall s. (Semigroup s, FactorialMonoid s, LeftReductiveMonoid s, Ord s, Typeable s, Show s, Enumerable s) =>+instance forall s. (Semigroup s, FactorialMonoid s, LeftReductive s, Ord s, Typeable s, Show s, Enumerable s) =>          Enumerable (DescribedParser s s) where    enumerate = share (choice [c0 (DescribedParser "anyToken" anyToken),                               c0 (DescribedParser "getInput" getInput),@@ -255,9 +262,9 @@                               binary " <> " (<>),                               binary " <|> " (<|>)]) -instance forall s r. (Ord s, Semigroup s, FactorialMonoid s, LeftReductiveMonoid s, Show s, Enumerable s) =>+instance forall s r. (Ord s, Semigroup s, FactorialMonoid s, LeftReductive s, Show s, Enumerable s) =>          Enumerable (DescribedParser s ()) where-   enumerate = share (choice [c0 (DescribedParser "endOfInput" endOfInput),+   enumerate = share (choice [c0 (DescribedParser "eof" eof),                               pay (c1 $ \(DescribedParser d p :: DescribedParser s s)-> DescribedParser ("void " <> d) (void p)),                               pay (c1 $ \(DescribedParser d p :: DescribedParser s s)->                                     DescribedParser ("(notFollowedBy " <> d <> ")") (notFollowedBy p))])
test/Test/Ambiguous.hs view
@@ -30,6 +30,4 @@                     <|> Xyzw <$> amb <*> string "w")    } -instance Lexical Test- $(Rank2.TH.deriveAll ''Test)
test/Test/Examples.hs view
@@ -1,4 +1,4 @@-{-# Language FlexibleInstances, MultiParamTypeClasses, RankNTypes, ScopedTypeVariables #-}+{-# Language FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, RankNTypes, ScopedTypeVariables #-} module Test.Examples where  import Control.Applicative (empty, (<|>))@@ -29,19 +29,19 @@ parseBoolean :: String -> Either String BooleanTree parseBoolean = uniqueParse (fixGrammar boolean) (Boolean.expr . Rank2.snd) -comparisons :: (Rank2.Functor g, Lexical g, LexicalConstraint Parser g String) =>+comparisons :: (Rank2.Functor g, LexicalParsing (Parser g String)) =>                GrammarBuilder ArithmeticComparisons g Parser String comparisons (Rank2.Pair a c) =    Rank2.Pair (Arithmetic.arithmetic a) (Comparisons.comparisons c){Comparisons.term= Arithmetic.expr a} -boolean :: (Rank2.Functor g, Lexical g, LexicalConstraint Parser g String) =>+boolean :: (Rank2.Functor g, LexicalParsing (Parser g String)) =>            GrammarBuilder ArithmeticComparisonsBoolean g Parser String boolean (Rank2.Pair ac b) = Rank2.Pair (comparisons ac) (Boolean.boolean (Comparisons.test $ Rank2.snd ac) b)  parseConditional :: String -> Either String (ConditionalTree ArithmeticTree) parseConditional = uniqueParse (fixGrammar conditionals) (Conditionals.expr . Rank2.snd) -conditionals :: (Rank2.Functor g, Lexical g, LexicalConstraint Parser g String) => GrammarBuilder ACBC g Parser String+conditionals :: (Rank2.Functor g, LexicalParsing (Parser g String)) => GrammarBuilder ACBC g Parser String conditionals (Rank2.Pair acb c) =    boolean acb `Rank2.Pair`    Conditionals.conditionals c{Conditionals.test= Boolean.expr (Rank2.snd acb),@@ -142,14 +142,22 @@ instance Enumerable Relation where    enumerate = share (choice $ pay . pure . Relation <$> ["<", "<=", "==", ">=", ">"]) -uniqueParse :: (Eq s, TextualMonoid s, Rank2.Apply g, Rank2.Traversable g, Rank2.Distributive g) =>+uniqueParse :: (Ord s, TextualMonoid s, Show r, Rank2.Apply g, Rank2.Traversable g, Rank2.Distributive g) =>                Grammar g Parser s -> (forall f. g f -> f r) -> s -> Either String r uniqueParse g p s = case getCompose (p $ parseComplete g s)                     of Right [r] -> Right r                        Right [] -> Left "Unparseable"-                       Right _ -> Left "Ambiguous"+                       Right rs -> Left ("Ambiguous: " ++ show rs)                        Left err -> Left (toString mempty $ failureDescription s err 3) -instance Lexical ArithmeticComparisons-instance Lexical ArithmeticComparisonsBoolean-instance Lexical ACBC+instance TokenParsing (Parser ArithmeticComparisons String) where+   token = lexicalToken+instance TokenParsing (Parser ArithmeticComparisonsBoolean String) where+   token = lexicalToken+instance TokenParsing (Parser ACBC String) where+   token = lexicalToken++instance LexicalParsing (Parser ArithmeticComparisons String)+instance LexicalParsing (Parser ArithmeticComparisonsBoolean String)+instance LexicalParsing (Parser ACBC String)+