packages feed

grammatical-parsers 0.4.1 → 0.4.1.1

raw patch · 5 files changed

+118/−4 lines, 5 filesdep ~checkersPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: checkers

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+Version 0.4.1.1+---------------+* Fixed the doctests after cabal get+ Version 0.4.1 --------------- * Adjustments for monoid-subclasses-1.0
grammatical-parsers.cabal view
@@ -1,5 +1,5 @@ name:                grammatical-parsers-version:             0.4.1+version:             0.4.1.1 synopsis:            parsers that combine into grammars description:   /Gram/matical-/pa/rsers, or Grampa for short, is a library of parser types whose values are meant to be assigned@@ -60,7 +60,7 @@   build-depends:     base >=4.9 && < 5, containers >= 0.5.7.0 && < 0.7,                      monoid-subclasses < 1.1, parsers < 0.13,                      rank2classes >= 1.0.2 && < 1.4, grammatical-parsers,-                     QuickCheck >= 2 && < 3, checkers >= 0.4.6 && < 0.5, size-based < 0.2,+                     QuickCheck >= 2 && < 3, checkers >= 0.4.6 && < 0.6, size-based < 0.2,                      testing-feat >= 1.1 && < 1.2,                      tasty >= 0.7, tasty-quickcheck >= 0.7   main-is:           Test.hs@@ -73,6 +73,7 @@   hs-source-dirs:     test   default-language:   Haskell2010   main-is:            Doctest.hs+  other-modules:      README   ghc-options:        -threaded -pgmL markdown-unlit   build-depends:      base, rank2classes, grammatical-parsers, parsers, doctest >= 0.8   build-tool-depends: markdown-unlit:markdown-unlit >= 0.5 && < 0.6
src/Text/Grampa/ContextFree/Memoizing.hs view
@@ -13,7 +13,7 @@ import Data.List (genericLength, maximumBy, nub) import Data.Semigroup (Semigroup(..)) import Data.Monoid (Monoid(mappend, mempty))-import Data.Monoid.Cancellative (LeftReductiveMonoid, isPrefixOf)+import Data.Monoid.Cancellative (isPrefixOf) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid, length, splitPrimePrefix) import Data.Monoid.Textual (TextualMonoid)
src/Text/Grampa/ContextFree/SortedMemoizing.hs view
@@ -12,7 +12,7 @@ import Data.List.NonEmpty (NonEmpty((:|))) import Data.Semigroup (Semigroup(..)) import Data.Monoid (Monoid(mappend, mempty))-import Data.Monoid.Cancellative (LeftReductiveMonoid, isPrefixOf)+import Data.Monoid.Cancellative (isPrefixOf) import Data.Monoid.Null (MonoidNull(null)) import Data.Monoid.Factorial (FactorialMonoid, splitPrimePrefix) import Data.Monoid.Textual (TextualMonoid)
+ test/README.lhs view
@@ -0,0 +1,109 @@+Grammatical Parsers+===================++Behold, yet another parser combinator library in Haskell. Except this one is capable of working with grammars rather than mere parsers. A more in-depth description is available in the [paper](../Grampa.lhs.pdf) from Haskell Symposium 2017, what follows is a short tutorial.++You can apply the usual+[Applicative](http://hackage.haskell.org/package/base/docs/Control-Applicative.html#t:Applicative),+[Alternative](http://hackage.haskell.org/package/base/docs/Control-Applicative.html#t:Alternative), and+[Monad](http://hackage.haskell.org/package/base/docs/Control-Monad.html#t:Monad) operators to combine primitive parsers+into larger ones. The combinators from the [parsers](http://hackage.haskell.org/package/parsers) library type classes+are also available. Here are some typical imports you may need:++~~~ {.haskell}+{-# LANGUAGE RecordWildCards, ScopedTypeVariables, TemplateHaskell #-}+module README where+import Control.Applicative+import Data.Char (isDigit)+import Data.Functor.Classes (Show1, showsPrec1)+import Text.Grampa+import Text.Grampa.ContextFree.LeftRecursive (Parser)+import qualified Rank2.TH+~~~++What puts this library apart from most is that these parsers are *grammatical*, just as the library name says. Instead+of writing the parser definitions as top-level bindings, you can and should group them into a grammar record definition,+like this:++~~~ {.haskell}+arithmetic :: GrammarBuilder Arithmetic g Parser String+arithmetic Arithmetic{..} = Arithmetic{+   sum= product+         <|> string "-" *> (negate <$> product)+         <|> (+) <$> sum <* string "+" <*> product+         <|> (-) <$> sum <* string "-" <*> product,+   product= factor+         <|> (*) <$> product <* string "*" <*> factor+         <|> div <$> product <* string "/" <*> factor,+   factor= read <$> number+           <|> string "(" *> sum <* string ")",+   number= takeCharsWhile1 isDigit <?> "number"}+~~~++What on Earth for? One good reason is that these parser definitions can then be left-recursive, which is normally a+death knell for parser libraries. There are other benefits like memoization and grammar composability, and the main+downside is the obligation to declare the grammar record:++~~~ {.haskell}+data Arithmetic f = Arithmetic{sum     :: f Int,+                               product :: f Int,+                               factor  :: f Int,+                               number  :: f String}+~~~++and to make it an instance of several rank 2 type classes:++~~~ {.haskell}+$(Rank2.TH.deriveAll ''Arithmetic)+~~~++Optionally, you may also be inclined to declare a proper ``Show`` instance, as it's often handy:++~~~ {.haskell}+instance Show1 f => Show (Arithmetic f) where+   show Arithmetic{..} =+      "Arithmetic{\n  sum=" ++ showsPrec1 0 sum+           (",\n  product=" ++ showsPrec1 0 factor+           (",\n  factor=" ++ showsPrec1 0 factor+           (",\n  number=" ++ showsPrec1 0 number "}")))+~~~++Once that's done, use [fixGrammar](http://hackage.haskell.org/package/grammatical-parsers/docs/Text-Grampa.html#v:fixGrammar) to, well, fix the grammar++~~~ {.haskell}+grammar = fixGrammar arithmetic+~~~++and then [parseComplete](http://hackage.haskell.org/package/grammatical-parsers/docs/Text-Grampa.html#v:parseComplete)+or [parsePrefix](http://hackage.haskell.org/package/grammatical-parsers/docs/Text-Grampa.html#v:parsePrefix) to parse+some input.++~~~ {.haskell}+-- |+-- >>> parseComplete grammar "42"+-- Arithmetic{+--   sum=Compose (Right [42]),+--   product=Compose (Right [42]),+--   factor=Compose (Right [42]),+--   number=Compose (Right ["42"])}+-- >>> parseComplete grammar "1+2*3"+-- Arithmetic{+--   sum=Compose (Right [7]),+--   product=Compose (Left (ParseFailure 1 ["endOfInput"])),+--   factor=Compose (Left (ParseFailure 1 ["endOfInput"])),+--   number=Compose (Left (ParseFailure 1 ["endOfInput"]))}+-- >>> parsePrefix grammar "1+2*3 apples"+-- Arithmetic{+--   sum=Compose (Compose (Right [("+2*3 apples",1),("*3 apples",3),(" apples",7)])),+--   product=Compose (Compose (Right [("+2*3 apples",1)])),+--   factor=Compose (Compose (Right [("+2*3 apples",1)])),+--   number=Compose (Compose (Right [("+2*3 apples","1")]))}+~~~++To see more grammar examples, go straight to the+[examples](https://github.com/blamario/grampa/tree/master/grammatical-parsers/examples) directory that builds up several+smaller grammars and combines them all together in the+[Combined](https://github.com/blamario/grampa/blob/master/grammatical-parsers/examples/Combined.hs) module.++For more conventional tastes there are monolithic examples of+[Lua](https://github.com/blamario/language-lua2/blob/master/src/Language/Lua/Grammar.hs) and [Oberon](http://hackage.haskell.org/package/language-oberon) grammars as well.