#!/usr/bin/perl use v5.12; use warnings; use Text::ParseWords qw/quotewords/; # 1 Definitions # 1.1 Global program state my $empty = ''; # currently buffered empty lines my $close = ''; # buffered closing tag for currently opened element # 1.2 Elements # 1.2.1 Block elements my %blels = ( Pp_0 => '
%
', Qp_0 => '', Pr_0 => '%
%', Sh_0 => '
\\$1
\\$2',
Cs_1 => '',
Em_0 => '\\$3\\$1\\$2',
Hy_0 => '\\$1',
Im_0 => '',
It_0 => '\\$3\\$1\\$2',
St_0 => '\\$3\\$1\\$2',
Tt_0 => '\\$3\\$1\\$2',
Ul_0 => '\\$3\\$1\\$2',
);
# 1.3 Subroutines
# 1.3.1 Handle element request
sub request {
my ($el, $args) = @_;
my @argv = quotewords('\s+', 0, $args);
my $n = @argv;
my $elkey = "${el}_$n";
if (exists $blels{$elkey}) {
# Clear empty line buffer
$empty = '';
# Close currently open block element, open new
print $close;
$close = interpol(end($blels{$elkey}), @argv) . "\n";
print interpol(start($blels{$elkey}), @argv) . "\n";
} elsif (exists $inels{$elkey}) {
print interpol($inels{$elkey}, @argv) . "\n";
} else {
print STDERR "Error: $el/$n not implemented\n";
exit 1;
}
}
# 1.3.2 Interpolate \$n parameters
sub interpol {
my $s = shift;
my $i = 1;
my $arg;
while ($arg = shift) {
$s =~ s/\\\$$i/$arg/g;
$i++;
}
return $s;
}
# 1.3.3 Retrieve first portion of block element string
sub start {
return (split '%', shift)[0];
}
# 1.3.4 Retrieve second portion of block element string
sub end {
return (split '%', shift)[1];
}
# 2 Program
# 2.1 Translate mh source text to HTML
while (<>) {
chomp;
if (/^\.([A-Za-z][a-z])\s*(.*)/) {
request($1, $2);
} elsif ($_ eq '') {
$empty .= "\n";
} else {
print $empty; $empty = '';
print "$_\n";
}
}
# 2.2 Close currently open block element
print $close;