module Radium.FormulaParser ( Molecule(..)
, parseFormula
) where
import Text.ParserCombinators.Parsec
data Molecule = Ion Molecule Int
| Molecule [Molecule] Int
| Element String Int
deriving (Eq, Show)
parseFormula :: String -> Molecule
parseFormula xs = case parse ion "" xs of
Left _ -> Molecule [] 0
Right val -> val
ion :: Parser Molecule
ion = do
c <- number
m <- formula
n <- optionMaybe ionNumber
return $ case n of
Just val -> Ion (Molecule m c) val
_ -> Molecule m c
formula :: Parser [Molecule]
formula = many (subformula <|> element)
subformula :: Parser Molecule
subformula = do
s <- between (char '(') (char ')') formula
n <- number
return (Molecule s n)
element :: Parser Molecule
element = do
s <- symbol
n <- number
return (Element s n)
symbol :: Parser String
symbol = do
s <- upper
ss <- many lower
return (s:ss)
number :: Parser Int
number = do
ds <- many digit
return $ if null ds then 1 else read ds :: Int
ionNumber :: Parser Int
ionNumber = do
s <- char '-' <|> char '+'
n <- number
return $ if s == '+' then n else (n)