# This for weave
token @ category binop translation <"\\ATSIGN">
 From leavens@cs.iastate.edu Wed Mar 11 20:35:11 1992
Received: from Princeton.EDU (Princeton.EDU.) by fs.Princeton.EDU (4.0/1.105)
	id AA20432; Wed, 11 Mar 92 20:35:09 EST
Received: from flash.cs.iastate.edu by Princeton.EDU (5.65b/2.86/princeton)
	id AA26935; Wed, 11 Mar 92 20:34:59 -0500
Received: from bambam.cs.iastate.edu by flash.cs.iastate.edu with SMTP
	(16.7/16.2) id AA24210; Wed, 11 Mar 92 19:34:50 -0600
Received: by bambam.cs.iastate.edu (4.1/SMI-4.1)
	id AA29309; Wed, 11 Mar 92 19:34:49 CST
Date: Wed, 11 Mar 92 19:34:49 CST
From: leavens@cs.iastate.edu (Gary Leavens)
Message-Id: <9203120134.AA29309@bambam.cs.iastate.edu>
To: nr@Princeton.EDU
In-Reply-To: Norman Ramsey's message of Wed, 11 Mar 92 18:12:19 -0500 <9203112312.AA02296@cs.Princeton.EDU>
Subject:  Literate programming for SML?
Status: RO

Norman,
	I read your TOSE paper on noweb, and all I can say is: hooray!
Really, for giving students an introduction to literate programming,
and for getting started in a new language, etc., it seems like a great
idea.  I guess I'm just echoing the points you make in the paper, but I've
been trying to think of how to make some literate programming stuff available
to graduate students, and this seems like it has more of a chance of catching
on than anything else.

	As far as sml.spider goes, I had not planned on worrying about infix
for a while...  I haven't done a lot of programming in SML, do you find you
use infix signficantly?  Perhaps it's a personal style thing.

	I'm very happy to send you the sml.spider file, which follows.
The main problem I'm having with it at the moment is that in the formatting
I don't get anything combined in a big math format, instead I get lots of
little math shifts, which causes code to look pretty ugly.  But I'm sure
you would see many, many other problems.  My basic approach, which may not
be a good one, was to type in the grammar from the defintion of SML,
making changes along the way to make it left recursive, and adding context
and some formatting stuff.  Clearly it needs work.  So if you'd like to build
on that base, please do so...  Anyway, the file follows.
	Gary

# sml.spider
# AUTHOR: Gary T. Leavens

language SML extension sml version 1.4

at_sign @

comment begin <"(*"> end <"*)">

line begin <"(*"-space-"line"> end <"*)">

default mathness yes
default translation <*>

token identifier category id
token number category scon
token newline category ignore_scrap mathness maybe translation <>
token pseudo_semi category semi mathness maybe translation <force>

# web's idea of modules...
module definition topdec use id


# nonfix functions in standard basis
ilk functions category unop

reserved map ilk functions
reserved rev ilk functions
reserved not ilk functions
token ~ category unop translation <"\\TI"> mathness yes
reserved abs ilk functions
reserved floor ilk functions
reserved real ilk functions
reserved sqrt ilk functions
reserved sin ilk functions
reserved cos ilk functions
reserved arctan ilk functions
reserved exp ilk functions
reserved ln ilk functions
reserved size ilk functions
reserved chr ilk functions
reserved ord ilk functions
reserved explode ilk functions
reserved implode ilk functions
token ! category unop translation <*>
reserved ref ilk functions

# constants in the standard basis
ilk constants category con

reserved true ilk constants
reserved false ilk constants
reserved nil ilk constants

# infix functions in the standard basis
ilk infixfun category binop

# precedence 7
token / category binop
reserved div ilk infixfun
reserved mod ilk infixfun
token * category star translation <"\\times">
# precedence 6
token + category binop
token - category binop
token ^ category binop
# precedence 5
token :: category binop
token @ category binop
# precedence 4
token = category equals
token <> category binop translation <"\\I">
token < category binop
token > category binop
token <= category binop translation <"\\L">
token >= category binop translation <"\\G">
# precedence 3
token := category binop translation <"\\leftarrow">
ilk compose category binop translation <"\\circ">
reserved o ilk compose

