I\'m having a hard time implementing Read for a tree structure. I want to take a left-associative string (with parens) like ABC(DE)F and convert it into a tree.
The parsec answer by dbaupp is very easy to understand. As an example of a "low-level" approach, here is a hand written parser which uses a success continuation to handle the left-associative tree building:
instance Read Tree where readsPrec _prec s = maybeToList (readTree s)
type TreeCont = (Tree,String) -> Maybe (Tree,String)
readTree :: String -> Maybe (Tree,String)
readTree = read'top Just where
valid ')' = False
valid '(' = False
valid _ = True
read'top :: TreeCont -> String -> Maybe (Tree,String)
read'top acc s@(x:ys) | valid x =
case ys of
[] -> acc (Leaf x,[])
(y:zs) -> read'branch acc s
read'top _ _ = Nothing
-- The next three are mutually recursive
read'branch :: TreeCont -> String -> Maybe (Tree,String)
read'branch acc (x:y:zs) | valid x = read'right (combine (Leaf x) >=> acc) y zs
read'branch _ _ = Nothing
read'right :: TreeCont -> Char -> String -> Maybe (Tree,String)
read'right acc y ys | valid y = acc (Leaf y,ys)
read'right acc '(' ys = read'branch (drop'close >=> acc) ys
where drop'close (b,')':zs) = Just (b,zs)
drop'close _ = Nothing
read'right _ _ _ = Nothing -- assert y==')' here
combine :: Tree -> TreeCont
combine build (t, []) = Just (Branch build t,"")
combine build (t, ys@(')':_)) = Just (Branch build t,ys) -- stop when lookahead shows ')'
combine build (t, y:zs) = read'right (combine (Branch build t)) y zs