MiniLatex: Adding Macro Expansion

James Carlson
2 min readOct 24, 2018
Macro Expansion

MiniLatex is a technology for parsing and rendering a subset of LaTeX into HTML. It relies on MathJax to render math-mode text (the formulas and equations), and it relies on Elm, a statically typed functional programming language, to render the text-mode material — auto-numbered section headings, tables of contents, cross-references, etc.

Today I am announcing a new, experimental feature for MiniLatex: macro expansion. This feature allows an author to define new text-mode macros in a MiniLatex document. For example, if one adds the text

\newcommand{\hello}[1]{Hello \strong{#1}!}\hello{John}

Then the macro \hello{John} renders as

Hello John!

A silly example, but illustrates the point.

The macro expansion feature will need a lot more work and testing, but this is good start. We also plan to add a feature so that authors can define new environments.

PS. What is it that makes it possible, and not even difficult, to parse and render a subset of LaTeX? Answer: Elm’s expressive type system and the elm/parser library of parser combinators.

Technical note

A few words about how the macro expansion facility was implemented. First, a new line was added to the type definition for the abstract syntax tree (AST):

NewCommand String Int LateExpression

A parser function newcommand is added to handle input text like \newcommand{macro-name}[number-of-args]{definition} . Then one defines a function

expandMacro : LatexExpression -> LatexExpression -> LatexExpression
expandMacro macro macroDef =
"Use the data in macro to make subtitutions in macroDef"

that can make transformations on the AST. Basically, what one does is to make substitutions in the macroDef based on the arguments in the macro to obtain a LatexExpression that can be rendered in the normal way. For example, suppose one says \newcommand{\hello}[1]{Hello \strong{#1}!} and then \hello{John}. The macro \hello is not part of MiniLatex, so the renderer looks to see if there is a macro definition with name hello. There is, so the renderer substitutes John for #1 in the macro definition. The result is a valid AST element that can now be rendered.

Example

> import Parser exposing(run)
> import MiniLatex.Parser exposing(..)
> import MiniLatex.Macro exposing(..)
############> run latexExpression "\\newcommand{\\hello}[1]{Hello \\strong{#1}!}"Ok (NewCommand "hello" 1 (LatexList [LXString ("Hello "),Macro "strong" [] [LatexList [LXString "#1"]],LXString "!"]))> run latexExpression "\\hello{John}"
Ok (Macro "hello" [] [LatexList [LXString "John"]])
############> macroDef = NewCommand "hello" 1 (LatexList [LXString ("Hello "),Macro "strong" [] [LatexList [LXString "#1"]],LXString "!"])> macro = Macro "hello" [] [LatexList [LXString "John"]]############> expandMacro macro macroDefLatexList [LXString ("Hello "),Macro "strong" [] [LatexList [LXString "John"]],LXString "!"]

References

--

--