%
% $Header: /home/cvs/root/haskell-report/report/syntax-iso.verb,v 1.12 2003/01/13 13:08:56 simonpj Exp $
%
%**<title>Haskell 98 Syntax</title>
%**~header
\section{Syntax Reference}
\label{syntax}
\index{syntax}

\subsection{Notational Conventions}

These notational conventions are used for presenting syntax:

\[\ba{cl}
"[pattern]"		& \tr{optional} \\
"\{pattern\}"		& \tr{zero or more repetitions} \\
"(pattern)"		& \tr{grouping} \\
"pat_1 | pat_2"		& \tr{choice} \\
"pat_{\langle{}pat'\rangle{}}"	& \tr{difference---elements generated by "pat"} \\
			& \tr{except those generated by "pat'"} \\
"@fibonacci@"		& \tr{terminal syntax in typewriter font}
\ea\]

BNF-like syntax is used throughout, with productions having the form:
@@@
nonterm		-> alt_1 | alt_2 | ... | alt_n
@@@

There are some families of nonterminals indexed by
precedence levels (written as a superscript).  Similarly, the
nonterminals "op", "varop", and "conop" may have a double index:
a letter "l", "r", or "n" for left-, right- or nonassociativity and
a precedence level.  A precedence-level variable "i" ranges from 0 to 9;
an associativity variable "a" varies over "\{l, r, n\}".
Thus, for example
@@@
aexp	->  @(@ exp^{i+1} qop^{(a,i)} @)@
@@@
actually stands for 30 productions, with 10 substitutions for "i"
and 3 for "a".

In both the lexical and the context-free syntax, there are some
ambiguities that are to be resolved by making grammatical phrases as
long as possible, proceeding from left to right (in shift-reduce
parsing, resolving shift/reduce conflicts by shifting).  In the lexical
syntax, this is the ``maximal munch'' rule\index{maximal munch rule}.  In the
context-free syntax, this means that conditionals, let-expressions, and
lambda abstractions extend to the right as far as possible.

% here we input a list of the main changes in version 1.1
% \input{syntax-changes-11}

%*anchor on
\subsection{Lexical Syntax}

% This covers only part of the lexical syntax.  The rest is directly
% included since it is much more scattered.

\input{syntax-lexical}

@@@
varid	-> (small \{small | large | digit | @'@ \})_{\langle{}reservedid\rangle{}}
conid		-> large \{small | large | digit | @'@ \} 
reservedid -> @case@ | @class@ | @data@ | @default@ | @deriving@ | @do@ | @else@
	| @if@ | @import@ | @in@ | @infix@ | @infixl@ | @infixr@ | @instance@
	| @let@ | @module@ | @newtype@ | @of@ | @then@ | @type@ | @where@ | @_@

varsym		-> ( symbol \{symbol | @:@\} )_{\langle{}reservedop | dashes\rangle{}}
consym		-> (@:@ \{symbol | @:@\})_{\langle{}reservedop\rangle{}}
reservedop	-> @..@ | @:@ | @::@ | @=@ | @\@ | @|@ | @<-@ | @->@ | {\tt @@} | @~@ | @=>@

varid			&& (\tr{variables})
conid			&& (\tr{constructors})
tyvar	->  varid	& (\tr{type variables})
tycon	->  conid 	& (\tr{type constructors})
tycls	->  conid 	& (\tr{type classes})
modid   ->  conid	& (\tr{modules})

qvarid   -> [ modid @.@ ] varid
qconid   -> [ modid @.@ ] conid
qtycon   -> [ modid @.@ ] tycon
qtycls   -> [ modid @.@ ] tycls
qvarsym  -> [ modid @.@ ] varsym
qconsym  -> [ modid @.@ ] consym

decimal		-> digit\{digit\}
octal		-> octit\{octit\}
hexadecimal	-> hexit\{hexit\}

integer		-> decimal
                |  @0o@ octal | @0O@ octal
                |  @0x@ hexadecimal | @0X@ hexadecimal
float		-> decimal @.@ decimal [exponent]
	        |  decimal exponent
exponent	-> (@e@ | @E@) [@+@ | @-@] decimal

char    ->  @'@ (graphic_{\langle{}@'@ | @\@\rangle{}} | space | escape_{\langle{}@\&@\rangle{}}) @'@
string  ->  @"@ \{graphic_{\langle{}@"@  | @\@\rangle{}} | space | escape | gap\} @"@
escape  ->  @\@ ( charesc | ascii | decimal | @o@ octal | @x@ hexadecimal )
charesc -> @a@ | @b@ | @f@ | @n@ | @r@ | @t@ | @v@ | @\@ | @"@ | @'@ | @&@
ascii   -> @^@cntrl | @NUL@ | @SOH@ | @STX@ | @ETX@ | @EOT@ | @ENQ@ | @ACK@ 
       | @BEL@ | @BS@ | @HT@ | @LF@ | @VT@ | @FF@ | @CR@ | @SO@ | @SI@ | @DLE@ 
       | @DC1@ | @DC2@ | @DC3@ | @DC4@ | @NAK@ | @SYN@ | @ETB@ | @CAN@ 
       | @EM@ | @SUB@ | @ESC@ | @FS@ | @GS@ | @RS@ | @US@ | @SP@ | @DEL@
