Current section

Files

Jump to
commonmark src commonmark@internal@parser.erl
Raw

src/commonmark@internal@parser.erl

-module(commonmark@internal@parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([parse_text/1, parse_paragraph/1, parse_block_state/1, parse_blocks/1]).
-export_type([parser_state/0, block_parse_state/0]).
-type parser_state() :: outside_block |
{paragraph_builder, list(binary())} |
{code_block_builder,
binary(),
gleam@option:option(binary()),
gleam@option:option(binary()),
list(binary())}.
-opaque block_parse_state() :: {paragraph, list(binary())} |
horizontal_break |
{heading, integer(), gleam@option:option(list(binary()))} |
{code_block,
gleam@option:option(binary()),
gleam@option:option(binary()),
list(binary())}.
-spec parse_text(list(binary())) -> list(commonmark@ast:inline_node()).
parse_text(Text) ->
Len = erlang:length(Text) - 1,
_assert_subject = gleam@regex:from_string(<<"( |\\\\)$"/utf8>>),
{ok, Hard_break_regex} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"commonmark/internal/parser"/utf8>>,
function => <<"parse_text"/utf8>>,
line => 23})
end,
_pipe = Text,
_pipe@5 = gleam@list:index_map(
_pipe,
fun(L, I) -> case gleam@regex:check(Hard_break_regex, L) of
_ when I =:= Len ->
[{text,
begin
_pipe@1 = L,
gleam@string:trim(_pipe@1)
end}];
true ->
[{text,
begin
_pipe@2 = L,
_pipe@3 = gleam@string:drop_right(_pipe@2, 1),
gleam@string:trim(_pipe@3)
end},
hard_line_break];
_ ->
[{text,
begin
_pipe@4 = L,
gleam@string:trim(_pipe@4)
end},
soft_line_break]
end end
),
gleam@list:concat(_pipe@5).
-spec parse_paragraph(list(binary())) -> commonmark@ast:block_node().
parse_paragraph(Lines) ->
_pipe = Lines,
_pipe@1 = parse_text(_pipe),
{paragraph, _pipe@1}.
-spec parse_block_state(block_parse_state()) -> list(commonmark@ast:block_node()).
parse_block_state(State) ->
case State of
{paragraph, Lines} ->
[begin
_pipe = Lines,
_pipe@1 = lists:reverse(_pipe),
_pipe@2 = parse_text(_pipe@1),
{paragraph, _pipe@2}
end];
{code_block, Info, Full_info, Lines@1} ->
[{code_block,
Info,
Full_info,
begin
_pipe@3 = Lines@1,
_pipe@4 = lists:reverse(_pipe@3),
gleam@string:join(_pipe@4, <<"\n"/utf8>>)
end}];
horizontal_break ->
[horizontal_break];
{heading, Level, {some, Contents}} ->
[{heading, Level, parse_text(Contents)}];
{heading, Level@1, none} ->
[{heading, Level@1, parse_text([])}]
end.
-spec do_parse_blocks(parser_state(), list(block_parse_state()), list(binary())) -> list(block_parse_state()).
do_parse_blocks(State, Acc, Lines) ->
_assert_subject = gleam@regex:from_string(
<<"^ {0,3}(?:\\*[* \t]*\\*[* \t]*\\*|\\-[- \t]*\\-[- \t]*\\-|\\_[_ \t]*\\_[_ \t]*\\_)[ \t]*$"/utf8>>
),
{ok, Hr_regex} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"commonmark/internal/parser"/utf8>>,
function => <<"do_parse_blocks"/utf8>>,
line => 62})
end,
_assert_subject@1 = gleam@regex:from_string(
<<"^ {0,3}(#{1,6})([ \t]+.*?)?(?:(?<=[ \t])#*)?[ \t]*$"/utf8>>
),
{ok, Atx_header_regex} = case _assert_subject@1 of
{ok, _} -> _assert_subject@1;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@1,
module => <<"commonmark/internal/parser"/utf8>>,
function => <<"do_parse_blocks"/utf8>>,
line => 66})
end,
_assert_subject@2 = gleam@regex:from_string(
<<"^ {0,3}([-=])+[ \t]*$"/utf8>>
),
{ok, Setext_header_regex} = case _assert_subject@2 of
{ok, _} -> _assert_subject@2;
_assert_fail@2 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@2,
module => <<"commonmark/internal/parser"/utf8>>,
function => <<"do_parse_blocks"/utf8>>,
line => 68})
end,
_assert_subject@3 = case State of
{code_block_builder, Break, _, _, _} ->
gleam@regex:from_string(
<<<<"^ {0,3}"/utf8, Break/binary>>/binary, "+[ \t]*$"/utf8>>
);
_ ->
gleam@regex:from_string(
<<"^ {0,3}([~`]{3,})[ \t]*(([^\\s]+).*?)?[ \t]*$"/utf8>>
)
end,
{ok, Fenced_code_regex} = case _assert_subject@3 of
{ok, _} -> _assert_subject@3;
_assert_fail@3 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail@3,
module => <<"commonmark/internal/parser"/utf8>>,
function => <<"do_parse_blocks"/utf8>>,
line => 70})
end,
L = begin
_pipe = gleam@list:first(Lines),
gleam@result:unwrap(_pipe, <<""/utf8>>)
end,
case {State,
Lines,
gleam@regex:check(Hr_regex, L),
gleam@regex:scan(Atx_header_regex, L),
gleam@regex:scan(Setext_header_regex, L),
gleam@regex:scan(Fenced_code_regex, L)} of
{{paragraph_builder, Lines@1}, [], _, _, _, _} ->
_pipe@1 = [{paragraph, Lines@1} | Acc],
lists:reverse(_pipe@1);
{{code_block_builder, _, Info, Full_info, Contents},
[<<""/utf8>>],
_,
_,
_,
_} ->
_pipe@2 = [{code_block, Info, Full_info, [<<""/utf8>> | Contents]} |
Acc],
lists:reverse(_pipe@2);
{{code_block_builder, _, Info, Full_info, Contents}, [], _, _, _, _} ->
_pipe@2 = [{code_block, Info, Full_info, [<<""/utf8>> | Contents]} |
Acc],
lists:reverse(_pipe@2);
{outside_block, [], _, _, _, _} ->
_pipe@3 = Acc,
lists:reverse(_pipe@3);
{{paragraph_builder, Bs}, [<<" "/utf8>> | Ls], _, _, _, _} ->
do_parse_blocks(outside_block, [{paragraph, Bs} | Acc], Ls);
{{paragraph_builder, Bs}, [<<"\\"/utf8>> | Ls], _, _, _, _} ->
do_parse_blocks(outside_block, [{paragraph, Bs} | Acc], Ls);
{{paragraph_builder, Bs}, [<<""/utf8>> | Ls], _, _, _, _} ->
do_parse_blocks(outside_block, [{paragraph, Bs} | Acc], Ls);
{outside_block, [<<" "/utf8>> | Ls@1], _, _, _, _} ->
do_parse_blocks(outside_block, Acc, Ls@1);
{outside_block, [<<"\\"/utf8>> | Ls@1], _, _, _, _} ->
do_parse_blocks(outside_block, Acc, Ls@1);
{outside_block, [<<""/utf8>> | Ls@1], _, _, _, _} ->
do_parse_blocks(outside_block, Acc, Ls@1);
{{paragraph_builder, Bs@1},
[_ | Ls@2],
_,
_,
_,
[{match, _, [{some, Exit}]}]} ->
do_parse_blocks(
{code_block_builder, Exit, none, none, []},
[{paragraph, Bs@1} | Acc],
Ls@2
);
{{paragraph_builder, Bs@2},
[_ | Ls@3],
_,
_,
_,
[{match, _, [{some, Exit@1}, Full_info@1, Info@1]}]} ->
do_parse_blocks(
{code_block_builder, Exit@1, Info@1, Full_info@1, []},
[{paragraph, Bs@2} | Acc],
Ls@3
);
{outside_block, [_ | Ls@4], _, _, _, [{match, _, [{some, Exit@2}]}]} ->
do_parse_blocks(
{code_block_builder, Exit@2, none, none, []},
Acc,
Ls@4
);
{outside_block,
[_ | Ls@5],
_,
_,
_,
[{match, _, [{some, Exit@3}, Full_info@2, Info@2]}]} ->
do_parse_blocks(
{code_block_builder, Exit@3, Info@2, Full_info@2, []},
Acc,
Ls@5
);
{{code_block_builder, _, Info@3, Full_info@3, Bs@3},
[_ | Ls@6],
_,
_,
_,
[{match, _, _}]} ->
do_parse_blocks(
outside_block,
[{code_block, Info@3, Full_info@3, [<<""/utf8>> | Bs@3]} | Acc],
Ls@6
);
{{code_block_builder, Break@1, Info@4, Full_info@4, Bs@4},
[L@1 | Ls@7],
_,
_,
_,
_} ->
do_parse_blocks(
{code_block_builder, Break@1, Info@4, Full_info@4, [L@1 | Bs@4]},
Acc,
Ls@7
);
{{paragraph_builder, Bs@5},
[_ | Ls@8],
_,
_,
[{match, _, [{some, <<"="/utf8>>}]}],
_} ->
do_parse_blocks(
outside_block,
[{heading, 1, {some, lists:reverse(Bs@5)}} | Acc],
Ls@8
);
{{paragraph_builder, Bs@6},
[_ | Ls@9],
_,
_,
[{match, _, [{some, <<"-"/utf8>>}]}],
_} ->
do_parse_blocks(
outside_block,
[{heading, 2, {some, lists:reverse(Bs@6)}} | Acc],
Ls@9
);
{{paragraph_builder, Bs@7}, [_ | Ls@10], true, _, _, _} ->
do_parse_blocks(
outside_block,
[horizontal_break, {paragraph, Bs@7} | Acc],
Ls@10
);
{outside_block, [_ | Ls@11], true, _, _, _} ->
do_parse_blocks(outside_block, [horizontal_break | Acc], Ls@11);
{outside_block, [_ | Ls@12], _, [{match, _, [{some, Heading}]}], _, _} ->
do_parse_blocks(
outside_block,
[{heading, gleam@string:length(Heading), none} | Acc],
Ls@12
);
{outside_block,
[_ | Ls@13],
_,
[{match, _, [{some, Heading@1}, {some, Contents@1}]}],
_,
_} ->
do_parse_blocks(
outside_block,
[{heading, gleam@string:length(Heading@1), {some, [Contents@1]}} |
Acc],
Ls@13
);
{{paragraph_builder, Bs@8},
[_ | Ls@14],
_,
[{match, _, [{some, Heading@2}]}],
_,
_} ->
do_parse_blocks(
outside_block,
[{heading, gleam@string:length(Heading@2), none},
{paragraph, Bs@8} |
Acc],
Ls@14
);
{{paragraph_builder, Bs@9},
[_ | Ls@15],
_,
[{match, _, [{some, Heading@3}, {some, Contents@2}]}],
_,
_} ->
do_parse_blocks(
outside_block,
[{heading, gleam@string:length(Heading@3), {some, [Contents@2]}},
{paragraph, Bs@9} |
Acc],
Ls@15
);
{outside_block, [Line | Ls@16], _, _, _, _} ->
do_parse_blocks({paragraph_builder, [Line]}, Acc, Ls@16);
{{paragraph_builder, Bs@10}, [Line@1 | Ls@17], _, _, _, _} ->
do_parse_blocks({paragraph_builder, [Line@1 | Bs@10]}, Acc, Ls@17)
end.
-spec parse_blocks(list(binary())) -> list(block_parse_state()).
parse_blocks(Lines) ->
do_parse_blocks(outside_block, [], Lines).