summaryrefslogtreecommitdiff
path: root/Haskell-book/24/ParserExercises/src/Base10Integer.hs
blob: 4e8ee3ac09239e90157ebeb01eafe44a169d3488 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
module Base10Integer where

import Control.Applicative
import Text.Trifecta

-- 2. Write a parser for positive integer values. Don't reuse the preexisting
-- digit or integer functions, but you can use the rest of the libraries we've
-- shown you so far. You are not expected to write a parsing library from
-- scratch.
--
-- Hint: Assume you're parsing base-10 numbers. Use arithmetic as a cheap
-- "accumulator" for your final number as you parse each digit left-to-right.

parseDigit :: Parser Char
parseDigit = (char '0')
    <|> (char '1')
    <|> (char '2')
    <|> (char '3')
    <|> (char '4')
    <|> (char '5')
    <|> (char '6')
    <|> (char '7')
    <|> (char '8')
    <|> (char '9')

charToDigit :: Char -> Integer
charToDigit c = case c of
                    '0' -> 0
                    '1' -> 1
                    '2' -> 2
                    '3' -> 3
                    '4' -> 4
                    '5' -> 5
                    '6' -> 6
                    '7' -> 7
                    '8' -> 8
                    '9' -> 9

base10Integer :: Parser Integer
base10Integer = do
    number <- some parseDigit
    let n = foldl (\acc x -> (acc * 10) + (charToDigit x)) 0 number
    return n

-- 3. Extend the parser your wrote to handle negative and positive integers.
-- Try writing a new parser in terms of the one you already have to do this.
base10Integer' :: Parser Integer
base10Integer' = do
    negative <- (char '-' >> (return negate)) <|> (return id)
    number <- some parseDigit
    let n = foldl (\acc x -> (acc * 10) + (charToDigit x)) 0 number
    return $ negative n