aboutsummaryrefslogtreecommitdiff
path: root/src/parser.hs
blob: df0ac1053ae13bc345258d8803b7ab2bb0a5079c (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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
module Parser where

import Control.Applicative
import Control.Monad
import Data.Char
import Numeric.Natural

import Equation


newtype Parser a = Parser (String -> Maybe (a, String))

parse :: Parser a -> String -> Maybe (a, String)
parse (Parser p) input = p input

instance Functor Parser where
    -- fmap :: (a -> b) -> Parser a -> Parser b
    fmap f (Parser p) = Parser new_p
        where new_p s = do
                (x, s') <- p s
                return (f x, s')

instance Applicative Parser where
    -- pure :: a -> Parser a
    pure x = Parser (\s -> Just (x, s))
    -- (<*>) :: Parser (a -> b) -> Parser a -> Parser b
    (Parser p1) <*> (Parser p2) = Parser new_p
        where new_p s = do
                (f, s') <- p1 s
                (x, s'') <- p2 s'
                return (f x, s'')

instance Alternative Parser where
    -- empty :: Parser a
    empty = Parser (\_ -> Nothing)
    -- (<|>) :: Parser a -> Parser a -> Parser a
    (Parser p1) <|> (Parser p2) = Parser new_p
        where new_p s = p1 s <|> p2 s


charP :: Char -> Parser Char
charP x = Parser p
    where p ""     = Nothing
          p (c:cs) = if c == x then Just (c, cs)
                               else Nothing

digitsP :: Parser String
digitsP = Parser (\s -> Just $ span isDigit s)

sepBy :: Parser a -> Parser b -> Parser [a]
sepBy x sep = ((:) <$> x <*> many (sep *> x)) <|> pure []


-- Equation parsers
-- 1 * X^0 + 2 * X^1 + 1 * 3 * X^2 = 0

coefficientP :: Parser Float
coefficientP = read <$> (floatP <|> digitsP)
    where floatP = (\i _ f -> (i ++ "." ++ f))
                        <$> digitsP <*> charP '.' <*> digitsP

exponentP :: Parser Natural
exponentP = read <$> digitsP

termP :: Parser Term
termP = (\coef _ exp -> Term coef exp)
         <$> coefficientP
         <*> (charP '*' *> charP 'X' *> charP '^')
         <*> exponentP

polynomialP :: Parser Polynomial
polynomialP = sepBy termP (charP '+')

equationP :: Parser Equation
equationP = (\l _ r -> Equation l r)
             <$> polynomialP
             <*> charP '='
             <*> polynomialP