From 9f951a05d4f78cf59190ee4f3cd8de85e1c33bd1 Mon Sep 17 00:00:00 2001 From: Gil Mizrahi Date: Mon, 24 Jan 2022 09:23:52 +0200 Subject: [PATCH] Chapter 4.4 - Markup parsing --- Markup.hs | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 Markup.hs diff --git a/Markup.hs b/Markup.hs new file mode 100644 index 0000000..4715b3a --- /dev/null +++ b/Markup.hs @@ -0,0 +1,81 @@ +-- Markup.hs + +module Markup + ( Document + , Structure(..) + , parse + ) +where + +import Numeric.Natural +import Data.Maybe (maybeToList) + +type Document + = [Structure] + +data Structure + = Heading Natural String + | Paragraph String + | UnorderedList [String] + | OrderedList [String] + | CodeBlock [String] + deriving (Eq, Show) + + +parse :: String -> Document +parse = parseLines Nothing . lines + +parseLines :: Maybe Structure -> [String] -> Document +parseLines context txts = + case txts of + -- done case + [] -> maybeToList context + + -- Heading 1 case + ('*' : ' ' : line) : rest -> + maybe id (:) context (Heading 1 (trim line) : parseLines Nothing rest) + + -- Unordered list case + ('-' : ' ' : line) : rest -> + case context of + Just (UnorderedList list) -> + parseLines (Just (UnorderedList (list <> [trim line]))) rest + + _ -> + maybe id (:) context (parseLines (Just (UnorderedList [trim line])) rest) + + -- Ordered list case + ('#' : ' ' : line) : rest -> + case context of + Just (OrderedList list) -> + parseLines (Just (OrderedList (list <> [trim line]))) rest + + _ -> + maybe id (:) context (parseLines (Just (OrderedList [trim line])) rest) + + -- Code block case + ('>' : ' ' : line) : rest -> + case context of + Just (CodeBlock code) -> + parseLines (Just (CodeBlock (code <> [line]))) rest + + _ -> + maybe id (:) context (parseLines (Just (CodeBlock [line])) rest) + + -- Paragraph case + currentLine : rest -> + let + line = trim currentLine + in + if line == "" + then + maybe id (:) context (parseLines Nothing rest) + else + case context of + Just (Paragraph paragraph) -> + parseLines (Just (Paragraph (unwords [paragraph, line]))) rest + _ -> + maybe id (:) context (parseLines (Just (Paragraph line)) rest) + +trim :: String -> String +trim = unwords . words