cntrl   -> ascLarge | @@ | @[@ | @\@ | @]@ | @^@ | @_@
gap     ->  @\@ whitechar \{whitechar\} @\@
@@@
\indexsyn{varid}%
\indexsyn{conid}%
\indexsyn{reservedid}%
\indexsyn{varsym}%
\indexsyn{consym}%
\indexsyn{symbol}%
\indexsyn{reservedop}%
\indexsyn{tyvar}%
\indexsyn{tycon}%
\indexsyn{tycls}%
\indexsyn{modid}%
\indexsyn{qvarid}%
\indexsyn{qconid}%
\indexsyn{qtycon}%
\indexsyn{qtycls}%
\indexsyn{qvarsym}%
\indexsyn{qconsym}%
\indexsyn{decimal}%
\indexsyn{octal}%
\indexsyn{hexadecimal}%
\indexsyn{char}%
\indexsyn{string}%
\indexsyn{escape}%
\indexsyn{charesc}%
\indexsyn{ascii}%
\indexsyn{cntrl}%
\indexsyn{gap}%


\subsection{Layout}
\label{layout}
\index{layout}

Section~\ref{lexemes-layout} gives an informal discussion of the layout
rule. This section defines it more precisely.

The meaning of a Haskell program may depend on its {\em layout}.
The effect of layout on its meaning can be completely described by adding
braces and semicolons in places determined by the layout.  The meaning of
this augmented program is now layout insensitive.

