class: center, middle
name: parsers
template: parsers
type Parser a = Free ParserF a
data ParserF a
= Draw (Maybe Char → a)
| Fail String
| ...
template: parsers
- Simple, imperative primitives
--
- Context-sensitive
--
- Impossible to analyze
template: parsers
type Parser a = Compose List (FreeAp ParserF) a
data ParserF a
= Lit Char
| ...
template: parsers
- Complex, declarative primitives
--
- Context-free
--
- Easy to analyze
name: grammars
template: grammars
--
- Stringly-typed
--
- Awkward type class based interpreter
class: middle center
and well-typed
name: build
template: build
csv = {line}
line = cell, {',', cell}, newline
cell = '"', {NOT_QUOTE} , '"'
template: build
data CSVRule
= RCSV
| RLine
| RCell
--
csv ∷ CSV -> Grammar ???
template: build name: rules
import Data.Leibniz (type (~))
type Doc = List Line
type Line = List Cell
type Cell = List Char
data CSVRule a
= RCSV (a ~ Doc)
| RLine (a ~ Line)
| RCell (a ~ Cell)
template: rules
csv ∷ CSVRule ~> Grammar ???
template: rules
csv ∷ CSVRule ~> Grammar CSVRule ???
template: rules
csv ∷ CSVRule ~> Grammar CSVRule Char ???
template: build
import Data.Leibniz (type (~))
type Doc = List Line
type Line = List Cell
type Cell = List Char
data CSVRule a
= RCSV (a ~ Doc)
| RLine (a ~ Line)
| RCell (a ~ Cell)
data CSVPrim a
= PNotQuote (a ~ Char)
csv ∷ CSVRule ~> Grammar CSVRule CSVPrim Char
template: build name: gtype
data GTerm (r ∷ * → *) (p ∷ * → *) t a
= Terminal (a ~ t) t
| NonTerminal (r a)
| Primitive (p a)
template: gtype
data Grammar (r ∷ * → *) (p ∷ * → *) t a
= Term (GTerm r p t a)
| ???
template: gtype
data Grammar (r ∷ * → *) (p ∷ * → *) t a
= Term (GTerm r p t a)
| Alt (List (Grammar r p t a))
| ???
template: gtype
data Grammar (r ∷ * → *) (p ∷ * → *) t a
= Term (GTerm r p t a)
| Alt (List (Grammar r p t a))
| Ap (FreeAp (Grammar r p t) a)
| ???
class: center middle
template: build name: rep
many ∷ ∀ r p t a. Grammar r p t a → Grammar r p t (List a)
template: gtype
data Grammar (r ∷ * → *) (p ∷ * → *) t a
= Term (GTerm r p t a)
| Alt (List (Grammar r p t a))
| Ap (FreeAp (Grammar r p t) a)
* | Repeat (a ~ List a)
template: build
- Provide a contract for
a → List a
over some functorf
- Interpreter must satisfy it
template: gtype
data Grammar (r ∷ * → *) (p ∷ * → *) t a
= Term (GTerm r p t a)
| Alt (List (Grammar r p t a))
| Ap (FreeAp (Grammar r p t) a)
* | Repeat (Inj (Grammar r p t) List a)
template: build
data Inj (f ∷ * → *) (g ∷ * → *) a
= Inj (a → g a) (Exists f)
mkInj
∷ ∀ f g a b
. Applicative g
⇒ (g a → b)
→ f a
→ Inj f g b
mkInj _ = Inj pure <<< mkExists
runInj
∷ ∀ f g h a
. (∀ b. f b → h (g b))
→ Inj f g a → h a
runInj f (Inj _ x) = runExists (unsafeCoerce <<< f) x
template: build
instance functorGrammar ∷ Functor (Grammar r p t)
instance applyGrammar ∷ Apply (Grammar r p t)
instance applicativeGrammar ∷ Applicative (Grammar r p t)
instance altGrammar ∷ Alt (Grammar r p t)
instance plusGrammar ∷ Plus (Grammar r p t)
instance alternativeGrammar ∷ Alternative (Grammar r p t)
template: build
lit ∷ ∀ r p t. t → Grammar r p t t
lit = Term <<< Terminal id
rule ∷ ∀ r p t a. r a → Grammar r p t a
rule = Term <<< NonTerminal
prim ∷ ∀ r p t a. p a → Grammar r p t a
prim = Term <<< Primitive
many ∷ ∀ r p t a. Grammar r p t a → Grammar r p t (List a)
many = Repeat <<< mkInj id
As well as many1
, sepBy
, etc
template: build
interpretGrammar
∷ ∀ r p t f a
. (Grammar r p t ~> f)
→ (r ~> Grammar r p t)
→ r a
→ f a
interpretGrammar = (<<<)
template: build
interpretGrammar
∷ ∀ r p t f a
. (Grammar r p t ~> f)
→ (r ~> Grammar r p t)
→ r a
→ f a
interpretGrammar = (<<<)
define
∷ ∀ r p t a b
. (a ~ b)
→ Grammar r p t b
→ Grammar r p t a
define _ = unsafeCoerce
infix 0 define as ::=
template: build
type Doc = List Line
type Line = List Cell
type Cell = List Char
data CSVRule a
= RCSV (a ~ Doc)
| RLine (a ~ Line)
| RCell (a ~ Cell)
data CSVPrim a
= PNotQuote (a ~ Char)
template: build
root ∷ ∀ p t. Grammar CSVRule p t Doc
root = rule (RCSV id)
line ∷ ∀ p t. Grammar CSVRule p t Line
line = rule (RLine id)
cell ∷ ∀ p t. Grammar CSVRule p t Cell
cell = rule (RCell id)
notQuote ∷ ∀ r t. Grammar r CSVPrim t Char
notQuote = prim <<< PNotQuote id
template: build
csv ∷ CSVRule ~> Grammar CSVRule CSVPrim Char
template: build
csv ∷ CSVRule ~> Grammar CSVRule CSVPrim Char
csv = case _ of
RCSV p →
p ::= many line
template: build
csv ∷ CSVRule ~> Grammar CSVRule CSVPrim Char
csv = case _ of
RCSV p →
p ::= many line
RLine p →
p ::= commaSeparated cell <* newline
template: build
csv ∷ CSVRule ~> Grammar CSVRule CSVPrim Char
csv = case _ of
RCSV p →
p ::= many line
RLine p →
p ::= commaSeparated cell <* newline
RCell p →
p ::= lit '"' *> many notQuote <* lit '"'
template: build
csv ∷ CSVRule ~> Grammar CSVRule CSVPrim Char
csv = case _ of
RCSV p →
p ::= many line
RLine p →
p ::= commaSeparated cell <* newline
RCell p →
p ::= lit '"' *> many notQuote <* lit '"'
where
commaSeparated = sepBy (lit ',')
newline = lit '\n'
class: middle center
--
Earley (Hackage)
--
- Applicative interface
--
- Embedded in a
Grammar
Monad
--
MonadFix
used for sharing
--
- Efficient parsers
--
- Better error handling
--
- Abstract over parsing strategy?
class: middle center
fin