Skip to content

Instantly share code, notes, and snippets.

@RobertDober
Last active April 2, 2025 15:22
Show Gist options
  • Save RobertDober/d6885d863bbd50131395190b192f7066 to your computer and use it in GitHub Desktop.
Save RobertDober/d6885d863bbd50131395190b192f7066 to your computer and use it in GitHub Desktop.
High Level Architecture for NimbleParsec Integration into EarmarkParser
defmodule HLArch do
# We get a binary from ex_doc anyway, therefore we can ...
@spec parse(binary, ast) :: ast
def parse(input, ast \\ []) do
input
|> put_into_struct() # getting fields content: input, lnb: 1, col: 1
|> parse_into_ast()
|> semantic_checks()
end
# We need more info here than in the eventual result, because in case
# of errors during semantic checks we will need some context information
# concerning the location in the input **at least**
# Probably we will also add another argument context :: map or struct, but we will see
@spec parse_into_ast(Input.t, ast()) :: annotated_ast()
def parse_into_ast(input, ast \\ [])
def parse_into_ast("", ast), do: ast |> some_post_processing() # Probably just Enum.reverse
def parse_into_ast(input, ast) do
# No more pattern matching on function definitions because, unless we have alreadya a very stable codebase,
# we can avoid the pain of debugging with...
# IO.inspect(input, label: ">>>parse_into_ast")
{new_input, new_ast} =
case input.content do
<<"<", html::binary>> -> {html, rest, position, _} = Nimble.HtmlParser(html)
# Ignoring Error Handling here
update_ast_and_input(ast, html)
_ -> {line, rest} = get_next_line(input.content)
# Some of Jonatan's optimizations will be obsoleted by that approach #100, #101
# because we will not read lines inside multiline code blocks anymore
# This should make the code clearer though
typed_line = LineScanner.type_of(line)
# Integrating this with recursive calls into parse_into_ast will be all
# save trivial
parse_old_logic(typed_line, rest, ast)
end
# |> IO.inspect(input, label: "<<<parse_into_ast")
parse_into_ast(new_input, new_ast)
end
# I believe a Regex is perfect for that, some better idea?
defp get_next_line(input_string) do
case Regex.run(~r/\A(.*?)\n(.*)/msu, input.content) do
nil -> {input_string, nil}
[_, line, rest ] -> {line, rest}
end
end
end
@RobertDober
Copy link
Author

Here are the links of Jonathan's PRs mention in the gist RobertDober/earmark_parser#100 RobertDober/earmark_parser#101

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment