diff --git a/Library/ocaml.fmt b/Library/ocaml.fmt new file mode 100644 index 0000000..1ab3ce5 --- /dev/null +++ b/Library/ocaml.fmt @@ -0,0 +1,403 @@ +%if False +% +% Permission is granted to include this file (or parts of this file) +% literally into other documents, regardless of the conditions or +% license applying to these documents. +% +%endif +%if not lhs2tex_lhs2tex_fmt_read +%let lhs2tex_lhs2tex_fmt_read = True +%subst verb a = "\text{\tt " a "}" +%subst verbatim a = "\begin{tabbing}\tt'n" a "'n\end{tabbing}'n" +%subst verbnl = "\\'n\tt " +%if style == tt +%subst inline a = "\text{\texfamily " a "}" +%subst thinspace = "\Sp " +%subst code a = "\begin{tabbing}\texfamily'n" a "'n\end{tabbing}'n" +%subst comment a = "{\rmfamily-{}- " a "}" +%subst nested a = "{\rmfamily\enskip\{- " a " -\}\enskip}" +%subst pragma a = "{\rmfamily\enskip\{-\#" a " \#-\}\enskip}" +%subst tex a = a +%subst spaces a = a +%subst special a = a +%subst space = "~" +%subst newline = "\\'n\texfamily " +%subst conid a = "{\itshape " a "}" +%subst varid a = a +%subst tyvarid a = "'" a +%subst consym a = a +%subst varsym a = a +%subst backquoted a = "`" a "`" +%subst numeral a = a +%subst char a = "''" a "''" +%subst string a = "\char34 " a "\char34 " +%if underlineKeywords +%subst keyword a = "\uline{" a "}" +%else +%subst keyword a = "{\bfseries " a "}" +%endif +%format \ = "\char''10" +%format . = "\char''00" +%if not spacePreserving +%format alpha = "\char''02" +%format beta = "\char''03" +%format gamma = "\char''11" +%format delta = "\char''12" +%format pi = "\char''07" +%format infty = "\char''16" +%format intersect = "\char''22" +%format union = "\char''23" +%format forall = "\char''24" +%format exists = "\char''25" +%format not = "\char''05" +%format && = "\char''04" +%format || = "\char''37" +%format <- = "\char''06" +%format -> = "\char''31" +%format == = "\char''36" +%format /= = "\char''32" +%format <= = "\char''34" +%format >= = "\char''35" +%endif +%if meta +%format M.a = "\ensuremath{a}" +%format M.b = "\ensuremath{b}" +%format M.c = "\ensuremath{c}" +%format M.d = "\ensuremath{d}" +%format M.e = "\ensuremath{e}" +%format M.f = "\ensuremath{f}" +%format M.g = "\ensuremath{g}" +%format M.h = "\ensuremath{h}" +%format M.i = "\ensuremath{i}" +%format M.j = "\ensuremath{j}" +%format M.k = "\ensuremath{k}" +%format M.l = "\ensuremath{l}" +%format M.m = "\ensuremath{m}" +%format M.n = "\ensuremath{n}" +%format M.o = "\ensuremath{o}" +%format M.p = "\ensuremath{p}" +%format M.q = "\ensuremath{q}" +%format M.r = "\ensuremath{r}" +%format M.s = "\ensuremath{s}" +%format M.t = "\ensuremath{t}" +%format M.u = "\ensuremath{u}" +%format M.v = "\ensuremath{v}" +%format M.w = "\ensuremath{w}" +%format M.x = "\ensuremath{x}" +%format M.y = "\ensuremath{y}" +%format M.z = "\ensuremath{z}" +%format M.A = "\ensuremath{A}" +%format M.B = "\ensuremath{B}" +%format M.C = "\ensuremath{C}" +%format M.D = "\ensuremath{D}" +%format M.E = "\ensuremath{E}" +%format M.F = "\ensuremath{F}" +%format M.G = "\ensuremath{G}" +%format M.H = "\ensuremath{H}" +%format M.I = "\ensuremath{I}" +%format M.J = "\ensuremath{J}" +%format M.K = "\ensuremath{K}" +%format M.L = "\ensuremath{L}" +%format M.M = "\ensuremath{M}" +%format M.N = "\ensuremath{N}" +%format M.O = "\ensuremath{O}" +%format M.P = "\ensuremath{P}" +%format M.Q = "\ensuremath{Q}" +%format M.R = "\ensuremath{R}" +%format M.S = "\ensuremath{S}" +%format M.T = "\ensuremath{T}" +%format M.U = "\ensuremath{U}" +%format M.V = "\ensuremath{V}" +%format M.W = "\ensuremath{W}" +%format M.X = "\ensuremath{X}" +%format M.Y = "\ensuremath{Y}" +%format M.Z = "\ensuremath{Z}" +%format M.alpha = "\ensuremath{\alpha}" +%format M.beta = "\ensuremath{\beta}" +%format M.gamma = "\ensuremath{\gamma}" +%format M.delta = "\ensuremath{\delta}" +%format M.epsilon = "\ensuremath{\epsilon}" +%format M.zeta = "\ensuremath{\zeta}" +%format M.eta = "\ensuremath{\eta}" +%format M.theta = "\ensuremath{\theta}" +%format M.iota = "\ensuremath{\iota}" +%format M.kappa = "\ensuremath{\kappa}" +%format M.lambda = "\ensuremath{\lambda}" +%format M.mu = "\ensuremath{\mu}" +%format M.nu = "\ensuremath{\nu}" +%format M.xi = "\ensuremath{\xi}" +%format M.pi = "\ensuremath{\pi}" +%format M.rho = "\ensuremath{\rho}" +%format M.sigma = "\ensuremath{\sigma}" +%format M.tau = "\ensuremath{\tau}" +%format M.upsilon = "\ensuremath{\upsilon}" +%format M.phi = "\ensuremath{\phi}" +%format M.chi = "\ensuremath{\chi}" +%format M.psi = "\ensuremath{\psi}" +%format M.omega = "\ensuremath{\omega}" +%format M.Gamma = "\ensuremath{\Gamma}" +%format M.Delta = "\ensuremath{\Delta}" +%format M.Theta = "\ensuremath{\Theta}" +%format M.Lambda = "\ensuremath{\Lambda}" +%format M.Xi = "\ensuremath{\Xi}" +%format M.Pi = "\ensuremath{\Pi}" +%format M.Sigma = "\ensuremath{\Sigma}" +%format M.Upsilon = "\ensuremath{\Upsilon}" +%format M.Phi = "\ensuremath{\Phi}" +%format M.Psi = "\ensuremath{\Psi}" +%format M.Omega = "\ensuremath{\Omega}" +%format M.forall = "\ensuremath{\forall}" +%format M.exists = "\ensuremath{\exists}" +%format M.not = "\ensuremath{\neg}" +%format ==> = "\ensuremath{\Longrightarrow}" +%format <== = "\ensuremath{\Longleftarrow}" +%format /\ = "\ensuremath{\wedge}" +%format \/ = "\ensuremath{\vee}" +%format M.= = "\ensuremath{=}" +%format M./= = "\ensuremath{\neq}" +%format M.< = "\ensuremath{<}" +%format M.<= = "\ensuremath{\leq}" +%format M.>= = "\ensuremath{\geq}" +%format M.> = "\ensuremath{>}" +%endif +%elif style == newcode +%subst comment a = "-- " a +%subst nested a = "{- " a " -}" +%subst code a = a "'n" +%subst newline = "'n" +%subst dummy = +%subst pragma a = "{-# " a " #-}" +%subst tex a = +%subst numeral a = a +%subst keyword a = a +%subst spaces a = a +%subst special a = a +%subst space = " " +%subst conid a = a +%subst varid a = a +%subst tyvarid a = "'" a +%subst consym a = a +%subst varsym a = a +%subst backquoted a = "`" a "`" +%subst char a = "''" a "''" +%subst string a = "'d" a "'d" +%elif style == math +%subst phantom a = "\phantom{" a "\mbox{}}" +%subst comment a = "\mbox{\qquad-{}- " a "}" +%subst nested a = "\mbox{\enskip\{- " a " -\}\enskip}" +%if array +%subst code a = "\[\begin{array}{@{}lcl}'n\hspace{\lwidth}&\hspace{\cwidth}&\\[-10pt]'n" a "'n\end{array}\]" +%subst column3 l c r = "{}" l " & " c " & {" r "}" +%subst column1 a = "\multicolumn{3}{@{}l}{" a "}" +%else +%subst code a = "\begin{tabbing}'n\qquad\=\hspace{\lwidth}\=\hspace{\cwidth}\=\+\kill'n" a "'n\end{tabbing}" +%subst column3 l c r = "$" l "$ \> \makebox[\cwidth]{$" c "$} \> ${" r "}$" +%subst column1 a = "${" a "}$" +%endif +%subst newline = "\\'n" +%subst blankline = "\\[0.66084ex]%'n" +%let anyMath = True +%elif style == poly +%subst comment a = "\mbox{\onelinecomment " a "}" +%subst nested a = "\mbox{\commentbegin " a " \commentend}" +%if array +%subst code a = "\['n\begin{parray}\SaveRestoreHook'n" a "\ColumnHook'n\end{parray}'n\]\resethooks'n" +%else +%subst code a = "\begingroup\par\noindent\advance\leftskip\mathindent\('n\begin{pboxed}\SaveRestoreHook'n" a "\ColumnHook'n\end{pboxed}'n\)\par\noindent\endgroup\resethooks'n" +%endif +%subst column c a = "\column{" c "}{" a "}%'n" +%subst fromto b e t = "\>[" b "]{}" t "{}\<[" e "]%'n" +%subst left = "@{}>{\hspre}l<{\hspost}@{}" +%subst centered = "@{}>{\hspre}c<{\hspost}@{}" +%subst dummycol = "@{}l@{}" +%subst newline = "\\'n" +%subst blankline = "\\[\blanklineskip]%'n" +%subst indent n = "\hsindent{" n "}" +%let anyMath = True +%endif +%if anyMath +%let autoSpacing = True +%subst dummy = "\cdot " +%subst inline a = "\ensuremath{" a "}" +%subst hskip a = "\hskip" a "em\relax" +%subst pragma a = "\mbox{\enskip\{-\#" a " \#-\}\enskip}" +%subst tex a = a +%if latex209 +%subst numeral a = "{\mathrm " a "}" +%subst keyword a = "{\mathbf " a "}" +%else +%subst numeral a = "\mathrm{" a "}" +%subst keyword a = "\Keyword{" a "}" +%endif +%subst spaces a = a +%subst special a = a +%subst space = "\;" +%subst conid a = "\Conid{" a "}" +%subst varid a = "\Varid{" a "}" +%subst tyvarid a = "\Tyvarid{" a "}" +%subst consym a = "\mathbin{" a "}" +%subst varsym a = "\mathbin{" a "}" +%subst backquoted a = "\mathbin{`" a "`}" +%subst char a = "\text{\tt ''" a "''}" +%subst string a = "\text{\tt \char34 " a "\char34}" +%format _ = "\anonymous " +%format -> = "\to " +%format <- = "\leftarrow " +%format => = "\Rightarrow " +%format | = "\mid " +%format { = "\{\mskip1.5mu " +%format } = "\mskip1.5mu\}" +%format [ = "[\mskip1.5mu " +%format ] = "\mskip1.5mu]" +%format = = "\mathrel{=}" +%format : = "\mathrel{:}" +%format .. = "\mathinner{\ldotp\ldotp}" +%format ~ = "\mathord{\sim}" +%format . = "." +%format !! = "\mathbin{!!}" +%format ^ = "\mathbin{\mbox{}^\wedge}" +%format ^^ = "\mathbin{\char94\char94}" +%format ** = "\mathbin{**}" +%format / = "\mathbin{/}" +%format % = "\mathbin{\%}" +%format ++ = "\plus " +%format == = "\equiv " +%% ODER: format == = "\mathrel{==}" +%format /= = "\not\equiv " +%% ODER: format /= = "\neq " +%format <= = "\leq " +%format >= = "\geq " +%format && = "\mathrel{\wedge}" +%format || = "\mathrel{\vee}" +%%% %format && = "\mathrel{\&\!\!\&}" +%%% %format || = "\mathrel{|\;|}" +%format >> = "\sequ " +%format >>= = "\bind " +%format =<< = "\rbind " +%format $ = "\mathbin{\$}" +%format ! = "\mathbin{!}" +%format // = "\mathbin{//}" +%format undefined = "\bot " +%format not = "\neg " +%format += = "\mathrel{+\!\!\!=}" +%format := = "\mathrel{:=}" +%format * = "\mathbin{\times}" +%format @ = "\mathbin{@}" +%format @@ = "\mathbin{@\!\!\!@}" +%format @@@ = "\mathbin{@\!\!\!@\!\!\!@}" +%%% not technically keywords +%format raise = "\Keyword{raise}" +%format invalid_arg = "\Keyword{invalid\_arg}" +%format failwith = "\Keyword{failwith}" +%if meta +%format M.a = "a" +%format M.b = "b" +%format M.c = "c" +%format M.d = "d" +%format M.e = "e" +%format M.f = "f" +%format M.g = "g" +%format M.h = "h" +%format M.i = "i" +%format M.j = "j" +%format M.k = "k" +%format M.l = "l" +%format M.m = "m" +%format M.n = "n" +%format M.o = "o" +%format M.p = "p" +%format M.q = "q" +%format M.r = "r" +%format M.s = "s" +%format M.t = "t" +%format M.u = "u" +%format M.v = "v" +%format M.w = "w" +%format M.x = "x" +%format M.y = "y" +%format M.z = "z" +%format M.A = "A" +%format M.B = "B" +%format M.C = "C" +%format M.D = "D" +%format M.E = "E" +%format M.F = "F" +%format M.G = "G" +%format M.H = "H" +%format M.I = "I" +%format M.J = "J" +%format M.K = "K" +%format M.L = "L" +%format M.M = "M" +%format M.N = "N" +%format M.O = "O" +%format M.P = "P" +%format M.Q = "Q" +%format M.R = "R" +%format M.S = "S" +%format M.T = "T" +%format M.U = "U" +%format M.V = "V" +%format M.W = "W" +%format M.X = "X" +%format M.Y = "Y" +%format M.Z = "Z" +%format M.alpha = "\alpha " +%format M.beta = "\beta " +%format M.gamma = "\gamma " +%format M.delta = "\delta " +%format M.epsilon = "\epsilon " +%format M.zeta = "\zeta " +%format M.eta = "\eta " +%format M.theta = "\theta " +%format M.iota = "\iota " +%format M.kappa = "\kappa " +%format M.lambda = "\lambda " +%format M.mu = "\mu " +%format M.nu = "\nu " +%format M.xi = "\xi " +%format M.pi = "\pi " +%format M.rho = "\rho " +%format M.sigma = "\sigma " +%format M.tau = "\tau " +%format M.upsilon = "\upsilon " +%format M.phi = "\phi " +%format M.chi = "\chi " +%format M.psi = "\psi " +%format M.omega = "\omega " +%format M.Gamma = "\Gamma " +%format M.Delta = "\Delta " +%format M.Theta = "\Theta " +%format M.Lambda = "\Lambda " +%format M.Xi = "\Xi " +%format M.Pi = "\Pi " +%format M.Sigma = "\Sigma " +%format M.Upsilon = "\Upsilon " +%format M.Phi = "\Phi " +%format M.Psi = "\Psi " +%format M.Omega = "\Omega " +%format M.forall = "\forall " +%format M.exists = "\exists " +%format M.not = "\neg " +%format ==> = "\enskip\Longrightarrow\enskip " +%format <== = "\enskip\Longleftarrow\enskip " +%format /\ = "\enskip\mathrel{\wedge}\enskip " +%format \/ = "\enskip\mathrel{\vee}\enskip " +%format M.= = "=" +%format M./= = "\neq " +%format M.< = "<" +%format M.<= = "\leq " +%format M.>= = "\geq " +%format M.> = ">" +%endif +%endif +%include lhs2TeX.sty +\renewcommand{\commentbeginchars}{\quad(\ensuremath{\ast\;}} +\renewcommand{\commentendchars}{\ensuremath{\;\ast})\quad} +\renewcommand{\commentbegin}{\commentbeginchars} +\renewcommand{\commentend}{\commentendchars} +\newcommand{\Tyvarid}[1]{\Varid{\!\!\mbox{}^\shortmid\!\!#1}} +\newcommand{\Keyword}[1]{\mathbf{#1}} +% \newcommand{\Tyvarid}[1]{\Varid{'\!\!#1}} +\renewcommand{\Conid}[1]{\mathrm{#1}} +%endif diff --git a/Library/ocamlpoly.fmt b/Library/ocamlpoly.fmt new file mode 100644 index 0000000..e64a463 --- /dev/null +++ b/Library/ocamlpoly.fmt @@ -0,0 +1,197 @@ +%if False +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% polycode.fmt +% +% better code environment for poly style in lhs2TeX +% +% Permission is granted to include this file (or parts of this file) +% literally into other documents, regardless of the conditions or +% license applying to these documents. +% +% Andres Loeh, February 2013, ver 1.12 +% +% TODO: use \[ \] in arrayhs (fleqn problem) +% think about penalties and better pagebreaks +% by using \allowdisplaybreaks +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%endif +%if not lhs2tex_ocamlpoly_fmt_read +%let lhs2tex_ocamlpoly_fmt_read = True +%include ocaml.fmt +% +%if style == poly +% +%if False +% The follwing subst replaces the bad default from lhs2TeX.fmt. +% The idea is to just provide the basic structure in the subst, and +% let the rest be handled by a LaTeX environment. +%endif +% +%subst code a = "\begin{hscode}\SaveRestoreHook'n" a "\ColumnHook'n\end{hscode}\resethooks'n" +% +% +% This package provides two environments suitable to take the place +% of hscode, called "plainhscode" and "arrayhscode". +% +% The plain environment surrounds each code block by vertical space, +% and it uses \abovedisplayskip and \belowdisplayskip to get spacing +% similar to formulas. Note that if these dimensions are changed, +% the spacing around displayed math formulas changes as well. +% All code is indented using \leftskip. +% +% Changed 19.08.2004 to reflect changes in colorcode. Should work with +% CodeGroup.sty. +% +\ReadOnlyOnce{polycode.fmt}% +\makeatletter + +\newcommand{\hsnewpar}[1]% + {{\parskip=0pt\parindent=0pt\par\vskip #1\noindent}} + +% can be used, for instance, to redefine the code size, by setting the +% command to \small or something alike +\newcommand{\hscodestyle}{} + +% The command \sethscode can be used to switch the code formatting +% behaviour by mapping the hscode environment in the subst directive +% to a new LaTeX environment. + +\newcommand{\sethscode}[1]% + {\expandafter\let\expandafter\hscode\csname #1\endcsname + \expandafter\let\expandafter\endhscode\csname end#1\endcsname} + +% "compatibility" mode restores the non-polycode.fmt layout. + +\newenvironment{compathscode}% + {\par\noindent + \advance\leftskip\mathindent + \hscodestyle + \let\\=\@@normalcr + \let\hspre\(\let\hspost\)% + \pboxed}% + {\endpboxed\)% + \par\noindent + \ignorespacesafterend} + +\newcommand{\compaths}{\sethscode{compathscode}} + +% "plain" mode is the proposed default. +% It should now work with \centering. +% This required some changes. The old version +% is still available for reference as oldplainhscode. + +\newenvironment{plainhscode}% + {\hsnewpar\abovedisplayskip + \advance\leftskip\mathindent + \hscodestyle + \let\hspre\(\let\hspost\)% + \pboxed}% + {\endpboxed% + \hsnewpar\belowdisplayskip + \ignorespacesafterend} + +\newenvironment{oldplainhscode}% + {\hsnewpar\abovedisplayskip + \advance\leftskip\mathindent + \hscodestyle + \let\\=\@@normalcr + \(\pboxed}% + {\endpboxed\)% + \hsnewpar\belowdisplayskip + \ignorespacesafterend} + +% Here, we make plainhscode the default environment. + +\newcommand{\plainhs}{\sethscode{plainhscode}} +\newcommand{\oldplainhs}{\sethscode{oldplainhscode}} +\plainhs + +% The arrayhscode is like plain, but makes use of polytable's +% parray environment which disallows page breaks in code blocks. + +\newenvironment{arrayhscode}% + {\hsnewpar\abovedisplayskip + \advance\leftskip\mathindent + \hscodestyle + \let\\=\@@normalcr + \(\parray}% + {\endparray\)% + \hsnewpar\belowdisplayskip + \ignorespacesafterend} + +\newcommand{\arrayhs}{\sethscode{arrayhscode}} + +% The mathhscode environment also makes use of polytable's parray +% environment. It is supposed to be used only inside math mode +% (I used it to typeset the type rules in my thesis). + +\newenvironment{mathhscode}% + {\parray}{\endparray} + +\newcommand{\mathhs}{\sethscode{mathhscode}} + +% texths is similar to mathhs, but works in text mode. + +\newenvironment{texthscode}% + {\(\parray}{\endparray\)} + +\newcommand{\texths}{\sethscode{texthscode}} + +% The framed environment places code in a framed box. + +\def\codeframewidth{\arrayrulewidth} +\RequirePackage{calc} + +\newenvironment{framedhscode}% + {\parskip=\abovedisplayskip\par\noindent + \hscodestyle + \arrayrulewidth=\codeframewidth + \tabular{@@{}||p{\linewidth-2\arraycolsep-2\arrayrulewidth-2pt}||@@{}}% + \hline\framedhslinecorrect\\{-1.5ex}% + \let\endoflinesave=\\ + \let\\=\@@normalcr + \(\pboxed}% + {\endpboxed\)% + \framedhslinecorrect\endoflinesave{.5ex}\hline + \endtabular + \parskip=\belowdisplayskip\par\noindent + \ignorespacesafterend} + +\newcommand{\framedhslinecorrect}[2]% + {#1[#2]} + +\newcommand{\framedhs}{\sethscode{framedhscode}} + +% The inlinehscode environment is an experimental environment +% that can be used to typeset displayed code inline. + +\newenvironment{inlinehscode}% + {\(\def\column##1##2{}% + \let\>\undefined\let\<\undefined\let\\\undefined + \newcommand\>[1][]{}\newcommand\<[1][]{}\newcommand\\[1][]{}% + \def\fromto##1##2##3{##3}% + \def\nextline{}}{\) }% + +\newcommand{\inlinehs}{\sethscode{inlinehscode}} + +% The joincode environment is a separate environment that +% can be used to surround and thereby connect multiple code +% blocks. + +\newenvironment{joincode}% + {\let\orighscode=\hscode + \let\origendhscode=\endhscode + \def\endhscode{\def\hscode{\endgroup\def\@@currenvir{hscode}\\}\begingroup} + %\let\SaveRestoreHook=\empty + %\let\ColumnHook=\empty + %\let\resethooks=\empty + \orighscode\def\hscode{\endgroup\def\@@currenvir{hscode}}}% + {\origendhscode + \global\let\hscode=\orighscode + \global\let\endhscode=\origendhscode}% + +\makeatother +\EndFmtInput +% +%endif +%endif diff --git a/src/Directives.lhs b/src/Directives.lhs index c806cff..164a7e7 100644 --- a/src/Directives.lhs +++ b/src/Directives.lhs @@ -73,15 +73,15 @@ Format directives. \NB @%format ( = "(\;"@ is legal. > tex (Conid s) = subscript Conid s > tex (Qual [] s) = tex s > tex (Qual (m:ms) s) = Conid m : tex (Qual ms s) -> -- ks, 03.09.2003: was "tex (Qual m s) = Conid m : tex s"; +> -- ks, 03.09.2003: was "tex (Qual m s) = Conid m : tex s"; > -- seems strange though ... -> subscript f s +> subscript f s > | null t && not (null w) && (null v || head w == '_') > = underscore f s > | otherwise = [f (reverse w) > , TeX False > (Text ((if not (null v) -> then "_{" ++ reverse v ++ "}" +> then "_{" ++ reverse v ++ "}" > else "" > ) ++ reverse t)) > ] @@ -97,7 +97,7 @@ Format directives. \NB @%format ( = "(\;"@ is legal. > (if end then [Varid "_"] else []) ks, 02.02.2004: I have added implicit formatting via |underscore|. -The above condition should guarantee that it is (almost) only used in +The above condition should guarantee that it is (almost) only used in cases where previously implicit formatting did not do anything useful. The function |underscore| typesets an identifier such as |a_b_c| as $a_{b_{c}}$. TODO: Instead of hard-coded subscripting a @@ -172,6 +172,7 @@ because "=" will never occur in a Varid constructor. > conid = do x <- satisfy isConid; return (string x) > varsym Agda s = satisfy (\ x -> x == Varsym s || x == Varid s) -- Agda has no symbol/id distinction > varsym Haskell s = satisfy (== (Varsym s)) +> varsym OCaml s = varsym Haskell s > > isTeX (TeX _ _) = True > isTeX _ = False diff --git a/src/Document.lhs b/src/Document.lhs index bee595c..43a0a4b 100644 --- a/src/Document.lhs +++ b/src/Document.lhs @@ -48,6 +48,7 @@ Substitution strings. > sub'code a = Sub "code" [a] > sub'conid a = Sub "conid" [a] > sub'varid a = Sub "varid" [a] +> sub'tyvarid a = Sub "tyvarid" [a] > sub'consym a = Sub "consym" [a] > sub'varsym a = Sub "varsym" [a] > sub'backquoted a = Sub "backquoted" [a] diff --git a/src/HsLexer.lhs b/src/HsLexer.lhs index e59974c..8cede83 100644 --- a/src/HsLexer.lhs +++ b/src/HsLexer.lhs @@ -7,7 +7,7 @@ > {-# LANGUAGE NPlusKPatterns #-} > module HsLexer ( module HsLexer ) --Token(..), isVarid, isConid, isNotSpace, string, tokenize ) > where -> import Data.Char ( isSpace, isUpper, isLower, isDigit, isAlphaNum, isPunctuation ) +> import Data.Char ( isSpace, isUpper, isLower, isDigit, isHexDigit, isOctDigit, isAlpha, isAlphaNum, isPunctuation ) > import qualified Data.Char ( isSymbol ) > import Control.Monad > import Control.Monad.Error () @@ -21,6 +21,7 @@ A Haskell lexer, based on the Prelude function \hs{lex}. > data Token = Space String > | Conid String > | Varid String +> | Tyvarid String -- type variable (OCaml) > | Consym String > | Varsym String > | Numeral String @@ -42,6 +43,7 @@ hierarchical modules. Also added Pragma. > isVarid, isConid, isNotSpace :: Token -> Bool > isVarid (Varid _) = True +> isVarid (Tyvarid _) = True > isVarid (Qual _ t) = isVarid t > isVarid _ = False > @@ -56,6 +58,7 @@ hierarchical modules. Also added Pragma. > string (Space s) = s > string (Conid s) = s > string (Varid s) = s +> string (Tyvarid s) = "'" ++ s > string (Consym s) = s > string (Varsym s) = s > string (Numeral s) = s @@ -98,6 +101,10 @@ ks, 28.08.2008: New: Agda and Haskell modes. > > lex' :: Lang -> String -> Maybe (Token, String) > lex' lang "" = Nothing +> lex' OCaml ('\'' : s) = Just $ let (t, u) = ocamlQuote s +> in case u of +> ('\'' : v) -> (Char ("'" ++ t ++ "'"), v) +> _ -> (Tyvarid t, u) > lex' lang ('\'' : s) = do let (t, u) = lexLitChar s > v <- match "\'" u > return (Char ("'" ++ t ++ "'"), v) @@ -105,23 +112,31 @@ ks, 28.08.2008: New: Agda and Haskell modes. > v <- match "\"" u > return (String ("\"" ++ t ++ "\""), v) > lex' lang ('-' : '-' : s) -> | not (null s') && isSymbol lang (head s') +> | hsOrAgda lang && not (null s') && isSymbol lang (head s') > = case s' of > (c : s'') -> return (varsymid lang ("--" ++ d ++ [c]), s'') -> | otherwise = return (Comment t, u) +> | hsOrAgda lang = return (Comment t, u) > where (d, s') = span (== '-') s > (t, u) = break (== '\n') s' -> lex' lang ('{' : '-' : '"' : s) +> lex' lang ('{' : '-' : '"' : s) -- Important: this syntax is used internally for generating code (even in OCaml mode) > = do let (t, u) = inlineTeX s > v <- match "\"-}" u > return (TeX True (Text t), v) > lex' lang ('{' : '-' : '#' : s) -> = do let (t, u) = nested 0 s +> | hsOrAgda lang = do let (t, u) = nested 0 s > v <- match "#-}" u > return (Pragma t, v) -> lex' lang ('{' : '-' : s) = do let (t, u) = nested 0 s +> lex' lang ('{' : '-' : s) +> | hsOrAgda lang = do let (t, u) = nested 0 s > v <- match "-}" u > return (Nested t, v) +> lex' OCaml ('(' : '*' : '"' : s) +> = do let (t, u) = inlineTeX s +> v <- match "\"*)" u +> return (TeX True (Text t), v) +> lex' OCaml ('(' : '*' : s) = do let (t, u) = nestedOCaml 0 s +> v <- match "*)" u +> return (Nested t, v) > lex' lang (c : s) > | isSpace c = let (t, u) = span isSpace s in return (Space (c : t), u) > | isSpecial lang c = Just (Special c, s) @@ -135,13 +150,16 @@ ks, 28.08.2008: New: Agda and Haskell modes. > | otherwise = Nothing > where > numeral Agda = Varid -> numeral Haskell = Numeral +> numeral _ = Numeral > classify s > | s `elem` keywords lang > = Keyword s > | otherwise = Varid s -> -> + +> hsOrAgda Haskell = True +> hsOrAgda Agda = True +> hsOrAgda OCaml = False + > lexFracExp :: String -> Maybe (String, String) > lexFracExp s = do t <- match "." s > (ds, u) <- lexDigits' t @@ -163,9 +181,9 @@ ks, 28.08.2008: New: Agda and Haskell modes. > lexDigits' s = do (cs@(_ : _), t) <- Just (span isDigit s); return (cs, t) > varsymid Agda = Varid -> varsymid Haskell = Varsym +> varsymid _ = Varsym > consymid Agda = Conid -> consymid Haskell = Consym +> consymid _ = Consym %} @@ -193,6 +211,49 @@ incorrectly reject programs that contain comments like the following one: {- start normal, but close as pragma #-} ... I don't expect this to be a problem, though. +> nestedOCaml :: Int -> String -> (String, String) +> nestedOCaml = go +> where +> go _ [] = ([], []) +> go 0 ('*' : ')' : s) = ([], '*':')':s) +> go (n+1) ('*' : ')' : s) = '*' <| ')' <| go n s +> go n ('(' : '*' : s) = '(' <| '*' <| go (n + 1) s +> go n (c : s) = c <| go n s + +fb, 2017-03-20: the quote character is used to prefix type +variables as well as for character literals. ocamlQuote +parses either the type variable up to the next non-identifer +character, or a character literal, up to the next quote +character. + +> ocamlQuote :: String -> (String, String) +> ocamlQuote [] = ([],[]) +> ocamlQuote ('\'' : s) = ([], '\'' : s) +> ocamlQuote ('\\' : c : '\'' : s) +> | ocamlEsc c = (['\\', c], '\'' : s) +> ocamlQuote ('\\' : a : b : c : '\'' : s) +> | all isDigit [a, b, c] = (['\\', a, b, c], '\'' : s) +> ocamlQuote ('\\' : 'x' : a : b : '\'' : s) +> | all isHexDigit [a, b] = (['\\', a, b], '\'' : s) +> ocamlQuote ('\\' : 'o' : a : b : c : '\'' : s) +> | isOctal a b c = (['\\', a, b, c], '\'' : s) +> ocamlQuote (c : '\'' : s) = ([c], '\'' : s) +> ocamlQuote (c : s) +> | isAlpha c || c == '_' = c <| ocamlIdent s +> ocamlQuote s = ([],s) +> ocamlIdent [] = ([],[]) +> ocamlIdent (c : s) +> | isIdChar OCaml c = c <| ocamlIdent s +> | otherwise = ([], c : s) + +Escape sequences for OCaml character literals. +[ocamlEsc c == True] iff ['\c'] is a valid character. + +> ocamlEsc :: Char -> Bool +> ocamlEsc c = c `elem` "\\\"'ntbr " + +> isOctal a b c = all isOctDigit [a,b,c] && read [a] <= 3 + > lexLitChar, lexLitStr :: String -> (String, String) > lexLitChar [] = ([], []) > lexLitChar ('\'' : s) = ([], '\'' : s) @@ -206,14 +267,14 @@ I don't expect this to be a problem, though. > isSpecial :: Lang -> Char -> Bool > isIdChar, isSymbol :: Lang -> Char -> Bool -> isSpecial Haskell c = c `elem` ",;()[]{}`" > isSpecial Agda c = c `elem` ";(){}" -> isSymbol Haskell c = not (isSpecial Haskell c) && notElem c "'\"" && +> isSpecial _ c = c `elem` ",;()[]{}`" +> isSymbol Agda c = isIdChar Agda c +> isSymbol _ c = not (isSpecial Haskell c) && notElem c "'\"" && > (c `elem` "!@#$%&*+./<=>?\\^|:-~" || > Data.Char.isSymbol c || Data.Char.isPunctuation c) -> isSymbol Agda c = isIdChar Agda c -> isIdChar Haskell c = isAlphaNum c || c `elem` "_'" > isIdChar Agda c = not (isSpecial Agda c || isSpace c) +> isIdChar _ c = isAlphaNum c || c `elem` "_'" > match :: String -> String -> Maybe String > match p s @@ -236,6 +297,17 @@ Keywords > "infixl", "infixr", "mutual", "abstract", > "private", "forall", "using", "hiding", > "renaming", "public" ] +> keywords OCaml = [ "and", "as", "assert", "asr", "begin", "class", +> "constraint", "do", "done", "downto", "else", +> "end", "exception", "external", "false", "for", +> "fun", "function", "functor", "if", "in", +> "include", "inherit", "initializer", "land", +> "lazy", "let", "lor", "lsl", "lsr", "lxor", +> "match", "method", "mod", "module", "mutable", +> "new", "nonrec", "object", "of", "open", "or", +> "private", "rec", "sig", "struct", "then", "to", +> "true", "try", "type", "val", "virtual", "when", +> "while", "with" ] % - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - - \subsubsection{Phase 2} @@ -349,12 +421,13 @@ an improvement. > catCode (Space _) = White > catCode (Conid _) = NoSep > catCode (Varid _) = NoSep +> catCode (Tyvarid _) = NoSep > catCode (Consym _) = Sep -- Sep is necessary for correct Haskell formatting > catCode (Varsym _) = Sep -- in Agda mode, Consym/Varsym don't occur > catCode (Numeral _) = NoSep > catCode (Char _) = NoSep > catCode (String _) = NoSep -> catCode (Special c) +> catCode (Special c) -- How can we deal with OCaml array brackets [| |] ? > | c `elem` "([{}])" = Del c > | otherwise = Sep @@ -376,4 +449,3 @@ This is related to the change above in function |string|. > token = id > inherit _ t = t > fromToken = id - diff --git a/src/Main.lhs b/src/Main.lhs index ee01d46..429a278 100644 --- a/src/Main.lhs +++ b/src/Main.lhs @@ -143,7 +143,7 @@ ks, 20.07.2003: The short option for @--align@ has been changed into @-A@. Other @-align@ would not trigger compatibility mode, but be interpreted as a valid option usage. -ks, 24.03.2004: The long option @--verbose@ has been removed for now, +ks, 24.03.2004: The long option @--verbose@ has been removed for now, because with some versions of GHC it triggers ambiguity errors with @--verb@. @@ -161,6 +161,7 @@ because with some versions of GHC it triggers ambiguity errors with > , Option [] ["verb"] (NoArg (return, id, [Verb])) "verbatim" > , Option [] ["haskell"] (NoArg (\s -> return $ s { lang = Haskell}, id, [])) "Haskell lexer (default)" > , Option [] ["agda"] (NoArg (\s -> return $ s { lang = Agda}, id, [])) "Agda lexer" +> , Option [] ["ocaml"] (NoArg (\s -> return $ s { lang = OCaml}, id, [])) "OCaml lexer" > , Option [] ["pre"] (NoArg (return, id, [Pre])) "act as ghc preprocessor" > , Option ['o'] ["output"] (ReqArg (\f -> (\s -> do h <- openOutputFile f > return $ s { output = h }, id, [])) "file") "specify output file" @@ -314,9 +315,9 @@ by another line and the included file does not end in a blank line, then there will not be a single space between the last character of the included file and the first character of the following line. It would be possible to split a TeX control sequence over two different files that way. Seems -strange. So we add a newline, or even two if none has been there before, +strange. So we add a newline, or even two if none has been there before, to make sure that exactly one linebreak ends up in the output, but not -more, as a double newline is interpreted as a \par by TeX, and that might +more, as a double newline is interpreted as a \par by TeX, and that might also not be desired. > format (Directive Begin _) = modify (\st -> st{stack = fmts st : stack st}) @@ -340,7 +341,7 @@ ks, 11.09.03: added exception handling for unbalanced grouping \NB @%align@ also resets the left identation stacks. -Also, the @poly@ directives @%separation@ and @%latency@ reset +Also, the @poly@ directives @%separation@ and @%latency@ reset the corresponding indentation stack |pstack|. > format (Directive Separation s ) @@ -543,7 +544,7 @@ This function can be used to stop all external processes by sending the > hFlush pin > waitForProcess pid) pis -To extract the answer from @ghci@'s or @hugs@' output +To extract the answer from @ghci@'s or @hugs@' output we use a simple technique which should work in most cases: we print the string |magic| before and after the expression we are interested in. We assume that everything @@ -586,4 +587,3 @@ and the second |magic| plus prompt is the result we look for. > | null d = "" > | otherwise = reverse d > where d = dropWhile (/= '/') (reverse filePath) - diff --git a/src/NewCode.lhs b/src/NewCode.lhs index ba731de..2d4215f 100644 --- a/src/NewCode.lhs +++ b/src/NewCode.lhs @@ -69,6 +69,7 @@ functionality is actually desired. > tex q (Conid s) = replace q s (sub'conid (q <> convert s)) > tex _ (Varid "") = sub'dummy -- HACK > tex q (Varid s) = replace q s (sub'varid (q <> convert s)) +> tex q (Tyvarid s) = replace q s (sub'tyvarid (q <> convert s)) > tex q (Consym s) = replace q s (sub'consym (q <> convert s)) > tex q (Varsym s) = replace q s (sub'varsym (q <> convert s)) > tex _ (Numeral s) = replace Empty s (sub'numeral (convert s)) -- NEU @@ -102,4 +103,3 @@ Conversion of strings and characters. > conv ' ' = sp > conv '\n' = nl > conv c = Text [c] - diff --git a/src/TeXCommands.lhs b/src/TeXCommands.lhs index 5d0fa21..0ab9654 100644 --- a/src/TeXCommands.lhs +++ b/src/TeXCommands.lhs @@ -19,7 +19,7 @@ These don't really belong into a module named TeXCommands: > data Style = Version | Help | SearchPath | Copying | Warranty | CodeOnly | NewCode | Verb | Typewriter | Poly | Math | Pre > deriving (Eq, Show, Enum, Bounded) -> data Lang = Haskell | Agda +> data Lang = Haskell | Agda | OCaml > deriving (Eq, Show, Enum, Bounded) \Todo{Better name for |Class|.} @@ -74,7 +74,7 @@ Encoding and decoding of commands, environments, and directives. > ("pre", Pre), ("version", Version), > ("copying", Copying), ("warranty", Warranty), ("help", Help), ("searchpath", SearchPath) ] > instance Representation Lang where -> representation = [ ("haskell", Haskell), ("agda", Agda) ] +> representation = [ ("haskell", Haskell), ("agda", Agda), ("ocaml", OCaml) ] > instance Representation Command where > representation = [ ("hs", Hs), ("eval", Eval), > ("perform", Perform), ("verb*", Vrb True), diff --git a/src/Typewriter.lhs b/src/Typewriter.lhs index aa4f06c..b0681c4 100644 --- a/src/Typewriter.lhs +++ b/src/Typewriter.lhs @@ -48,6 +48,7 @@ > tex q (Conid s) = replace q s (sub'conid (q <> convert False s)) > tex _ (Varid "") = sub'dummy -- HACK > tex q (Varid s) = replace q s (sub'varid (q <> convert False s)) +> tex q (Tyvarid s) = replace q s (sub'tyvarid (q <> convert False s)) > tex q (Consym s) = replace q s (sub'consym (q <> convert False s)) > tex q (Varsym s) = replace q s (sub'varsym (q <> convert False s)) > tex _ (Numeral s) = replace Empty s (sub'numeral (convert True s)) -- NEU