module StartTag where

import FPPrac.Trees

data NT = NTStartTag | NTAttributeList | NTAttribute
        deriving Show

data Tree = Leaf Token
          | Node NT [ Tree ]
          deriving Show

data Token = LBrack           -- '<'
           | RBrack           -- '>'
           | Close            -- '</'
           | Assignment       -- '='
           | ConstStr String  -- " ... "
           | Id String        -- [a-zA-Z]+
           deriving (Show, Eq)

letter = ['a'..'z'] ++ ['A'..'Z']
digit  = ['0' .. '9']
letdig = letter ++ digit

tokenize :: String -> [Token]
tokenize [] = []
tokenize (' ':xs)         = tokenize xs
tokenize ('\t':xs)        = tokenize xs
tokenize ('<': '/' : xs)  = Close : tokenize xs
tokenize ('<' : xs)       = LBrack : tokenize xs
tokenize ('>' : xs)       = RBrack : tokenize xs
tokenize ('=' : xs)       = Assignment : tokenize xs
tokenize ('"' : xs)       = ConstStr string : tokenize rem
  where (string, '"':rem) = break (=='"') xs
tokenize s@(x:xs) | x `elem` letter = Id id : tokenize rem
  where (id, rem) = span (`elem` letdig) s


parseStarttag :: [Token] -> (Tree, [Token])
parseStarttag (LBrack : id@(Id tag) : xs) = (Node NTStartTag
                                              [Leaf LBrack,
                                               Leaf id, tattr,
                                               Leaf RBrack],
                                             ys)
  where (tattr, RBrack: ys) = parseAttrL xs

parseAttrL :: [Token] -> (Tree, [Token])
parseAttrL xs@((Id _):_) = (Node NTAttributeList [tattr,
                                                  ttail],
                            zs)
  where (tattr, ys) = parseAttr xs
        (ttail, zs) = parseAttrL ys
parseAttrL  xs = (Node NTAttributeList [], xs) -- epsilon


parseAttr :: [Token] -> (Tree, [Token])
parseAttr (tid@(Id id) : Assignment : tc@(ConstStr str) : xs)
  = (Node NTAttribute [Leaf tid,
                       Leaf Assignment,
                       Leaf tc],
     xs)


pp :: Tree -> RoseTree
pp (Leaf nt)   = RoseNode (show nt) []
pp (Node nt t) = RoseNode (show nt) $ map pp t


test :: IO ()
test = showTree $ pp $ fst $ parseStarttag  (tokenize "<a q=\"1\" r=\"11\">")
