use v5.10;
use warnings;
my $parser = do{
use Regexp::Grammars;
qr{
<file>
<rule: file>
<[element]>*
<rule: element>
<special> | <command> | <literal>
<token: special>
<MATCH= mathematical>
| <MATCH= group>
| <MATCH= comment>
| <MATCH= vinculum>
| <MATCH= newline>
| <MATCH= super>
| <MATCH= sub>
| <MATCH= column_separator>
<rule: mathematical>
\$ <[element]>* \$
<rule: comment>
\# <MATCH= ( [^\n]* \n [^\S\n]* )>
<rule: vinculum>
\~
<rule: newline>
\\ \\
<rule: super>
\^
<rule: sub>
\_
<rule: column_separator>
\$
<rule: command>
\\ <name> <options>? <[arg=group]>*
<rule: options>
\[ <[option]>+ % <_Sep=(,)> \]
<rule: group>
\{ <[element]>* \}
<rule: option>
[^][\$&%#_{}~^\s,]++
<token: literal>
<MATCH=( [^][\\\$&%#_{}~^\s]*+ (?: \\[^\w\\] [^][\\\$&%#_{}~^\s]*+ )*+ )>
<require: (?{ length($CAPTURE) > 0 })>
<token: name>
<MATCH=alphas> | <MATCH=single_nonalpha>
<token: alphas>
<MATCH=([^\W\d_]++)>
<token: single_nonalpha>
<MATCH=([\W\d_])>
}xms
};
my $input = do{ local $/; <DATA>};
if ($input =~ $parser) {
use Data::Dumper 'Dumper';
warn Dumper [ \%/ ];
}
__DATA__
\documentclass[a4paper,11pt]{article}
\usepackage{latexsym}
\author{D.~Conway}
\title{Parsing \LaTeX{}}
\begin{document}
\maketitle
\tableofcontents
\section{Description}
...is easy \footnote{But not\\ \emph{necessarily} simple}.
In fact it's $easy_peasy^2$ to do.
\end{document}