SlideShare a Scribd company logo
8   :
    ruicc (ruicc.rail@gmail.com)
•        (             )

•@ruicc
•http://d.hatena.ne.jp/ruicc
•LinkThink ! Altplus
Haskell 8
•   Google Suggest
•Haskell
P.90 †2[        ]
•

    Web
                     10
P.90 †2[        ]
•

    Web
                     10
P.90 †2[   ]
P.90 †2[   ]
P.90 †2[                 ]

•              =>

•   import Prelude hiding(return,(>>=),(>>))

•   do         (Mona*                      )

•
•
•
•Haskell
•
 •   *

•
•advanced   :
•
•Parser   [pärsəәr]

•
“-32.4”   Parser   -32.4
Programming Haskell Chapter8
•

type Parser = String -> Tree


                  ※Tree
•


type Parser = String -> (Tree, String)
•


type Parser = String -> [(Tree, String)]
•                          a




type Parser a = String -> [(a, String)]

   ※
                            advanced:
•

“1.4aaa”   Parser   [(1.4,“aaa”)]
•

“+.4aaa”   Parser   []
• return    :: a -> Parser a

 •
• failure    :: Parser a

 •
• item   :: Parser Char

 •
parse
• Parser   String

   • Parser
  parse:: Parser a -> String -> [(a,String)]
parse
  •parse

“1.4aaa”     Parser       [(1.4,“aaa”)]


           parse      !
“-3.24”    sign    [(‘-’,“3.24”)]



“3.24”    digits   [(“3”,“.24”)]



“.24”     point    [(‘.’,“24”)]
•
•
    •
    •
sign


            digits
“-3.24”              [(-3.24,“”)]
            point
parse   1
            digits
                       ※
•
 •
•p,   then q

               double

                 =
digits   >>= point >>=   digits

                           ※
•                     (>>=)

                               p
(>>=):: Parser a -> (a -> Parser b) -> Parser b
p >>= f = inp -> case parse p inp of
                   [] -> []
                   [(v,out)] -> parse (f v) out


                                   (f v)
•p,   or q

                 char ‘+’


  sign       =     +++


                 char ‘-’
•
                          p
(+++):: Parser a -> Parser a -> Parser a
p +++ q = inp -> case parse p inp of
                   [] -> parse q inp
                   [(v,out)] -> [(v,out)]

                                        q
              advanced:           p
“-3.24”    sign    [(‘-’,“3.24”)]



“3.24”    digits   [(“3”,“.24”)]



“.24”     point    [(‘.’,“24”)]
“-3.24”    sign    [(‘-’,“3.24”)]



“3.24”    digits   [(“3”,“.24”)]



“.24”     point    [(‘.’,“24”)]
“-3.24”    sign    [(‘-’,“3.24”)]



“3.24”    digits   [(“3”,“.24”)]



“.24”     point    [(‘.’,“24”)]
•         (>>=)
double =
  sign     >>= s    ->
  digits   >>= num ->
  point    >>= p    ->
  digits   >>= num2 ->
  return   (func s num p num2)

             ※sign,digits,point   given
•     return
double =
  sign     >>= s    ->
  digits   >>= num ->
  point    >>= p    ->
  digits   >>= num2 ->
  return   (func s num p num2)
do
 •        Parser
double :: Parser Double
double = do
    s    <- sign
    num <- digits
    p    <- point
    num2 <- digits
    return (func s num p num2)
• type Parser a = String -> [(a, String)]
 •          Char

 • Parser            a

 • Parser
do
      •
    double :: Parser Double
    double = do
 Char   s    <- sign   :: Parser Char
        num <- digits :: Parser String
String
        p    <- point :: Parser Char
 Char   num2 <- digits :: Parser String
String return (func s num p num2) :: Parser Double
do

•
•
•           String

•   (>>=)
sign


          digits
“-3.24”            [(-3.24,“”)]
          point


          digits
• return, failure,   item

•     (>>=)

•     (+++)

• (do )
•
•   (>>=)

•   (+++)

•   (   )
Programming Haskell Chapter8
• item                          sat

             item
sat :: (Char -> Bool) -> Parser Char
sat p = do x <- item
            if p x then return x else failure


     (p x)    True            False
                               ※p   predicate
• sat
  digit    = sat isDigit
  lower    = sat isLower

  upper    = sat isUpper
  letter   = sat isAlpha

  alphanum = sat isAlphanum
  char x   = sat (==x)
• char                  string

  string :: String -> Parser String
  string []     = return []
  string (x:xs) = do char x
                     string xs
                     return (x:xs)
•                           many, many1

    many, many1 :: Parser a -> Parser [a]

    many p   = many1 p +++ return []

    many1 p = do v <- p

                  vs <- many p

                  return (v:vs)
