Operand

_

gram: legal

> ./lib/us_congress/bill_dtd/shape.ex

defmodule UsCongress.BillDtd.Shape do
@doc """
`&combine/2` is used to combine a sequence of nodes,
once `end_element` is found.
"""
def combine(
%{scheme: "enum", body: enum} = former,
%{label: "header", measure: [header], params: %{}} = current
), do:
%{scheme: "header", enum: former.body, body: header}
def combine(
%{measure: measure} = former,
%{scheme: s, body: b} = current
), do:
former |> Map.put(:measure, [current | measure])
def combine(
%{scheme: a_scheme, body: a_body},
%{scheme: b_scheme, body: b_body} = b
), do:
b |> Map.put(a_scheme, a_body)
def combine(
%{measure: measure} = basis,
%{measure: _measure} = current
) do
current = Map.put(current, :measure, current.measure |> Enum.reverse)
basis
|> Map.put(:measure, [current | measure])
end
@doc """
`&merge/2` is used to merge a sequence of nodes,
before `end_element` is found.
In practice this only seems to apply on the `characters` event.
"""
def merge(%{measure: measure} = prior, current) when is_bitstring(current) do
prior |> Map.put(:measure, [current | measure])
end
@doc """
"""
def scheme(%{ label: name, measure: [body], params: params}) do
%{ scheme: name, body: body }
end
def reshape(label) when is_atom(label), do: Atom.to_string(label)
def reshape(label) when is_binary(label), do: label
def reshape(l) when is_list(l), do: l |> Enum.map(&reshape/1)
def reshape(record) when is_map(record) do
record = if Map.has_key?(record, :params) and Map.size(record.params) == 0,
do: Map.delete(record, :params),
else: record
record = if Map.has_key?(record, :measure) do
if length(record.measure) == 0,
do: Map.delete(record, :measure),
else: Map.put(record, :measure, record.measure |> Enum.reverse)
else
record
end
record |> Map.new(fn {l, n} -> { reshape(l), reshape(n) } end)
end
end