1497 lines
40 KiB
TeX
1497 lines
40 KiB
TeX
%
|
|
% @TAG(OTHER_BSD)
|
|
%
|
|
|
|
% Copyright © 2000 Patryk Zadarnowski «pat@jantar.org»
|
|
%
|
|
% Redistribution and use in source and binary forms, with or without
|
|
% modification, are permitted provided that the following conditions are met:
|
|
% (1) Redistributions of source code must retain the above copyright notice,
|
|
% this list of conditions and the following disclaimer. (2) Redistributions
|
|
% in binary form must reproduce the above copyright notice, this list of
|
|
% conditions and the following disclaimer in the documentation and/or other
|
|
% materials provided with the distribution. (3) The name of any author may
|
|
% not be used to endorse or promote products derived from this software
|
|
% without their specific prior written permission.
|
|
%
|
|
% THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
% FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
% AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
|
% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS
|
|
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
% POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
%% lambdaTeX v1.0.5 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% Limitations:
|
|
%
|
|
% - no support for nested comments
|
|
% - no support for LaTeX mode
|
|
% - no support for non-literate mode
|
|
% - no support for strings in inline mode
|
|
% - function names must be marked as such explicitely
|
|
% - < > as the first character in math mode don't work.
|
|
% - code lines don't wrap well.
|
|
%
|
|
% Quirks:
|
|
%
|
|
% 1. HaskellTeX reserves <, > and " as active characters, but, of
|
|
% course restores their meaning of < and > in math mode. However,
|
|
% this doesn't work as well as expected. When TeX sees the $
|
|
% character, it reads the following character to see if it is
|
|
% another $ beginning a math display. If that character is active,
|
|
% it attempts to expand it (a bug in TeX?! or just a mis-feature?
|
|
% I couldn't find anything in the TeXbook.) So, you must write
|
|
% $ >$ rather than $>$. Oh well. To make amends for this, I define
|
|
% \lt and \gt math macros to complement \le and \ge already in
|
|
% plain TeX, as $\gt$ looks better than $ >$. Fortunately, one rarely
|
|
% needs to write a relational operator as the first character in
|
|
% a formula, and, of course, $a>b$ works as expected.
|
|
%
|
|
% 2. When parsing comments, the lexical analyzer temporarily switches
|
|
% out of Haskell mode, so normal fonts, etc can take effect.
|
|
% Specifically, it switches out of TeX mode after processing the
|
|
% initial <dashes> token of a comment. This means that it must
|
|
% process the token immediately following the dashes, too, before
|
|
% leaving Haskell mode. Therefore, if this token is an active
|
|
% character, it will not work as expected (its category code will
|
|
% be 12.) Again, this normally is not a problem as the character
|
|
% immediately following the -- should be a space, anyway.
|
|
|
|
\ProvidesPackage{lambdaTeX}
|
|
|
|
\catcode`@=11
|
|
|
|
\newskip\hsparskip \hsparskip=8pt
|
|
\newdimen\hsleftskip \hsleftskip=20pt
|
|
\newdimen\hsrightskip \hsrightskip=10pt
|
|
\newdimen\hscommentskip \hscommentskip=1em
|
|
\newdimen\hswordspace \hswordspace=.3em
|
|
\newdimen\hsspacewidth \hsspacewidth=0.5em
|
|
\newdimen\hstabwidth \hstabwidth=8em
|
|
|
|
\def\everyhs{}
|
|
\def\beforehs{\vskip 4pt plus3pt minus1pt}
|
|
\def\afterhs{\vskip 4pt plus3pt minus1pt}
|
|
|
|
\let\hs@family\empty
|
|
\let\hs@family\hsfamily
|
|
\ifx\hs@family\empty\let\hs@family\ttfamily\fi
|
|
|
|
\newcommand{\hs@keyface}{\hs@family\bfseries}
|
|
\newcommand{\hs@funface}{\hs@family}
|
|
\newcommand{\hs@varface}{\hs@family\itshape}
|
|
\newcommand{\hs@conface}{\hs@family\scshape}
|
|
\newcommand{\hs@numface}{\hs@family}
|
|
\newcommand{\hs@strface}{\ttfamily}
|
|
\newcommand{\hs@symface}{\hs@family}
|
|
|
|
%%% Lexical modes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% The lexical analyzer can operate in one of three modes:
|
|
%
|
|
% 0. Inline - Haskell code appearing within a paragraph
|
|
% 1. Bird - Bird-style literate Haskell code
|
|
%
|
|
% The Inline mode is used to typeset a short fragment of Haskell code
|
|
% in the middle of a paragraph, for example when referring to a variable
|
|
% defined within the program. The mode is entered by the " character.
|
|
% The lexical analyzer exits when it encounters another " character.
|
|
% Newlines are treated as simple whitespace, and comments are illegal.
|
|
% Because the " character is reserved, strings cannot appear in the Inline
|
|
% mode.
|
|
%
|
|
% The Bird mode is used to process Bird-style literate scripts. The mode
|
|
% is entered by the > character (note that this is a hack - in Haskell, >
|
|
% designates literate code only when it appears as the first character on
|
|
% a line.) The mode exits when it encounters a blank line. The text is typeset
|
|
% as a separate paragraph, idented by \hsleftskip on the left and \hsrightskip
|
|
% on the right. The \beforehs macro is inserted before the fragment of code
|
|
% and \afterhs is inserted after it. The > character itself is not displayed.
|
|
|
|
% In both modes, the \everyhs macro is inserted immediately after entering
|
|
% the Haskell mode.
|
|
%
|
|
% One thing worth noting is that, because spaces are skipped following active
|
|
% characters, in the Inline mode any spaces immediately following the operning
|
|
% " are ignored. For consistency, we also ignore any spaces preceeding the
|
|
% closing ". In Bird mode, TeX swallows spaces following the opening >, so
|
|
% the lexical analyzer _assumes_ that the > was followed by a single space,
|
|
% and strips one space-worth of indentation from all remaining lines in the
|
|
% code fragment.
|
|
|
|
\newif\ifhs@inline
|
|
|
|
% The \lambdaTeX macro:
|
|
\def\lambdaTeX{$\lambda$\kern-1.5pt\TeX}
|
|
|
|
% The amount to kern the current token by:
|
|
\newdimen\hs@space
|
|
\newdimen\hs@guardpos
|
|
\newdimen\hs@previndent
|
|
\newdimen\hs@indent
|
|
|
|
% The boxes used to build up the current line:
|
|
\newbox\voidb@x % permanently void
|
|
\newbox\hs@i
|
|
\newbox\hs@ii
|
|
\newbox\hs@iii
|
|
|
|
% Subscripts and superscripts
|
|
\def\hs@scripts{$\fam=15 ^{\hs@sup}_{\hs@sub}$}
|
|
|
|
% Macros for requesting special formatting of a specific lexeme:
|
|
\def\typeset#1#2{\expandafter\def\csname<#1>\endcsname{#2}}
|
|
|
|
% Define the Haskell keywords:
|
|
\typeset{case}{{\hs@keyface case}}
|
|
\typeset{class}{{\hs@keyface class}}
|
|
\typeset{data}{{\hs@keyface data}}
|
|
\typeset{default}{{\hs@keyface default}}
|
|
\typeset{deriving}{{\hs@keyface deriving}}
|
|
\typeset{do}{{\hs@keyface do}}
|
|
\typeset{else}{{\hs@keyface else}}
|
|
\typeset{if}{{\hs@keyface if}}
|
|
\typeset{import}{{\hs@keyface import}}
|
|
\typeset{in}{{\hs@keyface in}}
|
|
\typeset{infix}{{\hs@keyface infix}}
|
|
\typeset{infixl}{{\hs@keyface infixl}}
|
|
\typeset{infixr}{{\hs@keyface infixr}}
|
|
\typeset{instance}{{\hs@keyface instance}}
|
|
\typeset{let}{{\hs@keyface let}}
|
|
\typeset{module}{{\hs@keyface module}}
|
|
\typeset{newtype}{{\hs@keyface newtype}}
|
|
\typeset{of}{{\hs@keyface of}}
|
|
\typeset{then}{{\hs@keyface then}}
|
|
\typeset{type}{{\hs@keyface type}}
|
|
\typeset{where}{{\hs@keyface where}}
|
|
\typeset{as}{{\hs@keyface as}}
|
|
\typeset{qualified}{{\hs@keyface qualified}}
|
|
\typeset{hiding}{{\hs@keyface hiding}}
|
|
\typeset{otherwise}{{\hs@keyface otherwise}}
|
|
|
|
% Define Greek letters:
|
|
\typeset{alpha}{$\alpha$\hs@scripts}
|
|
\typeset{beta}{$\beta$\hs@scripts}
|
|
\typeset{gamma}{$\gamma$\hs@scripts}
|
|
\typeset{delta}{$\delta$\hs@scripts}
|
|
\typeset{epsilon}{$\epsilon$\hs@scripts}
|
|
\typeset{zeta}{$\zeta$\hs@scripts}
|
|
\typeset{eta}{$\eta$\hs@scripts}
|
|
\typeset{theta}{$\theta$\hs@scripts}
|
|
\typeset{iota}{$\iota$\hs@scripts}
|
|
\typeset{kappa}{$\kappa$\hs@scripts}
|
|
\typeset{lambda}{$\lambda$\hs@scripts}
|
|
\typeset{mu}{$\mu$\hs@scripts}
|
|
\typeset{nu}{$\nu$\hs@scripts}
|
|
\typeset{xi}{$\xi$\hs@scripts}
|
|
\typeset{pi}{$\pi$\hs@scripts}
|
|
\typeset{rho}{$\rho$\hs@scripts}
|
|
\typeset{sigma}{$\sigma$\hs@scripts}
|
|
\typeset{tau}{$\tau$\hs@scripts}
|
|
\typeset{upsilon}{$\upsilon$\hs@scripts}
|
|
\typeset{phi}{$\phi$\hs@scripts}
|
|
\typeset{chi}{$\chi$\hs@scripts}
|
|
\typeset{psi}{$\psi$\hs@scripts}
|
|
\typeset{omega}{$\omega$\hs@scripts}
|
|
|
|
\typeset{Alpha}{$\mit A$\hs@scripts}
|
|
\typeset{Beta}{$\mit B$\hs@scripts}
|
|
\typeset{Gamma}{$\mit\Gamma$\hs@scripts}
|
|
\typeset{Delta}{$\mit\Delta$\hs@scripts}
|
|
\typeset{Epsilon}{$\mit E$\hs@scripts}
|
|
\typeset{Zeta}{$\mit Z$\hs@scripts}
|
|
\typeset{Eta}{$\mit H$\hs@scripts}
|
|
\typeset{Theta}{$\mit\Theta$\hs@scripts}
|
|
\typeset{Iota}{$\mit I$\hs@scripts}
|
|
\typeset{Kappa}{$\mit K$\hs@scripts}
|
|
\typeset{Lambda}{$\mit\Lambda$\hs@scripts}
|
|
\typeset{Mu}{$\mit M$\hs@scripts}
|
|
\typeset{Nu}{$\mit N$\hs@scripts}
|
|
\typeset{Xi}{$\mit\Xi$\hs@scripts}
|
|
\typeset{Pi}{$\mit\Pi$\hs@scripts}
|
|
\typeset{Rho}{$\mit P$\hs@scripts}
|
|
\typeset{Sigma}{$\mit\Sigma$\hs@scripts}
|
|
\typeset{Tau}{$\mit T$\hs@scripts}
|
|
\typeset{Upsilon}{$\mit\Upsilon$\hs@scripts}
|
|
\typeset{Phi}{$\mit\Phi$\hs@scripts}
|
|
\typeset{Chi}{$\mit X$\hs@scripts}
|
|
\typeset{Psi}{$\mit\Psi$\hs@scripts}
|
|
\typeset{Omega}{$\mit\Omega$\hs@scripts}
|
|
|
|
\typeset{ALPHA}{$\rm A$\hs@scripts}
|
|
\typeset{BETA}{$\rm B$\hs@scripts}
|
|
\typeset{GAMMA}{$\Gamma$\hs@scripts}
|
|
\typeset{DELTA}{$\Delta$\hs@scripts}
|
|
\typeset{EPSILON}{$\rm E$\hs@scripts}
|
|
\typeset{ZETA}{$\rm Z$\hs@scripts}
|
|
\typeset{ETA}{$\rm H$\hs@scripts}
|
|
\typeset{THETA}{$\Theta$\hs@scripts}
|
|
\typeset{IOTA}{$\rm I$\hs@scripts}
|
|
\typeset{KAPPA}{$\rm K$\hs@scripts}
|
|
\typeset{LAMBDA}{$\Lambda$\hs@scripts}
|
|
\typeset{MU}{$\rm M$\hs@scripts}
|
|
\typeset{NU}{$\rm N$\hs@scripts}
|
|
\typeset{XI}{$\Xi$\hs@scripts}
|
|
\typeset{PI}{$\Pi$\hs@scripts}
|
|
\typeset{RHO}{$\rm P$\hs@scripts}
|
|
\typeset{SIGMA}{$\Sigma$\hs@scripts}
|
|
\typeset{TAU}{$\rm T$\hs@scripts}
|
|
\typeset{UPSILON}{$\Upsilon$\hs@scripts}
|
|
\typeset{PHI}{$\Phi$\hs@scripts}
|
|
\typeset{CHI}{$\rm X$\hs@scripts}
|
|
\typeset{PSI}{$\Psi$\hs@scripts}
|
|
\typeset{OMEGA}{$\Omega$\hs@scripts}
|
|
|
|
% Other math letters:
|
|
\typeset{aleph}{$\aleph$}
|
|
\typeset{infinity}{$\infty$}
|
|
\typeset{nabla}{$\nabla$}
|
|
\typeset{any}{$\exists$}
|
|
\typeset{all}{$\forall$}
|
|
\typeset{sum}{$\sum$}
|
|
\typeset{product}{$\prod$}
|
|
\typeset{and}{$\bigwedge$}
|
|
\typeset{or}{$\bigvee$}
|
|
\typeset{undefined}{$\bot$}
|
|
\typeset{not}{$\lnot$}
|
|
|
|
% Define common symbols:
|
|
\typeset{=}{{\hs@symface=}}
|
|
\typeset{<-}{$\leftarrow$}
|
|
\typeset{->}{$\rightarrow$}
|
|
\typeset{=>}{$\Rightarrow$}
|
|
\typeset{++}{$+\kern-.2em+$}
|
|
\typeset{==}{$=$}
|
|
\typeset{/=}{$\neq$}
|
|
\typeset{<=}{$\leq$}
|
|
\typeset{>=}{$\geq$}
|
|
\typeset{||}{$\vee$}
|
|
\typeset{&&}{$\wedge$}
|
|
|
|
% Symbols with a backslash are a little tricky:
|
|
\expandafter\def\csname<\string\>\endcsname{\lambda}
|
|
|
|
% Define a space letter (used in a few places)
|
|
{\catcode32=12\gdef\hs@{ }}
|
|
|
|
% Prepare the character codes, etc for use in haskell mode:
|
|
\def\hs@preparecodemode{%
|
|
{\hs@symface\global\textfont15=\font
|
|
\scriptsize\global\scriptfont15=\font
|
|
\tiny\global\scriptscriptfont15=\font}%
|
|
% Category codes:
|
|
\chardef\hs@catcodeIX=\catcode9 \catcode9=12
|
|
\chardef\hs@catcodeXIII=\catcode13 \catcode13=12
|
|
\chardef\hs@catcodeXXXII=\catcode32 \catcode32=12
|
|
\chardef\hs@catcodeXXXIII=\catcode33 \catcode33=12
|
|
\chardef\hs@catcodeXXXIV=\catcode34 \catcode34=12
|
|
\chardef\hs@catcodeXXXV=\catcode35 \catcode35=12
|
|
\chardef\hs@catcodeXXXVI=\catcode36 \catcode36=12
|
|
\chardef\hs@catcodeXXXVII=\catcode37 \catcode37=12
|
|
\chardef\hs@catcodeXXXVIII=\catcode38 \catcode38=12
|
|
\chardef\hs@catcodeXXXIX=\catcode39 \catcode39=12
|
|
\chardef\hs@catcodeXL=\catcode40 \catcode40=12
|
|
\chardef\hs@catcodeXLI=\catcode41 \catcode41=12
|
|
\chardef\hs@catcodeXLII=\catcode42 \catcode42=12
|
|
\chardef\hs@catcodeXLIII=\catcode43 \catcode43=12
|
|
\chardef\hs@catcodeXLIV=\catcode44 \catcode44=12
|
|
\chardef\hs@catcodeXLV=\catcode45 \catcode45=12
|
|
\chardef\hs@catcodeXLVI=\catcode46 \catcode46=12
|
|
\chardef\hs@catcodeXLVII=\catcode47 \catcode47=12
|
|
\chardef\hs@catcodeLVIII=\catcode58 \catcode58=12
|
|
\chardef\hs@catcodeLIX=\catcode59 \catcode59=12
|
|
\chardef\hs@catcodeLX=\catcode60 \catcode60=12
|
|
\chardef\hs@catcodeLXI=\catcode61 \catcode61=12
|
|
\chardef\hs@catcodeLXII=\catcode62 \catcode62=12
|
|
\chardef\hs@catcodeLXIII=\catcode63 \catcode63=12
|
|
\chardef\hs@catcodeLXIV=\catcode64 \catcode64=12
|
|
\chardef\hs@catcodeXCI=\catcode91 \catcode91=12
|
|
\chardef\hs@catcodeXCII=\catcode92 \catcode92=12
|
|
\chardef\hs@catcodeXCIII=\catcode93 \catcode93=12
|
|
\chardef\hs@catcodeXCIV=\catcode94 \catcode94=12
|
|
\chardef\hs@catcodeXCV=\catcode95 \catcode95=12
|
|
\chardef\hs@catcodeXCVI=\catcode96 \catcode96=12
|
|
\chardef\hs@catcodeCXXIII=\catcode123 \catcode123=12
|
|
\chardef\hs@catcodeCXXIV=\catcode124 \catcode124=12
|
|
\chardef\hs@catcodeCXXV=\catcode125 \catcode125=12
|
|
\chardef\hs@catcodeCXXVI=\catcode126 \catcode126=12
|
|
% Math codes for Haskell symbols:
|
|
\mathchardef\hs@mathcodeXXXIII=\mathcode33 \mathcode33="0F21 % !
|
|
\mathchardef\hs@mathcodeXXXV=\mathcode35 \mathcode35="0F23 % #
|
|
\mathchardef\hs@mathcodeXXXVI=\mathcode36 \mathcode36="0F24 % $
|
|
\mathchardef\hs@mathcodeXXXVII=\mathcode37 \mathcode37="0F25 % %
|
|
\mathchardef\hs@mathcodeXXXVIII=\mathcode38 \mathcode38="0F26 % &
|
|
\mathchardef\hs@mathcodeXL=\mathcode40 \mathcode40="0028 % (
|
|
\mathchardef\hs@mathcodeXLI=\mathcode41 \mathcode41="0029 % )
|
|
\mathchardef\hs@mathcodeXLII=\mathcode42 \mathcode42="0203 % *
|
|
\mathchardef\hs@mathcodeXLIII=\mathcode43 \mathcode43="002B % +
|
|
\mathchardef\hs@mathcodeXLIV=\mathcode44 \mathcode44="0F2C % ,
|
|
\mathchardef\hs@mathcodeXLV=\mathcode45 \mathcode45="0200 % -
|
|
\mathchardef\hs@mathcodeXLVI=\mathcode46 \mathcode46="0F2E % .
|
|
\mathchardef\hs@mathcodeXLVII=\mathcode47 \mathcode47="002F % /
|
|
\mathchardef\hs@mathcodeLVIII=\mathcode58 \mathcode58="003A % :
|
|
\mathchardef\hs@mathcodeLVIX=\mathcode59 \mathcode59="0F3B % ;
|
|
\mathchardef\hs@mathcodeLX=\mathcode60 \mathcode60="013C % <
|
|
\mathchardef\hs@mathcodeLXI=\mathcode61 \mathcode61="003D % =
|
|
\mathchardef\hs@mathcodeLXII=\mathcode62 \mathcode62="013E % >
|
|
\mathchardef\hs@mathcodeLXIII=\mathcode63 \mathcode63="0F3F % ?
|
|
\mathchardef\hs@mathcodeLXIV=\mathcode64 \mathcode64="0F40 % @
|
|
\mathchardef\hs@mathcodeXCI=\mathcode91 \mathcode91="005B % [
|
|
\mathchardef\hs@mathcodeXCII=\mathcode92 \mathcode92="026E % \
|
|
\mathchardef\hs@mathcodeXCIII=\mathcode93 \mathcode93="005D % ]
|
|
\mathchardef\hs@mathcodeXCVI=\mathcode96 \mathcode96="0012 % `
|
|
\mathchardef\hs@mathcodeCXXIII=\mathcode123 \mathcode123="0266 % {
|
|
\mathchardef\hs@mathcodeCXXIV=\mathcode124 \mathcode124="026A % |
|
|
\mathchardef\hs@mathcodeCXXV=\mathcode125 \mathcode125="0267 % {
|
|
\mathchardef\hs@mathcodeCXXVI=\mathcode126 \mathcode126="0F7E % ~
|
|
\relax}
|
|
|
|
% Restore "normal" TeX environment within haskell comments:
|
|
\def\hs@preparecommentmode{%
|
|
% Category codes:
|
|
\catcode9=\hs@catcodeIX
|
|
\catcode13=\hs@catcodeXIII
|
|
\catcode32=\hs@catcodeXXXII
|
|
\catcode33=\hs@catcodeXXXIII
|
|
\catcode34=\hs@catcodeXXXIV
|
|
\catcode35=\hs@catcodeXXXV
|
|
\catcode36=\hs@catcodeXXXVI
|
|
\catcode37=\hs@catcodeXXXVII
|
|
\catcode38=\hs@catcodeXXXVIII
|
|
\catcode39=\hs@catcodeXXXIX
|
|
\catcode40=\hs@catcodeXL
|
|
\catcode41=\hs@catcodeXLI
|
|
\catcode42=\hs@catcodeXLII
|
|
\catcode43=\hs@catcodeXLIII
|
|
\catcode44=\hs@catcodeXLIV
|
|
\catcode45=\hs@catcodeXLV
|
|
\catcode46=\hs@catcodeXLVI
|
|
\catcode47=\hs@catcodeXLVII
|
|
\catcode58=\hs@catcodeLVIII
|
|
\catcode59=\hs@catcodeLIX
|
|
\catcode60=\hs@catcodeLX
|
|
\catcode61=\hs@catcodeLXI
|
|
\catcode62=\hs@catcodeLXII
|
|
\catcode63=\hs@catcodeLXIII
|
|
\catcode64=\hs@catcodeLXIV
|
|
\catcode91=\hs@catcodeXCI
|
|
\catcode92=\hs@catcodeXCII
|
|
\catcode93=\hs@catcodeXCIII
|
|
\catcode94=\hs@catcodeXCIV
|
|
\catcode95=\hs@catcodeXCV
|
|
\catcode96=\hs@catcodeXCVI
|
|
\catcode123=\hs@catcodeCXXIII
|
|
\catcode124=\hs@catcodeCXXIV
|
|
\catcode125=\hs@catcodeCXXV
|
|
\catcode126=\hs@catcodeCXXVI
|
|
% Math codes for Haskell symbols:
|
|
\mathcode33=\hs@mathcodeXXXIII % !
|
|
\mathcode35=\hs@mathcodeXXXV % #
|
|
\mathcode36=\hs@mathcodeXXXVI % $
|
|
\mathcode37=\hs@mathcodeXXXVII % %
|
|
\mathcode38=\hs@mathcodeXXXVIII % &
|
|
\mathcode40=\hs@mathcodeXL % (
|
|
\mathcode41=\hs@mathcodeXLI % )
|
|
\mathcode42=\hs@mathcodeXLII % *
|
|
\mathcode43=\hs@mathcodeXLIII % +
|
|
\mathcode44=\hs@mathcodeXLIV % ,
|
|
\mathcode45=\hs@mathcodeXLV % -
|
|
\mathcode46=\hs@mathcodeXLVI % .
|
|
\mathcode47=\hs@mathcodeXLVII % /
|
|
\mathcode58=\hs@mathcodeLVIII % :
|
|
\mathcode59=\hs@mathcodeLVIX % ;
|
|
\mathcode60=\hs@mathcodeLX % <
|
|
\mathcode61=\hs@mathcodeLXI % =
|
|
\mathcode62=\hs@mathcodeLXII % >
|
|
\mathcode63=\hs@mathcodeLXIII % ?
|
|
\mathcode64=\hs@mathcodeLXIV % @
|
|
\mathcode91=\hs@mathcodeXCI % [
|
|
\mathcode92=\hs@mathcodeXCII % \
|
|
\mathcode93=\hs@mathcodeXCIII % ]
|
|
\mathcode96=\hs@mathcodeXCVI % `
|
|
\mathcode123=\hs@mathcodeCXXIII % {
|
|
\mathcode124=\hs@mathcodeCXXIV % |
|
|
\mathcode125=\hs@mathcodeCXXV % {
|
|
\mathcode126=\hs@mathcodeCXXVI % ~
|
|
\relax}
|
|
|
|
% Entry points for each of the three modes:
|
|
\def\hs@preparehaskell{%
|
|
% Initial token "registers":
|
|
\xdef\hs@tok{}\edef\hs@sup{}\edef\hs@sub{}\hs@space=0pt
|
|
\hs@preparecodemode}
|
|
|
|
\def\hs@beginInline{%
|
|
\begingroup
|
|
\hs@inlinetrue
|
|
\everyhs
|
|
\hs@preparehaskell\hs@lex@state}
|
|
\def\hs@endInline{%
|
|
\endgroup}
|
|
|
|
\def\hs@beginBird{%
|
|
\beforehs
|
|
\begingroup
|
|
\hs@inlinefalse
|
|
\everyhs
|
|
\offinterlineskip
|
|
\def\hs@parskip{}%
|
|
\hs@preparehaskell
|
|
\hs@previndent=0pt
|
|
\hs@indent=\hsleftskip
|
|
\hs@code@state}
|
|
|
|
% Entry point for the italic mode:
|
|
{\catcode`>=\active
|
|
\gdef\hs@beginitalic{\begingroup\it\catcode`>=\active\let>=\endgroup}}
|
|
|
|
% Lexeme formatting macros:
|
|
\def\hs@emitvar{%
|
|
\if\csname<\hs@tok>\endcsname\relax
|
|
\setbox255=\hbox{\hs@varface\hs@tok\/\hs@scripts}%
|
|
\else
|
|
\setbox255=\hbox{\csname<\hs@tok>\endcsname}%
|
|
\fi
|
|
\hs@emit}
|
|
|
|
\def\hs@emitcon{%
|
|
\if\csname<\hs@tok>\endcsname\relax
|
|
\setbox255=\hbox{\hs@conface\hs@tok\hs@scripts}%
|
|
\else
|
|
\setbox255=\hbox{\csname<\hs@tok>\endcsname}%
|
|
\fi
|
|
\hs@emit}
|
|
|
|
\def\hs@emitsym{%
|
|
\def\hs@guard{|}%
|
|
\ifx\hs@tok\hs@guard
|
|
\ifhs@inline
|
|
\kern\hs@space\hbox{$|$}%
|
|
\else
|
|
\ifhbox\hs@i
|
|
% Set the new guard position:
|
|
\hs@guardpos=\hs@indent
|
|
\advance\hs@guardpos by \wd\hs@i
|
|
\advance\hs@guardpos by \hs@space
|
|
\else
|
|
% Align the guard with the previous one:
|
|
\ifdim\hs@guardpos>0pt\hs@indent=\hs@guardpos\fi
|
|
\fi
|
|
\global\setbox\hs@i=\hbox{%
|
|
\ifhbox\hs@i\unhbox\hs@i\fi\kern\hs@space\vrule width.17pt\ }%
|
|
\hs@afteremit
|
|
\fi
|
|
\else
|
|
\if\csname<\hs@tok>\endcsname\relax
|
|
\setbox255=\hbox{$\hs@tok$}%
|
|
\else
|
|
\setbox255=\hbox{\csname<\hs@tok>\endcsname}%
|
|
\fi
|
|
\hs@emit
|
|
\fi}
|
|
|
|
\def\hs@emitnum#1{%
|
|
\if\csname<#1\hs@tok>\endcsname\relax
|
|
\setbox255=\hbox{\hs@numface\hs@tok$\fam=15 _{\hs@sub}$}%
|
|
\else
|
|
\setbox255=\hbox{\csname<#1\hs@tok>\endcsname}%
|
|
\fi
|
|
\hs@emit}
|
|
|
|
\def\hs@emitchr{%
|
|
\if\csname<\hs@tok>\endcsname\relax
|
|
\setbox255=\hbox{\hs@symface`{\hs@strface\hs@tok}'}%
|
|
\else
|
|
\setbox255=\hbox{\csname<\hs@tok>\endcsname}%
|
|
\fi
|
|
\hs@emit}
|
|
|
|
\def\hs@emit{%
|
|
\ifhs@inline
|
|
\kern\hs@space\box255
|
|
\else
|
|
\global\setbox\hs@i=\hbox{\ifhbox\hs@i\unhbox\hs@i\fi\kern\hs@space\box255}%
|
|
\fi
|
|
\hs@afteremit}
|
|
\def\hs@afteremit{%
|
|
\xdef\hs@tok{}\edef\hs@sup{}\edef\hs@sub{}\hs@space=0pt}
|
|
|
|
\def\hs@outputline{%
|
|
\ifhbox\hs@i
|
|
% Emit the previous line:
|
|
\dimen255=\hsize
|
|
\advance\dimen255 by -\hsrightskip
|
|
\ifdim\wd\hs@i>\dimen255
|
|
\dimen255=-\dimen255 \advance\dimen255 by \wd\hs@i
|
|
\count255=\inputlineno \advance\count255 by -1
|
|
\immediate\write16{}%
|
|
\immediate\write16{%
|
|
Overful \hbox (\the\dimen255\hs@ too wide)
|
|
in Haskell code at line \the\count255}%
|
|
\global\setbox\hs@i=\hbox{\unhbox\hs@i\vrule width\overfullrule}%
|
|
\fi
|
|
\hs@parskip
|
|
\hbox{\strut\kern\hs@indent\unhbox\hs@i}%
|
|
% Reset the guard position if necessary:
|
|
\ifdim\hs@indent>\hs@previndent\else
|
|
\hs@guardpos=0pt
|
|
\fi
|
|
% Update indentation levels:
|
|
\hs@previndent=\hs@indent
|
|
\hs@indent=\hsleftskip
|
|
\fi}
|
|
|
|
% Entry point for the comment mode:
|
|
\def\hs@emitdashes{%
|
|
\setbox255=\hbox{\hskip\hscommentskip\hs@symface---\hs@tok}\hs@emit}
|
|
\def\hs@preparecomment{%
|
|
\hs@emitdashes
|
|
\begingroup
|
|
\hs@preparecommentmode
|
|
\catcode13=12
|
|
\relax}
|
|
{\catcode13=12\gdef\hs@comment@state#1^^M{\hs@emitcomment{#1}}}
|
|
\def\hs@emitcomment#1{%
|
|
\endgroup
|
|
\ifhs@inline
|
|
\errmessage{Comment in inline Haskell mode}%
|
|
\else
|
|
\setbox255=\hbox{#1\hfill}\hs@emit
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\next}
|
|
|
|
% \endgroup
|
|
% \begingroup
|
|
% \hs@inlinefalse
|
|
% \everyhs
|
|
% \offinterlineskip
|
|
% \def\hs@parskip{}%
|
|
% \hs@preparehaskell
|
|
% \hs@previndent=0pt
|
|
% \hs@indent=\hsleftskip
|
|
% \hs@newline@state}
|
|
|
|
%%% Function detection %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% Haskell syntax does not distinguish between functions and variables, but
|
|
% we would like to typeset each kind of names differently. Therefore, I
|
|
% define a convinient \functions macro which accepts a comma-separated list
|
|
% of function names. To change a function back into a variable, prefix its
|
|
% name in the list with the ! character.
|
|
|
|
\def\functions(#1){\def\hs@tok{}\hs@funbegin#1\relax}
|
|
\def\hs@funbegin#1{%
|
|
\ifx#1\relax
|
|
\let\next=\relax
|
|
\else\ifx#1,
|
|
\let\next=\hs@funbegin
|
|
\else\ifnum`#1=9
|
|
\let\next=\hs@funbegin
|
|
\else\ifnum`#1=32
|
|
\let\next=\hs@funbegin
|
|
\else\if#1!
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@varcollect
|
|
\else
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@funcollect
|
|
\fi\fi\fi\fi\fi
|
|
\next}
|
|
\def\hs@funcollect#1{%
|
|
\ifx#1\relax
|
|
\typeset{\hs@tok}{{\hs@funface\hs@tok\hs@scripts}}%
|
|
\let\next=\relax
|
|
\else\ifx#1,
|
|
\typeset{\hs@tok}{{\hs@funface\hs@tok\hs@scripts}}%
|
|
\let\next=\hs@funbegin
|
|
\else\ifnum`#1=9
|
|
\typeset{\hs@tok}{{\hs@funface\hs@tok\hs@scripts}}%
|
|
\let\next=\hs@funbegin
|
|
\else\ifnum`#1=32
|
|
\typeset{\hs@tok}{{\hs@funface\hs@tok\hs@scripts}}%
|
|
\let\next=\hs@funbegin
|
|
\else
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@funcollect
|
|
\fi\fi\fi\fi
|
|
\next}
|
|
\def\hs@varcollect#1{%
|
|
\ifx#1\relax
|
|
\typeset{\hs@tok}{{\hs@varface\hs@tok\hs@scripts}}%
|
|
\let\next=\relax
|
|
\else\ifx#1,
|
|
\typeset{\hs@tok}{{\hs@varface\hs@tok\hs@scripts}}%
|
|
\let\next=\hs@funbegin
|
|
\else\ifnum`#1=9
|
|
\typeset{\hs@tok}{{\hs@varface\hs@tok\hs@scripts}}%
|
|
\let\next=\hs@funbegin
|
|
\else\ifnum`#1=32
|
|
\typeset{\hs@tok}{{\hs@varface\hs@tok\hs@scripts}}%
|
|
\let\next=\hs@funbegin
|
|
\else
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@varcollect
|
|
\fi\fi\fi\fi
|
|
\next}
|
|
|
|
% Define standard prelude functions:
|
|
% Prelude:
|
|
\functions (succ,pred,toEnum,fromEnum,enumFrom,enumFromThen,enumFromTo,
|
|
enumFromThenTo,minBound,maxBound,negate,abs,signum,fromInteger,toRational,
|
|
quot,rem,div,mod,quotRem,divMod,toInteger,recip,fromRational,exp,log,sqrt,
|
|
logBase,sin,cos,tan,asin,acos,atan,sinh,cosh,tanh,asinh,acosh,atanh,
|
|
properFraction,truncate,round,ceiling,floor,floatRadix,floatDigits,floatRange,
|
|
decodeFloat,encodeFloat,exponent,significand,scaleFloat,isNaN,isInfinite,
|
|
isDenormalized,isIEEE,isNegativeZero,atan2,return,fail,fmap,mapM,
|
|
sequence,maybe,either,otherwise,subtract,even,odd,gcd,lcm,
|
|
fromIntegral,realToFrac,fst,snd,curry,uncurry,id,const,flip,until,
|
|
asTypeOf,error,seq)
|
|
% PreludeList:
|
|
\functions (map,filter,concat,head,last,tail,init,null,length,foldl,scanl,
|
|
foldr,scanr,iterate,repeat,replicate,cycle,take,drop,splitAt,takeWhile,
|
|
dropWhile,span,break,lines,words,unlines,unwords,reverse,elem,notElem,lookup,
|
|
maximum,minimum,concatMap,zip,zipWith,unzip)
|
|
% PreludeText:
|
|
\functions (readsProc,readList,showsProc,showList,reads,shows,show,read,lex,
|
|
showChar,showString,readParen,showParen)
|
|
% PreludeIO:
|
|
\functions (ioError,userError,catch,putChar,putStr,putStrLn,print,getChar,
|
|
getLine,getContents,interact,readFile,writeFile,appendFile,readIO,readLn)
|
|
|
|
|
|
%%% Haskell category codes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% In a moment we will implement a relatively complete lexical analyser for
|
|
% Haskell. To make our job simpler, we collect all ASCII characters into
|
|
% the following ten equivalence classes:
|
|
%
|
|
% 0. SP - space
|
|
% 1. LC - lowercase letters
|
|
% 2. UC - uppercase letters
|
|
% 3. DI - digits
|
|
% 4. SY - symbols
|
|
% 5. PU - punctuators
|
|
% 6. AP - apostrophe
|
|
% 7. QT - double quotation mark
|
|
% 8. NL - newline
|
|
|
|
\chardef\hs@SP=0
|
|
\chardef\hs@LC=1
|
|
\chardef\hs@UC=2
|
|
\chardef\hs@DI=3
|
|
\chardef\hs@SY=4
|
|
\chardef\hs@PU=5
|
|
\chardef\hs@AP=6
|
|
\chardef\hs@QT=7
|
|
\chardef\hs@NL=8
|
|
|
|
% The macro \hs@getcc#1 computes the Haskell category code of its argument
|
|
% ans stores it in the counter variable \hs@cc.
|
|
|
|
\newcount\hs@cc
|
|
\def\hs@getcc#1{%
|
|
\hs@cc=`#1
|
|
\ifnum\hs@cc<65 %%% NUL - @
|
|
\ifnum\hs@cc<32 %%% NUL - US
|
|
\ifnum\hs@cc=9
|
|
\hs@cc=\hs@SP
|
|
\else\ifnum\hs@cc=13
|
|
\hs@cc=\hs@NL
|
|
\else
|
|
\hs@cc=-1
|
|
\fi\fi
|
|
\else %%% SP - @
|
|
\ifnum\hs@cc<48 %%% SP - /
|
|
\ifnum\hs@cc=32 %%% SP
|
|
\hs@cc=\hs@SP
|
|
\else\ifnum\hs@cc=34 %%% "
|
|
\hs@cc=\hs@QT
|
|
\else\ifnum\hs@cc=39 %%% '
|
|
\hs@cc=\hs@AP
|
|
\else\ifnum\hs@cc=40 %%% (
|
|
\hs@cc=\hs@PU
|
|
\else\ifnum\hs@cc=41 %%% )
|
|
\hs@cc=\hs@PU
|
|
\else\ifnum\hs@cc=44 %%% ,
|
|
\hs@cc=\hs@PU
|
|
\else
|
|
\hs@cc=\hs@SY
|
|
\fi\fi\fi\fi\fi\fi
|
|
\else %%% 0 - @
|
|
\ifnum\hs@cc<58 %%% 0 - 9
|
|
\hs@cc=\hs@DI
|
|
\else\ifnum\hs@cc=59 %%% ;
|
|
\hs@cc=\hs@PU
|
|
\else
|
|
\hs@cc=\hs@SY
|
|
\fi\fi
|
|
\fi
|
|
\fi
|
|
\else %%% A - DEL
|
|
\ifnum\hs@cc<97 %%% A - `
|
|
\ifnum\hs@cc<91 %%% A - Z
|
|
\hs@cc=\hs@UC
|
|
\else\ifnum\hs@cc=92 %%% \
|
|
\hs@cc=\hs@SY
|
|
\else\ifnum\hs@cc=94 %%% ^
|
|
\hs@cc=\hs@SY
|
|
\else\ifnum\hs@cc=95 %%% _
|
|
\hs@cc=\hs@LC
|
|
\else %%% [ ] `
|
|
\hs@cc=\hs@PU
|
|
\fi\fi\fi\fi
|
|
\else %%% a - DEL
|
|
\ifnum\hs@cc<123 %%% a - z
|
|
\hs@cc=\hs@LC
|
|
\else\ifnum\hs@cc=123 %%% {
|
|
\hs@cc=\hs@PU
|
|
\else\ifnum\hs@cc=124 %%% |
|
|
\hs@cc=\hs@SY
|
|
\else\ifnum\hs@cc=125 %%% }
|
|
\hs@cc=\hs@PU
|
|
\else\ifnum\hs@cc=126 %%% ~
|
|
\hs@cc=\hs@SY
|
|
\else
|
|
\hs@cc=-1
|
|
\fi\fi\fi\fi\fi
|
|
\fi
|
|
\fi}
|
|
|
|
%%% The lexical analyzer %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% Now we are ready to implement the actual lexical analyzer.
|
|
%
|
|
|
|
\def\hs@code@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\ifnum`#1=9\advance\hs@indent by \hstabwidth
|
|
\else\advance\hs@indent by \hsspacewidth\fi
|
|
\let\next=\hs@code@state
|
|
\or % LC - lowercase letters
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@var@state
|
|
\or % UC - uppercase letters
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@con@state
|
|
\or % DI - digits
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#10\let\next=\hs@zero@state\else\let\next=\hs@dec@state\fi
|
|
\or % SY - symbols
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\let\next=\hs@chr@state
|
|
\or % QT - double quotation mark
|
|
\let\next=\hs@str@state
|
|
\or % NL - newline
|
|
\def\hs@parskip{\vskip\hsparskip\def\hs@parskip{}}%
|
|
\let\next=\hs@newline@state
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@newline@state#1{%
|
|
\hs@outputline
|
|
\ifx#1>
|
|
\hs@space=0pt
|
|
\let\next=\hs@code@state
|
|
\else
|
|
% It must be a space or a newline; just drop it.
|
|
\par
|
|
\endgroup
|
|
\afterhs
|
|
\par\noindent\ignorespaces
|
|
\let\next=\relax
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@lex@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\or % LC - lowercase letters
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@var@state
|
|
\or % UC - uppercase letters
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@con@state
|
|
\or % DI - digits
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#10\let\next=\hs@zero@state\else\let\next=\hs@dec@state\fi
|
|
\or % SY - symbols
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@chr@state
|
|
\or % QT - double quotation mark
|
|
\ifhs@inline
|
|
\hs@endInline
|
|
\let\next=\relax
|
|
\else
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@str@state
|
|
\fi
|
|
\or % NL - newline
|
|
\ifhs@inline
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\else
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@var@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\hs@emitvar
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\or % LC - lowercase letters
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@var@state
|
|
\or % UC - uppercase letters
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@var@state
|
|
\or % DI - digits
|
|
\edef\hs@sub{\hs@sub#1}%
|
|
\let\next=\hs@var@state
|
|
\or % SY - symbols
|
|
\hs@emitvar
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\hs@emitvar
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\edef\hs@sup{\hs@sup\prime}%
|
|
\let\next=\hs@var@state
|
|
\or % QT - double quotation mark
|
|
\hs@emitvar
|
|
\ifhs@inline
|
|
\hs@endInline
|
|
\let\next=\relax
|
|
\else
|
|
\let\next=\hs@str@state
|
|
\fi
|
|
\or % NL - newline
|
|
\hs@emitvar
|
|
\ifhs@inline
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\else
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@con@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\hs@emitcon
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\or % LC - lowercase letters
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@con@state
|
|
\or % UC - uppercase letters
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@con@state
|
|
\or % DI - digits
|
|
\edef\hs@sub{\hs@sub#1}%
|
|
\let\next=\hs@con@state
|
|
\or % SY - symbols
|
|
\hs@emitcon
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\hs@emitcon
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\edef\hs@sup{\hs@sup\prime}%
|
|
\let\next=\hs@con@state
|
|
\or % QT - double quotation mark
|
|
\hs@emitcon
|
|
\ifhs@inline
|
|
\hs@endInline
|
|
\let\next=\relax
|
|
\else
|
|
\let\next=\hs@str@state
|
|
\fi
|
|
\or % NL - newline
|
|
\hs@emitcon
|
|
\ifhs@inline
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\else
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@sym@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\hs@emitsym
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\or % LC - lowercase letters
|
|
\hs@emitsym
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@var@state
|
|
\or % UC - uppercase letters
|
|
\hs@emitsym
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@con@state
|
|
\or % DI - digits
|
|
\hs@emitsym
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#10\let\next=\hs@zero@state\else\let\next=\hs@dec@state\fi
|
|
\or % SY - symbols
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@sym@state
|
|
\or % PU - punctuators
|
|
\hs@emitsym
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\hs@emitsym
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@chr@state
|
|
\or % QT - double quotation mark
|
|
\hs@emitsym
|
|
\ifhs@inline
|
|
\hs@endInline
|
|
\let\next=\relax
|
|
\else
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@str@state
|
|
\fi
|
|
\or % NL - newline
|
|
\hs@emitsym
|
|
\ifhs@inline
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\else
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@dash@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\hs@emitsym
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\or % LC - lowercase letters
|
|
\hs@emitsym
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@var@state
|
|
\or % UC - uppercase letters
|
|
\hs@emitsym
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@con@state
|
|
\or % DI - digits
|
|
\hs@emitsym
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#10\let\next=\hs@zero@state\else\let\next=\hs@dec@state\fi
|
|
\or % SY - symbols
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\ifx#1-\let\next=\hs@dashdash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\hs@emitsym
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\hs@emitsym
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@chr@state
|
|
\or % QT - double quotation mark
|
|
\hs@emitsym
|
|
\ifhs@inline
|
|
\hs@endInline
|
|
\let\next=\relax
|
|
\else
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@str@state
|
|
\fi
|
|
\or % NL - newline
|
|
\hs@emitsym
|
|
\ifhs@inline
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\else
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
%%% XXX
|
|
\def\hs@dashdash@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\xdef\hs@tok{\hs@}%
|
|
\hs@preparecomment
|
|
\let\next=\hs@comment@state
|
|
\or % LC - lowercase letters
|
|
\xdef\hs@tok{#1}%
|
|
\hs@preparecomment
|
|
\let\next=\hs@comment@state
|
|
\or % UC - uppercase letters
|
|
\xdef\hs@tok{#1}%
|
|
\hs@preparecomment
|
|
\let\next=\hs@comment@state
|
|
\or % DI - digits
|
|
\xdef\hs@tok{#1}%
|
|
\hs@preparecomment
|
|
\let\next=\hs@comment@state
|
|
\or % SY - symbols
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\ifx#1-\let\next=\hs@dashdash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\xdef\hs@tok{#1}%
|
|
\hs@preparecomment
|
|
\let\next=\hs@comment@state
|
|
\or % AP - apostrophe
|
|
\xdef\hs@tok{#1}%
|
|
\hs@preparecomment
|
|
\let\next=\hs@comment@state
|
|
\or % QT - double quotation mark
|
|
\xdef\hs@tok{#1}%
|
|
\hs@preparecomment
|
|
\let\next=\hs@comment@state
|
|
\or % NL - newline
|
|
\ifhs@inline
|
|
\errmessage{Comment in inline Haskell mode}%
|
|
\else
|
|
\xdef\hs@tok{}%
|
|
\hs@emitdashes
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@zero@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\hs@emitnum{}%
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\or % LC - lowercase letters
|
|
\ifx#1o
|
|
\edef\hs@sub{8}%
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@oct@state
|
|
\else\ifx#1x
|
|
\edef\hs@sub{16}%
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@hex@state
|
|
\else
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@var@state
|
|
\fi\fi
|
|
\or % UC - uppercase letters
|
|
\ifx#1O
|
|
\edef\hs@sub{8}%
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@oct@state
|
|
\else\ifx#1X
|
|
\edef\hs@sub{16}%
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@hex@state
|
|
\else
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@con@state
|
|
\fi\fi
|
|
\or % DI - digits
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@dec@state
|
|
\or % SY - symbols
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@chr@state
|
|
\or % QT - double quotation mark
|
|
\hs@emitnum{}%
|
|
\ifhs@inline
|
|
\hs@endInline
|
|
\let\next=\relax
|
|
\else
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@str@state
|
|
\fi
|
|
\or % NL - newline
|
|
\hs@emitnum{}%
|
|
\ifhs@inline
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\else
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@dec@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\hs@emitnum{}%
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\or % LC - lowercase letters
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@var@state
|
|
\or % UC - uppercase letters
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@con@state
|
|
\or % DI - digits
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@dec@state
|
|
\or % SY - symbols
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\hs@emitnum{}%
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@chr@state
|
|
\or % QT - double quotation mark
|
|
\hs@emitnum{}%
|
|
\ifhs@inline
|
|
\hs@endInline
|
|
\let\next=\relax
|
|
\else
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@str@state
|
|
\fi
|
|
\or % NL - newline
|
|
\hs@emitnum{}%
|
|
\ifhs@inline
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\else
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@oct@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\hs@emitnum{0o}%
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\or % LC - lowercase letters
|
|
\hs@emitnum{0o}%
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@var@state
|
|
\or % UC - uppercase letters
|
|
\hs@emitnum{0o}%
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@con@state
|
|
\or % DI - digits
|
|
\ifnum`#1<`8
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@oct@state
|
|
\else
|
|
\hs@emitnum{0o}%
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@dec@state
|
|
\fi
|
|
\or % SY - symbols
|
|
\hs@emitnum{0o}%
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\hs@emitnum{0o}%
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\hs@emitnum{0o}%
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@chr@state
|
|
\or % QT - double quotation mark
|
|
\hs@emitnum{0o}%
|
|
\ifhs@inline
|
|
\hs@endInline
|
|
\let\next=\relax
|
|
\else
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@str@state
|
|
\fi
|
|
\or % NL - newline
|
|
\hs@emitnum{0o}%
|
|
\ifhs@inline
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\else
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@hex@state#1{%
|
|
\hs@getcc#1%
|
|
\ifcase\hs@cc
|
|
% SP - space
|
|
\hs@emitnum{0x}%
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\or % LC - lowercase letters
|
|
\ifnum`#1<`g
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@hex@state
|
|
\else
|
|
\hs@emitnum{0x}%
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@var@state
|
|
\fi
|
|
\or % UC - uppercase letters
|
|
\ifnum`#1<`G
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@hex@state
|
|
\else
|
|
\hs@emitnum{0x}%
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@con@state
|
|
\fi
|
|
\or % DI - digits
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@hex@state
|
|
\or % SY - symbols
|
|
\hs@emitnum{0x}%
|
|
\xdef\hs@tok{#1}%
|
|
\ifx#1-\let\next=\hs@dash@state\else\let\next=\hs@sym@state\fi
|
|
\or % PU - punctuators
|
|
\hs@emitnum{0x}%
|
|
\xdef\hs@tok{#1}%
|
|
\hs@emitsym
|
|
\let\next=\hs@lex@state
|
|
\or % AP - apostrophe
|
|
\hs@emitnum{0x}%
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@chr@state
|
|
\or % QT - double quotation mark
|
|
\hs@emitnum{0x}%
|
|
\ifhs@inline
|
|
\hs@endInline
|
|
\let\next=\relax
|
|
\else
|
|
\xdef\hs@tok{}%
|
|
\let\next=\hs@str@state
|
|
\fi
|
|
\or % NL - newline
|
|
\hs@emitnum{0x}%
|
|
\ifhs@inline
|
|
\hs@space=\hswordspace
|
|
\let\next=\hs@lex@state
|
|
\else
|
|
\let\next=\hs@newline@state
|
|
\fi
|
|
\else
|
|
\errmessage{Illegal character in Haskell mode: #1}%
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@chr@state#1{%
|
|
\ifnum`#1=`'
|
|
\hs@emitchr
|
|
\let\next=\hs@lex@state
|
|
\else\ifnum`#1=92
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@chresc@state
|
|
\else
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@chr@state
|
|
\fi\fi
|
|
\next}
|
|
|
|
\def\hs@chresc@state#1{%
|
|
\xdef\hs@tok{\hs@tok#1}\hs@chr@state}
|
|
|
|
\def\hs@str@state{%
|
|
\def\hs@strprefix{\hs@symface``}%
|
|
\hs@strchr@state}
|
|
|
|
\def\hs@strchr@state#1{%
|
|
\ifx#1"
|
|
\setbox255=\hbox{\hs@strprefix\hs@strface\hs@tok\hs@symface''}%
|
|
\hs@emit
|
|
\let\next=\hs@lex@state
|
|
\else\ifnum`#1=92
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@stresc@state
|
|
\else
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@strchr@state
|
|
\fi\fi
|
|
\next}
|
|
|
|
\def\hs@stresc@state#1{%
|
|
\hs@getcc#1%
|
|
\ifnum\hs@cc=\hs@SP
|
|
\let\next=\hs@gap@state
|
|
\else\ifnum\hs@cc=\hs@NL
|
|
\let\next=\hs@gapnewline@state
|
|
\else
|
|
\xdef\hs@tok{\hs@tok#1}%
|
|
\let\next=\hs@strchr@state
|
|
\fi\fi
|
|
\next}
|
|
|
|
\def\hs@gap@state#1{%
|
|
\hs@getcc#1%
|
|
\ifnum\hs@cc=\hs@SP
|
|
\let\next=\hs@gap@state
|
|
\else\ifnum\hs@cc=\hs@NL
|
|
\let\next=\hs@gapnewline@state
|
|
\else
|
|
\ifnum`#1=92
|
|
\xdef\hs@tok{\hs@tok\hs@#1}%
|
|
\let\next=\hs@strchr@state
|
|
\else
|
|
\errmessage{Unexpected character in a gap: #1}%
|
|
\fi
|
|
\fi\fi
|
|
\next}
|
|
|
|
\def\hs@gapnewline@state#1{%
|
|
\setbox255=\hbox{\hs@strprefix\hs@strface\hs@tok}%
|
|
\hs@emit
|
|
\hs@outputline
|
|
\ifx#1>
|
|
\def\hs@strprefix{}%
|
|
\hs@space=0pt
|
|
\let\next=\hs@gapcode@state
|
|
\else
|
|
\errmessage{Literate comments cannot appear in a gap}
|
|
\fi
|
|
\next}
|
|
|
|
\def\hs@gapcode@state#1{%
|
|
\hs@getcc#1%
|
|
\ifnum\hs@cc=\hs@SP
|
|
\ifnum`#1=9\advance\hs@indent by \hstabwidth
|
|
\else\advance\hs@indent by \hsspacewidth\fi
|
|
\let\next=\hs@gapcode@state
|
|
\else\ifnum\hs@cc=\hs@NL
|
|
\def\hs@parskip{\vskip\hsparskip\def\hs@parskip{}}%
|
|
\let\next=\hs@gapnewline@state
|
|
\else
|
|
\ifnum`#1=92
|
|
\xdef\hs@tok{#1}%
|
|
\let\next=\hs@strchr@state
|
|
\else
|
|
\errmessage{Unexpected character in a gap: #1}%
|
|
\fi
|
|
\fi\fi
|
|
\next}
|
|
|
|
%%% The "hidden" environment %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
|
|
\newbox\hs@junkbox
|
|
\def\beginhidden{\begingroup\setbox\hs@junkbox=\vbox\bgroup}
|
|
\def\endhidden{\egroup\endgroup}
|
|
|
|
%%% Activate active characters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%
|
|
% As we've already confiscated > as an active character, let's take < too
|
|
% and use <...> to typeset ... in italic.
|
|
|
|
% To make amends for the above quirk, I define \lt and \gt math macros
|
|
% to complement the \le, \ge, etc. already in plain TeX:
|
|
\def\inch{"}
|
|
\def\lt{<}
|
|
\def\gt{>}
|
|
|
|
% Finally, we are ready to active our three active characters:
|
|
\catcode`"=\active \let"=\hs@beginInline
|
|
\catcode`>=\active \let>=\hs@beginBird
|
|
\catcode`<=\active \let<=\hs@beginitalic
|
|
|
|
% Restore the meaning of < and > in math mode.
|
|
% WARNING: this doesn't work as well as expected. When TeX sees the $
|
|
% character, it reads the following character to see if it is another $.
|
|
% If that character is active, it attempts to expand it (a bug in TeX?!
|
|
% or just a mis-feature?) So, you must write $ >$ rather than $>$. Oh well.
|
|
\everymath{\let<\lt\let>\gt\relax}
|
|
\everydisplay{\let<\lt\let>\gt\relax}
|
|
|
|
|
|
\catcode`@=12
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% THE END %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
|