]> git.rmz.io Git - my-scheme.git/commitdiff
Add Character parser
authorSamir Benmendil <me@rmz.io>
Sun, 21 Jan 2018 12:06:07 +0000 (12:06 +0000)
committerSamir Benmendil <me@rmz.io>
Sun, 21 Jan 2018 12:06:07 +0000 (12:06 +0000)
Refactor `nonPrintableChar` into its own Parser type to be reused in
`parseCharacter` and `parseString`

app/Main.hs

index c71126b500c4a581a4e6d2bf61577352bd89cd1b..03dbb41ad56467919b06e5c72b886c640e697253 100644 (file)
@@ -9,6 +9,7 @@ data LispVal = Atom String
              | DottedList [LispVal] LispVal
              | Number Integer
              | String String
+             | Character Char
              | Bool Bool
              deriving Show
 
@@ -18,21 +19,29 @@ symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
 spaces :: Parser ()
 spaces = skipMany space
 
+nonPrintableChar :: Parser Char
+nonPrintableChar = do c <- char '\\' >> oneOf "\\nrtf"
+                      return $ case c of '\\' -> '\\'
+                                         'n'  -> '\n'
+                                         'r'  -> '\r'
+                                         't'  -> '\t'
+                                         'f'  -> '\f'
+
+parseCharacter :: Parser LispVal
+parseCharacter = do char '\''
+                    c <- noneOf ['\\', '\''] <|> try singleQuote <|> try nonPrintableChar
+                    char '\''
+                    return $ Character c
+                 where
+                    singleQuote = char '\\' >> char '\''
+
 parseString :: Parser LispVal
 parseString = do char '"'
                  x <- many innerChar
                  char '"'
                  return $ String x
-              where innerChar = noneOf ['\\', '\"'] <|> escapeChar
-                    escapeChar = do char '\\'
-                                    c <- oneOf ['\"', '\\', 'n', 'r', 't', 'f']
-                                    return $ case c of
-                                                '\"' -> '\"'
-                                                '\\' -> '\\'
-                                                'n'  -> '\n'
-                                                'r'  -> '\r'
-                                                't'  -> '\t'
-                                                'f'  -> '\f'
+              where innerChar = noneOf ['\\', '"'] <|> try doubleQuote <|> try nonPrintableChar
+                    doubleQuote = char '\\' >> char '"'
 
 parseAtom :: Parser LispVal
 parseAtom = do
@@ -58,6 +67,7 @@ parseNumber = do toNum <- radix
 
 parseExpr :: Parser LispVal
 parseExpr = parseString
+        <|> parseCharacter
         <|> parseNumber
         <|> parseAtom