default translation <*-"\\"-space>

# core ilks
ilk abstype_like category abstype
ilk and_like category and
ilk andalso_like category andalso
ilk as_like category as
ilk case_like category case
ilk do_like category do
ilk datatype_like category datatype
ilk else_like category else
ilk end_like category end
ilk exception_like category exception
ilk fn_like category fn
ilk fun_like category fun
ilk handle_like category handle
ilk if_like category if
ilk in_like category in
ilk infix_like category infix
ilk let_like category let
ilk local_like category local
ilk nonfix_like category nonfix
ilk of_like category of
ilk op_like category op
ilk open_like category open
ilk orelse_like category orelse
ilk raise_like category raise
ilk rec_like category rec
ilk then_like category then
ilk type_like category type
ilk val_like category val
ilk with_like category with
ilk withtype_like category withtype
ilk while_like category while

# modules ilks
ilk eqtype_like category  eqtype
ilk functor_like category  functor
ilk include_like category  include
ilk sharing_like category  sharing
ilk sig_like category  sig
ilk signature_like category  signature
ilk struct_like category  struct
ilk structure_like category  structure
ilk use_like category use

default translation <*>

# core reserved words
reserved abstype ilk abstype_like
reserved and ilk and_like
reserved andalso ilk andalso_like
reserved as ilk as_like
reserved case ilk case_like
reserved do ilk do_like
reserved datatype ilk datatype_like
reserved else ilk else_like
reserved end ilk end_like
reserved exception ilk exception_like
reserved fn ilk fn_like
# reserved fn translation <\\lambda>
reserved fun ilk fun_like
reserved handle ilk handle_like
reserved if ilk if_like
reserved in ilk in_like
reserved infix ilk infix_like
reserved infixr ilk infix_like
reserved let ilk let_like
reserved local ilk local_like
reserved nonfix ilk nonfix_like
reserved of ilk of_like
reserved op ilk op_like
reserved open ilk open_like
reserved orelse ilk orelse_like
reserved raise ilk raise_like
reserved rec ilk rec_like
reserved then ilk then_like
reserved type ilk type_like
reserved val ilk val_like
reserved with ilk with_like
reserved withtype ilk withtype_like
reserved while ilk while_like

# modules reserved words
reserved eqtype ilk  eqtype_like
reserved functor ilk  functor_like
reserved include ilk  include_like
reserved sharing ilk  sharing_like
reserved sig ilk  sig_like
reserved signature ilk  signature_like
reserved struct ilk  struct_like
reserved structure ilk  structure_like
reserved use ilk use_like

token ( category lparen
token ) category rparen
token [ category lsqbracket
token ] category rsqbracket
token { category lcurly translation <"\\{">
token } category rcurly translation <"\\}">
token , category comma translation <",\\,">
token : category colon
token ; category semi
token ... category dotdotdot translation <"\\ldots">
token | category vertbar
token => category reducesto translation <"\\Rightarrow">
token -> category arrow translation <"\\rightarrow">
token # category sharp translation <"\\#"> 
token . category dot
token ' category prime


# 
? ignore_scrap --> #1

# lexical rules
id --> longvar
longvar dot id --> longvar
longvar dot con --> longvar
longvar prime --> longvar

prime id --> tyvar
prime tyvar --> tyvar

# core language syntax
scon --> atexp
longvar --> atexp
unop --> atexp
op (longvar|binop|equals|star|unop) --> atexp
lcurly exprow rcurly --> atexp
sharp id --> atexp
lparen rparen --> atexp
lparen <indent> exptupling <outdent> rparen --> atexp
lsqbracket rsqbracket --> atexp
lsqbracket <indent> explist <outdent> rsqbracket --> atexp
lparen expblock rparen --> atexp
let dec in exp end --> atexp
lparen exp rparen --> atexp

exp comma <opt-9> exp --> exptupling
exptupling comma <opt-9> exp --> exptupling

