import gleam/dict import gleam/int import gleam/list import gleam/result import gleam/string import luma/definition import luma/mode /// main parse function /// takes in some input text and returns instructions on how to parse it pub fn handler(line: String) -> definition.TextInstructions { let result = parse(line) let result = list.map(result, whatsthat) definition.TextInstructions(result) } fn whatsthat(mod: String) -> definition.Instruction { let modes = dict.from_list([ #("!", #(mode.Marking, definition.Marking)), #("@", #(mode.Truth, definition.Truth)), #(">", #(mode.Quote, definition.Quote)), #("#", #(mode.Hirachy, definition.Hirachy)), ]) case string.pop_grapheme(mod) { Ok(#(prefix, rest)) -> { case dict.get(modes, prefix) { Ok(#(m, make_definition)) -> { case rest { "-" -> definition.Pop(m) _ -> { let value = int.parse(rest) |> result.unwrap(1) definition.Push(make_definition(value)) } } } Error(_) -> definition.Text(mod) } } Error(_) -> definition.Text(mod) } } fn parse(modificators: String) -> List(String) { modificators // 1. Target the tags + their trailing space, wrapping them in "|" |> string.replace(each: "#", with: " |#") |> string.replace(each: "@", with: " |@") |> string.replace(each: "!", with: " |!") |> string.replace(each: ">", with: " |>") // 2. Split by the space-marker combination |> string.split(on: " |") // 3. For each block, split out the tag itself from any trailing words |> list.flat_map(fn(block) { case string.starts_with(block, "#") || string.starts_with(block, "@") || string.starts_with(block, "!") || string.starts_with(block, ">") { True -> { // Separate the tag from the text following it case string.split_once(block, on: " ") { Ok(#(tag, rest)) -> [tag, rest] Error(_) -> [block] } } False -> [block] } }) // 4. Clean up padding and drop empty elements |> list.map(string.trim) |> list.filter(fn(x) { x != "" }) }