use 5.010; use warnings; use Test::More 'no_plan'; # Use this class declaration to check that classes with ctors # actually call the ctor when objrules use them... { package file; sub new { my ($class, $data_ref) = @_; my $new_obj = bless {'check'=>'check',%{$data_ref}}, $class; return $new_obj; } } my $parser = do{ use Regexp::Grammars; qr{ <[element]>* | \\ ? ? \[ <[option]> ** (,) \] \{ <[element]>* \} [^][\$&%#_{}~^\s,]+ [^][\$&%#_{}~^\s]+ }xms }; my $target = { "file" => bless({ "" => "\\documentclass[a4paper,11pt]{article}\n\\usepackage{latexsym}\n\\author{D. Conway}\n\\title{Parsing \\LaTeX{}}\n\\begin{document}\n\\maketitle\n\\tableofcontents\n\\section{Description}\n...is easy \\footnote{But not \\emph{necessarily} simple}.\n\\end{document}", "check" => "check", "element" => [ bless({ "command" => bless({ "" => "\\documentclass[a4paper,11pt]{article}", "args" => bless({ "" => "{article}", "element" => [ bless({ "literal" => bless({ "" => "article", }, "literal"), }, "element"), ], }, "args"), "name" => bless({ "" => "documentclass", }, "literal"), "options" => bless({ "option" => [ bless({ "" => "a4paper", }, "option"), bless({ "" => "11pt", }, "option"), ], }, "options"), }, "command"), }, "element"), bless({ "command" => bless({ "" => "\\usepackage{latexsym}", "args" => bless({ "" => "{latexsym}", "element" => [ bless({ "literal" => bless({ "" => "latexsym", }, "literal"), }, "element"), ], }, "args"), "name" => bless({ "" => "usepackage", }, "literal"), }, "command"), }, "element"), bless({ "command" => bless({ "" => "\\author{D. Conway}", "args" => bless({ "" => "{D. Conway}", "element" => [ bless({ "literal" => bless({ "" => "D.", }, "literal"), }, "element"), bless({ "literal" => bless({ "" => "Conway", }, "literal"), }, "element"), ], }, "args"), "name" => bless({ "" => "author", }, "literal"), }, "command"), }, "element"), bless({ "command" => bless({ "" => "\\title{Parsing \\LaTeX{}}", "args" => bless({ "" => "{Parsing \\LaTeX{}}", "element" => [ bless({ "literal" => bless({ "" => "Parsing", }, "literal"), }, "element"), bless({ "command" => bless({ "" => "\\LaTeX{}", "args" => bless({ "" => "{}", }, "args"), "name" => bless({ "" => "LaTeX", }, "literal"), }, "command"), }, "element"), ], }, "args"), "name" => bless({ "" => "title", }, "literal"), }, "command"), }, "element"), bless({ "command" => bless({ "" => "\\begin{document}", "args" => bless({ "" => "{document}", "element" => [ bless({ "literal" => bless({ "" => "document", }, "literal"), }, "element"), ], }, "args"), "name" => bless({ "" => "begin", }, "literal"), }, "command"), }, "element"), bless({ "command" => bless({ "" => "\\maketitle\n", "name" => bless({ "" => "maketitle", }, "literal"), }, "command"), }, "element"), bless({ "command" => bless({ "" => "\\tableofcontents\n", "name" => bless({ "" => "tableofcontents", }, "literal"), }, "command"), }, "element"), bless({ "command" => bless({ "" => "\\section{Description}", "args" => bless({ "" => "{Description}", "element" => [ bless({ "literal" => bless({ "" => "Description", }, "literal"), }, "element"), ], }, "args"), "name" => bless({ "" => "section", }, "literal"), }, "command"), }, "element"), bless({ "literal" => bless({ "" => "...is", }, "literal"), }, "element"), bless({ "literal" => bless({ "" => "easy", }, "literal"), }, "element"), bless({ "command" => bless({ "" => "\\footnote{But not \\emph{necessarily} simple}", "args" => bless({ "" => "{But not \\emph{necessarily} simple}", "element" => [ bless({ "literal" => bless({ "" => "But", }, "literal"), }, "element"), bless({ "literal" => bless({ "" => "not", }, "literal"), }, "element"), bless({ "command" => bless({ "" => "\\emph{necessarily}", "args" => bless({ "" => "{necessarily}", "element" => [ bless({ "literal" => bless({ "" => "necessarily", }, "literal"), }, "element"), ], }, "args"), "name" => bless({ "" => "emph", }, "literal"), }, "command"), }, "element"), bless({ "literal" => bless({ "" => "simple", }, "literal"), }, "element"), ], }, "args"), "name" => bless({ "" => "footnote", }, "literal"), }, "command"), }, "element"), bless({ "literal" => bless({ "" => ".", }, "literal"), }, "element"), bless({ "command" => bless({ "" => "\\end{document}", "args" => bless({ "" => "{document}", "element" => [ bless({ "literal" => bless({ "" => "document", }, "literal"), }, "element"), ], }, "args"), "name" => bless({ "" => "end", }, "literal"), }, "command"), }, "element"), ], }, "file"), }; my $input = do{ local $/; }; chomp $input; my $original_input = $input; ok +($input =~ $parser) => 'Matched'; is_deeply \%/, $target => 'Returned correct data structure'; ok ! exists $/{""} => "Didn't capture entire text"; __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}. \end{document}