The effect of layout is specified in this section by describing
how to add braces and semicolons to a laid-out program.  The specification
takes the form of a function "L" that performs the translation.
The input to "L" is:
\begin{itemize}
\item 
A stream of lexemes as specified by the lexical syntax in the Haskell report,
with the following additional tokens: 
\begin{itemize}
\item If a @let@, @where@, @do@, or @of@ keyword is not followed by the lexeme @{@, 
the token "\{n\}" is inserted after the keyword, where "n" is the indentation of the 
next lexeme if there is one, or "0" if the end of file has been reached.
\item If the first lexeme of a module is not @{@ or @module@, 
then it is preceded by "\{n\}" where "n" is the indentation of the lexeme. 
\item Where the start of a lexeme is preceded only by white space on the
   same line, this lexeme is preceded by "<n>" where "n"
   is the indentation of the lexeme, provided that it is not,
   as a consequence of the first two rules, preceded by "\{n\}".
   (NB: a string literal may span multiple lines -- Section~\ref{lexemes-char}.  So in the fragment
\bprog
@
  f = ("Hello \
          \Bill", "Jake")
@
\eprog
There is no "<n>" inserted before the "@\Bill@", because it is not the beginning of
a complete lexeme; nor before the "@,@", because it is not preceded only by white space.)
\end{itemize}

\item A stack of ``layout contexts'', in which each element is either:
\begin{itemize}
\item Zero, indicating that the enclosing context is explicit (i.e. the programmer 
supplied the opening brace. 
If the innermost context is 0, then no layout tokens will be inserted 
until either the enclosing context ends or a new context is pushed. 
\item A positive integer, which is the indentation column of the enclosing layout context. 
\end{itemize}
\end{itemize}

The ``indentation'' of a lexeme is the column number
of the first character of that lexeme; the indentation of a line is the
indentation of its leftmost lexeme.  To determine the column number,
assume a fixed-width font with the following conventions:
\begin{itemize}
\item The characters "newline", "return", "linefeed", and "formfeed", all start a new line.
\item The first column is designated column 1, not 0.
\item Tab stops are 8 characters apart.
\item A tab character causes the insertion of
enough spaces to align the current position with the next tab stop.
\end{itemize}
For the purposes of the layout rule, Unicode characters in a source program
are considered to be of the same, fixed, width as an ASCII character.
However, to avoid visual confusion, programmers should avoid writing programs in which 
the meaning of implicit layout depends on the width of non-space characters.

The application
\[
L~tokens~[]
\]
delivers a layout-insensitive translation of "tokens", where "tokens"
is the result of lexically analysing a module and adding column-number
indicators to it as described above.
The definition of "L" is as follows, where we use ``":"'' as a stream
construction operator, and ``"\emptystr"'' for the empty stream.
% \begin{center}
% \[\ba{lcll}
%      L~ (<n>:ts)~ (m:ms)   & = & @;@ ~:~ (L~ ts~(m:ms))           &\mbox{if}~ m = n \\
%                            & = & @}@ ~:~ (L~ (<n>:ts)~ ms)       & \mbox{if}~ n < m \\
%                            & = & L~ ts~(m:ms)                   & \mbox{otherwise} \\
% \\
%      L~ (\{n\}:ts)~ (m:ms)   & = & @{@ ~:~ (L~ ts~(n:m:ms))         & \mbox{if}~n > m~   (Note~ 1)\\
% 			     & = & @{@ ~:~ @}@ ~:~  (L~ ts~(<n>:m:ms))	& \mbox{otherwise}~   (Note~ 2)\\
% \\
%      L~ (t:ts)~ (m:ms)       & = & @}@ ~:~ (L~ (t:ts)~ ms)           & \mbox{if}~ m /= 0 ~\mbox{and}~ \mbox{parse-error}(t) \\
% 			    &&& (Note~ 3) \\
% \\
%      L~ (@}@:ts)~ (0:ms)     & = & @}@ ~:~ (L~ ts~ms)     &                       (Note~ 4) \\
% \\
%      L~ (@{@:ts)~ ms         & = & @{@ ~:~ (L~ ts~(0:ms))                   &     (Note~ 5)\\
% \\
%      L~ (t:ts)~ ms           & = & t ~:~ (L~ ts~ms)\\
% \\
%      L~ \emptystr~ [0]		   & = & \emptystr\\
%      L~ \emptystr~ (m:ms)	   & = & @}@ ~:~ L~ \emptystr~ ms	   & \mbox{if}~m \neq 0~  (Note~ 6)
% \ea\]
% \end{center}
\begin{center}
\[\ba{lcll}
     L~ (<n>:ts)~ (m:ms)   & = & @;@ ~:~ (L~ ts~(m:ms))           &\mbox{if}~ m = n \\
                           & = & @}@ ~:~ (L~ (<n>:ts)~ ms)       & \mbox{if}~ n < m \\
     L~ (<n>:ts)~ms        & = & L~ ts~ms \\
\\
     L~ (\{n\}:ts)~ (m:ms)   & = & @{@ ~:~ (L~ ts~(n:m:ms))      & \mbox{if}~n > m~   (Note~ 1)\\
     L~ (\{n\}:ts)~ []       & = & @{@ ~:~ (L~ ts~[n])           & \mbox{if}~n > 0~   (Note~ 1)\\
     L~ (\{n\}:ts)~ ms 	     & = & @{@ ~:~ @}@ ~:~  (L~ (<n>:ts)~ms) & (Note~ 2)\\
\\
     L~ (@}@:ts)~ (0:ms)     & = & @}@ ~:~ (L~ ts~ms)     	& (Note~ 3) \\
     L~ (@}@:ts)~ ms         & = & \mbox{parse-error}	 	& (Note~ 3) \\
     
