packages feed

grammatical-parsers 0.2.2 → 0.3

raw patch · 25 files changed

+758/−204 lines, 25 filesdep ~basedep ~containersdep ~rank2classesPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, containers, rank2classes

API changes (from Hackage documentation)

- Text.Grampa: token :: (MonoidParsing m, Eq s, FactorialMonoid s) => s -> m s s
- Text.Grampa: whiteSpace :: (MonoidParsing m, TextualMonoid s) => m s ()
- Text.Grampa.ContextFree.Continued: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.ContextFree.Continued.Parser 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.Combinators.Parsing (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), 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.Parser.Token.TokenParsing (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.Token.TokenParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s)
- Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.Class.GrammarParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.Memoizing.Parser)
- Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.Class.MonoidParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.Memoizing.Parser g)
- Text.Grampa.ContextFree.LeftRecursive: instance Text.Grampa.Class.MultiParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.Memoizing.Parser)
- Text.Grampa.ContextFree.Memoizing: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.ContextFree.Memoizing.Parser g s)
- Text.Grampa.ContextFree.Parallel: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.ContextFree.Parallel.Parser g s)
- Text.Grampa.PEG.Backtrack: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.PEG.Backtrack.Parser g s)
- Text.Grampa.PEG.Packrat: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Token.TokenParsing (Text.Grampa.PEG.Packrat.Parser g s)
+ Text.Grampa: (Applicative (m g ()), Monad (m g s), CharParsing (m g s),
+ Text.Grampa: -> * -> * -> *) g s :: Constraint;
+ Text.Grampa: Ambiguous :: (NonEmpty a) -> Ambiguous a
+ Text.Grampa: MonoidParsing (m g), Show s, TextualMonoid s);
+ Text.Grampa: ambiguous :: AmbiguousParsing m => m a -> m (Ambiguous a)
+ Text.Grampa: class AmbiguousParsing m
+ Text.Grampa: class Lexical (g :: (* -> *) -> *) where {
+ Text.Grampa: identifier :: (Lexical g, LexicalConstraint m g s, Monad (m g s), Alternative (m g s), MonoidParsing (m g), TextualMonoid s) => m g s s
+ 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: isIdentifierFollowChar :: Lexical g => Char -> Bool
+ Text.Grampa: isIdentifierStartChar :: Lexical g => 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: lexicalComment :: (Lexical g, Alternative (m g s)) => m g s ()
+ Text.Grampa: lexicalSemicolon :: (Lexical g, LexicalConstraint m g s, CharParsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s 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: lexicalWhiteSpace :: (Lexical g, LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s ()
+ Text.Grampa: newtype Ambiguous a
+ Text.Grampa: someLexicalSpace :: (Lexical g, LexicalConstraint m g s, Parsing (m g s), MonoidParsing (m g), TextualMonoid s) => m g s ()
+ Text.Grampa: type LexicalConstraint m g 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.Semigroup.Semigroup x => Data.Semigroup.Semigroup (Text.Grampa.ContextFree.Continued.Parser g s x)
+ Text.Grampa.ContextFree.LeftRecursive: [appendResultsArrow] :: SeparatedParser p g s a -> ResultAppend g s a
+ Text.Grampa.ContextFree.LeftRecursive: instance (GHC.Base.Alternative (p g s), Data.Semigroup.Semigroup x) => Data.Semigroup.Semigroup (Text.Grampa.ContextFree.LeftRecursive.Fixed p g s x)
+ Text.Grampa.ContextFree.LeftRecursive: instance (Rank2.Apply g, Rank2.Distributive g) => Data.Semigroup.Semigroup (Text.Grampa.ContextFree.LeftRecursive.Union g)
+ 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.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.MultiParsing (Text.Grampa.ContextFree.LeftRecursive.Fixed Text.Grampa.ContextFree.SortedMemoizing.Parser)
+ 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.Semigroup.Semigroup (Text.Grampa.ContextFree.Memoizing.ResultList g s r)
+ Text.Grampa.ContextFree.Memoizing: instance Data.Semigroup.Semigroup x => Data.Semigroup.Semigroup (Text.Grampa.ContextFree.Memoizing.Parser g s x)
+ 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.Semigroup.Semigroup (Text.Grampa.ContextFree.Parallel.ResultList s r)
+ Text.Grampa.ContextFree.Parallel: instance Data.Semigroup.Semigroup Text.Grampa.ContextFree.Parallel.FailureInfo
+ Text.Grampa.ContextFree.Parallel: instance Data.Semigroup.Semigroup x => Data.Semigroup.Semigroup (Text.Grampa.ContextFree.Parallel.Parser g s x)
+ Text.Grampa.ContextFree.SortedMemoizing: (<<|>) :: Parser g s a -> Parser g s a -> Parser g s a
+ Text.Grampa.ContextFree.SortedMemoizing: FailureInfo :: !Int -> Word64 -> [String] -> FailureInfo
+ Text.Grampa.ContextFree.SortedMemoizing: Parser :: ([(s, g (ResultList g s))] -> ResultList g s r) -> Parser g s r
+ Text.Grampa.ContextFree.SortedMemoizing: ResultList :: ![ResultsOfLength g s r] -> !FailureInfo -> ResultList g s r
+ Text.Grampa.ContextFree.SortedMemoizing: [applyParser] :: Parser g s r -> [(s, g (ResultList g s))] -> ResultList g s r
+ Text.Grampa.ContextFree.SortedMemoizing: data FailureInfo
+ Text.Grampa.ContextFree.SortedMemoizing: data ResultList g s r
+ Text.Grampa.ContextFree.SortedMemoizing: infixl 3 <<|>
+ Text.Grampa.ContextFree.SortedMemoizing: instance (GHC.Show.Show s, Data.Monoid.Textual.TextualMonoid s) => Text.Parser.Char.CharParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ 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 Data.Monoid.Null.MonoidNull s => Text.Parser.Combinators.Parsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance Data.Monoid.Null.MonoidNull s => Text.Parser.LookAhead.LookAheadParsing (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance Data.Semigroup.Semigroup x => Data.Semigroup.Semigroup (Text.Grampa.ContextFree.SortedMemoizing.Parser g s x)
+ Text.Grampa.ContextFree.SortedMemoizing: instance GHC.Base.Alternative (Text.Grampa.ContextFree.SortedMemoizing.Parser g i)
+ Text.Grampa.ContextFree.SortedMemoizing: instance GHC.Base.Applicative (Text.Grampa.ContextFree.SortedMemoizing.Parser g i)
+ Text.Grampa.ContextFree.SortedMemoizing: instance GHC.Base.Functor (Text.Grampa.ContextFree.SortedMemoizing.Parser g i)
+ Text.Grampa.ContextFree.SortedMemoizing: instance GHC.Base.Monad (Text.Grampa.ContextFree.SortedMemoizing.Parser g i)
+ Text.Grampa.ContextFree.SortedMemoizing: instance GHC.Base.MonadPlus (Text.Grampa.ContextFree.SortedMemoizing.Parser g s)
+ Text.Grampa.ContextFree.SortedMemoizing: instance GHC.Base.Monoid x => GHC.Base.Monoid (Text.Grampa.ContextFree.SortedMemoizing.Parser g s x)
+ Text.Grampa.ContextFree.SortedMemoizing: instance Text.Grampa.Class.AmbiguousParsing (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: longest :: Parser g s a -> Parser g [(s, g (ResultList g s))] a
+ Text.Grampa.ContextFree.SortedMemoizing: newtype Parser g s r
+ Text.Grampa.ContextFree.SortedMemoizing: peg :: Parser g [(s, g (ResultList g s))] a -> Parser g s a
+ Text.Grampa.ContextFree.SortedMemoizing: reparseTails :: Functor g => g (Parser g s) -> [(s, g (ResultList g s))] -> [(s, g (ResultList g s))]
+ Text.Grampa.ContextFree.SortedMemoizing: terminalPEG :: Monoid s => Parser g s a -> Parser g s a
+ 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.Semigroup.Semigroup x => Data.Semigroup.Semigroup (Text.Grampa.PEG.Backtrack.Parser g s x)
+ 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.Semigroup.Semigroup x => Data.Semigroup.Semigroup (Text.Grampa.PEG.Packrat.Parser g s x)
- Text.Grampa: class MultiParsing m => GrammarParsing m where type GrammarFunctor m :: ((* -> *) -> *) -> * -> * -> * selfReferring = cotraverse nonTerminal id fixGrammar = ($ selfReferring) recursive = id where {
+ Text.Grampa: class MultiParsing m => GrammarParsing m where {
- Text.Grampa: class MonoidParsing m where token x = satisfy (== x)
+ Text.Grampa: class MonoidParsing m
- Text.Grampa: class MultiParsing m where type ResultFunctor m :: * -> * type GrammarConstraint m (g :: (* -> *) -> *) :: Constraint type GrammarConstraint m g = Functor g where {
+ Text.Grampa: class MultiParsing m where {
- Text.Grampa: type family GrammarFunctor m :: ((* -> *) -> *) -> * -> * -> *;
+ Text.Grampa: type family LexicalConstraint (m :: ((* -> *) -> *)
- Text.Grampa.ContextFree.LeftRecursive: CycleParser :: p g s a -> p 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 g s a -> g (Const Bool) -> SeparatedParser p g s a

Files

examples/Arithmetic.hs view
@@ -5,10 +5,11 @@ import Data.Char (isDigit) import Data.Functor.Compose (Compose(..)) import Data.Monoid ((<>))+import Text.Parser.Token (symbol)  import Text.Grampa import Text.Grampa.ContextFree.LeftRecursive (Parser)-import Utilities (infixJoin, symbol)+import Utilities (infixJoin)  import qualified Rank2 import Prelude hiding (negate, product, subtract, sum)@@ -87,7 +88,10 @@                   <*> f (factor a)                   <*> f (primary a) -arithmetic :: ArithmeticDomain e => GrammarBuilder (Arithmetic e) g Parser String+instance Lexical (Arithmetic e)++arithmetic :: (Lexical g, LexicalConstraint Parser g String, ArithmeticDomain e) =>+              GrammarBuilder (Arithmetic e) g Parser String arithmetic Arithmetic{..} = Arithmetic{    expr= sum,    sum= product@@ -99,7 +103,7 @@          <|> divide <$> product <* symbol "/" <*> factor,    factor= primary            <|> symbol "(" *> expr <* symbol ")",-   primary= whiteSpace *> ((number . read) <$> takeCharsWhile1 isDigit <?> "digits")}+   primary= lexicalToken ((number . read) <$> takeCharsWhile1 isDigit) <?> "digits"}  main :: IO () main = getContents >>=
examples/Boolean.hs view
@@ -1,15 +1,17 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, KindSignatures, RecordWildCards, ScopedTypeVariables, TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, KindSignatures, RecordWildCards, ScopedTypeVariables,+             TypeFamilies, TemplateHaskell #-} module Boolean where  import Control.Applicative import qualified Data.Bool import Data.Char (isSpace) import Data.Monoid ((<>))+import Text.Parser.Token (TokenParsing, symbol)  import qualified Rank2.TH  import Text.Grampa-import Utilities (infixJoin, keyword, symbol)+import Utilities (infixJoin)  import Prelude hiding (and, or, not) @@ -41,10 +43,13 @@       factor :: f e}    deriving Show +instance Lexical (Boolean e)+ $(Rank2.TH.deriveAll ''Boolean)  boolean :: forall e p (g :: (* -> *) -> *).-           (BooleanDomain e, Alternative (p g String), Parsing (p g String), MonoidParsing (p g)) =>+           (Lexical g, LexicalConstraint p g String,+            BooleanDomain e, TokenParsing (p g String), MonoidParsing (p g)) =>            p g String e -> Boolean e (p g String) -> Boolean e (p g String) boolean p Boolean{..} = Boolean{    expr= term
examples/Combined.hs view
@@ -7,7 +7,7 @@ import Data.Map (Map) import qualified Data.Map as Map import qualified Rank2.TH-import Text.Grampa (GrammarBuilder)+import Text.Grampa (Lexical, LexicalConstraint, GrammarBuilder) import Text.Grampa.ContextFree.LeftRecursive (Parser) import qualified Arithmetic import qualified Boolean@@ -117,6 +117,8 @@                            (", conditionalGrammar=" ++ showsPrec prec (conditionalGrammar g)                            (", lambdaGrammar=" ++ showsPrec prec (lambdaGrammar g) ("}" ++ rest)))))) +instance Lexical Expression+ $(Rank2.TH.deriveAll ''Expression)  {-@@ -186,7 +188,7 @@                   <*> Rank2.traverse f (lambdaGrammar g) -} -expression :: GrammarBuilder Expression g Parser String+expression :: (Lexical g, LexicalConstraint Parser g String) => GrammarBuilder Expression g Parser String expression Expression{..} =    let combinedExpr = Arithmetic.expr arithmeticGrammar                       <|> Boolean.expr booleanGrammar
examples/Comparisons.hs view
@@ -3,10 +3,10 @@  import Control.Applicative import Data.Monoid ((<>))+import Text.Parser.Token (TokenParsing, symbol)  import qualified Rank2 import Text.Grampa-import Utilities (symbol)  class ComparisonDomain c e where    greaterThan :: c -> c -> e@@ -62,7 +62,8 @@                   <$> f (test g)                   <*> f (term g) -comparisons :: (ComparisonDomain c e, Alternative (p g String), MonoidParsing (p 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 Comparisons{..} =    Comparisons{
examples/Conditionals.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, RecordWildCards, TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, RecordWildCards,+             TypeFamilies, TemplateHaskell #-} module Conditionals where  import Control.Applicative@@ -8,7 +9,6 @@  import Text.Grampa import Text.Grampa.ContextFree.LeftRecursive (Parser)-import Utilities (keyword)  class ConditionalDomain c e where    ifThenElse :: c -> e -> e -> e@@ -29,9 +29,13 @@                            (", 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)+ $(Rank2.TH.deriveAll ''Conditionals) -conditionals :: ConditionalDomain t e => GrammarBuilder (Conditionals t e) g Parser String+conditionals :: (ConditionalDomain t e, Lexical g, LexicalConstraint Parser g String)+             => GrammarBuilder (Conditionals t e) g Parser String conditionals Conditionals{..} =    Conditionals{expr= ifThenElse <$> (keyword "if" *> test) <*> (keyword "then" *> term) <*> (keyword "else" *> term),                 test= empty,
examples/Lambda.hs view
@@ -6,13 +6,13 @@ import Data.Char (isAlphaNum, isLetter) import Data.Map (Map, insert, (!)) import Data.Monoid ((<>))+import Text.Parser.Token (symbol, whiteSpace)  import qualified Rank2 import qualified Rank2.TH  import Text.Grampa import Text.Grampa.ContextFree.LeftRecursive (Parser)-import Utilities (symbol)  class LambdaDomain e where    apply :: e -> e -> e@@ -96,7 +96,8 @@  $(Rank2.TH.deriveAll ''Lambda) -lambdaCalculus :: LambdaDomain e => GrammarBuilder (Lambda e) g Parser String+lambdaCalculus :: (Lexical g, LexicalConstraint 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, MultiParamTypeClasses, RankNTypes, KindSignatures, UndecidableInstances #-}+{-# LANGUAGE 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 (GrammarBuilder, ParseResults, fixGrammar, parseComplete)+import Text.Grampa (Lexical, LexicalConstraint, GrammarBuilder, ParseResults, fixGrammar, parseComplete) import Text.Grampa.ContextFree.LeftRecursive (Parser) import Arithmetic (Arithmetic, arithmetic) import qualified Arithmetic@@ -37,17 +37,22 @@                  <$> (getCompose . Combined.expr $ parseComplete (fixGrammar Combined.expression) args)                  :: ParseResults [Combined.Tagged]) -comparisons :: GrammarBuilder (Rank2.Product (Arithmetic.Arithmetic Int) (Comparisons.Comparisons Int Bool))-                              g Parser String+comparisons :: (Lexical g, LexicalConstraint 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 :: GrammarBuilder ArithmeticComparisonsBoolean g Parser String+boolean :: (Lexical g, LexicalConstraint 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 :: GrammarBuilder ACBC g Parser String+conditionals :: (Lexical g, LexicalConstraint 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)+
examples/Utilities.hs view
@@ -21,11 +21,3 @@  infixJoin :: String -> String -> String -> String infixJoin op a b = "(" <> a <> op <> b <> ")"--keyword :: forall s (g :: (* -> *) -> *) p.-           (Show s, TextualMonoid s, Parsing (p g s), MonoidParsing (p g)) => s -> p g s s-keyword kwd = whiteSpace *> string kwd <* notFollowedBy (satisfyChar isAlphaNum)--symbol :: forall s (g :: (* -> *) -> *) p.-          (Show s, TextualMonoid s, Applicative (p g s), MonoidParsing (p g)) => s -> p g s s-symbol s = whiteSpace *> string s
grammatical-parsers.cabal view
@@ -1,5 +1,5 @@ name:                grammatical-parsers-version:             0.2.2+version:             0.3 synopsis:            parsers that can 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@@ -26,7 +26,8 @@   exposed-modules:     Text.Grampa,                        Text.Grampa.PEG.Backtrack, Text.Grampa.PEG.Packrat,                        Text.Grampa.ContextFree.Continued, Text.Grampa.ContextFree.Parallel,-                       Text.Grampa.ContextFree.Memoizing, Text.Grampa.ContextFree.LeftRecursive+                       Text.Grampa.ContextFree.Memoizing, Text.Grampa.ContextFree.SortedMemoizing,+                       Text.Grampa.ContextFree.LeftRecursive   other-modules:       Text.Grampa.Class, Text.Grampa.Internal,                        Text.Grampa.PEG.Backtrack.Measured,                        Text.Grampa.PEG.Continued, Text.Grampa.PEG.Continued.Measured,@@ -34,35 +35,34 @@   default-language:    Haskell2010   -- other-modules:   ghc-options:         -Wall-  build-depends:       base >=4.7 && <5,+  build-depends:       base >=4.9 && <5,                        containers >= 0.4 && < 0.6,                        transformers >= 0.5 && < 0.6,                        monoid-subclasses >=0.4 && <0.5,                        parsers < 0.13,-                       rank2classes == 1.0.*-  -- hs-source-dirs:      -  default-language:    Haskell2010+                       rank2classes >= 1.0.2 && < 1.2  executable             arithmetic   hs-source-dirs:      examples   main-is:             Main.hs   other-modules:       Arithmetic, Boolean, Combined, Comparisons, Conditionals, Lambda, Utilities   default-language:    Haskell2010-  build-depends:       base >=4.7 && <5, containers >= 0.5.7.0 && < 0.6,+  build-depends:       base >=4.9 && <5, containers >= 0.5.7.0 && < 0.6,                        parsers < 0.13,-                       rank2classes == 1.0.*, grammatical-parsers,+                       rank2classes >= 1.0.2 && < 1.2, grammatical-parsers,                        monoid-subclasses >=0.4 && <0.5  test-suite           quicktests   type:              exitcode-stdio-1.0   hs-source-dirs:    test, examples   x-uses-tf:         true-  build-depends:     base >=4.7 && < 5, monoid-subclasses < 0.5, parsers < 0.13,-                     rank2classes == 1.0.*, grammatical-parsers,+  build-depends:     base >=4.9 && < 5, containers >= 0.5.7.0 && < 0.6,+                     monoid-subclasses < 0.5, parsers < 0.13,+                     rank2classes >= 1.0.2 && < 1.2, grammatical-parsers,                      QuickCheck >= 2 && < 3, checkers >= 0.4.6 && < 0.5, testing-feat < 0.5,                      tasty >= 0.7, tasty-quickcheck >= 0.7   main-is:           Test.hs-  other-modules:     Test.Examples, Arithmetic, Boolean, Combined, Comparisons, Conditionals, Utilities+  other-modules:     Test.Examples, Arithmetic, Boolean, Combined, Comparisons, Conditionals, Lambda, Utilities   default-language:  Haskell2010  test-suite           doctests@@ -77,8 +77,9 @@   type:              exitcode-stdio-1.0   hs-source-dirs:    test, examples   ghc-options:       -O2 -Wall -rtsopts -main-is Benchmark.main-  Build-Depends:     base >=4.7 && < 5, rank2classes == 1.0.*, grammatical-parsers, monoid-subclasses >=0.4 && <0.5,+  Build-Depends:     base >=4.9 && < 5, rank2classes >= 1.0.2 && < 1.2, grammatical-parsers,+                     monoid-subclasses >=0.4 && <0.5,                      criterion >= 1.0, deepseq >= 1.1, containers >= 0.5.7.0 && < 0.6, text >= 1.1   main-is:           Benchmark.hs-  other-modules:     Arithmetic+  other-modules:     Main, Arithmetic, Boolean, Combined, Comparisons, Conditionals, Lambda, Utilities   default-language:  Haskell2010
src/Text/Grampa.hs view
@@ -6,9 +6,9 @@    MultiParsing(..),    simply,    -- * Types-   Grammar, GrammarBuilder, ParseResults, ParseFailure(..),+   Grammar, GrammarBuilder, ParseResults, ParseFailure(..), Ambiguous(..),    -- * Parser combinators and primitives-   GrammarParsing(..), MonoidParsing(..),+   GrammarParsing(..), MonoidParsing(..), AmbiguousParsing(..), Lexical(..),    module Text.Parser.Char,    module Text.Parser.Combinators,    module Text.Parser.LookAhead)@@ -19,7 +19,8 @@ import Text.Parser.LookAhead (LookAheadParsing(lookAhead))  import qualified Rank2-import Text.Grampa.Class (MultiParsing(..), GrammarParsing(..), MonoidParsing(..), ParseResults, ParseFailure(..))+import Text.Grampa.Class (Lexical(..), MultiParsing(..), GrammarParsing(..), MonoidParsing(..), AmbiguousParsing(..),+                          Ambiguous(..), ParseResults, ParseFailure(..))  -- | 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)
src/Text/Grampa/Class.hs view
@@ -1,14 +1,25 @@-{-# LANGUAGE ConstraintKinds, RankNTypes, TypeFamilies #-}-module Text.Grampa.Class (MultiParsing(..), GrammarParsing(..), MonoidParsing(..),-                          ParseResults, ParseFailure(..), completeParser) where+{-# LANGUAGE AllowAmbiguousTypes, ConstraintKinds, DefaultSignatures, RankNTypes, ScopedTypeVariables,+             TypeApplications, TypeFamilies, DeriveDataTypeable, DeriveFunctor #-}+module Text.Grampa.Class (MultiParsing(..), AmbiguousParsing(..), GrammarParsing(..), MonoidParsing(..), Lexical(..),+                          ParseResults, ParseFailure(..), Ambiguous(..), completeParser) where +import Control.Applicative (Alternative(empty), liftA2, (<|>))+import Control.Monad (guard)+import Data.Char (isAlphaNum, isLetter, isSpace)+import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..))-import Data.Monoid (Monoid)+import Data.List.NonEmpty (NonEmpty((:|)))+import Data.Data (Data)+import Data.Typeable (Typeable)+import Data.Monoid (Monoid, (<>)) import Data.Monoid.Cancellative (LeftReductiveMonoid) import qualified Data.Monoid.Null as Null import Data.Monoid.Null (MonoidNull) import Data.Monoid.Factorial (FactorialMonoid) import Data.Monoid.Textual (TextualMonoid)+import Text.Parser.Combinators (Parsing(notFollowedBy), skipMany, skipSome)+import Text.Parser.Char (CharParsing(char))+import Text.Parser.Token (TokenParsing, IdentifierStyle) import GHC.Exts (Constraint)  import qualified Rank2@@ -18,6 +29,15 @@ -- | 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) +-- | 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, Functor, Ord, Show, Typeable)++instance Show1 Ambiguous where+   liftShowsPrec sp sl d (Ambiguous (h :| l)) t+      | d > 5 = "(Ambiguous $ " <> sp 0 h (" :| " <> sl l (')' : t))+      | otherwise = "Ambiguous (" <> sp 0 h (" :| " <> sl l (')' : t))+ completeParser :: MonoidNull s => Compose ParseResults (Compose [] ((,) s)) r -> Compose ParseResults [] r completeParser (Compose (Left failure)) = Compose (Left failure) completeParser (Compose (Right (Compose results))) =@@ -38,7 +58,7 @@    parsePrefix :: (GrammarConstraint m g, FactorialMonoid s) =>                   g (m g s) -> s -> g (Compose (ResultFunctor m) ((,) s)) --- | Parsers that belong to this class memoize the parse results to avoid exponential performance complexity.+-- | 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 :: ((* -> *) -> *) -> * -> * -> *    -- | Used to reference a grammar production, only necessary from outside the grammar itself@@ -63,8 +83,6 @@     -- | A parser that accepts any single input atom.    anyToken :: FactorialMonoid s => m s s-   -- | A parser that accepts a specific input atom.-   token :: (Eq s, FactorialMonoid s) => 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@@ -111,9 +129,70 @@    -- | 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-   -- | Consume all whitespace characters.-   whiteSpace :: TextualMonoid s => m s ()    -- | Zero or more argument occurrences like 'many', with concatenated monoidal results.    concatMany :: Monoid a => m s a -> m s a -   token x = satisfy (== x)+-- | Parsers that can produce alternative parses and collect them into an 'Ambiguous' node+class 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 'TokenParsing' class.+class Lexical (g :: (* -> *) -> *) where+   type LexicalConstraint (m :: ((* -> *) -> *) -> * -> * -> *) g s :: Constraint+   -- | Always succeeds, consuming all white space and comments+   lexicalWhiteSpace :: LexicalConstraint m g s => m g s ()+   -- | Consumes all whitespace and comments, failing if there are none+   someLexicalSpace :: LexicalConstraint m g s => m g s ()+   -- | Consumes a single comment, defaults to 'empty'+   lexicalComment :: LexicalConstraint m g s => m g s ()+   -- | 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+   -- | Applies the argument parser and consumes the trailing 'lexicalWhitespace'+   lexicalToken :: LexicalConstraint m g s => m g s a -> m g s 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+   -- | 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+   -- | 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 ()++   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),+                          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)+   lexicalComment = empty+   lexicalSemicolon = lexicalToken (char ';')+   lexicalToken p = p <* lexicalWhiteSpace+   isIdentifierStartChar c = isLetter c || c == '_'+   isIdentifierFollowChar c = isAlphaNum c || c == '_'+   identifier = identifierToken (liftA2 (<>) (satisfyCharInput (isIdentifierStartChar @g))+                                             (takeCharsWhile (isIdentifierFollowChar @g)))+   identifierToken = lexicalToken+   keyword s = lexicalToken (string s *> notSatisfyChar (isIdentifierFollowChar @g))
src/Text/Grampa/ContextFree/Continued.hs view
@@ -1,15 +1,15 @@-{-# LANGUAGE InstanceSigs, RankNTypes, ScopedTypeVariables, TypeFamilies #-}+{-# LANGUAGE InstanceSigs, RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-} -- | Continuation-passing parser for context-free grammars module Text.Grampa.ContextFree.Continued (Parser(..), Result(..), alt) where  import Control.Applicative (Applicative(..), Alternative(..), liftA2) import Control.Monad (Monad(..), MonadPlus(..)) -import Data.Char (isSpace) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (nub)-import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Semigroup (Semigroup(..))+import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Factorial(FactorialMonoid) import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString)@@ -25,8 +25,9 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))-import Text.Grampa.Class (MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token+import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,@@ -81,6 +82,9 @@    mzero = empty    mplus = (<|>) +instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)+ instance Monoid x => Monoid (Parser g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -112,8 +116,10 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = () <$ takeCharsWhile1 isSpace+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@@ -204,13 +210,12 @@       p s' success failure          | Just suffix <- Cancellative.stripPrefix s s' = success s suffix failure          | otherwise = failure (FailureInfo 1 (fromIntegral $ Factorial.length s') ["string " ++ show s])-   whiteSpace = () <$ takeCharsWhile isSpace    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 . (prefix <>)) (const $ success prefix suffix failure')+                        q suffix (success . mappend prefix) (const $ success prefix suffix failure')    {-# INLINABLE string #-}  -- | Continuation-passing context-free parser
src/Text/Grampa/ContextFree/Continued/Measured.hs view
@@ -1,15 +1,15 @@-{-# LANGUAGE BangPatterns, InstanceSigs, RankNTypes, ScopedTypeVariables, TypeFamilies #-}+{-# LANGUAGE BangPatterns, InstanceSigs, RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-} -- | Continuation-passing parser for context-free grammars that keeps track of the parsed prefix length module Text.Grampa.ContextFree.Continued.Measured (Parser(..), Result(..), alt) where  import Control.Applicative (Applicative(..), Alternative(..), liftA2) import Control.Monad (Monad(..), MonadPlus(..)) -import Data.Char (isSpace) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (nub)-import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Semigroup (Semigroup(..))+import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Factorial(FactorialMonoid) import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString)@@ -25,8 +25,9 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))-import Text.Grampa.Class (MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token+import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,@@ -83,6 +84,9 @@    mzero = empty    mplus = (<|>) +instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)+ instance Monoid x => Monoid (Parser g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -115,8 +119,10 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = () <$ takeCharsWhile1 isSpace+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@@ -216,14 +222,13 @@       p s' success failure          | Just suffix <- Cancellative.stripPrefix s s', !len <- Factorial.length s = success s len suffix failure          | otherwise = failure (FailureInfo 1 (fromIntegral $ Factorial.length s') ["string " ++ show s])-   whiteSpace = () <$ takeCharsWhile isSpace    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 (prefix <> prefix') (len + len')) +                          (\prefix' !len'-> success (mappend prefix prefix') (len + len'))                            (const $ success prefix len suffix failure')    {-# INLINABLE string #-} 
src/Text/Grampa/ContextFree/LeftRecursive.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, InstanceSigs,-             RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeFamilies, UndecidableInstances #-}+             RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeFamilies, TypeOperators, UndecidableInstances #-} {-# OPTIONS -fno-full-laziness #-}-module Text.Grampa.ContextFree.LeftRecursive (Fixed, Parser, SeparatedParser(..), longest, peg, terminalPEG, +module Text.Grampa.ContextFree.LeftRecursive (Fixed, Parser, SeparatedParser(..),+                                              longest, peg, terminalPEG,                                               parseSeparated, separated, (<<|>)) where @@ -9,11 +10,12 @@ import Control.Monad (Monad(..), MonadPlus(..)) import Control.Monad.Trans.State.Lazy (State, evalState, get, put) -import Data.Char (isSpace) import Data.Functor.Compose (Compose(..))+import Data.List.NonEmpty (NonEmpty((:|))) import Data.Maybe (isJust) -import Data.Monoid (Monoid(mempty), All(..), Any(..), (<>))+import Data.Semigroup (Semigroup(..))+import Data.Monoid (Monoid(mempty), All(..), Any(..)) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid) import Data.Monoid.Textual (TextualMonoid)@@ -25,22 +27,26 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token as Token  import qualified Rank2-import Text.Grampa.Class (GrammarParsing(..), MonoidParsing(..), MultiParsing(..), ParseResults)-import Text.Grampa.Internal (BinTree(EmptyTree))-import Text.Grampa.ContextFree.Memoizing (ResultList(..), fromResultList)-import qualified Text.Grampa.ContextFree.Memoizing as Memoizing+import Text.Grampa.Class (GrammarParsing(..), MonoidParsing(..), MultiParsing(..), AmbiguousParsing(..),+                          Lexical(..), Ambiguous(..), ParseResults)+import Text.Grampa.Internal (ResultList(..), ResultsOfLength(..), fromResultList)+import qualified Text.Grampa.ContextFree.SortedMemoizing as Memoizing import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack  import Prelude hiding (cycle, null, span, takeWhile)  type Parser = Fixed Memoizing.Parser +type ResultAppend g s = ResultList g s Rank2.~> ResultList g s Rank2.~> ResultList 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,       cyclicDescendants :: Rank2.Apply g => g (Const (ParserFlags g)) -> ParserFlags g}    | DirectParser {       complete, direct0, direct1 :: p g s a}@@ -51,6 +57,7 @@                              | 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}@@ -69,6 +76,9 @@ --instance Rank2.Applicative g => Monoid (Union g) where --   mempty = Union (Rank2.pure $ Const False) +instance (Rank2.Apply g, Rank2.Distributive g) => Semigroup (Union g) where+   Union g1 <> Union g2 = Union (Rank2.liftA2 union g1 g2)+ instance (Rank2.Apply g, Rank2.Distributive g) => Monoid (Union g) where    mempty = Union (Rank2.cotraverse (Const . getConst) (Const False))    mappend (Union g1) (Union g2) = Union (Rank2.liftA2 union g1 g2)@@ -81,6 +91,7 @@    direct0= direct0 p',    direct1= direct1 p',    indirect= indirect p',+   appendResults= appendResults p',    cyclicDescendants= cyclicDescendants p'}    where p' = general' p @@ -90,6 +101,7 @@    direct0= empty,    direct1= complete p,    indirect= empty,+   appendResults= (<>),    cyclicDescendants= \cd-> ParserFlags False (const (Const False) Rank2.<$> cd)} general' p@DirectParser{} = Parser{    complete= complete p,@@ -97,6 +109,7 @@    direct0= direct0 p,    direct1= direct1 p,    indirect= empty,+   appendResults= (<>),    cyclicDescendants= \cd-> ParserFlags True (const (Const False) Rank2.<$> cd)} general' p@Parser{} = p @@ -129,6 +142,7 @@       direct0= empty,       direct1= empty,       indirect= ind,+      appendResults= (<>),       cyclicDescendants= parserFlags . f . Rank2.fmap (ParserFlagsFunctor . getConst) . addSelf}       where ind = nonTerminal (parserResults . f . Rank2.fmap ParserResultsFunctor)             addSelf g = Rank2.liftA2 adjust bits g@@ -159,7 +173,8 @@       direct= fmap f (direct p),       direct0= fmap f (direct0 p),       direct1= fmap f (direct1 p),-      indirect= fmap f (indirect p)}+      indirect= fmap f (indirect p),+      appendResults= (<>)}    {-# INLINABLE fmap #-}  instance Alternative (p g s) => Applicative (Fixed p g s) where@@ -180,6 +195,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= (<>),       cyclicDescendants= \deps-> let            pcd@(ParserFlags pn pd) = cyclicDescendants p' deps            ParserFlags qn qd = cyclicDescendants q deps@@ -193,6 +209,7 @@       direct0= direct0 p' <*> direct0 q',       direct1= direct0 p' <*> direct1 q' <|> direct1 p' <*> complete q',       indirect= indirect p' <*> complete q',+      appendResults= (<>),       cyclicDescendants= \deps-> let            pcd@(ParserFlags pn pd) = cyclicDescendants p' deps            ParserFlags qn qd = cyclicDescendants q' deps@@ -224,6 +241,7 @@                     direct0= direct0 p' <|> direct0 q',                     direct1= direct1 p' <|> direct1 q',                     indirect= indirect p' <|> indirect q',+                    appendResults= (<>),                     cyclicDescendants= \deps-> let                          ParserFlags pn pd = cyclicDescendants p' deps                          ParserFlags qn qd = cyclicDescendants q' deps@@ -244,6 +262,7 @@       direct0= d0,       direct1= d1,       indirect= (:) <$> indirect p <*> mcp,+      appendResults= (<>),       cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}       where d0 = pure [] <|> (:[]) <$> direct0 p             d1 = (:) <$> direct1 p <*> mcp@@ -259,6 +278,7 @@       direct0= d0,       direct1= d1,       indirect= (:) <$> indirect p <*> many (complete p),+      appendResults= (<>),       cyclicDescendants= cyclicDescendants p}       where d0 = (:[]) <$> direct0 p             d1= (:) <$> direct1 p <*> many (complete p)@@ -281,6 +301,7 @@                  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@@ -302,6 +323,7 @@       direct0= d0,       direct1= d1,       indirect= direct0 p >>= indirect . general' . cont,+      appendResults= (<>),       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)@@ -311,14 +333,23 @@       direct0= d0,       direct1= d1,       indirect= (indirect p >>= complete . cont) <|> (direct0 p >>= indirect . general' . cont),-      cyclicDescendants= \cd-> (ParserFlags True $ Rank2.fmap (const $ Const True) cd)}+      appendResults= (<>),+      cyclicDescendants= \cd->+         let pcd@(ParserFlags pn _) = cyclicDescendants p' cd+         in if pn+            then ParserFlags True (Rank2.fmap (const $ Const True) cd)+            else pcd}       where d0 = direct0 p >>= direct0 . general' . cont             d1 = (direct0 p >>= direct1 . general' . cont) <|> (direct1 p >>= complete . cont)+            p'@Parser{} = general' p  instance MonadPlus (p g s) => MonadPlus (Fixed p g s) where    mzero = empty    mplus = (<|>) +instance (Alternative (p g s), Semigroup x) => Semigroup (Fixed p g s x) where+   (<>) = liftA2 (<>)+ instance (Alternative (p g s), Monoid x) => Monoid (Fixed p g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -331,7 +362,7 @@ positivePrimitive :: String -> p g s a -> Fixed p g s a positivePrimitive _name p = PositiveDirectParser{complete= p} -instance (LookAheadParsing (p g s), MonoidParsing (Fixed p g)) => Parsing (Fixed p g s) where+instance (Parsing (p g s), MonoidParsing (Fixed p g)) => Parsing (Fixed p g s) where    eof = primitive "eof" eof empty eof    try (PositiveDirectParser p) = PositiveDirectParser (try p)    try p@DirectParser{} = DirectParser{@@ -368,6 +399,7 @@       direct= notFollowedBy (direct p),       direct0= notFollowedBy (direct p),       direct1= empty,+      appendResults= (<>),       indirect= notFollowedBy (indirect p),       cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}    unexpected msg = positivePrimitive "unexpected" (unexpected msg)@@ -387,6 +419,7 @@       direct= lookAhead (direct p),       direct0= lookAhead (direct p),       direct1= empty,+      appendResults= appendResults p,       indirect= lookAhead (indirect p),       cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}} @@ -394,7 +427,6 @@    endOfInput = primitive "endOfInput" endOfInput empty endOfInput    getInput = primitive "getInput" (endOfInput *> getInput) (notFollowedBy endOfInput *> getInput) getInput    anyToken = positivePrimitive "anyToken" anyToken-   token x = positivePrimitive "token" (token x)    satisfy predicate = positivePrimitive "satisfy" (satisfy predicate)    satisfyChar predicate = positivePrimitive "satisfyChar" (satisfyChar predicate)    satisfyCharInput predicate = positivePrimitive "satisfyCharInput" (satisfyCharInput predicate)@@ -415,30 +447,30 @@    takeCharsWhile predicate = primitive "takeCharsWhile" (mempty <$ notSatisfyChar predicate)                                                          (takeCharsWhile1 predicate) (takeCharsWhile predicate)    takeCharsWhile1 predicate = positivePrimitive "takeCharsWhile1" (takeCharsWhile1 predicate)-   whiteSpace = primitive "whiteSpace" (notSatisfyChar isSpace) (satisfyChar isSpace *> whiteSpace) whiteSpace    concatMany p@PositiveDirectParser{} = DirectParser{       complete= cmp,       direct0= d0,       direct1= d1}       where d0 = pure mempty-            d1 = (<>) <$> complete p <*> cmp+            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 = (<>) <$> direct1 p <*> cmp+            d1 = mappend <$> direct1 p <*> cmp             cmp = concatMany (complete p)    concatMany p@Parser{} = Parser{       complete= cmp,       direct= d0 <|> d1,       direct0= d0,       direct1= d1,-      indirect= (<>) <$> indirect p <*> cmp,+      indirect= mappend <$> indirect p <*> cmp,+      appendResults= mappend,       cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}       where d0 = pure mempty <|> direct0 p-            d1 = (<>) <$> direct1 p <*> cmp+            d1 = mappend <$> direct1 p <*> cmp             cmp = concatMany (complete p)    {-# INLINABLE string #-} @@ -446,7 +478,6 @@    endOfInput = primitive "endOfInput" endOfInput empty endOfInput    getInput = primitive "getInput" (endOfInput *> getInput) (notFollowedBy endOfInput *> getInput) getInput    anyToken = positivePrimitive "anyToken" anyToken-   token x = positivePrimitive "token" (token x)    satisfy predicate = positivePrimitive "satisfy" (satisfy predicate)    satisfyChar predicate = positivePrimitive "satisfyChar" (satisfyChar predicate)    satisfyCharInput predicate = positivePrimitive "satisfyCharInput" (satisfyCharInput predicate)@@ -467,35 +498,34 @@    takeCharsWhile predicate = primitive "takeCharsWhile" (mempty <$ notSatisfyChar predicate)                                                          (takeCharsWhile1 predicate) (takeCharsWhile predicate)    takeCharsWhile1 predicate = positivePrimitive "takeCharsWhile1" (takeCharsWhile1 predicate)-   whiteSpace = primitive "whiteSpace" (notSatisfyChar isSpace) (satisfyChar isSpace *> whiteSpace) whiteSpace    concatMany p@PositiveDirectParser{} = DirectParser{       complete= cmp,       direct0= d0,       direct1= d1}       where d0 = pure mempty-            d1 = (<>) <$> complete p <*> cmp+            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 = (<>) <$> direct1 p <*> cmp+            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= (<>) <$> indirect p <*> cmp,+      indirect= mappend <$> indirect p <*> cmp,+      appendResults= mappend,       cyclicDescendants= \deps-> (cyclicDescendants p deps){nullable= True}}       where d0 = pure mempty `Backtrack.alt` direct0 p-            d1 = (<>) <$> direct1 p <*> cmp+            d1 = mappend <$> direct1 p <*> cmp             cmp = concatMany (complete p)    {-# INLINABLE string #-} -instance (LookAheadParsing (p g s), MonoidParsing (Fixed p g), Show s, TextualMonoid s) =>-         CharParsing (Fixed p g s) where+instance (Parsing (p g s), MonoidParsing (Fixed p g), Show s, TextualMonoid s) => CharParsing (Fixed p g s) where    satisfy = satisfyChar    string s = Textual.toString (error "unexpected non-character") <$> string (fromString s)    char = satisfyChar . (==)@@ -503,10 +533,41 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (LookAheadParsing (p g s), TokenParsing (p g s), MonoidParsing (Fixed p g), Show s, TextualMonoid s) => -         TokenParsing (Fixed p g s) where-   someSpace = positivePrimitive "someSpace" someSpace+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+   ambiguous (PositiveDirectParser p) = PositiveDirectParser (ambiguous p)+   ambiguous p@DirectParser{} = DirectParser{complete= ambiguous (complete p),+                                             direct0=  ambiguous (direct0 p),+                                             direct1=  ambiguous (direct1 p)}+   ambiguous p@Parser{} = Parser{complete= ambiguous (complete p),+                                 direct=   ambiguous (direct p),+                                 direct0=  ambiguous (direct0 p),+                                 direct1=  ambiguous (direct1 p),+                                 indirect= ambiguous (indirect p),+                                 appendResults= appendAmbiguous,+                                 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"+ -- | Turns a context-free parser into a backtracking PEG parser that consumes the longest possible prefix of the list -- of input tails, opposite of 'peg' longest :: Fixed Memoizing.Parser g s a -> Fixed Backtrack.Parser g [(s, g (ResultList g s))] a@@ -519,6 +580,7 @@                             direct0=  Memoizing.longest (direct0 p),                             direct1=  Memoizing.longest (direct1 p),                             indirect=  Memoizing.longest (indirect p),+                            appendResults= (<>),                             cyclicDescendants= cyclicDescendants p}  -- | Turns a backtracking PEG parser of the list of input tails into a context-free parser, opposite of 'longest'@@ -532,6 +594,7 @@                         direct0=  Memoizing.peg (direct0 p),                         direct1=  Memoizing.peg (direct1 p),                         indirect=  Memoizing.peg (indirect p),+                        appendResults= (<>),                         cyclicDescendants= cyclicDescendants p}  -- | Turns a backtracking PEG parser into a context-free parser@@ -545,6 +608,7 @@                                 direct0=  Memoizing.terminalPEG (direct0 p),                                 direct1=  Memoizing.terminalPEG (direct1 p),                                 indirect=  Memoizing.terminalPEG (indirect p),+                                appendResults= (<>),                                 cyclicDescendants= cyclicDescendants p}  parseRecursive :: forall g s. (Rank2.Apply g, Rank2.Distributive g, Rank2.Traversable g, FactorialMonoid s) =>@@ -562,7 +626,8 @@          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 (Const circular) (Const follower) (Const deps) p-            | circular || leader && follower = CycleParser (indirect p) (direct p) deps+            | circular || leader && follower =+              CycleParser (indirect p) (direct p) (Rank2.Arrow (Rank2.Arrow . appendResults p)) deps             | follower = BackParser (complete p)             | otherwise = FrontParser (complete p)             where leader = getAny (Rank2.foldMap (Any . getConst) $ Rank2.liftA2 intersection circulars deps)@@ -621,27 +686,30 @@          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)          recurseOnce :: s -> [(s, g (ResultList g s))] -> g (ResultList g s) -> g (ResultList g s)-         maybeDependencies :: g (Const (Maybe (g (Const Bool))))+         maybeDependencies :: g (Rank2.Product (Const (Maybe (g (Const Bool)))) (ResultAppend g s))+         maybeDependency :: SeparatedParser Memoizing.Parser g s r+                         -> Rank2.Product (Const (Maybe (g (Const Bool)))) (ResultAppend g s) r           directs = Rank2.fmap backParser parsers          indirects = Rank2.fmap (\p-> case p of {CycleParser{}-> cycleParser p; _ -> empty}) parsers-         maybeDependencies = Rank2.fmap (Const . maybeDependency) parsers-         maybeDependency p@CycleParser{} = Just (dependencies p)-         maybeDependency _ = Nothing-                                                                   +         maybeDependencies = Rank2.fmap maybeDependency parsers+         maybeDependency p@CycleParser{} = Rank2.Pair (Const $ Just $ dependencies p) (appendResultsArrow p)+         maybeDependency _ = Rank2.Pair (Const Nothing) (Rank2.Arrow (Rank2.Arrow . (<>)))+          fixRecursive s parsedTail initial =             foldr1 whileAnyContinues (iterate (recurseOnce s parsedTail) initial)           whileAnyContinues g1 g2 = Rank2.liftA3 choiceWhile maybeDependencies g1 g2-            where choiceWhile :: Const (Maybe (g (Const Bool))) x -> ResultList g i x -> ResultList g i x -                                 -> ResultList g i x-                  combine :: Const Bool x -> ResultList g i x -> Const Bool x-                  choiceWhile (Const Nothing) r1 _ = r1-                  choiceWhile (Const (Just deps)) r1 r2-                     | getAny (Rank2.foldMap (Any . getConst) (Rank2.liftA2 combine deps g1)) = r1 <> r2+            where choiceWhile :: Rank2.Product (Const (Maybe (g (Const Bool)))) (ResultAppend g s) x+                              -> ResultList g s x -> ResultList g s x -> ResultList g s x+                  combine :: Const Bool x -> ResultList g s x -> Const Bool x+                  choiceWhile (Rank2.Pair (Const Nothing) _) r1 _ = r1+                  choiceWhile (Rank2.Pair (Const (Just deps)) append) r1 r2+                     | getAny (Rank2.foldMap (Any . getConst) (Rank2.liftA2 combine deps g1)) =+                       append `Rank2.apply` r1 `Rank2.apply` r2                      | otherwise = r1                   combine (Const False) _ = Const False-                  combine (Const True) (ResultList EmptyTree _) = Const False+                  combine (Const True) (ResultList [] _) = Const False                   combine (Const True) _ = Const True           recurseOnce s parsedTail initial = Rank2.fmap (($ parsed) . Memoizing.applyParser) indirects
src/Text/Grampa/ContextFree/Memoizing.hs view
@@ -1,18 +1,18 @@ {-# LANGUAGE FlexibleContexts, GeneralizedNewtypeDeriving, InstanceSigs,-             RankNTypes, ScopedTypeVariables, TypeFamilies #-}+             RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-} module Text.Grampa.ContextFree.Memoizing (FailureInfo(..), ResultList(..), Parser(..), BinTree(..), (<<|>),                                           fromResultList, reparseTails, longest, peg, terminalPEG) where  import Control.Applicative import Control.Monad (Monad(..), MonadPlus(..))-import Data.Char (isSpace) import Data.Function (on) import Data.Foldable (toList) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (genericLength, maximumBy, nub)-import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Semigroup (Semigroup(..))+import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Cancellative (LeftReductiveMonoid (isPrefixOf)) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid(length, splitPrimePrefix))@@ -25,11 +25,13 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token  import qualified Rank2 -import Text.Grampa.Class (GrammarParsing(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Grampa.Class (Lexical(..), GrammarParsing(..), MonoidParsing(..), MultiParsing(..), +                          ParseResults, ParseFailure(..)) import Text.Grampa.Internal (BinTree(..), FailureInfo(..)) import qualified Text.Grampa.PEG.Backtrack.Measured as Backtrack @@ -58,9 +60,12 @@ instance Functor (ResultList g s) where    fmap f (ResultList l failure) = ResultList ((f <$>) <$> l) failure +instance Semigroup (ResultList g s r) where+   ResultList rl1 f1 <> ResultList rl2 f2 = ResultList (rl1 <> rl2) (f1 <> f2)+ instance Monoid (ResultList g s r) where    mempty = ResultList mempty mempty-   ResultList rl1 f1 `mappend` ResultList rl2 f2 = ResultList (rl1 <> rl2) (f1 <> f2)+   mappend = (<>)  instance Functor (Parser g i) where    fmap f (Parser p) = Parser (fmap f . p)@@ -103,6 +108,9 @@    mzero = empty    mplus = (<|>) +instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)+ instance Monoid x => Monoid (Parser g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -205,9 +213,8 @@          | s `isPrefixOf` s' = ResultList (Leaf $ ResultInfo l (Factorial.drop l rest) s) mempty       p rest = ResultList mempty (FailureInfo 1 (genericLength rest) ["string " ++ show s])       l = Factorial.length s-   whiteSpace = () <$ takeCharsWhile isSpace    concatMany p = go-      where go = mempty <|> (<>) <$> p <*> go+      where go = mempty <|> mappend <$> p <*> go    notSatisfy predicate = Parser p       where p rest@((s, _):_)                | Just (first, _) <- splitPrimePrefix s, @@ -250,8 +257,10 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = () <$ takeCharsWhile1 isSpace+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)) =
src/Text/Grampa/ContextFree/Parallel.hs view
@@ -1,16 +1,16 @@ {-# LANGUAGE FlexibleContexts, InstanceSigs, GeneralizedNewtypeDeriving,-             RankNTypes, ScopedTypeVariables, TypeFamilies #-}+             RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-} module Text.Grampa.ContextFree.Parallel (FailureInfo(..), ResultList(..), Parser, fromResultList) where  import Control.Applicative import Control.Monad (Monad(..), MonadPlus(..))-import Data.Char (isSpace) import Data.Foldable (toList) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (nub)-import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Semigroup (Semigroup(..))+import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid) import Data.Monoid.Textual (TextualMonoid)@@ -24,11 +24,12 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token  import qualified Rank2 -import Text.Grampa.Class (MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..)) import Text.Grampa.Internal (BinTree(..))  import Prelude hiding (iterate, null, showList, span, takeWhile)@@ -57,13 +58,15 @@ instance Functor (ResultList s) where    fmap f (ResultList l failure) = ResultList ((f <$>) <$> l) failure +instance Semigroup (ResultList s r) where+   ResultList rl1 f1 <> ResultList rl2 f2 = ResultList (rl1 <> rl2) (f1 <> f2)+ instance Monoid (ResultList s r) where    mempty = ResultList mempty mempty-   ResultList rl1 f1 `mappend` ResultList rl2 f2 = ResultList (rl1 <> rl2) (f1 <> f2)+   mappend = (<>) -instance Monoid FailureInfo where-   mempty = FailureInfo 0 maxBound []-   f1@(FailureInfo s1 pos1 exp1) `mappend` f2@(FailureInfo s2 pos2 exp2)+instance Semigroup FailureInfo where+   f1@(FailureInfo s1 pos1 exp1) <> f2@(FailureInfo s2 pos2 exp2)       | s1 < s2 = f2       | s1 > s2 = f1       | otherwise = FailureInfo s1 pos' exp'@@ -71,6 +74,10 @@                          | pos1 > pos2 = (pos2, exp2)                          | otherwise = (pos1, exp1 <> exp2) +instance Monoid FailureInfo where+   mempty = FailureInfo 0 maxBound []+   mappend = (<>)+ instance Functor (Parser g s) where    fmap f (Parser p) = Parser (fmap f . p) @@ -98,6 +105,9 @@    mzero = empty    mplus = (<|>) +instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)+ instance Monoid x => Monoid (Parser g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -175,11 +185,10 @@    string s = Parser p where       p s' | Just suffix <- Cancellative.stripPrefix s s' = ResultList (Leaf $ ResultInfo suffix s) mempty            | otherwise = ResultList mempty (FailureInfo 1 (Factorial.length s') ["string " ++ show s])-   whiteSpace = () <$ takeCharsWhile isSpace    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) = (prefix <>) <$> q suffix+            continue (ResultInfo suffix prefix) = mappend prefix <$> q suffix  instance FactorialMonoid s => Parsing (Parser g s) where    try (Parser p) = Parser (weakenResults . p)@@ -207,8 +216,10 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = () <$ takeCharsWhile1 isSpace+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 s (ResultList EmptyTree (FailureInfo _ pos msgs)) = 
+ src/Text/Grampa/ContextFree/SortedMemoizing.hs view
@@ -0,0 +1,271 @@+{-# LANGUAGE FlexibleContexts, GeneralizedNewtypeDeriving, InstanceSigs,+             RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-}+module Text.Grampa.ContextFree.SortedMemoizing +       (FailureInfo(..), ResultList(..), Parser(..), (<<|>),+        reparseTails, longest, peg, terminalPEG)+where++import Control.Applicative+import Control.Monad (Monad(..), MonadPlus(..))+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 (LeftReductiveMonoid (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.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.Internal (FailureInfo(..), ResultList(..), ResultsOfLength(..), fromResultList)+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 of parse results. It does not support left-recursive+-- grammars.+newtype Parser g s r = Parser{applyParser :: [(s, g (ResultList g s))] -> ResultList g s r}++instance Functor (Parser g i) where+   fmap f (Parser p) = Parser (fmap f . p)+   {-# INLINABLE fmap #-}++instance Applicative (Parser g i) where+   pure a = Parser (\rest-> ResultList [ResultsOfLength 0 rest (a:|[])] mempty)+   Parser p <*> Parser q = Parser r where+      r rest = case p rest+               of ResultList results failure -> ResultList mempty failure <> foldMap continue results+      continue (ResultsOfLength l rest' fs) = foldMap (continue' l $ q rest') fs+      continue' l (ResultList rs failure) f = ResultList (adjust l f <$> rs) failure+      adjust l f (ResultsOfLength l' rest' as) = ResultsOfLength (l+l') rest' (f <$> as)+   {-# INLINABLE pure #-}+   {-# INLINABLE (<*>) #-}++instance Alternative (Parser g i) where+   empty = Parser (\rest-> ResultList mempty $ FailureInfo 0 (genericLength rest) ["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 [] _failure) -> rl <> q rest+               rl -> rl++instance Monad (Parser g i) 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 (ResultsOfLength l rest' rs) = foldMap (continue' l . flip applyParser rest' . f) rs+      continue' l (ResultList rs failure) = ResultList (adjust l <$> rs) failure+      adjust l (ResultsOfLength l' rest' rs) = ResultsOfLength (l+l') rest' rs++instance MonadPlus (Parser g s) where+   mzero = empty+   mplus = (<|>)++instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)++instance Monoid x => Monoid (Parser g s x) where+   mempty = pure mempty+   mappend = liftA2 mappend++instance GrammarParsing Parser where+   type GrammarFunctor Parser = ResultList+   nonTerminal f = Parser p where+      p ((_, d) : _) = f d+      p _ = ResultList mempty (FailureInfo 1 0 ["NonTerminal at endOfInput"])+   {-# INLINE nonTerminal #-}++-- | 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' [])+-- @+instance MultiParsing Parser where+   type ResultFunctor Parser = Compose ParseResults []+   -- | 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 [])+   parseComplete g input = Rank2.fmap ((snd <$>) . Compose . fromResultList input)+                              (snd $ head $ reparseTails close $ parseTails g input)+      where close = Rank2.fmap (<* endOfInput) 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)+   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+   getInput = Parser p+      where p rest@((s, _):_) = ResultList [ResultsOfLength (length rest) [last 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 1 (genericLength rest) ["anyToken"])+            p [] = ResultList mempty (FailureInfo 1 0 ["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 1 (genericLength rest) ["satisfy"])+            p [] = ResultList mempty (FailureInfo 1 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 1 (genericLength rest) ["satisfyChar"])+            p [] = ResultList mempty (FailureInfo 1 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 1 (genericLength rest) ["satisfyCharInput"])+            p [] = ResultList mempty (FailureInfo 1 0 ["satisfyCharInput"])+   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+   takeWhile predicate = Parser p+      where p rest@((s, _) : _)+               | x <- Factorial.takeWhile predicate s, l <- Factorial.length x =+                    ResultList [ResultsOfLength l (drop l rest) (x:|[])] mempty+            p [] = ResultList [ResultsOfLength 0 [] (mempty:|[])] mempty+   takeWhile1 predicate = Parser p+      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 1 (genericLength rest) ["takeWhile1"])+   takeCharsWhile predicate = Parser p+      where p rest@((s, _) : _)+               | x <- Textual.takeWhile_ False predicate s, l <- Factorial.length x =+                    ResultList [ResultsOfLength l (drop l rest) (x:|[])] mempty+            p [] = ResultList [ResultsOfLength 0 [] (mempty:|[])] mempty+   takeCharsWhile1 predicate = Parser p+      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 1 (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 1 (genericLength rest) ["string " ++ show s])+      l = Factorial.length s+   concatMany p = go+      where go = mempty <|> mappend <$> p <*> go+   notSatisfy predicate = Parser p+      where p rest@((s, _):_)+               | Just (first, _) <- splitPrimePrefix s, +                 predicate first = ResultList mempty (FailureInfo 1 (genericLength rest) ["notSatisfy"])+            p rest = ResultList [ResultsOfLength 0 rest (():|[])] mempty+   notSatisfyChar predicate = Parser p+      where p rest@((s, _):_)+               | Just first <- Textual.characterPrefix s, +                 predicate first = ResultList mempty (FailureInfo 1 (genericLength rest) ["notSatisfyChar"])+            p rest = ResultList [ResultsOfLength 0 rest (():|[])] mempty+   {-# INLINABLE string #-}++instance MonoidNull s => Parsing (Parser g s) where+   try (Parser p) = Parser (weakenResults . p)+      where weakenResults (ResultList rl (FailureInfo s pos msgs)) = ResultList rl (FailureInfo (pred s) pos msgs)+   Parser p <?> msg  = Parser (strengthenResults . p)+      where strengthenResults (ResultList rl (FailureInfo s pos _msgs)) = ResultList rl (FailureInfo (succ s) pos [msg])+   notFollowedBy (Parser p) = Parser (\input-> rewind input (p input))+      where rewind t (ResultList [] _) = ResultList [ResultsOfLength 0 t (():|[])] mempty+            rewind t ResultList{} = ResultList mempty (FailureInfo 1 (genericLength t) ["notFollowedBy"])+   skipMany p = go+      where go = pure () <|> p *> go+   unexpected msg = Parser (\t-> ResultList mempty $ FailureInfo 0 (genericLength t) [msg])+   eof = Parser f+      where f rest@((s, _):_)+               | null s = ResultList [ResultsOfLength 0 rest (():|[])] mempty+               | otherwise = ResultList mempty (FailureInfo 1 (genericLength rest) ["endOfInput"])+            f [] = ResultList [ResultsOfLength 0 [] (():|[])] mempty++instance MonoidNull s => LookAheadParsing (Parser g s) where+   lookAhead (Parser p) = Parser (\input-> rewind input (p input))+      where rewind _ rl@(ResultList [] _) = rl+            rewind t (ResultList rl failure) = ResultList [ResultsOfLength 0 t $ foldr1 (<>) (results <$> rl)] failure+            results (ResultsOfLength _ _ r) = r++instance (Show s, TextualMonoid s) => CharParsing (Parser g s) where+   satisfy = satisfyChar+   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+            groupByLength (ResultsOfLength l rest rs) = ResultsOfLength l rest (Ambiguous 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 :: 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+               ResultList rs _ -> parsed (last rs)+   parsed (ResultsOfLength l s (r:|_)) = Backtrack.Parsed l r s++-- | 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++-- | Turns a backtracking PEG parser into a context-free parser+terminalPEG :: Monoid s => Backtrack.Parser g s a -> Parser g s a+terminalPEG p = Parser q where+   q [] = case Backtrack.applyParser p mempty+            of Backtrack.Parsed l result _ -> ResultList [ResultsOfLength l [] (result:|[])] mempty+               Backtrack.NoParse failure -> ResultList mempty failure+   q rest@((s, _):_) = case Backtrack.applyParser p s+                       of Backtrack.Parsed l result _ -> +                             ResultList [ResultsOfLength l (drop l rest) (result:|[])] mempty+                          Backtrack.NoParse failure -> ResultList mempty failure
src/Text/Grampa/Internal.hs view
@@ -1,18 +1,39 @@-module Text.Grampa.Internal (BinTree(..), FailureInfo(..)) where+module Text.Grampa.Internal (BinTree(..), FailureInfo(..), ResultList(..), ResultsOfLength(..), fromResultList) where -import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Foldable (toList)+import Data.Functor.Classes (Show1(..))+import Data.List.NonEmpty (NonEmpty)+import Data.List (nub)+import Data.Monoid (Monoid(mappend, mempty))+import Data.Semigroup (Semigroup((<>))) import Data.Word (Word64) +import Data.Monoid.Factorial (FactorialMonoid(length))++import Text.Grampa.Class (ParseFailure(..), ParseResults)++import Prelude hiding (length, showList)+ data FailureInfo = FailureInfo !Int Word64 [String] 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 BinTree a = Fork !(BinTree a) !(BinTree a)                | Leaf !a                | EmptyTree                deriving (Show) -instance Monoid FailureInfo where-   mempty = FailureInfo 0 maxBound []-   f1@(FailureInfo s1 pos1 exp1) `mappend` f2@(FailureInfo s2 pos2 exp2)+fromResultList :: FactorialMonoid s => s -> ResultList g s r -> ParseResults [(s, r)]+fromResultList s (ResultList [] (FailureInfo _ pos msgs)) =+   Left (ParseFailure (length s - fromIntegral pos + 1) (nub msgs))+fromResultList _ (ResultList rl _failure) = Right (foldMap f rl)+   where f (ResultsOfLength _ ((s, _):_) r) = (,) s <$> toList r+         f (ResultsOfLength _ [] r) = (,) mempty <$> toList r++instance Semigroup FailureInfo where+   f1@(FailureInfo s1 pos1 exp1) <> f2@(FailureInfo s2 pos2 exp2)       | s1 < s2 = f2       | s1 > s2 = f1       | otherwise = FailureInfo s1 pos' exp'@@ -20,18 +41,55 @@                          | pos1 > pos2 = (pos2, exp2)                          | otherwise = (pos1, exp1 <> exp2) +instance Monoid FailureInfo where+   mempty = FailureInfo 0 maxBound []+   mappend = (<>)++instance Show r => Show (ResultList g s r) where+   show (ResultList l f) = "ResultList (" ++ shows l (") (" ++ shows f ")")++instance 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) ""++instance Show r => Show (ResultsOfLength g s r) where+   show (ResultsOfLength l _ r) = "(ResultsOfLength @" ++ show l ++ " " ++ shows r ")"++instance Functor (ResultsOfLength g s) where+   fmap f (ResultsOfLength l t r) = ResultsOfLength l t (f <$> r)++instance Functor (ResultList g s) where+   fmap f (ResultList l failure) = ResultList ((f <$>) <$> l) failure++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++instance Monoid (ResultList g s r) where+   mempty = ResultList mempty mempty+   mappend = (<>)+ instance Functor BinTree where    fmap f (Fork left right) = Fork (fmap f left) (fmap f right)    fmap f (Leaf a) = Leaf (f a)    fmap _ EmptyTree = EmptyTree  instance Foldable BinTree where-   foldMap f (Fork left right) = foldMap f left <> foldMap f right+   foldMap f (Fork left right) = foldMap f left `mappend` foldMap f right    foldMap f (Leaf a) = f a    foldMap _ EmptyTree = mempty +instance Semigroup (BinTree a) where+   EmptyTree <> t = t+   t <> EmptyTree = t+   l <> r = Fork l r+ instance Monoid (BinTree a) where    mempty = EmptyTree-   mappend EmptyTree t = t-   mappend t EmptyTree = t-   mappend l r = Fork l r+   mappend = (<>)
src/Text/Grampa/PEG/Backtrack.hs view
@@ -1,16 +1,17 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies, UndecidableInstances #-} -- | Backtracking parser for Parsing Expression Grammars module Text.Grampa.PEG.Backtrack (Parser(..), Result(..), alt) where  import Control.Applicative (Applicative(..), Alternative(..), liftA2) import Control.Monad (Monad(..), MonadPlus(..)) -import Data.Char (isSpace) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (nub)-import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Semigroup (Semigroup(..))+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@@ -24,8 +25,9 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))-import Text.Grampa.Class (MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token+import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,@@ -78,6 +80,9 @@    mzero = empty    mplus = (<|>) +instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)+ instance Monoid x => Monoid (Parser g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -104,8 +109,10 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Show s, Textual.TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = () <$ takeCharsWhile1 isSpace+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@@ -166,11 +173,10 @@    string s = Parser p where       p s' | Just suffix <- Cancellative.stripPrefix s s' = Parsed s suffix            | otherwise = NoParse (FailureInfo 1 (fromIntegral $ Factorial.length s') ["string " ++ show s])-   whiteSpace = () <$ takeCharsWhile isSpace    concatMany (Parser p) = Parser q       where q rest = case p rest                      of Parsed prefix suffix -> let Parsed prefix' suffix' = q suffix-                                                in Parsed (prefix <> prefix') suffix'+                                                in Parsed (mappend prefix prefix') suffix'                         NoParse{} -> Parsed mempty rest    {-# INLINABLE string #-} 
src/Text/Grampa/PEG/Backtrack/Measured.hs view
@@ -1,16 +1,17 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies, UndecidableInstances #-} -- | Backtracking parser for Parsing Expression Grammars, tracking the consumed input length module Text.Grampa.PEG.Backtrack.Measured (Parser(..), Result(..), alt) where  import Control.Applicative (Applicative(..), Alternative(..), liftA2) import Control.Monad (Monad(..), MonadPlus(..)) -import Data.Char (isSpace) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (nub)-import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Semigroup (Semigroup(..))+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@@ -24,8 +25,9 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))-import Text.Grampa.Class (MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token+import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedLength :: !Int,@@ -83,6 +85,9 @@    mzero = empty    mplus = (<|>) +instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)+ instance Monoid x => Monoid (Parser g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -109,8 +114,10 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Show s, Textual.TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = () <$ takeCharsWhile1 isSpace+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@@ -174,11 +181,10 @@       p s' | Just suffix <- Cancellative.stripPrefix s s' = Parsed l s suffix            | otherwise = NoParse (FailureInfo 1 (fromIntegral $ Factorial.length s') ["string " ++ show s])       l = Factorial.length s-   whiteSpace = () <$ takeCharsWhile isSpace    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') (prefix <> prefix') suffix'+                                                  in Parsed (l+l') (mappend prefix prefix') suffix'                         NoParse{} -> Parsed 0 mempty rest    {-# INLINABLE string #-} 
src/Text/Grampa/PEG/Continued.hs view
@@ -1,15 +1,15 @@-{-# LANGUAGE InstanceSigs, RankNTypes, ScopedTypeVariables, TypeFamilies #-}+{-# LANGUAGE InstanceSigs, RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-} -- | Continuation-passing parser for Parsing Expression Grammars module Text.Grampa.PEG.Continued (Parser(..), Result(..), alt) where  import Control.Applicative (Applicative(..), Alternative(..), liftA2) import Control.Monad (Monad(..), MonadPlus(..)) -import Data.Char (isSpace) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (nub)-import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Semigroup (Semigroup(..))+import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Factorial(FactorialMonoid) import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString)@@ -25,8 +25,9 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))-import Text.Grampa.Class (MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token+import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,@@ -79,6 +80,9 @@    mzero = empty    mplus = (<|>) +instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)+ instance Monoid x => Monoid (Parser g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -110,8 +114,10 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = () <$ takeCharsWhile1 isSpace+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@@ -201,12 +207,11 @@       p s' success failure          | Just suffix <- Cancellative.stripPrefix s s' = success s suffix          | otherwise = failure (FailureInfo 1 (fromIntegral $ Factorial.length s') ["string " ++ show s])-   whiteSpace = () <$ takeCharsWhile isSpace    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 . (prefix <>)) (const $ success prefix suffix)+               where success' prefix suffix = q suffix (success . mappend prefix) (const $ success prefix suffix)                      failure _ = success mempty rest    {-# INLINABLE string #-} 
src/Text/Grampa/PEG/Continued/Measured.hs view
@@ -1,15 +1,15 @@-{-# LANGUAGE BangPatterns, InstanceSigs, RankNTypes, ScopedTypeVariables, TypeFamilies #-}+{-# LANGUAGE BangPatterns, InstanceSigs, RankNTypes, ScopedTypeVariables, TypeFamilies, UndecidableInstances #-} -- | Continuation-passing parser for Parsing Expression Grammars that keeps track of the parsed prefix length module Text.Grampa.PEG.Continued.Measured (Parser(..), Result(..), alt) where  import Control.Applicative (Applicative(..), Alternative(..), liftA2) import Control.Monad (Monad(..), MonadPlus(..)) -import Data.Char (isSpace) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (nub)-import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Semigroup (Semigroup(..))+import Data.Monoid (Monoid(mappend, mempty)) import Data.Monoid.Factorial(FactorialMonoid) import Data.Monoid.Textual(TextualMonoid) import Data.String (fromString)@@ -25,8 +25,9 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))-import Text.Grampa.Class (MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token+import Text.Grampa.Class (Lexical(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..)) import Text.Grampa.Internal (FailureInfo(..))  data Result (g :: (* -> *) -> *) s v = Parsed{parsedPrefix :: !v,@@ -82,6 +83,9 @@    mzero = empty    mplus = (<|>) +instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)+ instance Monoid x => Monoid (Parser g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -113,8 +117,10 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Show s, TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = () <$ takeCharsWhile1 isSpace+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@@ -213,13 +219,12 @@       p s' success failure          | Just suffix <- Cancellative.stripPrefix s s', !len <- Factorial.length s = success s len suffix          | otherwise = failure (FailureInfo 1 (fromIntegral $ Factorial.length s') ["string " ++ show s])-   whiteSpace = () <$ takeCharsWhile isSpace    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 (prefix <> prefix') (len + len')) +                        q suffix (\prefix' !len'-> success (mappend prefix prefix') (len + len'))                            (const $ success prefix len suffix)                      failure _ = success mempty 0 rest    {-# INLINABLE string #-}
src/Text/Grampa/PEG/Packrat.hs view
@@ -1,16 +1,17 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies, UndecidableInstances #-} -- | Packrat parser module Text.Grampa.PEG.Packrat (Parser(..), Result(..)) where  import Control.Applicative (Applicative(..), Alternative(..), liftA2) import Control.Monad (Monad(..), MonadPlus(..)) -import Data.Char (isSpace) import Data.Functor.Classes (Show1(..)) import Data.Functor.Compose (Compose(..)) import Data.List (genericLength, nub)-import Data.Monoid (Monoid(mappend, mempty), (<>))+import Data.Semigroup (Semigroup(..))+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@@ -24,8 +25,10 @@ import Text.Parser.Char (CharParsing) import Text.Parser.Combinators (Parsing(..)) import Text.Parser.LookAhead (LookAheadParsing(..))-import Text.Parser.Token (TokenParsing(someSpace))-import Text.Grampa.Class (GrammarParsing(..), MonoidParsing(..), MultiParsing(..), ParseResults, ParseFailure(..))+import Text.Parser.Token (TokenParsing)+import qualified Text.Parser.Token+import Text.Grampa.Class (Lexical(..), GrammarParsing(..), MonoidParsing(..), MultiParsing(..), +                          ParseResults, ParseFailure(..)) import Text.Grampa.Internal (FailureInfo(..)) import qualified Text.Grampa.PEG.Backtrack as Backtrack (Parser) @@ -74,6 +77,9 @@    mzero = empty    mplus = (<|>) +instance Semigroup x => Semigroup (Parser g s x) where+   (<>) = liftA2 (<>)+ instance Monoid x => Monoid (Parser g s x) where    mempty = pure mempty    mappend = liftA2 mappend@@ -100,8 +106,10 @@    anyChar = satisfyChar (const True)    text t = (fromString . Textual.toString (error "unexpected non-character")) <$> string (Textual.fromText t) -instance (Show s, Textual.TextualMonoid s) => TokenParsing (Parser g s) where-   someSpace = () <$ takeCharsWhile1 isSpace+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@@ -181,9 +189,8 @@       p rest@((s', _) : _)          | Cancellative.isPrefixOf s s' = Parsed s (Factorial.drop (Factorial.length s) rest)       p rest = NoParse (FailureInfo 1 (genericLength rest) ["string " ++ show s])-   whiteSpace = () <$ takeCharsWhile isSpace    concatMany p = go-      where go = (<>) <$> p <*> go <|> mempty+      where go = mappend <$> p <*> go <|> mempty   -- | Packrat parser
test/Test.hs view
@@ -17,6 +17,7 @@  import Data.Functor.Compose (Compose(..)) import Text.Parser.Combinators (sepBy1, skipMany)+import Text.Parser.Token (whiteSpace)  import Test.Feat (Enumerable(..), Enumerate, FreePair(Free), consts, shared, unary, uniform) import Test.Feat.Enumerate (pay)@@ -29,7 +30,7 @@  import qualified Rank2 import qualified Rank2.TH-import Text.Grampa+import Text.Grampa hiding (symbol) import qualified Text.Grampa.ContextFree.Parallel as Parallel import qualified Text.Grampa.ContextFree.LeftRecursive as LeftRecursive @@ -43,6 +44,8 @@                              next :: f String} deriving instance (Show (f String), Show (f [String])) => Show (Recursive f) +instance Lexical Recursive+ $(Rank2.TH.deriveAll ''Recursive)  recursiveManyGrammar Recursive{..} = Recursive{@@ -56,7 +59,7 @@ nameListGrammarBuilder g@Recursive{..} = Recursive{    start= pure (const . unwords) <*> rec <*> (True <$ symbol "," <* symbol "..." <|> pure False) <|>           pure id <*> symbol "..." <?> "start",-   rec= sepBy1 one (ignorable *> string "," <* whiteSpace <?> "comma") <?> "rec",+   rec= sepBy1 one (ignorable *> string "," <?> "comma") <?> "rec",    one= do ignorable            identifier <- ((:) <$> satisfyChar isLetter <*> (toString (const "") <$> takeCharsWhile isLetter))            guard (identifier /= "reserved")@@ -93,11 +96,6 @@              [testProperty "anyToken mempty" $ simpleParse anyToken "" == Left (ParseFailure 0 ["anyToken"]),               testProperty "anyToken list" $                 \(x::Word8) xs-> simpleParse anyToken (x:xs) == Right [(xs, [x])],-              testProperty "token success" $-                \(x::Word8) xs-> simpleParse (token [x]) (x:xs) == Right [(xs, [x])],-              testProperty "token failure" $ \(x::Word8) y xs->-                   x /= y ==> results (simpleParse (token [y]) (x:xs)) == [],-              testProperty "token mempty" $ \x-> results (simpleParse (token [x]) "") == [],               testProperty "satisfy success" $ \bools->                    simpleParse (satisfy head) (True:bools) == Right [(bools, [True])],               testProperty "satisfy failure" $ \bools-> results (simpleParse (satisfy head) (False:bools)) == [],@@ -205,7 +203,6 @@                                  DescribedParser "getInput" getInput,                                  DescribedParser "empty" empty,                                  DescribedParser "mempty" mempty])-               <> pay (unary $ \t-> DescribedParser "token" (token t))                <> pay (unary $ \s-> DescribedParser "string" (string s))                <> pay (unary $ \pred-> DescribedParser "satisfy" (satisfy pred))                <> pay (unary $ \pred-> DescribedParser "takeWhile" (takeWhile pred))
test/Test/Examples.hs view
@@ -1,4 +1,4 @@-{-# Language RankNTypes, ScopedTypeVariables #-}+{-# Language FlexibleInstances, RankNTypes, ScopedTypeVariables #-} module Test.Examples where  import Control.Applicative (empty, (<|>))@@ -30,7 +30,8 @@    where f = uniqueParse (fixGrammar comparisons) (Comparisons.test . Rank2.snd)          s' = f s -comparisons :: Rank2.Functor g => GrammarBuilder ArithmeticComparisons g Parser String+comparisons :: (Rank2.Functor g, Lexical g, LexicalConstraint 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} @@ -39,7 +40,8 @@    where f = uniqueParse (fixGrammar boolean) (Boolean.expr . Rank2.snd)          s' = f s -boolean :: Rank2.Functor g => GrammarBuilder ArithmeticComparisonsBoolean g Parser String+boolean :: (Rank2.Functor g, Lexical g, LexicalConstraint 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 :: Conditional -> Bool@@ -47,7 +49,7 @@    where f = uniqueParse (fixGrammar conditionals) (Conditionals.expr . Rank2.snd)          s' = f s -conditionals :: Rank2.Functor g => GrammarBuilder ACBC g Parser String+conditionals :: (Rank2.Functor g, Lexical g, LexicalConstraint 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),@@ -129,3 +131,7 @@                        Right [] -> error "Unparseable"                        Right _ -> error "Ambiguous"                        Left (ParseFailure pos exp) -> error ("At " <> show pos <> " expected one of " <> show exp)++instance Lexical ArithmeticComparisons+instance Lexical ArithmeticComparisonsBoolean+instance Lexical ACBC