lookahead_helpers.ex (2643B)
1 defmodule EarmarkParser.Helpers.LookaheadHelpers do 2 3 @moduledoc false 4 5 import EarmarkParser.Helpers.LeexHelpers 6 7 @doc """ 8 Indicates if the _numbered_line_ passed in leaves an inline code block open. 9 10 If so returns a tuple whre the first element is the opening sequence of backticks, 11 and the second the linenumber of the _numbered_line_ 12 13 Otherwise `{nil, 0}` is returned 14 """ 15 def opens_inline_code(%{line: line, lnb: lnb}) do 16 # case tokenize(line, with: :string_lexer) |> IO.inspect() |> has_still_opening_backtix(nil) do 17 case tokenize(line, with: :string_lexer) |> has_still_opening_backtix(nil) do 18 nil -> {nil, 0} 19 {_, btx} -> {btx, lnb} 20 end 21 end 22 23 @doc """ 24 returns false if and only if the line closes a pending inline code 25 *without* opening a new one. 26 The opening backtix are passed in as second parameter. 27 If the function does not return false it returns the (new or original) 28 opening backtix 29 """ 30 # (#{},{_,_}) -> {_,_} 31 def still_inline_code(%{line: line, lnb: lnb}, old = {pending, _pending_lnb}) do 32 case tokenize(line, with: :string_lexer) |> has_still_opening_backtix({:old, pending}) do 33 nil -> {nil, 0} 34 {:new, btx} -> {btx, lnb} 35 {:old, _} -> old 36 end 37 end 38 39 # A tokenized line {:verabtim, text} | {:backtix, ['``+]} is analyzed for 40 # if it is closed (-> nil), not closed (-> {:old, btx}) or reopened (-> {:new, btx}) 41 # concerning backtix 42 defp has_still_opening_backtix(tokens, opened_so_far) 43 44 # Empty, done, but take care of tangeling escape (\) 45 defp has_still_opening_backtix([], :force_outside), do: nil 46 defp has_still_opening_backtix([], open), do: open 47 48 # Outside state, represented by nil 49 defp has_still_opening_backtix([{:other, _} | rest], nil), 50 do: has_still_opening_backtix(rest, nil) 51 52 defp has_still_opening_backtix([{:backtix, btx} | rest], nil), 53 do: has_still_opening_backtix(rest, {:new, btx}) 54 55 defp has_still_opening_backtix([{:escape, _} | rest], nil), 56 do: has_still_opening_backtix(rest, :force_outside) 57 58 # Next state forced outside, represented by :force_outside 59 defp has_still_opening_backtix([_ | rest], :force_outside), 60 do: has_still_opening_backtix(rest, nil) 61 62 # Inside state, represented by { :old | :new, btx } 63 defp has_still_opening_backtix([{:backtix, btx} | rest], open = {_, openedbtx}) do 64 if btx == openedbtx do 65 has_still_opening_backtix(rest, nil) 66 else 67 has_still_opening_backtix(rest, open) 68 end 69 end 70 71 defp has_still_opening_backtix([_ | rest], open = {_, _}), 72 do: has_still_opening_backtix(rest, open) 73 end 74 75 # SPDX-License-Identifier: Apache-2.0