> For the complete documentation index, see [llms.txt](https://minilatex.gitbook.io/project/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://minilatex.gitbook.io/project/accumulator.md).

# Accumulator

As noted in the overview, one uses an accumulator to collect information about sequentially numbered sections, cross-references, tables of content, etc., then uses a second accumulator to render the source text with these features. Accumulators are made of up of reducers and folds:

```
type alias Reducer a b : a -> b -> b
List.foldl : (a -> b -> b ) -> b -> List a -> b
```

A `Reducer` is a name for the type of the first argument of a fold. Consider a reducer of the form

```
Reducer state a b  = a -> (state, List b) -> (state, List b)
```

It fits into a fold of the form

```
Reducer state a b  -> (state, List b) -> List a -> (state, List b)
```

Let `transform` have type `StateReducer state a b`. Define

```
acc transformer state_ inputList =
  List.foldl transformer (state_, []) inputList
```

The type of this function is

```
Accumulator state a b = state -> List a -> (state, List b)
```

To restate in plainer English, an `Accumulator state a b` takes as input a `State a b` and a `List a` and returns a tuple consisting of an updated `State a b` and another list, one of type `List b`.

## Accumulator.parse

Let us discuss the accumulators used in MiniLatex. The first of these is `Accumulator.parse`. Its function is to take a `LatexState` and a list of paragraphs, i.e., a `List String`, and produce an updated `LatexState` and a `List (List LatexExpression)`. Each element of the latter is a `List LatexExpression` representing the application of the MiniLatex parser to a paragraph.

```
Accumulator.parse :
    LatexState
    -> List String
    -> ( LatexState, List (List LatexExpression) )
Accumulator.parse latexState paragraphs =
    paragraphs
        |> List.foldl parseReducer ( latexState, [] )
```

The `Accumulator.parse` function applies a `List.foldl` to a pair consisting of an initial `LatexState` and an empty list using a `parseReducer`. The latter is defined as follows:

```
parseReducer :
    String
    -> ( LatexState, List (List LatexExpression) )
    -> ( LatexState, List (List LatexExpression) )
parseReducer inputString ( latexState, inputList ) =
    let
        parsedInput =
            Parser.parse inputString

        newLatexState =
            latexStateReducer parsedInput latexState
    in
    ( newLatexState, inputList ++ [ parsedInput ] )
```

The `parseReducer` takes as input a string, representing a logical paragraph of source text, and a pair consisting of a `LatexState` and a `List (List LatexExpression`. It parses the string and computes a new `LatexState` using `latexStateReducer`:

```
latexStateReducer : List LatexExpression -> LatexState -> LatexState
```

We discuss this function later on. The return value of the `parseReducer` is a pair consisting of the new `LatexState` and inputList with the parsedInput appended.

## Accumulator.render

`Accumulator.render renderer` is an accumulator which takes a `LatexState` and a `List (List LatexExpression)` as input, and produces a new `LatexState` and `List a` as output. The nature of `a` depends on the `renderer` function used:

```
Accumulator.render :
    (LatexState -> List LatexExpression -> a)
    -> LatexState
    -> List (List LatexExpression)
    -> ( LatexState, List a )
Accumulator.render renderer latexState paragraphs =
    paragraphs
        |> List.foldl (renderReducer renderer) ( latexState, [] )
```

The expression `renderReducer renderer` is a reducer of type

```
 List LatexExpression  -> ( LatexState, List a ) -> ( LatexState, List a )
```

It operates as follows:

1. Compute a new `LatexState` by applying `latexStateReducer` to (a) the given list of `LatexExpressions` and (b) the `LatexState` coming from the first element of the second argument, a tuple of type `(LatexState, List a)`
2. Apply the `renderer` to the new state computed in the previous step and the `List LatexExpression` given by the first argument.
3. Return a tuple consisting of the updated `LatexState` and the `inputList` with the newly rendered text appended.

```
renderReducer :
    (LatexState -> List LatexExpression -> a)
    -> List LatexExpression
    -> ( LatexState, List a )
    -> ( LatexState, List a )
renderReducer renderer listLatexExpression ( latexState, inputList ) =
    let
        newLatexState =
            latexStateReducer listLatexExpression latexState

        renderedInput =
            renderer newState listLatexExpression
    in
    ( newLatexState, inputList ++ [ renderedInput ] )
```

## LatexStateReducer

The purpose of the `latexStateReducer` is to update a given `LatexState` using the information contained in a `List LatexExpression`, i.e., the parse result of a paragraph.

```
latexStateReducer : List LatexExpression -> LatexState -> LatexState
latexStateReducer parsedParagraph latexState =
    let
        theInfo =
            parsedParagraph
                |> List.head
                |> Maybe.map info
                |> Maybe.withDefault (LatexInfo "null" "null" [] [])
    in
    (latexStateReducerDispatcher  theInfo) theInfo latexState
```

This a fairly complex reducer. In brief, it looks at the first `LatexExpression` in the `List LatexExpression` representing a given paragraph, then uses the function `info` to compute a record, `theInfo`, which extracts certain information from the paragraph. For example, if the paragraph is `\section{Introduction}`, the `theInfo` will contatin fields `name = section` and `typ = macro`. The call `latexStateReducerDispatcher theInfo` uses a dictionary lookup to produce a function of type `LatexInfo -> LatexState -> LatexState` from `theInfo`. Therefore the value of the expression

```
(latexStateReducerDispatcher theInfo) theInfo latexStae
```

is of type `LatexState`, in accord with what one reads from the type annotation of `latexStateReducer parsedParagraph latexState`.

Let's see how this works in a simple example:

```
> import MiniLatex.Parser exposing(..)
> import Parser exposing(run)
> import MiniLatex.Accumulator exposing(info)
> result = run latexExpression "\\section{foo}"
Ok (Macro "section" [] [LatexList [LXString "foo"]])
> expression = Macro "section" [] [LatexList [LXString "foo"]]
> theInfo = info expression
    { name = "section", options = [], typ = "macro", value = [LatexList [LXString "Foo"]] }
    : MiniLatex.Accumulator.LatexInfo
```

Now the dispatcher looks like this

```
latexStateReducerDispatcher : LatexInfo -> (LatexInfo -> LatexState -> LatexState)
latexStateReducerDispatcher theInfo =
    case Dict.get ( theInfo.typ, theInfo.name ) latexStateReducerDict of
        Just f ->
            f

        Nothing ->
            \latexInfo latexState -> latexState
```

where the dictionary has type

```
latexStateReducerDict : Dict.Dict ( String, String ) (LatexInfo -> LatexState -> LatexState)
```

If the key given by `theInfo` is not in the `latexStateReducerDict`, projection of the arguments to `LatexState` is returned. In the case at hand, `theInfo` has fields `name = "section"` and `typ = "macro"`, and the function returned by the dictionary is `SRH.updateSectionNumber x y`. Here `SRH` is an alias of the `StateReducerHelper` module. Referring to that module, we find that

```
updateSectionNumber : LatexInfo -> LatexState -> LatexState
updateSectionNumber info latexState =
    let
        label =
            getCounter "s1" latexState |> (\x -> x + 1) |> String.fromInt
    in
        latexState
            |> incrementCounter "s1"
            |> updateCounter "s2" 0
            |> updateCounter "s3" 0
            |> addSection (PT.unpackString info.value) label 1
```

Thus `updateSectionNumber` increments the "s1" counter in the `latexState` and sets the other section counters to zero. The `addSection` function, listed below, adds the current section to the table of contents field of the `LatexState`:

```
LatexState.addSection : String -> String -> Int -> LatexState -> LatexState
LatexState.addSection sectionName label level latexState =
    let
        newEntry =
            TocEntry sectionName label level

        toc =
            latexState.tableOfContents ++ [ newEntry ]
    in
    { latexState | tableOfContents = toc }
```

We will not go down the rabbit hole any further, but you get the general idea. The `LatexState` holds counters, the table of contents, cross references, and a general-purpose dictionaray. To add new abilities to `MiniLatex`, one can add new entries to `latexStateReducerDict` or new fields to `LatexState`.

```
type alias LatexState =
    { counters : Counters
    , crossReferences : CrossReferences
    , tableOfContents : TableOfContents
    , dictionary : Dictionary
    }
```

### Example: rendering a section

To conclude this discussion, we exhibit the render for sections: s

```
renderSection : LatexState -> List LatexExpression -> Html msg
renderSection latexState args =
    let
        sectionName =
            MiniLatex.Render.renderArg 0 latexState args

        s1 =
            getCounter "s1" latexState

        label =
            if s1 > 0 then
                String.fromInt s1 ++ " "

            else
                ""

        ref =
            idPhrase "section" sectionName
    in
    Html.h2 (headingStyle ref 24) [ Html.text <| label ++ sectionName ]
```

### Appendix: the latexStateReducerDict

```
latexStateReducerDict : Dict.Dict ( String, String ) (LatexInfo -> LatexState -> LatexState)
latexStateReducerDict =
    Dict.fromList
        [ ( ( "macro", "setcounter" ), \x y -> SRH.setSectionCounters x y )
        , ( ( "macro", "section" ), \x y -> SRH.updateSectionNumber x y )
        , ( ( "macro", "subsection" ), \x y -> SRH.updateSubsectionNumber x y )
        , ( ( "macro", "subsubsection" ), \x y -> SRH.updateSubsubsectionNumber x y )
        , ( ( "macro", "title" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "author" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "date" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "email" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "host" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "setclient" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "setdocid" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "revision" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "env", "theorem" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "proposition" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "lemma" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "definition" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "corollary" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "equation" ), \x y -> SRH.setEquationNumber x y )
        , ( ( "env", "align" ), \x y -> SRH.setEquationNumber x y )
        , ( ( "smacro", "bibitem" ), \x y -> SRH.setBibItemXRef x y )
        ]
```

## Some conclusions

The reliance of `Accumulator.parse` and `Accumulator.render` on the `LatexState` record, as well as the `latexStateReducerDict` for dispatching calls to `latexStateReducer`, makes it very easy to add new features, e.g., new macros and environments whose rendering requires a computed state. Moreover, it is not hard to add fields to `LatexState` in order to add further new features. Indeed, the first version of `LatexInfo` had only a `counters` field. Others were added later as the scope of MiniLatex grew.