\\
     L~ (@{@:ts)~ ms         & = & @{@ ~:~ (L~ ts~(0:ms))       &     (Note~ 4)\\
\\
     L~ (t:ts)~ (m:ms)       & = & @}@ ~:~ (L~ (t:ts)~ ms)      & \mbox{if}~ m /= 0 ~\mbox{and}~ \mbox{parse-error}(t) \\
								    &&& (Note~ 5) \\
     L~ (t:ts)~ ms           & = & t ~:~ (L~ ts~ms)\\
\\
     L~ \emptystr~ []		   & = & \emptystr\\
     L~ \emptystr~ (m:ms)	   & = & @}@ ~:~ L~ \emptystr~ ms	   & \mbox{if}~m \neq 0~  (Note~ 6)
\ea\]
\end{center}
\begin{description}
\item[Note 1.] A nested context must be further indented 
than the enclosing context ("n>m"). If not, "L" fails, and the compiler should indicate a
layout error.  An example is:
\bprog
@
  f x = let
           h y = let
    p z = z
                 in p
        in h
@
\eprog
Here, the definition of @p@ is indented less than the indentation of
the enclosing context, which is set in this case by the definition of @h@.

\item[Note 2.] If the first token after a @where@ (say) is not indented more
than the enclosing layout context, then the block must be empty, so empty
braces are inserted.  The $\{n\}$ token is replaced by $<n>$, to mimic the
situation if the empty braces had been explicit.

\item[Note 3.] By matching against 0 for the current layout context, 
we ensure that an explicit close brace can only match an explicit open brace. 
A parse error results if an explicit close brace matches an implicit open brace.

\item[Note 4.] This clause means that all brace pairs are treated as explicit layout 
contexts, including labelled construction and update (Section~\ref{field-ops}). 
This is a difference between this formulation and Haskell 1.4.

\item[Note 5.] The side condition "\mbox{parse-error}(t)" is to be interpreted as follows: 
if the tokens generated so far by "L" together with the next token "t" 
represent an invalid prefix of the Haskell grammar, and the 
tokens generated so far by "L" followed by the token ``@}@''
represent a valid prefix of the Haskell grammar, then "\mbox{parse-error}(t)" is true. 

The test $m /= 0$ checks that an implicitly-added closing brace would match
an implicit open brace.

\item[Note 6.] At the end of the input, any pending close-braces are inserted. 
It is an error at this point to be within a non-layout context (i.e.~ "m = 0"). 
\end{description}

If none of the rules given above matches, then the algorithm fails. It
can fail for instance when the end of the input is reached, and a
non-layout context is active, since the close brace is missing. Some
error conditions are not detected by the algorithm, although they
could be: for example @let }@.

Note 1 implements the feature that layout processing can be stopped
prematurely by a parse error.  For example
\bprog
@
        let x = e; y = x in e'
@
\eprog
is valid, because it translates to 
\bprog
@
        let { x = e; y = x } in e'
@
\eprog
The close brace is inserted due to the parse error rule above.
The parse-error rule is hard to implement in its full generality, because 
doing so involves fixities.  For example, the expression
\bprog
@
  do a == b == c
@
\eprog
has a single unambiguous (albeit probably type-incorrect) parse, namely
\bprog
@
  (do { a == b }) == c
@
\eprog
because @(==)@ is non-associative.   Programmers are therefore advised to avoid
writing code that requires the parser to insert a closing brace in such
situations.


\startnewsection
\subsection{Literate comments}
\label{literate}
\index{literate comments}

The ``literate comment''
convention, first developed by Richard Bird and Philip Wadler for
Orwell, and inspired in turn by Donald Knuth's ``literate
programming'', is an alternative style for encoding \Haskell{} source
code. 
The literate style encourages comments by making them the default.  A
line in which ``@>@'' is the first character is treated as part of the
program; all other lines are comment.

