Parsec

465 views

Published on

Published in: Technology, Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
465
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
4
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Parsec

  1. 1. A Very Quick Tour of Parsec For the LA Haskell User Group Setup: :set +m :set -XNoMonomorphismRestriction import Text.Parsec import Control.Monad
  2. 2. Types :i Parsec ParsecT :i State
  3. 3. Escaping the Monad :t runParser :t runParserT :t parse :t parseTest
  4. 4. Demonstration parseTest (char 'a') "a" parseTest (char 'a') "ab" parseTest (char 'a') "d"
  5. 5. Simple Parsers :t oneOf :t letter :t digit :t space
  6. 6. Do Notation fmap f p Parse using p and apply f to the result p >>= q Parse using p first, and then using q, possibly using the result of p. do { x ← … ; y ← … ; … } Combine several parse results
  7. 7. Modifying Parsers :t many :t count :t chainl :t chainr
  8. 8. Parsing Phone Book Entries let tel = do g1 <- count 3 digit; char '-' g2 <- count 3 digit char '-' g3 <- count 4 digit return (g1, g2, g3)
  9. 9. Parsing Phone Book Entries let name = many1 letter let fullName = do last <- name char ',' space first <- name return (first, last)
  10. 10. Parsing Phone Book Entries let phoneBook = do (first, last) <- fullName space char '(' (g1, g2, g3) <- tel char ')' return (first, last, g1, g2, g3)
  11. 11. Parsing Phone Book Entries parseTest phoneBook "Freeman, Phillip (555-555-5555)"
  12. 12. Combining Parsers :t sepBy :t (<|>)
  13. 13. Handling Failure :t try :t <?>
  14. 14. Handling Multiple First Names let nameSep = try $ do space notFollowedBy (char '(') let fullName = do last <- name char ',' space rest <- sepBy1 name nameSep return $ rest ++ [last]
  15. 15. Handling Multiple First Names let phoneBook = do names <- fullName space char '(' (g1, g2, g3) <- tel char ')' return (names, g1, g2, g3)
  16. 16. Parsing Phone Book Entries parseTest phoneBook "Freeman, Phillip Antony (555-555- 5555)"
  17. 17. User State Parsec(T) is a state monad, so we can carry around user state as well as the parser's internal state. :t getState :t setState :t modifyState
  18. 18. Example - { an bn | n ≥ 0 } let a = liftM2 (curry fst) (char 'a') (modifyState succ) an bn = do as <- many a n <- getState bs <- count n $ char 'b' eof return $ as ++ bs
  19. 19. Example - { an bn | n ≥ 0 } runParser an bn 0 "" "aaabb" runParser an bn 0 "" "aabb" runParser an bn 0 "" "aabbb"
  20. 20. Example – Print Debugging let char' c = lift (print c) >> char c chars = many $ (char' 'a') <|> (char' 'b') runParserT chars () "" "aabb"
  21. 21. Expression Parsers import Text.Parsec.Expr :t buildExpressionParser :i Operator OperatorTable Assoc
  22. 22. Example - Expression Parsers let number = fmap read $ many1 digit bracket = between (char '(') (char ')') numExpr atom = bracket <|> number numExpr = buildExpressionParser [ [ Infix (do { char '/'; return (/) }) AssocRight , Infix (do { char '*'; return (*) }) AssocRight ] , [ Infix (do { char '+'; return (+) }) AssocRight , Infix (do { char '-'; return (-) }) AssocRight ] , [ Prefix $ do { char '-'; return negate } ] ] atom
  23. 23. Example - Expression Parsers parseText numExpr “(1+2*4)/3”
  24. 24. Language Definitions import Text.Parsec.Token import Text.Parsec.Language :i GenLanguageDef GenTokenParser
  25. 25. Language Definitions let langDef = haskellStyle -- { ... } let parser = makeTokenParser langDef let stringLiteral' = stringLiteral parser integer' = integer parser float' = float parser lexeme' = lexeme parser
  26. 26. Language Definitions parseTest stringLiteral' ""Test"" parseTest (lexeme' stringLiteral') ""Test" {-# Comment #-}"

×