exp semi <opt-1> exp --> expblock
expblock semi <opt-1> exp --> expblock

lsqbracket [ exp ] --> lsqbracket explist
lsqbracket [ explist comma <opt-9> exp ] --> lsqbracket explist

id equals exp --> exprow
exprow comma <opt-8> id equals exp --> exprow

atexp --> appexp
appexp <"\\"-space> atexp --> appexp

appexp --> infexp
infexp (binop|equals|star) infexp --> infexp

infexp --> exp
exp colon ty --> exp
exp andalso exp --> exp
exp orelse exp --> exp
exp handle <indent> match <outdent> --> exp
raise exp --> exp
if exp <opt-2> then <indent> exp <outdent-opt-1> else <indent> exp <outdent> --> exp
while exp do <indent> exp <outdent> --> exp
case exp of <indent> match <outdent> --> exp
fn <indent> match <outdent> --> exp

mrule --> match
match vertbar mrule --> match

pat reducesto exp --> mrule

val valbind* --> dec
fun fvalbind* --> dec
type typbind* --> dec
datatype datbind* --> dec
datatype datbind* <force> withtype typbind --> dec
abstype datbind* <force> with dec end --> dec
abstype datbind* <force> withtype typbind <force> with dec end --> dec
exception exbind* --> dec
local <opt-1-indent> dec <outdent-opt-1> in <opt-1-indent> dec <outdent-opt-1> end --> dec
open longvarlist --> dec
dec <force> dec --> dec
dec semi <force> dec --> dec
infix scon idlist --> dec
infix idlist --> dec
nonfix idlist --> dec

open [ longvar ] --> open longvarlist
open [ longvarlist longvar ] --> open longvarlist

(infix|nonfix|include) [ id ] --> (infix|nonfix|include) idlist
(infix|nonfix|include) [ idlist id ] --> (infix|nonfix|include) idlist
infix scon [ id ] --> infix scon idlist
infix scon [ idlist id ] --> infix scon idlist

pat* equals exp --> valbind
valbind and pat* equals exp --> valbind
rec valbind* --> valbind

fun [ op id* atpatlist colon ty equals <opt-2-indent> exp <outdent> ] --> fun prefvalbind
fun [ id* atpatlist colon ty equals <opt-2-indent> exp <outdent> ] --> fun prefvalbind
fun [ prefvalbind vertbar op id atpatlist colon ty equals <opt-2-indent> exp <outdent> ] --> fun prefvalbind
fun [ prefvalbind vertbar id atpatlist colon ty equals <opt-2-indent> exp <outdent> ] --> fun prefvalbind
fvalbind and [ op id* atpatlist colon ty equals <opt-2-indent> exp <outdent> ] --> fvalbind and prefvalbind
fvalbind and [ vertbar id* atpatlist colon ty equals <opt-2-indent> exp <outdent> ] --> fvalbind and prefvalbind
fvalbind and [ prefvalbind vertbar op id atpatlist colon ty equals <opt-2-indent> exp <outdent> ] --> fvalbind and prefvalbind
fvalbind and [ prefvalbind vertbar id atpatlist colon ty equals <opt-2-indent> exp <outdent> ] --> fvalbind and prefvalbind

fun [ prefvalbind ] (and|semi) --> fun fvalbind (and|semi)
fun [ fvalbind and prefvalbind ] --> fun fvalbind

(fun|vertbar) op id [ atpat ] --> (fun|vertbar) op id atpatlist
(fun|vertbar) op id [ atpatlist atpat ] --> (fun|vertbar) op id atpatlist
(fun|vertbar) id [ atpat ] --> (fun|vertbar) id atpatlist
(fun|vertbar) id [ atpatlist atpat ] --> (fun|vertbar) id atpatlist

tyvarseq longvar* equals ty --> typbind
typbind and tyvarseq longvar* equals ty --> typbind