The program text is recovered
by taking only those lines beginning with ``@>@'', 
and replacing the leading ``@>@'' with a space.
Layout and comments apply
exactly as described in Chapter~\ref{syntax} in the resulting text.

To capture some cases where one omits an ``@>@'' by mistake, it is an
error for a program line to appear adjacent to a non-blank comment line,
where a line is taken as blank if it consists only of whitespace.

By convention, the style of comment is indicated by the file
extension, with ``@.hs@'' indicating a usual Haskell file and
``@.lhs@'' indicating a literate Haskell file.  Using this style, a
simple factorial program would be:
\bprog
@
   This literate program prompts the user for a number
   and prints the factorial of that number:

> main :: IO ()

> main = do putStr "Enter a number: "
>           l <- readLine
>           putStr "n!= "
>           print (fact (read l))
          
  This is the factorial function.

> fact :: Integer -> Integer
> fact 0 = 1
> fact n = n * fact (n-1)
@
\eprog


An alternative style of literate programming is particularly
suitable for use with the LaTeX text processing system.
In this convention, only those parts of the literate program that are
entirely enclosed between @\begin{code}@$\ldots$@\end{code}@ delimiters are
treated as program text; all other lines are comment.  More precisely:
\begin{itemize}
\item Program code begins on the first line following a line that begins @\begin{code}@.
\item Program code ends just before a subsequent line that begins @\end{code}@ (ignoring
string literals, of course).
\end{itemize}
It is not necessary
to insert additional blank lines before or after these delimiters, though
it may be stylistically desirable.  For example,
\bprog
@
\documentstyle{article}

\begin{document}

\section{Introduction}

This is a trivial program that prints the first 20 factorials.

\begin{code}
main :: IO ()
main =  print [ (n, product [1..n]) | n <- [1..20]]
\end{code}

\end{document}
@
\eprog
This style uses the same file extension.  It is not advisable to mix
these two styles in the same file.

\startnewsection
\subsection{Context-Free Syntax}
\label{bnf}
@@@
module -> @module@ modid [exports] @where@ body 
       |  body
body   -> @{@ impdecls @;@ topdecls @}@
	| @{@ impdecls  @}@
	| @{@ topdecls  @}@

impdecls     -> impdecl_1 @;@ ... @;@ impdecl_n 	&  (n>=1)
@@@
\indexsyn{module}%
\indexsyn{body}%
\indexsyn{modid}%
\indexsyn{impdecls}%

@@@
exports	 -> @(@ export_1 @,@ ... @,@ export_n [ @,@ ] @)@ & (n>=0)

export   -> qvar
	 |  qtycon [@(..)@ | @(@ cname_1 @,@ ... @,@ cname_n @)@] & (n>=0)
	 |  qtycls [@(..)@ | @(@ qvar_1 @,@ ... @,@ qvar_n @)@] & (n>=0)
         |  @module@ modid
@@@
\indexsyn{exports}%
\indexsyn{export}%

@@@
impdecl   -> @import@ [@qualified@] modid [@as@ modid] [impspec]
	  | 	& (\tr{empty declaration})

impspec   -> @(@ import_1 @,@ ... @,@ import_n [ @,@ ] @)@ & (n>=0)
             |  @hiding@ @(@ import_1 @,@ ... @,@ import_n [ @,@ ] @)@ &  (n>=0)

import    -> var
	  |  tycon [ @(..)@ | @(@ cname_1 @,@ ... @,@ cname_n @)@] & (n>=0)
	  |  tycls [@(..)@ | @(@ var_1 @,@ ... @,@ var_n @)@] & (n>=0)
cname     -> var | con
@@@
\indexsyn{impdecl}%
\indexsyn{impspec}%
\indexsyn{import}%
\indexsyn{cname}%

@@@
topdecls -> topdecl_1 @;@ ... @;@ topdecl_n 	&  (n>=0)
topdecl	-> @type@ simpletype @=@ type
	|  @data@ [context @=>@] simpletype @=@ constrs [deriving]
        |  @newtype@ [context @=>@] simpletype @=@ newconstr [deriving]
	|  @class@ [scontext @=>@] tycls tyvar [@where@ cdecls]
	|  @instance@ [scontext @=>@] qtycls inst [@where@ idecls]
	|  @default@ @(@type_1 @,@ ... @,@ type_n@)@ & (n>=0)
	|  decl
