Postscript Template Strings

I’m quite proud of this, even though the program I was writing it for ended up staying a shell script.

% realloc a string
/growstring {  % () -> ()
  dup length 2 mul string dup 0 4 3 roll putinterval
} bind def

% Just a simple template engine.
%
% Anything between curly braces is PS code which returns a
% single object that will be converted to string via cvs.
%
% The embedded code has full access to the environment and
% may invoke the template procedure recursively.
%
% To embed a literal brace, embed a literal string: { ({) }
%
/template {  % (txt { - -> any } txt) -> ()
  10 dict begin /src exch def
    /rv 256 string def
    /rvidx 0 def
    /template-append {
      /o exch def
      { /o load rv rvidx rv length rvidx sub getinterval
        { cvs } stopped
        { /rv rv growstring def }
        { length rvidx add /rvidx exch def exit } ifelse
      } loop
    } //bind def
    {
      % find { or end, appending text
      src ({) search {
        template-append pop
        % search excludes '{', we need it for token
        length 1 add /n exch def
        src dup length n sub n getinterval /src exch def
      } { template-append exit } ifelse

      % (src) is now ({code}...)
      % eval the code and append any resulting objects
      src token {
        exch /src exch def
        % a closure to restore our hidden local scope
        [ exch /exec cvx currentdict /begin cvx ] cvx
        end exec template-append
      } if
    } loop
    rv 0 rvidx getinterval
  end
} bind def

% tests
/bar (ggg) def
(foo) template ==
(foo{bar} foo) template ==
({bar}foo) template ==
(foo{bar}) template ==
(foo{({)}{bar}) template ==
/rvidx (uuu) def
(foo{rvidx}foo) template ==
55 44 33 (foo{1 index}foo) template == pop pop pop
(sss{ ({rvidx}) template }www) template ==
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s