type [ tyvar ] --> type tyvarseq
type [  ] --> type tyvarseq
type lparen [ tyvarseq comma tyvar ] --> type lparen tyvarseq
type [ lparen tyvarseq rparen ] --> type tyvarseq
datatype [ tyvar ] --> datatype tyvarseq
datatype [  ] --> datatype tyvarseq
datatype lparen [ tyvarseq comma tyvar ] --> datatype lparen tyvarseq
datatype [ lparen tyvarseq rparen ] --> datatype tyvarseq
abstype [ tyvar ] --> abstype tyvarseq
abstype [  ] --> abstype tyvarseq
abstype lparen [ tyvarseq comma tyvar ] --> abstype lparen tyvarseq
abstype [ lparen tyvarseq rparen ] --> abstype tyvarseq
typbind and [ tyvar ] --> typbind and tyvarseq
typbind and [  ] --> typbind and tyvarseq
typbind and lparen [ tyvarseq comma tyvar ] --> typbind and lparen tyvarseq
typbind and [ lparen tyvarseq rparen ] --> typbind and tyvarseq

tyvarseq longvar* equals conbind --> datbind
datbind and tyvarseq longvar* equals conbind --> datbind

datatype tyvarseq id equals [ op id* of ty ] --> datatype tyvarseq id equals conbind
datatype tyvarseq id equals [ op id* ] --> datatype tyvarseq id equals conbind
datatype tyvarseq id equals [ id* of ty ] --> datatype tyvarseq id equals conbind
datatype tyvarseq id equals [ id* ] --> datatype tyvarseq id equals conbind

conbind and op id* of ty --> conbind
conbind and op id* --> conbind
conbind and id* of ty  --> conbind
conbind and id* --> conbind

exception [ op id* of ty ] --> exception exbind
exception [ op id* ] --> exception exbind
exception [ id* of ty ] --> exception exbind
exception [ id* ] --> exception exbind
exception [ op id* equals op longvar ] --> exception exbind
exception [ op id* equals longvar ] --> exception exbind
exception [ id* equals op longvar ] --> exception exbind
exception [ id* equals longvar ] --> exception exbind

exbind and op id* of ty --> exbind
exbind and op id* --> exbind
exbind and id* of ty --> exbind
exbind and id* --> exbind
exbind and op id* equals op longvar --> exbind
exbind and op id* equals longvar --> exbind
exbind and id* equals op longvar --> exbind
exbind and id* equals longvar --> exbind

longvar --> atpat
scon --> atpat
op (longvar|unop) --> atpat
lcurly patrow rcurly --> atpat
lparen rparen --> atpat
lparen pattupling rparen --> atpat
lsqbracket rsqbracket --> atpat
lparen pat rparen --> atpat

pat comma pat --> pattupling
pattupling comma pat --> pattupling

lsqbracket [ pat ] --> lsqbracket patlist
lsqbracket [ patlist comma pat ] --> lsqbracket patlist

dotdotdot --> patrow
id equals pat --> patrow
id colon ty as pat  --> patrow
id as pat --> patrow
id colon ty  --> patrow
patrow comma id equals pat --> patrow
patrow comma id colon ty as pat --> patrow
patrow comma id as pat --> patrow
patrow comma id colon ty --> patrow

atpat --> pat
op longvar atpat --> pat
longvar atpat --> pat
pat (binop|equals|star) pat --> pat
pat colon ty --> pat
op id colon ty as pat --> pat
op id as pat --> pat
id colon ty as pat --> pat
id as pat --> pat

tyvar --> ty
lcurly tyrow rcurly --> ty
longvar --> ty
lparen ty rparen longvar --> ty
lparen tyseq rparen longvar --> ty
tytuple --> ty
ty arrow ty --> ty
lparen ty rparen --> ty

lparen [ ty comma ] --> lparen tyseq
tyseq comma ty --> tyseq

id colon ty --> tyrow
tyrow comma id colon ty --> tyrow

ty star ty --> tytuple
tytuple star ty --> tytuple


# modules, with permissive syntax
#struct strdec end --> strexp
struct <opt-1-indent> dec <outdent-opt-1> end --> exp

# whereever the SML grammar has strdec, have to use dec too
structure strbind --> dec