@@@
\indexsyn{topdecls}%
\indexsyn{topdecl}%

@@@
decls	-> @{@ decl_1 @;@ ... @;@ decl_n  @}@		&  (n>=0)
decl	-> gendecl
	|  (funlhs | pat^0) rhs

cdecls	-> @{@ cdecl_1 @;@ ... @;@ cdecl_n  @}@		&  (n>=0)
cdecl	-> gendecl
	|  (funlhs | var) rhs

idecls	-> @{@ idecl_1 @;@ ... @;@ idecl_n  @}@		&  (n>=0)
idecl	-> (funlhs | var) rhs
	|						& (\tr{empty})

gendecl	-> vars @::@ [context @=>@] type	& (\tr{type signature})
	|  fixity [integer] ops			& (\tr{fixity declaration})
	|					& (\tr{empty declaration})

ops	-> op_1 @,@ ... @,@ op_n		& (n>=1)
vars	-> var_1 @,@ ...@,@ var_n		& (n>=1)
fixity	-> @infixl@ | @infixr@ | @infix@
@@@
\indexsyn{vars}%
\indexsyn{fixity}%
\indexsyn{ops}%
\indexsyn{gendecl}%
\indexsyn{decls}%
\indexsyn{decl}%
\indexsyn{cdecls}%
\indexsyn{cdecl}%
\indexsyn{idecls}%
\indexsyn{idecl}%


@@@
type      -> btype [@->@ type]                    & (\tr{function type})

btype    ->  [btype] atype                        & (\tr{type application})

atype    ->  gtycon
          |  tyvar
          |  @(@ type_1 @,@ ... @,@ type_k @)@ & (\tr{tuple type}, k>=2)
          |  @[@ type @]@                      & (\tr{list type})
          |  @(@ type @)@                      & (\tr{parenthesized constructor})

gtycon    -> qtycon
          |  @()@                              & (\tr{unit type})
          |  @[]@                              & (\tr{list constructor})
          |  @(->)@                            & (\tr{function constructor})
          |  @(,@\{@,@\}@)@                    & (\tr{tupling constructors})

context -> class
        |  @(@ class_1 @,@ ... @,@ class_n @)@		&  (n>=0)
class	-> qtycls tyvar			
	|  qtycls @(@ tyvar atype_1 ...  atype_n @)@ &  (n>=1)
scontext -> simpleclass
        |  @(@ simpleclass_1 @,@ ... @,@ simpleclass_n @)@		&  (n>=0)
simpleclass -> qtycls tyvar			
@@@
\indexsyn{type}%
\indexsyn{btype}%
\indexsyn{atype}%
\indexsyn{gtycon}%
\indexsyn{context}%
\indexsyn{class}%
\indexsyn{simpleclass}%
\indexsyn{scontext}%


@@@
simpletype -> tycon tyvar_1 ... tyvar_k &  (k>=0)
constrs	   -> constr_1 @|@ ... @|@ constr_n	&  (n>=1)
constr	   -> con [@!@] atype_1 ... [@!@] atype_k	& (\tr{arity} con = k, k>=0)
           |  (btype | @!@ atype) conop (btype | @!@ atype) & (\tr{infix} conop)
           |  con @{@ fielddecl_1 @,@ ... @,@ fielddecl_n @}@ &  (n>=0)
newconstr  -> con atype
	   |  con @{@ var @::@ type @}@ 
fielddecl  -> vars @::@ (type | @!@ atype)
deriving   -> @deriving@ (dclass | @(@dclass_1@,@ ... @,@ dclass_n@)@)&  (n>=0)
dclass     -> qtycls
@@@
\indexsyn{simpletype}%
\indexsyn{constrs}%
\indexsyn{constr}%
\indexsyn{fielddecl}%
\indexsyn{deriving}%
\indexsyn{dclass}%
\indexsyn{newconstr}%

