# `Sat.Csf.Parser`

Parser de Constancia de Situación Fiscal (CSF) que toma el resultado
estructurado de `Pdf.Reader.read/2` y produce un `%Sat.Csf.Document{}`.

El parser asume que el PDF se leyó con `dictionary: :es` (necesario para
separar palabras pegadas como `iniciode → inicio de`). `Sat.Csf.from_file/2`
y `from_binary/2` lo configuran por defecto.

## Estrategia

- Identificación y Domicilio: se extraen pares `Label: valor` con un regex
  que conoce todos los labels esperados, manejando líneas con dos columnas
  (ej. `Código Postal: 77728 Tipo de Vialidad: AVENIDA (AV.)`).

- Actividades y Regímenes: regex sobre el texto de cada fila, anclado por el
  formato de fecha `dd/mm/yyyy` al final.

- Obligaciones: usa las posiciones X de los tokens para separar las cuatro
  columnas (descripción, vencimiento, fecha inicio, fecha fin). Una fila se
  extiende a múltiples líneas cuando la descripción se desborda; la presencia
  de `dd/mm/yyyy` en la columna de fecha inicio marca el comienzo de cada
  obligación.

# `parse`

```elixir
@spec parse(Pdf.Reader.Result.t()) ::
  {:ok, Sat.Csf.Document.t()} | {:error, :not_a_csf}
```

Parsea un `%Pdf.Reader.Result{}` y devuelve `{:ok, %Sat.Csf.Document{}}`.

Retorna `{:error, :not_a_csf}` si no detecta los marcadores de sección
esperados (sirve como guard para PDFs que no son CSF).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
