Skip to content

Instantly share code, notes, and snippets.

@dginev
Last active December 11, 2015 05:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dginev/4552809 to your computer and use it in GitHub Desktop.
Save dginev/4552809 to your computer and use it in GitHub Desktop.
A first bare-bone Devel::Declare compiler for state-ful subroutines in LaTeXML bindings.
# /=====================================================================\ #
# | LaTeXML::Util::PackageKeywords | #
# | Binding package keywords for LaTeXML | #
# |=====================================================================| #
# | Part of LaTeXML: | #
# | Public domain software, produced as part of work done by the | #
# | United States Government & not subject to copyright in the US. | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov> | #
# | Deyan Ginev <deyan.ginev@nist.gov> #_# | #
# | http://dlmf.nist.gov/LaTeXML/ (o o) | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Util::PackageKeywords;
use strict;
use warnings;
use LaTeXML::Package;
use Devel::Declare;
use base 'Devel::Declare::Context::Simple';
sub import
{
my $class = shift;
my $caller = caller;
my $context = __PACKAGE__->new;
Devel::Declare->setup_for(
$caller,
{
code => { const => sub { $context->code_parser(@_) } },
macro => {const => sub { $context->macro_parser(@_) } }
});
no strict 'refs';
*{$caller.'::code'} = sub ($) {};
*{$caller.'::macro'} = sub ($) {};
}
sub code_parser
{
my $self = shift;
$self->init(@_);
$self->skip_declarator;
my $code_name = $self->strip_name;
#$self->strip_proto;
#$self->strip_attrs;
my $pack = Devel::Declare::get_curstash_name;
Devel::Declare::shadow_sub(
"${pack}::code",
sub (&) {
my $code_body = shift;
no strict 'refs';
*{'LaTeXML::Package::Pool::'.$code_name} = $code_body;
}
);
return;
}
sub macro_parser {
my $self = shift;
$self->init(@_);
$self->skip_declarator;
my $pack = Devel::Declare::get_curstash_name;
my $macro_name = $self->strip_quoted;
if ($self->strip_comma) {
my $macro_body = $self->strip_quoted;
Devel::Declare::shadow_sub(
"${pack}::macro",
sub { DefMacro($macro_name,$macro_body); }
);
} else {
Devel::Declare::shadow_sub(
"${pack}::macro",
sub (&) {
my $macro_body = shift;
DefMacro($macro_name,$macro_body) if (defined $macro_body);
return;
}
);
}
return;
}
1;
########################################
## Additional parsing enhancements ##
## for LaTeXML's syntax ##
########################################
package Devel::Declare::Context::Simple;
sub strip_quoted {
my $self = shift;
$self->skipspace;
if (my $len = Devel::Declare::toke_scan_str( $self->offset)) {
my $linestr = $self->get_linestr();
my $name = substr( $linestr, $self->offset, $len );
substr( $linestr, $self->offset, $len ) = '';
$self->set_linestr($linestr);
$name =~ s/^(['"])(.+)\1$/$2/;
return $name;
}
return;
}
sub strip_comma {
my $self = shift;
my $found_comma;
$self->skipspace;
my $linestr = $self->get_linestr();
my $comma = substr( $linestr, $self->offset, 1 );
if ($comma eq ',') {
$found_comma = 1;
substr( $linestr, $self->offset, 1 ) = '';
$self->set_linestr($linestr);
$self->skipspace;
} else {
$found_comma = 0;
}
return $found_comma;
}
1;
__END__
package LaTeXML::Package::Pool;
use LaTeXML::Util::PackageKeywords;
code foo {
"It works! \n";
};
macro '\baz' {
return Tokenize(foo());
};
macro '\doublebaz', '\baz\baz';
1;
\documentclass{article}
\usepackage{packagekeywords}
\begin{document}
\doublebaz
\end{document}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment