Current section

Files

Jump to
cssex lib helpers at_parser.ex~
Raw

lib/helpers/at_parser.ex~

defmodule CSSEx.Helpers.AtParser do
@moduledoc false
import CSSEx.Helpers.Shared, only: [inc_col: 1]
import CSSEx.Helpers.Error, only: [error_msg: 1]
import CSSEx.Parser, only: [add_error: 2]
@line_terminators CSSEx.Helpers.LineTerminators.code_points()
@args_split_regex ~r/(?<maybe_var_1>\$::)?.+(?<split>:).+(?<maybe_var_2>\$::)|(?<split_2>:)/
defstruct column: 0, acc: [], parenthesis: 0, p_acc: %{}
def parse(rem, data) do
case do_parse(rem, data, %__MODULE__{}) do
{:ok, {_, _} = result} -> result
{:error, new_data} -> {rem, new_data}
end
end
def do_parse([], data, %{acc: acc, parenthesis: 0} = _state) do
parsed = IO.chardata_to_string(acc)
{:ok, {parsed, data}}
end
# we found an opening parenthesis (,
def do_parse([?( | rem], data, %{parenthesis: p, p_acc: p_acc} = state) do
new_p = p + 1
new_p_acc = Map.put(p_acc, new_p, [])
do_parse(rem, inc_col(data), %{state | parenthesis: new_p, p_acc: new_p_acc})
end
# we found a closing parenthesis )
def do_parse([?) | rem], data, %{acc: acc, parenthesis: p, p_acc: p_acc} = state)
when p > 0 do
{accumulator, new_p_acc} = Map.pop(p_acc, p)
try do
processed = process_parenthesis_content(accumulator, data)
previous_p = p - 1
new_state = inc_col(%{state | parenthesis: previous_p})
new_state_2 =
case Map.pop(new_p_acc, previous_p) do
# this means we're on the first opened parenthesis
{nil, new_p_acc_2} ->
%{new_state | p_acc: new_p_acc_2, acc: [acc, [?(, processed, ?)]]}
{previous_acc, new_p_acc_2} ->
%{
new_state
| p_acc: Map.put(new_p_acc_2, previous_p, [previous_acc, [?(, processed, ?)]])
}
end
do_parse(rem, data, new_state_2)
catch
{:error, _} = error ->
{:error, add_error(data, error_msg(error))}
end
end
end