0lexeme parser = whitespaces *> parser <* whitespaces
-Data Structure
-Remember from text to data structure
-data Tree = Node Element [Tree]
+Scheme
+Write Yourself a Scheme in 48 hours
+Remember from text to data structure. Our data structure:
+data LispVal = Atom String
+ | List [LispVal]
+ | DottedList [LispVal] LispVal
+ | Number Integer
+ | String String
+ | Bool Bool
+
+
+Parse String
+parseString :: Parser LispVal
+parseString = do
+ char '"'
+ x <- many (noneOf "\"")
+ char '"'
+ return (String x)
+-- parseString on '"toto"'
+(String "toto") :: LispVal
+-- parseString on '" hello"'
+(String " hello") :: LispVal
+
+
+Parse Atom
+symbol :: Parser Char
+symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
+
+parseAtom :: Parser LispVal
+parseAtom = do
+ first <- letter <|> symbol
+ rest <- many (letter <|> digit <|> symbol)
+ let atom = first:rest
+ return $ case atom of
+ "#t" -> Bool True
+ "#f" -> Bool False
+ _ -> Atom atom
+
+
+Test parseAtom
+-- parseAtom on '#t'
+(Bool True) :: LispVal
+-- parseAtom on '#f'
+(Bool False) :: LispVal
+-- parseAtom on 'some-atom'
+(Atom "some-atom") :: LispVal
+
+
+Parse Number
+parseNumber :: Parser LispVal
+parseNumber = Number . read <$> many1 digit
+-- parseNumber on '18'
+Number 18 :: LispVal
+-- parseNumber on '188930992344321234'
+Number 188930992344321234 :: LispVal
+
+
+Compose all parsers
+parseExpr :: Parser LispVal
+parseExpr = parseAtom
+ <||> parseString
+ <||> parseNumber
+
+
+Test the parser
+-- parseExpr on '188930992344321234'
+Number 188930992344321234 :: LispVal
+-- parseExpr on '#t'
+Bool True :: LispVal
+-- parseExpr on 'just-some-word'
+Atom "just-some-word" :: LispVal
+-- parseExpr on '%-symbol-start'
+Atom "%-symbol-start" :: LispVal
+-- parseExpr on '"a String"'
+String "a String" :: LispVal
+
+
+Recursive Parsers
+parseList :: Parser LispVal
+parseList = List <$>
+ (char '(' *> sepBy parseExpr' spaces <* char ')' )
+
+parseExpr' :: Parser LispVal
+parseExpr' = parseAtom
+ <||> parseString
+ <||> parseNumber
+ <||> parseList
+
+
+Test Parse List
+-- parseExpr' on '(foo (bar baz))'
+List [Atom "foo",List [Atom "bar",Atom "baz"]] :: LispVal
+
+-- parseExpr' on '(foo (bar)'
+"parseExpr'" (line 1, column 11):
+unexpected end of input
+expecting white space, letter, "\"", digit, "(" or ")"
+
+-- parseExpr' on '(((foo)) bar)'
+List [List [List [Atom "foo"]],Atom "bar"] :: LispVal
+
+
+Conclusion
+So Parser are more powerful than regular expression.
Parsec make it very easy to use.
Easy to read and to manipulate.
+Notice how you could use parser as any other object in Haskell. You could mapM
them for example.
+Any question?
diff --git a/parsec/content/.030_advanced.md.swp b/parsec/content/.030_advanced.md.swp
deleted file mode 100644
index 2fbb2b6..0000000
Binary files a/parsec/content/.030_advanced.md.swp and /dev/null differ
diff --git a/parsec/content/030_advanced.md b/parsec/content/030_advanced.md
index 177ab69..0167ff6 100644
--- a/parsec/content/030_advanced.md
+++ b/parsec/content/030_advanced.md
@@ -25,10 +25,141 @@ Let's write a minimal DSL
lexeme parser = whitespaces *> parser <* whitespaces
```
-## Data Structure
+## Scheme
-Remember from text to data structure
+[Write Yourself a Scheme in 48 hours](https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours)
+
+Remember from text to data structure. Our data structure:
``` haskell
-data Tree = Node Element [Tree]
+data LispVal = Atom String
+ | List [LispVal]
+ | DottedList [LispVal] LispVal
+ | Number Integer
+ | String String
+ | Bool Bool
```
+
+## Parse String
+
+``` haskell
+parseString :: Parser LispVal
+parseString = do
+ char '"'
+ x <- many (noneOf "\"")
+ char '"'
+ return (String x)
+```
+
+```
+-- parseString on '"toto"'
+(String "toto") :: LispVal
+-- parseString on '" hello"'
+(String " hello") :: LispVal
+```
+
+## Parse Atom
+
+``` haskell
+symbol :: Parser Char
+symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
+
+parseAtom :: Parser LispVal
+parseAtom = do
+ first <- letter <|> symbol
+ rest <- many (letter <|> digit <|> symbol)
+ let atom = first:rest
+ return $ case atom of
+ "#t" -> Bool True
+ "#f" -> Bool False
+ _ -> Atom atom
+```
+
+## Test `parseAtom`
+
+```
+-- parseAtom on '#t'
+(Bool True) :: LispVal
+-- parseAtom on '#f'
+(Bool False) :: LispVal
+-- parseAtom on 'some-atom'
+(Atom "some-atom") :: LispVal
+```
+
+## Parse Number
+
+``` haskell
+parseNumber :: Parser LispVal
+parseNumber = Number . read <$> many1 digit
+```
+
+```
+-- parseNumber on '18'
+Number 18 :: LispVal
+-- parseNumber on '188930992344321234'
+Number 188930992344321234 :: LispVal
+```
+
+## Compose all parsers
+
+``` haskell
+parseExpr :: Parser LispVal
+parseExpr = parseAtom
+ <||> parseString
+ <||> parseNumber
+```
+
+## Test the parser
+
+````
+-- parseExpr on '188930992344321234'
+Number 188930992344321234 :: LispVal
+-- parseExpr on '#t'
+Bool True :: LispVal
+-- parseExpr on 'just-some-word'
+Atom "just-some-word" :: LispVal
+-- parseExpr on '%-symbol-start'
+Atom "%-symbol-start" :: LispVal
+-- parseExpr on '"a String"'
+String "a String" :: LispVal
+````
+
+## Recursive Parsers
+
+``` haskell
+parseList :: Parser LispVal
+parseList = List <$>
+ (char '(' *> sepBy parseExpr' spaces <* char ')' )
+
+parseExpr' :: Parser LispVal
+parseExpr' = parseAtom
+ <||> parseString
+ <||> parseNumber
+ <||> parseList
+```
+
+## Test Parse List
+
+```
+-- parseExpr' on '(foo (bar baz))'
+List [Atom "foo",List [Atom "bar",Atom "baz"]] :: LispVal
+
+-- parseExpr' on '(foo (bar)'
+"parseExpr'" (line 1, column 11):
+unexpected end of input
+expecting white space, letter, "\"", digit, "(" or ")"
+
+-- parseExpr' on '(((foo)) bar)'
+List [List [List [Atom "foo"]],Atom "bar"] :: LispVal
+```
+
+## Conclusion
+
+So Parser are more powerful than regular expression.
+Parsec make it very easy to use.
+Easy to read and to manipulate.
+
+Notice how you could use parser as any other object in Haskell.
+You could `mapM` them for example.
+
+Any question?
diff --git a/parsec/examples/scheme.hs b/parsec/examples/scheme.hs
new file mode 100644
index 0000000..0534665
--- /dev/null
+++ b/parsec/examples/scheme.hs
@@ -0,0 +1,83 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+import Control.Applicative hiding (many, (<|>))
+import Text.Parsec
+import Data.Typeable
+import Control.Monad (guard)
+
+type Parser a = Parsec String () a
+
+data LispVal = Atom String
+ | List [LispVal]
+ | DottedList [LispVal] LispVal
+ | Number Integer
+ | String String
+ | Bool Bool
+ deriving (Show, Typeable)
+
+parseString :: Parser LispVal
+parseString = do
+ char '"'
+ x <- many (noneOf "\"")
+ char '"'
+ return (String x)
+
+symbol :: Parser Char
+symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
+
+parseAtom :: Parser LispVal
+parseAtom = do
+ first <- letter <|> symbol
+ rest <- many (letter <|> digit <|> symbol)
+ let atom = first:rest
+ return $ case atom of
+ "#t" -> Bool True
+ "#f" -> Bool False
+ _ -> Atom atom
+
+parseNumber :: Parser LispVal
+parseNumber = Number . read <$> many1 digit
+
+parseExpr :: Parser LispVal
+parseExpr = parseAtom
+ <||> parseString
+ <||> parseNumber
+
+(<||>) parser1 parser2 = try parser1 <|> parser2
+
+
+parseList :: Parser LispVal
+parseList = List <$>
+ (char '(' *> sepBy parseExpr' spaces <* char ')' )
+
+parseExpr' :: Parser LispVal
+parseExpr' = parseAtom
+ <||> parseString
+ <||> parseNumber
+ <||> parseList
+main :: IO ()
+main = do
+ -- test parseString "parseString" "\"toto\""
+ -- test parseString "parseString" "\" hello\""
+ -- test parseAtom "parseAtom" "#t"
+ -- test parseAtom "parseAtom" "#f"
+ -- test parseAtom "parseAtom" "some-atom"
+ -- test parseNumber "parseNumber" "18"
+ -- test parseNumber "parseNumber" "188930992344321234"
+ -- test parseExpr "parseExpr" "188930992344321234"
+ -- test parseExpr "parseExpr" "#t"
+ -- test parseExpr "parseExpr" "just-some-word"
+ -- test parseExpr "parseExpr" "%-symbol-start"
+ -- test parseExpr "parseExpr" "\"a String\""
+ test parseExpr' "parseExpr'" "(foo (bar baz))"
+ test parseExpr' "parseExpr'" "(foo (bar)"
+ test parseExpr' "parseExpr'" "(((foo)) bar)"
+
+test :: (Typeable a, Show a) => Parser a -> String -> String -> IO ()
+test parser description string = do
+ putStrLn $ "-- " ++ description ++ " on '" ++ string ++ "'"
+ let res = parse parser description string
+ case res of
+ Left err -> print err
+ Right value -> putStr $ show value ++ " :: " ++ show (typeOf value)
+ putStrLn ""
+