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
= [azAZ]
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 '.' [09]+ { realToFrac (read (show $1 ++ '.' : $2) :: Double) }
/ integer { fromInteger $1 }
integer :: Integer
= "-" natural { negate $1 }
/ natural
natural :: Integer
= [19] [09]* { 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"