@@@
inst	-> gtycon
	|  @(@ gtycon tyvar_1 ... tyvar_k @)@	& (k>=0, tyvars \tr{distinct})
	|  @(@ tyvar_1 @,@ ... @,@ tyvar_k @)@	& (k>=2, tyvars \tr{distinct})
	|  @[@ tyvar @]@
	|  @(@ tyvar_1 @->@ tyvar_2 @)@		& tyvar_1 \tr{and} tyvar_2 \tr{distinct}
@@@
\indexsyn{inst}%

@@@
funlhs	->  var apat \{ apat \}
	|   pat^{i+1} varop^{(a,i)} pat^{i+1}
	|   lpat^i varop^{({\rm{}l},i)} pat^{i+1}
	|   pat^{i+1} varop^{({\rm{}r},i)} rpat^i
	|   @(@ funlhs @)@  apat \{ apat \}

rhs	->  @=@ exp [@where@ decls]
	|   gdrhs [@where@ decls]

gdrhs	->  gd @=@ exp [gdrhs]

gd	->  @|@ exp^0 
@@@
\indexsyn{funlhs}%
\indexsyn{rhs}%
\indexsyn{gdrhs}%
\indexsyn{gd}%

@@@
exp	->  exp^0 @::@ [context @=>@] type	& (\tr{expression type signature})
        |   exp^0
exp^i	->  exp^{i+1} [qop^{({\rm{}n},i)} exp^{i+1}]
	|   lexp^i
	|   rexp^i
lexp^i	->  (lexp^i | exp^{i+1}) qop^{({\rm{}l},i)} exp^{i+1}
lexp^6	->  @-@ exp^7
rexp^i	->  exp^{i+1} qop^{({\rm{}r},i)} (rexp^i | exp^{i+1})
exp^{10} ->  @\@ apat_1 ... apat_n @->@ exp	& (\tr{lambda abstraction}, n>=1)
	|   @let@ decls @in@ exp	        & ({\tr{let expression}})
	|   @if@ exp @then@ exp @else@ exp	& (\tr{conditional})
	|   @case@ exp @of@ @{@ alts @}@	& (\tr{case expression})
        |   @do@ @{@ stmts  @}@            & (\tr{do expression})
	|   fexp
fexp	->  [fexp] aexp				& (\tr{function application})
@@@
\indexsyn{exp}%
\index{exp@@"exp^i"}%
\index{lexp@@"lexp^i"}%
\index{rexp@@"rexp^i"}%
\indexsyn{fexp}%

@@@
aexp 	->  qvar				& (\tr{variable})
	|   gcon				& (\tr{general constructor})
	|   literal				
	|   @(@ exp @)@			      & (\tr{parenthesized expression})
	|   @(@ exp_1 @,@ ... @,@ exp_k @)@	& (\tr{tuple}, k>=2)
	|   @[@ exp_1 @,@ ... @,@ exp_k @]@	& (\tr{list}, k>=1)
	|   @[@ exp_1 [@,@ exp_2] @..@ [exp_3] @]@ & (\tr{arithmetic sequence})
	|   @[@ exp @|@ qual_1 @,@ ... @,@ qual_n @]@	& (\tr{list comprehension}, n>=1)
	|   @(@ exp^{i+1} qop^{(a,i)} @)@        & (\tr{left section})
	|   @(@ lexp^{i} qop^{(l,i)} @)@        & (\tr{left section})
        |   @(@ qop^{(a,i)}_{\langle@-@\rangle}  exp^{i+1} @)@        & (\tr{right section})
        |   @(@ qop^{(r,i)}_{\langle@-@\rangle}  rexp^{i} @)@        & (\tr{right section})
        |   qcon @{@ fbind_1 @,@ ... @,@ fbind_n @}@ & (\tr{labeled construction}, n>=0)
        |   aexp_{\langle{}qcon\rangle{}} @{@ fbind_1 @,@ ... @,@ fbind_n @}@ & (\tr{labeled update}, n >= 1)
@@@
\indexsyn{aexp}%

