pChordSpec :: CharParser () ChordSpec
pChordSpec =
    createSpec <$> pChordQuality <*> pIntervalSpec <*> pAdditionalInterval
    where
        createSpec q mi ai =
            ChordSpec { chordQuality = q, mainInterval = mi, addInterval = ai }
        pChordQuality = "chord quality" <??>
            optionMaybe
                ((try $ MinorChord <$ char 'm') <|>
                (try $ MajorChord <$ char 'M'))
        pIntervalQuality = (<??>) "main chord interval" $
            -- @TODO seems broken
            optionMaybe $
                choice (map try 
                [Minor <$ (string "min")
                ,Major <$ (string "maj")
                ,Diminished <$ (string "dim")
                ,Augmented <$ (string "aug")
                ,Dominant <$ (string "dom")])
        pIntervalNumber = read <$> many1 digit
        pAdditionalInterval = (<??>) "additional chord note" $
            optionMaybe $
                read <$> (string "add" *> many1 digit)
        pIntervalSpec =
            optionMaybe $
                (,) <$> (char '(' *> pIntervalQuality) <*> (pIntervalNumber <* char ')')
pChordSpec :: CharParser () ChordSpec
pChordSpec =
    createSpec <$> pChordQuality <*> pIntervalSpec <*> pAdditionalInterval
    where
        createSpec q mi ai =
            ChordSpec { chordQuality = q, mainInterval = mi, addInterval = ai }
        pChordQuality = "chord quality" <??>
            optionMaybe
                ((try $ MinorChord <$ char 'm') <|>
                (try $ MajorChord <$ char 'M'))
        pIntervalQuality = (<??>) "main chord interval" $
            -- @TODO seems broken
            optionMaybe $
                choice (map try 
                [Minor <$ (string "min")
                ,Major <$ (string "maj")
                ,Diminished <$ (string "dim")
                ,Augmented <$ (string "aug")
                ,Dominant <$ (string "dom")])
        pIntervalNumber = read <$> many1 digit
        pAdditionalInterval = (<??>) "additional chord note" $
            optionMaybe $
                read <$> (string "add" *> many1 digit)
        pIntervalSpec =
            optionMaybe $
                (,) <$> (char '(' *> pIntervalQuality) <*> (pIntervalNumber <* char ')')
pChordSpec =
    createSpec <$> pChordQuality <*> pIntervalSpec <*> pAdditionalInterval
    where
        createSpec q mi ai =
            ChordSpec { chordQuality = q, mainInterval = mi, addInterval = ai }
        pChordQuality = "chord quality" <??>
            optionMaybe
                ((try $ MinorChord <$ char 'm') <|>
                (try $ MajorChord <$ char 'M'))
        pIntervalQuality = (<??>) "main chord interval" $
            -- @TODO seems broken
            optionMaybe $
                choice (map try 
                [Minor <$ (string "min")
                ,Major <$ (string "maj")
                ,Diminished <$ (string "dim")
                ,Augmented <$ (string "aug")
                ,Dominant <$ (string "dom")])
        pIntervalNumber = read <$> many1 digit
        pAdditionalInterval = (<??>) "additional chord note" $
            optionMaybe $
                read <$> (string "add" *> many1 digit)
        pIntervalSpec =
            optionMaybe $
                (,) <$> (char '(' *> pIntervalQuality) <*> (pIntervalNumber <* char ')')