| 1 | |
|---|
| 2 | import Data.Char |
|---|
| 3 | |
|---|
| 4 | main :: IO () |
|---|
| 5 | main = do xs <- getContents |
|---|
| 6 | putStr $ unlines $ unlit BirdAllowed $ lines xs |
|---|
| 7 | |
|---|
| 8 | data State = InCode | InBird | BirdAllowed | BirdNotAllowed |
|---|
| 9 | data LineType = BeginCode | EndCode | BirdTrack String | Blank | Normal |
|---|
| 10 | |
|---|
| 11 | unlit :: State -> [String] -> [String] |
|---|
| 12 | unlit InCode [] = error "File ended in a code block" |
|---|
| 13 | unlit _ [] = [] |
|---|
| 14 | unlit s (x:xs) |
|---|
| 15 | = case (lineType x, s) of |
|---|
| 16 | -- First deal with code blocks |
|---|
| 17 | (BeginCode, InCode) -> error "Can't nest code blocks" |
|---|
| 18 | (BeginCode, _) -> unlit InCode xs |
|---|
| 19 | (EndCode, InCode) -> unlit BirdAllowed xs |
|---|
| 20 | (EndCode, _) -> error "Closing non-existent code block" |
|---|
| 21 | (_, InCode) -> x : unlit InCode xs |
|---|
| 22 | -- Now deal with bird tracks |
|---|
| 23 | (BirdTrack _, BirdNotAllowed) -> error "Bird track next to stuff" |
|---|
| 24 | (BirdTrack x', _) -> x' : unlit InBird xs |
|---|
| 25 | (Normal, InBird) -> error "Bird track next to stuff" |
|---|
| 26 | (Normal, _) -> unlit BirdNotAllowed xs |
|---|
| 27 | (Blank, _) -> unlit BirdAllowed xs |
|---|
| 28 | |
|---|
| 29 | lineType :: String -> LineType |
|---|
| 30 | lineType x |
|---|
| 31 | | x `starts` "\\begin{code}" = BeginCode |
|---|
| 32 | | x `starts` "\\end{code}" = EndCode |
|---|
| 33 | | all isSpace x = Blank |
|---|
| 34 | lineType ('>':x') = BirdTrack (' ':x') |
|---|
| 35 | lineType _ = Normal |
|---|
| 36 | |
|---|
| 37 | starts :: String -> String -> Bool |
|---|
| 38 | x `starts` pref = case x `stripPrefix` pref of |
|---|
| 39 | Just s |
|---|
| 40 | | all isSpace s -> True |
|---|
| 41 | | otherwise -> error ("Trailing characters after " ++ pref) |
|---|
| 42 | Nothing -> False |
|---|
| 43 | |
|---|
| 44 | stripPrefix :: Eq a => [a] -> [a] -> Maybe [a] |
|---|
| 45 | xs `stripPrefix` [] = Just xs |
|---|
| 46 | [] `stripPrefix` _ = Nothing |
|---|
| 47 | (x:xs) `stripPrefix` (y:ys) |
|---|
| 48 | | x == y = xs `stripPrefix` ys |
|---|
| 49 | | otherwise = Nothing |
|---|