Atom parser

🧩 Syntax:
module Main where
import System.Environment (getArgs)
import Debug.Trace(trace)
import qualified Text.Parsec as Parsec
import qualified Text.Parsec.Char as Parsec
import Control.Applicative ((<|>))
import Data.Char
import Data.List

parse rule text = Parsec.parse rule "(source)" text 

data Simple = Electron | Atom Atom deriving (Eq, Ord, Show)
data Token a = Simple Simple | Complex [a] deriving (Eq, Ord, Show)
newtype Molecule = Molecule [Token Molecule] deriving (Eq, Ord, Show)
type Atom = String

type Replacement = (Simple, [Token Atom]) 

parseElectron :: Parsec.Parsec String () Simple
parseElectron = do
  Parsec.string "e"
  return Electron

parseAtom :: Parsec.Parsec String () Atom
parseAtom = do
  first <- Parsec.upper
  remainder <- Parsec.many Parsec.lower
  return (first:remainder)

onlySimple :: Token a -> Bool
onlySimple (Simple _) = True
onlySimple _        = False

parseToken :: Parsec.Parsec String () a -> Parsec.Parsec String () (Token a)
parseToken p = do
  Parsec.try (Complex <$> (Parsec.between (Parsec.string "Rn") (Parsec.string "Ar") $ p `Parsec.sepBy` (Parsec.string "Y"))) <|> (Simple <$> Atom <$> parseAtom)

parseMolecule :: Parsec.Parsec String () Molecule
parseMolecule = Molecule <$> Parsec.many1 (parseToken parseMolecule)