• many
  ident = do x <- lower
              xs <- many alphanum
              return (x:xs)
  nat    = do xs <- many1 digit
              return (read xs)
  space = do many (sat isSpace)
              return ()
•
    token :: Parser a -> Parser a
    token p = do space
                 v <- p
                 space
                 return v
• token
  identifier :: Parser String
  identifier = token ident
  natural :: Parser Int
  natural = token nat
  symbol :: Parser String
  symbol xs = token (string xs)
•
:

•BNF(Backus-Naur   Form)

 •
 • (|)                     (   )
•                                     BNF..?

    expr ::= expr ‘+’ expr

            | expr ‘*’ expr

            | ‘(‘ expr ‘)’

            | nat

    nat   ::= ‘0’ | ‘1’ | ‘2’ | ...
•(*)      (+)

•
 • (expr), (term),   (factor)
•                       BNF

    expr   ::= expr ‘+’ expr | term

    term   ::= term ‘*’ term | factor

    factor ::= ‘(‘ expr ‘)’ | nat

    nat    ::= ‘0’ | ‘1’ | ‘2’ | ...
•
•1   + 2 + 3 == 1 + (2 + 3)

•
•1   - 2 - 3 == (1 - 2) - 3

•
•                     BNF(             )

    expr   ::= term ‘+’ expr | term

    term   ::= factor ‘*’ term | factor

    factor ::= ‘(‘ expr ‘)’ | nat

    nat    ::= ‘0’ | ‘1’ | ‘2’ | ...
•                     BNF(            )

    expr   ::= term ‘+’ expr | term

    term   ::= factor ‘*’ term | factor




                →
•BNF                                   1
 -- expr ::= term ‘+’ expr | term
 expr :: Parser Int
 expr = do t <- (term :: Parser Int)
           symbol “+”
           e <- (expr :: Parser Int)
           return (t + e)
     +++ term
•BNF                                     2
 -- term ::= factor ‘*’ term | factor
 term :: Parser Int
 term = do f <- (factor :: Parser Int)
           symbol “*”
           t <- (term :: Parser Int)
           return (f * t)
     +++ factor
•BNF                                     3
 -- factor ::= ‘(‘ expr ‘)’ | nat
 factor :: Parser Int
 factor = do symbol “(“
             e <- (expr :: Parser Int)
             symbol “)”
             return e
       +++ natural
•                    expr
    ghci> parse expr "5 * (2) +   ( 4   +(2 * 2 + 4) * 2)   * 5 "
    [(110,””)]
Haskell
Parser
Package

•Parsec3
 •
•attoparsec
 •
•
    • letter,    digit, char, string, many, ...
•      (+++)              (<|>), try

    •
    • import    Control.Applicative (<|>)
    •               try
BNF
  BNF         BNF       (wikipedia       )

<syntax> ::= <rule> | <rule> <syntax>
<rule> ::= <opt-whitespace> "<" <rule-name> ">" <opt-whitespace> "::="
           <opt-whitespace> <expression> <line-end>