structure [ id* colon sigexp equals <opt-1-indent> exp <outdent-opt-1> ] --> structure strbind
structure [ id* colon id equals <opt-1-indent> exp <outdent-opt-1> ] --> structure strbind
structure [ id* equals <opt-1-indent> exp <outdent-opt-1> ] --> structure strbind
strbind <force> and id* colon sigexp equals <opt-1-indent> exp <outdent-opt-1> --> strbind
strbind <force> and id* colon id equals <opt-1-indent> exp <outdent-opt-1> --> strbind
strbind <force> and id* equals <opt-1-indent> exp <outdent-opt-1> --> strbind

# whereever the SML grammar has sigexp, have to use id too
sig <opt-1-indent> spec <outdent-opt-1> end --> sigexp

signature sigbind --> sigdec
sigdec <force> sigdec --> sigdec
sigdec semi <force> sigdec --> sigdec

signature [ id* equals <opt-1-indent> sigexp <outdent> ] --> signature sigbind
signature [ id* equals id ] --> signature sigbind
sigbind <force> and id* equals <opt-1-indent> sigexp <outdent> --> sigbind
sigbind <force> and id* equals id --> sigbind

val valdesc --> spec
type typdesc --> spec
eqtype typdesc --> spec
datatype datdesc --> spec
exception exdesc --> spec
structure strdesc --> spec
sharing shareq --> spec
local spec in spec end --> spec
open longvarlist --> spec
include idlist --> spec
sig [ ] end --> sig spec end
spec <force> spec --> spec
spec semi spec --> spec

val [ id* colon ty ] --> val valdesc
valdesc <opt-1> and id* colon ty --> valdesc

type [ tyvarseq id* ] --> type typdesc
typdesc <opt-1> and tyvarseq id* --> typdesc

typdesc and [ tyvar ] --> typdesc and tyvarseq
typdesc and [  ] --> typdesc and tyvarseq
typdesc and lparen [ tyvarseq comma tyvar ] --> typdesc and lparen tyvarseq
typdesc and [ lparen tyvarseq rparen ] --> typdesc and tyvarseq

tyvarseq id* equals condesc --> datdesc
datdesc <opt-1> and tyvarseq id* equals condesc --> datdesc

datatype tyvarseq id equals [ id* of ty ] --> datatype tyvarseq id equals condesc
datatype tyvarseq id equals [ id* ] --> datatype tyvarseq id equals condesc

condesc <opt-1> and id* of ty  --> condesc
condesc <opt-1> and id* --> condesc

exception [ id* of ty ] --> exception exdesc
exception [ id* ] --> exception exdesc

exdesc <opt-1> and id* of ty --> exdesc
exdesc <opt-1> and id* --> exdesc

structure [ id* colon sigexp ] --> structure strdesc
structure [ id* colon id ] --> structure strdesc
strdesc <opt-1> and id* colon sigexp --> strdesc
strdesc <opt-1> and id* colon id --> strdesc

sharing [ longvar equals longvar ] --> sharing shareq
shareq equals longvar --> shareq
sharing type [ longvar equals longvar ] --> sharing type shareq
shareq equals longvar --> shareq
shareq <opt-1> and longvar equals longvar --> shareq
shareq <opt-1> and type longvar equals longvar --> shareq

functor funbind --> fundec
fundec <force> fundec --> fundec
fundec semi fundec --> fundec

functor [ id* lparen id colon sigexp rparen colon sigexp equals <force-indent> exp ] --> functor funbind
functor [ id* lparen id colon sigexp rparen equals <force-indent> exp ] --> functor funbind
funbind <opt-1> and id* lparen id colon sigexp rparen colon sigexp equals <force-indent> exp --> funbind
funbind <opt-1> and id* lparen id colon sigexp rparen equals <force-indent> exp --> funbind

sigdec --> topdec
fundec --> topdec
dec --> topdec
use scon --> topdec


topdec <force> topdec --> topdec
topdec semi <force> topdec --> topdec

macros begin
\let\LN\langle
\let\RN\rangle
macros end

