MarkTeX is a lightweight domain-specific language and compiler written in Haskell that converts a Markdown-inspired document format into LaTeX and PDF output.
The project combines ideas from DSL design, language design, parsing, compiler construction, abstract syntax trees, semantic validation, and code generation. MarkTeX is designed to make academic writing easier by preserving Markdown's readability while supporting LaTeX-style structure, citations, labels, references, and document compilation.
Writing LaTeX directly can be powerful but verbose. Markdown is easier to read and write, but it lacks many features commonly needed in academic and technical documents, such as citations, labels, references, and structured LaTeX output.
MarkTeX bridges that gap.
It lets users write documents in a simple Markdown-like syntax, then processes the document through a compiler-style pipeline:
MarkTeX Input
|
v
Parser
|
v
Abstract Syntax Tree
|
v
Validation
|
v
LaTeX Generation
|
v
PDF Compilation
To run MarkTeX, install the following:
You need GHC and runghc.
Recommended installation options:
- GHCup
- Stack
- Cabal
The project uses:
parseccontainersfilepathprocess
Depending on your setup, these may already be available with your GHC installation.
To generate PDFs, install a LaTeX distribution that includes:
pdflatexbibtex
Recommended distributions:
- TeX Live
- MiKTeX
- MacTeX
git clone https://github.com/adityapatel149/markTeX/
cd markTeXCreate an input file such as:
example.md
To generate a .tex file using the default output filename:
runghc Main.hs example.mdThis creates:
example.tex
example.pdf
To specify the output .tex filename:
runghc Main.hs example.md output.texMarkTeX emits:
\bibliographystyle{plain}
\bibliography{references}Therefore, if your document uses citations, include a references.bib file in the same directory.
MarkTeX supports a clean, readable input format inspired by Markdown.
Supported block-level constructs include:
- Document metadata
- Paragraphs
- Headers
- Unordered lists
- Nested list content
- Code blocks
Supported inline constructs include:
- Italic text
- Bold text
- Underlined text
- Strikethrough text
- Nested formatting
- Citations
- Internal references
- Escaped special characters
% Title: My ~~Complex~~ **_*Simple*_ Paper**
% Author: \~John\_Doe
% Date: 2026
# Introduction {#sec:intro}
This is *italic*, **bold**, _underline_, and ~~strike~~.
See [](#sec:intro) and the [features section](#sec:features).
## Features {#sec:features}
Here is a citation: [@paper1, paper_2026]
MarkTeX generates LaTeX similar to the following:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{hyperref}
\usepackage{cleveref}
\usepackage[margin=1in]{geometry}
\usepackage[normalem]{ulem}
\title{My \sout{Complex} \textbf{\underline{\textit{Simple}} Paper}}
\author{\textasciitilde{}John\_Doe}
\date{2026}
\begin{document}
\maketitle
\section{Introduction }\label{sec:intro}
This is \textit{italic}, \textbf{bold}, \underline{underline}, and \sout{strike}.
See \Cref{sec:intro} and the \hyperref[sec:features]{features section} (\Cref{sec:features}).
\bibliographystyle{plain}
\bibliography{references}
\end{document}Metadata lines begin with % and appear at the top of the document.
% Title: My Paper
% Author: Jane Doe
% Date: 2026Supported metadata fields:
Title
Author
Date
These are rendered into LaTeX using:
\title{}
\author{}
\date{}If any metadata is present, MarkTeX automatically emits \maketitle.
Headers use Markdown-style # syntax.
# Introduction {#sec:intro}
## Background {#sec:background}
### Details {#sec:details}Header levels are mapped to LaTeX sectioning commands:
| MarkTeX | LaTeX |
|---|---|
# |
\section |
## |
\subsection |
### |
\subsubsection |
#### |
\paragraph |
##### and above |
\subparagraph |
Optional labels can be attached to headers:
# Introduction {#sec:intro}This becomes:
\section{Introduction}\label{sec:intro}MarkTeX supports several inline formatting constructs.
*italic*
**bold**
_underline_
~~strike~~These compile to:
\textit{italic}
\textbf{bold}
\underline{underline}
\sout{strike}Nested formatting is also supported:
**bold with *italic and _underline_ inside***Citations use a compact citation syntax:
[@paper1]
[@paper1, paper_2026]These compile to:
\cite{paper1}
\cite{paper1,paper_2026}Citation keys may contain letters, numbers, underscores, hyphens, and colons.
References use label-based linking syntax.
[](#sec:intro)
[Introduction](#sec:intro)
[these sections](#sec:intro, sec:background)MarkTeX supports both unnamed and named references.
An unnamed reference:
[](#sec:intro)becomes:
\Cref{sec:intro}A named reference:
[Introduction](#sec:intro)becomes:
\hyperref[sec:intro]{Introduction} (\Cref{sec:intro})Multiple-label references are also supported:
[these sections](#sec:intro, sec:background)Lists use Markdown-style dash syntax.
- First item
- Second item
- Third itemThese compile to LaTeX itemize environments.
\begin{itemize}
\item First item
\item Second item
\item Third item
\end{itemize}Indented blocks inside list items are also supported.
- Third list item
Second paragraph inside third item
## Header inside list item {#sec:list-header}
More text after headerCode blocks use triple backticks.
```haskell
main = putStrLn "Hello, MarkTeX!"
```Code blocks are rendered using LaTeX verbatim, meaning inline markup inside the code block is not parsed.
\begin{verbatim}
main = putStrLn "Hello, MarkTeX!"
\end{verbatim}MarkTeX supports escaping special characters with a backslash.
\# \$ \% \& \_ \{ \} \~ \^ \\ \[ \]These are safely rendered into LaTeX-safe output.
Before rendering LaTeX, MarkTeX performs semantic validation.
If the same label is defined more than once, MarkTeX reports an error.
# Introduction {#sec:intro}
# Duplicate Introduction {#sec:intro}Example error:
Duplicate label: sec:intro
If a reference points to a label that does not exist, MarkTeX reports an error.
See [missing section](#sec:missing)Example error:
Undefined reference: sec:missing
This validation step helps catch document errors before LaTeX generation.
A recommended repository structure is:
marktex/
├── Main.hs
├── MarkTex/
│ ├── AST.hs
│ ├── Parser.hs
│ └── Render/
│ └── LaTeX.hs
├── examples/
│ ├── marktex_sample.md
│ └── marktex_sample.tex
│ └── marktex_sample.pdf
│ └── references.bib
└── README.md
The command-line entry point.
Responsibilities:
- Reads command-line arguments
- Parses the input MarkTeX file
- Renders the AST to LaTeX
- Writes the generated
.texfile - Runs
pdflatex - Runs
bibtex - Re-runs
pdflatexto resolve references
Defines the core abstract syntax tree used by the compiler.
Main AST types:
DocumentBlockInlineLabelCitationKey
Implements the parser using Parsec.
Responsibilities:
- Parse metadata
- Parse block-level syntax
- Parse inline formatting
- Parse citations
- Parse references
- Parse escaped characters
- Convert source text into the AST
Implements validation and LaTeX code generation.
Responsibilities:
- Collect labels
- Detect duplicate labels
- Validate references
- Escape LaTeX special characters
- Render blocks and inline elements
- Generate complete LaTeX documents
MarkTeX follows a compiler-inspired architecture.
The parser reads the MarkTeX source file and recognizes document constructs such as metadata, headers, paragraphs, lists, code blocks, citations, and references.
The parsed document is represented using strongly typed Haskell data structures.
Example:
data Document = Document
{ docTitle :: Maybe [Inline]
, docAuthor :: Maybe [Inline]
, docDate :: Maybe [Inline]
, docBlocks :: [Block]
}Before rendering, MarkTeX validates document correctness.
It checks:
- Whether labels are unique
- Whether references point to existing labels
After validation, MarkTeX generates LaTeX code from the AST.
The generated LaTeX file is compiled using:
pdflatex
bibtex
pdflatex
pdflatexThis ensures that citations and cross-references are resolved correctly.
MarkTeX was built with the following goals:
- Provide a readable writing format for academic documents
- Preserve useful LaTeX features such as citations and references
- Demonstrate DSL design in Haskell
- Demonstrate compiler design concepts through a practical project
- Use a typed AST to represent document structure
- Validate documents before rendering
- Generate clean, compilable LaTeX output
MarkTeX is intentionally lightweight and educational. Some limitations include:
- Only unordered lists are currently supported
- Tables are not supported yet
- Images are not supported yet
- Math environments are not supported yet
- The bibliography file is assumed to be named
references.bib - The renderer always emits bibliography commands
- The CLI currently uses
runghcrather than a packaged executable
This project demonstrates several important programming language and compiler design concepts:
- Domain-specific language design
- Concrete syntax design
- Parser combinators
- Recursive descent parsing
- Abstract syntax trees
- Semantic analysis
- Symbol table construction
- Reference validation
- Code generation
- Pretty-printing target language output
- CLI-based compiler workflow
It also demonstrates functional programming concepts in Haskell, including:
- Algebraic data types
- Pattern matching
- Recursive data structures
- Pure rendering functions
Either-based error handling- Modular program organization
This project is intended for educational and academic use. Add your preferred open-source license here.
Example:
MIT License