<opt-whitespace> ::= " " <opt-whitespace> | ""
<expression> ::= <list> | <list> "|" <expression>
<line-end> ::= <opt-whitespace> <eol> | <line-end> <line-end>
<list> ::= <term> | <term> <opt-whitespace> <list>
<term> ::= <literal> | "<" <rule-name> ">"
<literal> ::= '"' <text> '"' | "'" <text> "'"
cabal install attoparsec
cabal install attoparsec-text
{-# LANGUAGE OverloadedStrings #-}
module BNFParser where
import Data.Attoparsec.Text
import Data.Text.Internal (Text)
import Data.Text as T
import Control.Applicative hiding(many)
BNF
type BNF = Syntax
type Syntax = [Rule]
data Rule = Rule Text Expr
type Expr = [List]
type List = [Term]
data Term = Lit Text | RuleName Text
BNF                      (10          !)
syntax = many1 rule
rule = Rule <$> (spaces *> "<" .*> text '>' <*. ">") <* spaces
     <* string "::=" <* spaces <*> expression <* line_end
spaces = T.pack <$> many (char ' ')
expression = sepBy1 list (spaces *> string "|" <* spaces)
line_end = many1 $ spaces *> endOfLine
list = sepBy1 term spaces
term = Lit <$> literal <|> RuleName <$> "<" .*> text '>' <*. ">"
literal = "'" .*> text ''' <*. "'" <|> """ .*> text '"' <*. """
text c = takeTill (==c)
3

Haskell
Parser
BNF
syntax = many1 rule
rule = Rule <$> (spaces *> "<" .*> text '>' <*. ">") <* spaces
     <* string "::=" <* spaces <*> expression <* line_end
spaces = T.pack <$> many (char ' ')
expression = sepBy1 list (spaces *> string "|" <* spaces)
line_end = many1 $ spaces *> endOfLine
list = sepBy1 term spaces
term = Lit <$> literal <|> RuleName <$> "<" .*> text '>' <*. ">"
literal = "'" .*> text ''' <*. "'" <|> """ .*> text '"' <*. """
text c = takeTill (==c)
3
Haskell


Mona*,Applicative,
Functor,Arrow,...
Happy Hacking Parser
in Haskell!

More Related Content

Programming Haskell Chapter8

  • 1. 8 : ruicc ([email protected])
  • 2. ( ) •@ruicc •http://d.hatena.ne.jp/ruicc •LinkThink ! Altplus
  • 3. Haskell 8 • Google Suggest
  • 5. P.90 †2[ ] • Web 10
  • 6. P.90 †2[ ] • Web 10
  • 9. P.90 †2[ ] • => • import Prelude hiding(return,(>>=),(>>)) • do (Mona* ) •
  • 11. • • * • •advanced :
  • 12.
  • 13. •Parser [pärsəәr] •
  • 14. “-32.4” Parser -32.4
  • 16. • type Parser = String -> Tree ※Tree
  • 17. • type Parser = String -> (Tree, String)
  • 18. • type Parser = String -> [(Tree, String)]
  • 19. a type Parser a = String -> [(a, String)] ※ advanced:
  • 20. • “1.4aaa” Parser [(1.4,“aaa”)]
  • 21. • “+.4aaa” Parser []
  • 22. • return :: a -> Parser a • • failure :: Parser a • • item :: Parser Char •
  • 23. parse • Parser String • Parser parse:: Parser a -> String -> [(a,String)]
  • 24. parse •parse “1.4aaa” Parser [(1.4,“aaa”)] parse !
  • 25. “-3.24” sign [(‘-’,“3.24”)] “3.24” digits [(“3”,“.24”)] “.24” point [(‘.’,“24”)]
  • 26. • • • •
  • 27. sign digits “-3.24” [(-3.24,“”)] point parse 1 digits ※
  • 29. •p, then q double = digits >>= point >>= digits ※
  • 30. (>>=) p (>>=):: Parser a -> (a -> Parser b) -> Parser b p >>= f = inp -> case parse p inp of [] -> [] [(v,out)] -> parse (f v) out (f v)
  • 31. •p, or q char ‘+’ sign = +++ char ‘-’
  • 32. p (+++):: Parser a -> Parser a -> Parser a p +++ q = inp -> case parse p inp of [] -> parse q inp [(v,out)] -> [(v,out)] q advanced: p
  • 33. “-3.24” sign [(‘-’,“3.24”)] “3.24” digits [(“3”,“.24”)] “.24” point [(‘.’,“24”)]
  • 34. “-3.24” sign [(‘-’,“3.24”)] “3.24” digits [(“3”,“.24”)] “.24” point [(‘.’,“24”)]
  • 35. “-3.24” sign [(‘-’,“3.24”)] “3.24” digits [(“3”,“.24”)] “.24” point [(‘.’,“24”)]
  • 36. (>>=) double = sign >>= s -> digits >>= num -> point >>= p -> digits >>= num2 -> return (func s num p num2) ※sign,digits,point given
  • 37. return double = sign >>= s -> digits >>= num -> point >>= p -> digits >>= num2 -> return (func s num p num2)
  • 38. do • Parser double :: Parser Double double = do s <- sign num <- digits p <- point num2 <- digits return (func s num p num2)
  • 39. • type Parser a = String -> [(a, String)] • Char • Parser a • Parser
  • 40. do • double :: Parser Double double = do Char s <- sign :: Parser Char num <- digits :: Parser String String p <- point :: Parser Char Char num2 <- digits :: Parser String String return (func s num p num2) :: Parser Double
  • 41. do • • • String • (>>=)
  • 42. sign digits “-3.24” [(-3.24,“”)] point digits
  • 43. • return, failure, item • (>>=) • (+++) • (do )
  • 44. • • (>>=) • (+++) • ( )
  • 46. • item sat item sat :: (Char -> Bool) -> Parser Char sat p = do x <- item if p x then return x else failure (p x) True False ※p predicate
  • 47. • sat digit = sat isDigit lower = sat isLower upper = sat isUpper letter = sat isAlpha alphanum = sat isAlphanum char x = sat (==x)
  • 48. • char string string :: String -> Parser String string [] = return [] string (x:xs) = do char x string xs return (x:xs)
  • 49. many, many1 many, many1 :: Parser a -> Parser [a] many p = many1 p +++ return [] many1 p = do v <- p vs <- many p return (v:vs)
  • 50. • many ident = do x <- lower xs <- many alphanum return (x:xs) nat = do xs <- many1 digit return (read xs) space = do many (sat isSpace) return ()
  • 51. token :: Parser a -> Parser a token p = do space v <- p space return v
  • 52. • token identifier :: Parser String identifier = token ident natural :: Parser Int natural = token nat symbol :: Parser String symbol xs = token (string xs)
  • 53.
  • 54. : •BNF(Backus-Naur Form) • • (|) ( )
  • 55. BNF..? expr ::= expr ‘+’ expr | expr ‘*’ expr | ‘(‘ expr ‘)’ | nat nat ::= ‘0’ | ‘1’ | ‘2’ | ...
  • 56. •(*) (+) • • (expr), (term), (factor)
  • 57. BNF expr ::= expr ‘+’ expr | term term ::= term ‘*’ term | factor factor ::= ‘(‘ expr ‘)’ | nat nat ::= ‘0’ | ‘1’ | ‘2’ | ...
  • 58. • •1 + 2 + 3 == 1 + (2 + 3) • •1 - 2 - 3 == (1 - 2) - 3 •
  • 59. BNF( ) expr ::= term ‘+’ expr | term term ::= factor ‘*’ term | factor factor ::= ‘(‘ expr ‘)’ | nat nat ::= ‘0’ | ‘1’ | ‘2’ | ...
  • 60. BNF( ) expr ::= term ‘+’ expr | term term ::= factor ‘*’ term | factor →
  • 61. •BNF 1 -- expr ::= term ‘+’ expr | term expr :: Parser Int expr = do t <- (term :: Parser Int) symbol “+” e <- (expr :: Parser Int) return (t + e) +++ term
  • 62. •BNF 2 -- term ::= factor ‘*’ term | factor term :: Parser Int term = do f <- (factor :: Parser Int) symbol “*” t <- (term :: Parser Int) return (f * t) +++ factor
  • 63. •BNF 3 -- factor ::= ‘(‘ expr ‘)’ | nat factor :: Parser Int factor = do symbol “(“ e <- (expr :: Parser Int) symbol “)” return e +++ natural
  • 64. expr ghci> parse expr "5 * (2) + ( 4 +(2 * 2 + 4) * 2) * 5 " [(110,””)]
  • 67. • letter, digit, char, string, many, ... • (+++) (<|>), try • • import Control.Applicative (<|>) • try
  • 68. BNF BNF BNF (wikipedia ) <syntax> ::= <rule> | <rule> <syntax> <rule> ::= <opt-whitespace> "<" <rule-name> ">" <opt-whitespace> "::=" <opt-whitespace> <expression> <line-end> <opt-whitespace> ::= " " <opt-whitespace> | "" <expression> ::= <list> | <list> "|" <expression> <line-end> ::= <opt-whitespace> <eol> | <line-end> <line-end> <list> ::= <term> | <term> <opt-whitespace> <list> <term> ::= <literal> | "<" <rule-name> ">" <literal> ::= '"' <text> '"' | "'" <text> "'"
  • 69. cabal install attoparsec cabal install attoparsec-text
  • 70. {-# LANGUAGE OverloadedStrings #-} module BNFParser where import Data.Attoparsec.Text import Data.Text.Internal (Text) import Data.Text as T import Control.Applicative hiding(many)
  • 71. BNF type BNF = Syntax type Syntax = [Rule] data Rule = Rule Text Expr type Expr = [List] type List = [Term] data Term = Lit Text | RuleName Text
  • 72. BNF (10 !) syntax = many1 rule rule = Rule <$> (spaces *> "<" .*> text '>' <*. ">") <* spaces <* string "::=" <* spaces <*> expression <* line_end spaces = T.pack <$> many (char ' ') expression = sepBy1 list (spaces *> string "|" <* spaces) line_end = many1 $ spaces *> endOfLine list = sepBy1 term spaces term = Lit <$> literal <|> RuleName <$> "<" .*> text '>' <*. ">" literal = "'" .*> text ''' <*. "'" <|> """ .*> text '"' <*. """ text c = takeTill (==c)
  • 74. BNF syntax = many1 rule rule = Rule <$> (spaces *> "<" .*> text '>' <*. ">") <* spaces <* string "::=" <* spaces <*> expression <* line_end spaces = T.pack <$> many (char ' ') expression = sepBy1 list (spaces *> string "|" <* spaces) line_end = many1 $ spaces *> endOfLine list = sepBy1 term spaces term = Lit <$> literal <|> RuleName <$> "<" .*> text '>' <*. ">" literal = "'" .*> text ''' <*. "'" <|> """ .*> text '"' <*. """ text c = takeTill (==c)
  • 75. 3

Editor's Notes