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
|
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE QuasiQuotes #-}
module Algebra.Ring.Polynomial.Parser ( monomial, expression, variable, variableWithPower
, number, integer, natural, parsePolyn) where
import Algebra.Ring.Polynomial.Monomorphic
import Control.Applicative hiding (many)
import qualified Data.Map as M
import Data.Ratio
import qualified Numeric.Algebra as NA
import Text.Peggy
[peggy|
expression :: Polynomial Rational
= expr !.
letter :: Char
= [a-zA-Z]
variable :: Variable
= letter ('_' integer)? { Variable $1 (fromInteger <$> $2) }
variableWithPower :: (Variable, Integer)
= variable "^" natural { ($1, $2) }
/ variable { ($1, 1) }
expr :: Polynomial Rational
= expr "+" term { $1 + $2 }
/ expr "-" term { $1 - $2 }
/ term
term :: Polynomial Rational
= number space* monoms { injectCoeff $1 * $3 }
/ number { injectCoeff $1 }
/ monoms
monoms :: Polynomial Rational
= monoms space * fact { $1 * $3 }
/ fact
fact :: Polynomial Rational
= fact "^" natural { $1 ^ $2 }
/ "(" expr ")"
/ monomial { toPolyn [($1, 1)] }
monomial :: Monomial
= variableWithPower+ { M.fromListWith (+) $1 }
number :: Rational
= integer "/" integer { $1 % $2 }
/ integer '.' [0-9]+ { realToFrac (read (show $1 ++ '.' : $2) :: Double) }
/ integer { fromInteger $1 }
integer :: Integer
= "-" natural { negate $1 }
/ natural
natural :: Integer
= [1-9] [0-9]* { read ($1 : $2) }
|]
toPolyn :: [(Monomial, Ratio Integer)] -> Polynomial (Ratio Integer)
toPolyn = normalize . Polynomial . M.fromList
parsePolyn :: String -> Either ParseError (Polynomial Rational)
parsePolyn = parseString expression "polynomial"
|