@@@
qual	-> pat @<-@ exp 	& (\tr{generator})
         | @let@ decls		& (\tr{local declaration})
         | exp 			& (\tr{guard})

alts	->  alt_1 @;@ ... @;@ alt_n 		&  (n>=1)
alt	->  pat @->@ exp [@where@ decls]
	|   pat gdpat [@where@ decls]
	|					& (empty alternative)

gdpat   ->  gd @->@ exp [ gdpat ]

stmts -> stmt_1 ... stmt_n exp [@;@]  &  (n>=0)
stmt -> exp @;@
      | pat @<-@ exp @;@
      | @let@ decls @;@
      | @;@			& (empty statement)

fbind   ->  qvar @=@ exp
        
@@@
\indexsyn{qual}%
\indexsyn{alts}%
\indexsyn{alt}%
\indexsyn{gdpat}%
\indexsyn{stmt}%
\indexsyn{stmts}%
\indexsyn{fbind}%

@@@
pat     ->  var @+@ integer & (\tr{successor pattern})
	|  pat^0
pat^i	->  pat^{i+1} [qconop^{({\rm{}n},i)} pat^{i+1}]
	|   lpat^i
	|   rpat^i
lpat^i	->  (lpat^i | pat^{i+1}) qconop^{({\rm{}l},i)} pat^{i+1}
lpat^6	->  @-@ (integer | float)		& (\tr{negative literal})
rpat^i	->  pat^{i+1} qconop^{({\rm{}r},i)} (rpat^i | pat^{i+1})
pat^{10} ->  apat
	|   gcon apat_1 ... apat_k		& (\tr{arity} gcon = k, k>=1)
@@@
\indexsyn{pat}%
\index{pat@@"pat^i"}%
\index{lpat@@"lpat^i"}%
\index{rpat@@"rpat^i"}%
\indexsyn{fpat}%
\indexsyn{fpats}%

@@@
apat	->  var [{\tt @@} apat]			& (\tr{as pattern})
	|   gcon				& (\tr{arity} gcon = 0) 
        |   qcon @{@ fpat_1 @,@ ... @,@ fpat_k @}@ & (\tr{labeled pattern}, k>=0)
	|   literal
	|   @_@					& (\tr{wildcard})
	|   @(@ pat @)@				& (\tr{parenthesized pattern})
	|   @(@ pat_1 @,@ ... @,@ pat_k @)@	& (\tr{tuple pattern}, k>=2)
	|   @[@ pat_1 @,@ ... @,@ pat_k @]@	& (\tr{list pattern}, k>=1) 
	|   @~@ apat				& (\tr{irrefutable pattern})

fpat    ->  qvar @=@ pat
@@@
\indexsyn{apat}%
@@@
gcon    ->  @()@
        |   @[]@
        |   @(,@\{@,@\}@)@
        |   qcon

var	->  varid | @(@ varsym @)@		& (\tr{variable})
qvar	->  qvarid | @(@ qvarsym @)@		& (\tr{qualified variable})
con	->  conid | @(@ consym @)@		& (\tr{constructor})
qcon	->  qconid | @(@ gconsym @)@		& (\tr{qualified constructor})
varop	->  varsym | \bkqB varid \bkqA		& (\tr{variable operator})
qvarop	->  qvarsym | \bkqB qvarid \bkqA	& (\tr{qualified variable operator})
conop	->  consym | \bkqB conid \bkqA		& (\tr{constructor operator})
qconop	->  gconsym | \bkqB qconid \bkqA	& (\tr{qualified constructor operator})
op	->  varop | conop 			& (\tr{operator})
qop     ->  qvarop | qconop			& (\tr{qualified operator})
gconsym ->  @:@ | qconsym
@@@
\indexsyn{gcon}%
\indexsyn{var}%
\indexsyn{qvar}%
\indexsyn{con}%
\indexsyn{qcon}%
\indexsyn{varop}%
\indexsyn{qvarop}%
\indexsyn{conop}%
\indexsyn{qconop}%
\indexsyn{op}%
\indexsyn{qop}%

%*anchor off
% Local Variables: 
% mode: latex
% End:
%**~footer

