\section{Recognized Syntax of Curry}
\label{sec:syntax}

The \CYS Curry compiler accepts a slightly extended version
of the grammar specified in the Curry Report \cite{Hanus16Curry}.
Furthermore, the syntax recognized by \CYS differs
from that specified in the Curry Report
regarding numeric or character literals.
We therefore present the complete description of the syntax below,
whereas \extension{syntactic extensions} are highlighted.

\subsection{Notational Conventions}

The syntax is given in extended Backus-Naur-Form (eBNF),
using the following notation:

\begin{table}[hbtp]
\begin{tabular}{rl}
$\nonterm{NonTerm} ::= \alpha$  & production               \\
\nonterm{NonTerm}               & nonterminal symbol       \\
\term{Term}                     & terminal symbol          \\
\opt{$\alpha$}                  & optional                 \\
\many{$\alpha$}                 & zero or more repetitions \\
\group{$\alpha$}                & grouping                 \\
$\alpha$ \sor{} $\beta$         & alternative              \\
\without{$\alpha$}{$\beta$}     & difference -- elements generated by $\alpha$\\
                                & without those generated by $\beta$
\end{tabular}
\end{table}

\noindent
The Curry files are expected to be encoded in UTF-8.
However, source programs are biased towards ASCII for compatibility reasons.

\subsection{Lexicon}

\subsubsection{Comments}

Comments either begin with \enquote{\term{-{}-}} and terminate at the end
of the line,
or begin with \enquote{\term{\{-}} and terminate with a matching
\enquote{\term{-\}}}, i.e., the delimiters \enquote{\term{\{-}} and
\enquote{\term{-\}}} act as parentheses and can be nested.

\subsubsection{Identifiers and Keywords}

The case of identifiers is important, i.e., the identifier \enquote{abc}
is different from \enquote{ABC}.
Although the Curry Report specifies four different case modes
(Prolog, G\"odel, Haskell, free),
the \CYS only supports the \emph{free} mode
which puts no constraints on the case of identifiers in certain
language constructs.

\begin{grammar}
\production{Letter}{\textnormal{any ASCII letter}} \\
\production{Dashes}{\term{-{}-} \many{\term{-}}}

% Ident and Symbol
\production{Ident}{
  \without
  {\group{Letter \many{Letter \sor{} Digit \sor{} \term{\us} \sor{} \term{'}}}}
  {ReservedID}
}\\
\production{Symbol}{
  \term{\textasciitilde} \sor{} \term{!} \sor{} \term{@}  \sor{} \term{\#}  \sor{} \term{\$} \sor{}
  \term{\%} \sor{} \term{\caret} \sor{} \term{\&} \sor{} \term{*}   \sor{} \term{+}  \sor{}
  \term{-}  \sor{} \term{=}      \sor{} \term{<}  \sor{} \term{>}   \sor{} \term{?}  \sor{}
  \term{.}  \sor{} \term{/}      \sor{} \term{|}  \sor{} \term{\bs} \sor{} \term{:}
}

% Identifiers
\production{ModuleID     }{\many{Ident \term{.}} Ident}\\
\production{TypeConstrID }{Ident}\\
\production{TypeVarID    }{Ident \extension{\sor{} \term{\us}}}\\
\production{ClassVarID   }{Ident}\\
\production{ExistVarID   }{Ident}\\
\production{DataConstrID }{Ident}\\
\production{InfixOpID    }{\without{\group{Symbol \many{Symbol}}}{Dashes \sor{} ReservedSym}}\\
\production{FunctionID   }{Ident}\\
\production{VariableID   }{Ident}\\
\production{LabelID      }{Ident}\\
\production{ClassID      }{Ident}

% Qualified identifiers
\production{QTypeConstrID}{\opt{ModuleID \term{.}} TypeConstrID}\\
\production{QDataConstrID}{\opt{ModuleID \term{.}} DataConstrID}\\
\production{QInfixOpID   }{\opt{ModuleID \term{.}} InfixOpID   }\\
\production{QFunctionID  }{\opt{ModuleID \term{.}} FunctionID  }\\
\production{QLabelID     }{\opt{ModuleID \term{.}} LabelID     }\\
\production{QClassID     }{\opt{ModuleID \term{.}} ClassID     }
\end{grammar}

\noindent
The following identifiers are recognized as keywords
and cannot be used as regular identifiers.

\begin{grammar}
\production{ReservedID}{
       \term{case}                 \sor{} \extension{\term{class}}
\sor{} \term{data}                 \sor{} \extension{\term{default}}
\sor{} \extension{\term{deriving}} \sor{} \term{do}
\sor{} \term{else}                 \sor{} \term{external}
\alt   \term{fcase}                \sor{} \term{free}
\sor{} \term{if}                   \sor{} \term{import}
\sor{} \term{in}                   \sor{} \term{infix}
\sor{} \term{infixl}               \sor{} \term{infixr}
\alt   \extension{\term{instance}} \sor{} \term{let}
\sor{} \term{module}               \sor{} \extension{\term{newtype}}
\sor{} \term{of}                   \sor{} \term{then}
\sor{} \term{type}                 \sor{} \term{where}
}
\end{grammar}

\noindent
Note that the identifiers \term{as}, \extension{\term{forall}},
\term{hiding} and \term{qualified} are no keywords.
They have only a special meaning in module headers
and can thus be used as ordinary identifiers elsewhere.
The following symbols also have a special meaning and cannot
be used as an infix operator identifier.

\begin{grammar}
\production{ReservedSym}{
\term{..} \sor{} \term{:} \sor{} \term{::} \sor{} \term{=} \sor{} \term{\bs} \sor{} \term{|} \sor{} \term{<-} \sor{} \term{->} \sor{} \term{@} \sor{} \term{\textasciitilde} \sor{} \extension{\term{=>}}
}
\end{grammar}

\subsubsection{Numeric and Character Literals}

In contrast to the Curry Report, \CYS adopts Haskell's notation of literals
for both numeric as well as character and string literals,
extended with the ability to denote binary integer literals.

\begin{grammar}
\production{Int}{
      Decimal
\extension{
\alt \term{0b} Binary      \sor{} \term{0B} Binary
}
\alt \term{0o} Octal       \sor{} \term{0O} Octal
\alt \term{0x} Hexadecimal \sor{} \term{0X} Hexadecimal
}

\production{Float}{
      Decimal \term{.} Decimal \opt{Exponent}
\alt Decimal Exponent
}\\
\production{Exponent}{
  \group{\term{e} \sor{} \term{E}} \opt{\term{+} \sor{} \term{-}} Decimal
}

\production{Decimal    }{Digit \many{Digit}}\\
\extension{
\production{Binary     }{Binit \many{Binit}}\\
}%
\production{Octal      }{Octit \many{Octit}}\\
\production{Hexadecimal}{Hexit \many{Hexit}}

\production{Digit}{
 \term{0} \sor{} \term{1} \sor{} \term{2} \sor{} \term{3} \sor{} \term{4} \sor{}
 \term{5} \sor{} \term{6} \sor{} \term{7} \sor{} \term{8} \sor{} \term{9}
}\\
\extension{
\production{Binit}{\term{0} \sor{} \term{1}}\\
}%
\production{Octit}{
 \term{0} \sor{} \term{1} \sor{} \term{2} \sor{} \term{3} \sor{} \term{4} \sor{}
 \term{5} \sor{} \term{6} \sor{} \term{7}
}\\
\production{Hexit}{
 \term{0} \sor{} \term{1} \sor{} \term{2} \sor{} \term{3} \sor{} \term{4} \sor{}
 \term{5} \sor{} \term{6} \sor{} \term{7} \sor{} \term{8} \sor{} \term{9} \sor{}
 \term{A} \sor{} \term{B} \sor{} \term{C} \sor{} \term{D} \sor{} \term{E} \sor{}
 \term{F} \sor{} \term{a} \sor{} \term{b} \sor{} \term{c} \sor{} \term{d} \sor{}
 \term{e} \sor{} \term{f}
}
\end{grammar}

\noindent
For character and string literals, the syntax is as follows:

\begin{grammar}
\production{Char}{
  \term{'}
  \group{
    \without{\nonterm{Graphic}}{\term{\bs}}
    \sor{} Space
    \sor{} \without{\nonterm{Escape}}{\term{\bs\&}}
  }
  \term{'}
}\\
\production{String}{
  \term{"}
  \many{
    \without{\nonterm{Graphic}}{\term{"} \sor{} \term{\bs}}
    \sor{} Space
    \sor{} Escape
    \sor{} Gap
  }
  \term{"}
}\\
\production{Escape}{
  \term{\bs}
  \group{
    CharEsc \sor{} AsciiEsc \sor{} Decimal
    \sor{} \term{o} Octal \sor{} \term{x} Hexadecimal
  }
}\\
\production{CharEsc}{
  \term{a} \sor{} \term{b} \sor{} \term{f} \sor{} \term{n} \sor{} \term{r} \sor{} \term{t}
  \sor{} \term{v} \sor{} \term{\bs} \sor{} \term{"} \sor{} \term{'} \sor{} \term{\&}
}\\
\production{AsciiEsc}{
  \term{\caret} Cntrl \sor{} \term{NUL} \sor{} \term{SOH} \sor{} \term{STX} \sor{} \term{ETX}
  \sor{} \term{EOT}     \sor{} \term{ENQ} \sor{} \term{ACK}
  \alt \term{BEL}     \sor{} \term{BS}  \sor{} \term{HT}  \sor{} \term{LF}  \sor{} \term{VT}
  \sor{} \term{FF}      \sor{} \term{CR}  \sor{} \term{SO}  \sor{} \term{SI}  \sor{} \term{DLE}
  \alt \term{DC1}     \sor{} \term{DC2} \sor{} \term{DC3} \sor{} \term{DC4} \sor{} \term{NAK}
  \sor{} \term{SYN}     \sor{} \term{ETB} \sor{} \term{CAN}
  \alt \term{EM}      \sor{} \term{SUB} \sor{} \term{ESC} \sor{} \term{FS}  \sor{} \term{GS}
  \sor{} \term{RS}      \sor{} \term{US}  \sor{} \term{SP}  \sor{} \term{DEL}
}\\
\production{Cntrl}{
  \term{A} \sor{} $\ldots$ \sor{} \term{Z} \sor{} \term{@} \sor{} \term{[} \sor{} \term{\bs} \sor{} \term{]}
  \sor{} \term{\caret} \sor{} \term{\us}
}\\
\production{Gap}{
  \term{\bs} WhiteChar \many{WhiteChar} \term{\bs}
}\\
\production{Graphic}{\textnormal{any graphical character}} \\
\production{WhiteChar}{\textnormal{any whitespace character}}
\end{grammar}

\subsection{Layout}
Similarly to Haskell, a Curry programmer can use layout
information to define the structure of blocks.
For this purpose, we define
the indentation of a symbol as the column number indicating
the start of this symbol, and
the indentation of a line is the
indentation of its first symbol.\footnote{In order to determine
the exact column number, we assume a fixed-width font with
tab stops at each 8th column.}

The layout (or \enquote{off-side}) rule applies to lists of syntactic
entities after the keywords \term{let},
\term{where}, \term{do}, or \code{of}.
In the subsequent context-free syntax,
these lists are enclosed with
curly braces (\term{\{ \}}) and the single entities are
separated by semicolons (\term{;}). Instead of using the curly
braces and semicolons of the context-free syntax,
a Curry programmer can also specify these lists by indentation:
the indentation of a list of syntactic
entities after \term{let}, \term{where}, \code{do}, or \code{of} is the
indentation of the next symbol following the
\term{let}, \term{where}, \code{do}, \code{of}.
Any item of this list starts with the same indentation as the list.
Lines with only whitespaces or an indentation greater
than the indentation of the list continue
the item in the previous line.
Lines with an indentation less than the indentation
of the list terminate the entire list.
Moreover, a list started by \term{let} is terminated by the
keyword \code{in}.
Thus, the sentence
\begin{curry}
f x = h x where { g y = y + 1 ; h z = (g z) * 2 }
\end{curry}
which is valid w.r.t.\ the context-free syntax,
can be written with the layout rules as
\begin{curry}
f x = h x
 where g y = y + 1
       h z = (g z) * 2
\end{curry}
or also as
\begin{curry}
f x = h x  where
  g y = y + 1
  h z = (g z)
          * 2
\end{curry}
To avoid an indentation of top-level declarations,
the keyword \term{module} and the end-of-file token are
assumed to start in column 0.

\subsection{Context-Free Grammar}

\begin{grammar}
\production{Module}{
     \term{module} ModuleID \opt{Exports} \term{where} Block
\alt Block
}

% Block
\production{Block}{
  \term{\{} \opt{ImportDecls \term{;}} \gseq{BlockDecl}{;}{n} \term{\}}
  \margcomb{\extension{no fixity declarations here}}{n \geq 0}
}

% Exports
\production{Exports}{\term{(} \gseq{Export}{,}{n} \term{)} \extension{\margin{n \geq 0}}}\\
\production{Export}{
     QFunction
\alt QTypeConstrID \extension{\opt{\term{(} \gseq{ConsLabel}{,}{n} \term{)}} \margin{n \geq 0}}
\alt QTypeConstrID \term{(..)}
\extension{
\alt QClassID \opt{\term{(} \gseq{Function}{,}{n} \term{)}} \margin{n \geq 0}
\alt QClassID \term{(..)}
}
\alt \term{module} ModuleID
}\\
\extension{
\production{ConsLabel}{DataConstr \sor{} Label}
}

% Import
\production{ImportDecls}{\gseq{ImportDecl}{;}{n} \margin{n \geq 1}} \\
\production{ImportDecl}{
\term{import} \opt{\term{qualified}} ModuleID
              \opt{\term{as} ModuleID} \opt{ImportSpec}}\\
\production{ImportSpec}{
     \term{(} \gseq{Import}{,}{n} \term{)} \extension{\margin{n \geq 0}}
\alt \term{hiding} \term{(} \gseq{Import}{,}{n} \term{)} \extension{\margin{n \geq 0}}
}\\
\production{Import}{
     Function
\alt TypeConstrID \extension{\opt{\term{(} \gseq{ConsLabel}{,}{n} \term{)}} \margin{n \geq 0}}
\alt TypeConstrID \term{(..)}
\extension{
\alt ClassID \opt{\term{(} \gseq{Function}{,}{n} \term{)}} \margin{n \geq 0}
\alt ClassID \term{(..)}
}
}

% Block Declaration
\production{BlockDecl}{
     TypeSynDecl
\alt DataDecl
\extension{
\alt NewtypeDecl
\alt FixityDecl
}
\alt FunctionDecl
\extension{
\alt DefaultDecl
\alt ClassDecl
\alt InstanceDecl
}
}

% Type Synonym
\production{TypeSynDecl}{\term{type} SimpleType \term{=} TypeExpr}\\
\production{SimpleType}{TypeConstrID \gseq{TypeVarID}{}{n} \margin{n \geq 0}}

% Data type
\production{DataDecl}{
     \extension{\term{external}} \term{data} SimpleType \margtext{external data type}
\alt \term{data} SimpleType \extension{\opt{\term{=} ConstrDecls} \opt{\term{deriving} DerivingDecl}}
}\\
\production{ConstrDecls}{\gseq{ConstrDecl}{|}{n} \margin{n \geq 1}}\\
\production{ConstrDecl}{
\extension{\opt{ExistVars} \opt{Context \term{=>}}} ConDecl
}\\
\extension{
\production{ExistVars}{
\term{forall} \gseq{ExistVarID}{}{n} \term{.} \margin{n \geq 1}
}
}\\
\production{ConDecl}{
\extension{DataConstr} \gseq{SimpleTypeExpr}{}{n} \margin{n \geq 0}%
\extension{%
\alt TypeAppExpr ConOp TypeAppExpr \margtext{infix data constructor}
}%
\alt \extension{DataConstr} \term{\{} \gseq{FieldDecl}{,}{n} \term{\}} \margin{n \geq 0}
}\\
\production{FieldDecl}{\gseq{\extension{Label}}{,}{n} \term{::} TypeExpr \margin{n \geq 1}}\\
\extension{
\production{DerivingDecl}{\term{(} \gseq{QClassID}{,}{n} \term{)} \margin{n \geq 0}}
}

% Newtype
\extension{
\production{NewtypeDecl}{\term{newtype} SimpleType \term{=} NewConstrDecl \opt{\term{deriving} DerivingDecl}}\\
\production{NewConstrDecl}{
      DataConstr SimpleTypeExpr
\alt DataConstr \term{\{} Label \term{::} TypeExpr \term{\}}
}
}

% Qualified type expression
\extension{
\production{QualTypeExpr}{\opt{Context \term{=>}} TypeExpr}\\
\production{Context}{
Constraint
\alt \term{(} \gseq{Constraint}{\term{,}}{n} \term{)}\margin{n \geq 0}
}\\
\production{Constraint}{
QClassID ClassVarID
\alt QClassID \term{(} ClassVarID \gseq{SimpleTypeExpr}{}{n} \term{)} \margin{n \geq 1}
}
}

% Type expression
\production{TypeExpr}{\extension{TypeAppExpr} \opt{\term{->} TypeExpr}}\\
\extension{
\production{TypeAppExpr}{\opt{TypeAppExpr} SimpleTypeExpr}
}\\
\production{SimpleTypeExpr}{
     TypeVarID
\alt \extension{GTypeConstr}
\alt \term{(} \gseq{TypeExpr}{,}{n} \term{)} \margcomb{tuple type}{n \geq 2}
\alt \term{[} TypeExpr \term{]} \margtext{list type}
\alt \term{(} TypeExpr \term{)} \margtext{parenthesized type}
}\\
\extension{
\production{GTypeConstr}{
\term{()} \margtext{unit type constructor}
\alt \term{[]} \margtext{list type constructor}
\alt \term{(->)} \margtext{function type constructor}
\alt \term{(,} \many{\term{,}} \term{)} \margtext{tuple type constructor}
\alt QTypeConstrID
}
}

% DefaultDecl
\extension{
\production{DefaultDecl}{
\term{default} \term{(} \gseq{TypeExpr}{,}{n} \term{)} \margin{n \geq 0}
}
}

% ClassDecl
\extension{
\production{ClassDecl}{
\term{class} \opt{SimpleContext \term{=>}} ClassID ClassVarID \opt{\term{where} ClsDecls}
}\\
\production{ClsDecls}{\term{\{} \gseq{ClsDecl}{\term{;}}{n} \term{\}} \margin{n \geq 0}}\\
\production{ClsDecl}{
Signature
\alt Equat
}\\
\production{SimpleContext}{
SimpleConstraint
\alt \term{(} \gseq{SimpleConstraint}{\term{,}}{n} \term{)} \margin{n \geq 0}
}\\
\production{SimpleConstraint}{QClassID ClassVarID}
}

% InstanceDecl
\extension{
\production{InstanceDecl}{
\term{instance} \opt{SimpleContext \term{=>}} QClassID InstType \opt{\term{where} InstDecls}
}\\
\production{InstDecls}{
\term{\{} \gseq{InstDecl}{\term{;}}{n} \term{\}} \margin{n \geq 0}
}\\
\production{InstDecl}{Equat}\\
\production{InstType}{
GTypeConstr
\alt\term{(} GTypeConstr \gseq{ClassVarID}{}{n} \term{)} \margin{n \geq 0}
\alt\term{(} \gseq{ClassVarID}{\term{,}}{n} \term{)} \margin{n \geq 2}
\alt\term{[} ClassVarID \term{]}
\alt\term{(} ClassVarID \term{->} ClassVarID \term{)}
}
}


% FixityDecl
\production{FixityDecl}{Fixity \extension{\opt{Int}} \gseq{\extension{Op}}{,}{n} \margin{n \geq 1}}\\
\production{Fixity}{\term{infixl} \sor{} \term{infixr} \sor{} \term{infix}}

% Function Declaration
\production{FunctionDecl}{Signature \extension{\sor{} ExternalDecl} \sor{} Equation}\\
\production{Signature}{Functions \term{::} \extension{QualTypeExpr}}\\
\extension{
\production{ExternalDecl}{
Functions \term{external} \margtext{externally defined operations}
}\\
}
\production{Functions}{\gseq{Function}{,}{n} \margin{n \geq 1}}\\
\production{Equation}{FunLhs Rhs}\\
\production{FunLhs}{
     Function \gseq{SimplePat}{}{n} \margin{n \geq 0}%
\extension{%
\alt ConsPattern FunOp ConsPattern
\alt \term{(} FunLhs \term{)} \gseq{SimplePat}{}{n} \margin{n \geq 1}
}%
}

\extension{
\production{Rhs}{
     \term{=} Expr \opt{\term{where} LocalDecls}
\alt CondExprs     \opt{\term{where} LocalDecls}
}}\\
\production{CondExprs}{\term{|} InfixExpr \term{=} Expr \opt{CondExprs}}

% Local Declarations
\production{LocalDecls}{\offside{LocalDecl}{;}{n} \extension{\margin{n \geq 0}}}\\
\production{LocalDecl}{
     FunctionDecl
\alt PatternDecl
\alt \gseq{Variable}{,}{n} \term{free} \margin{n \geq 1}%
  \extension{%
\alt FixityDecl
}%
}\\
\production{PatternDecl}{Pattern \extension{Rhs}}

% Pattern
\production{Pattern}{
  ConsPattern \opt{\extension{QConOp} Pattern}  \margtext{infix constructor pattern}
}\\
\production{ConsPattern}{
     \extension{GDataConstr} \gseq{SimplePat}{}{n} \margcomb{constructor pattern}{n \geq 1}%
\extension{
\alt \term{-} \group{Int \sor{} Float}                    \margtext{negative pattern}
}
\alt SimplePat
}\\
\production{SimplePat}{
     Variable
\alt \term{\us}                                            \margtext{wildcard}
\alt \extension{GDataConstr}                               \margtext{constructor}
\alt Literal                                               \margtext{literal}
\alt \term{(} Pattern \term{)}                             \margtext{parenthesized pattern}
\alt \term{(} \gseq{Pattern}{,}{n} \term{)}                \margcomb{tuple pattern}{n \geq 2}
\alt \term{[} \gseq{Pattern}{,}{n} \term{]}                \margcomb{list pattern}{n \geq 1}%
\alt Variable \term{@} SimplePat                           \margtext{as-pattern}
\extension{
\alt \term{\textasciitilde} SimplePat                      \margtext{irrefutable pattern}
\alt \term{(} QFunction \gseq{SimplePat}{}{n} \term{)}     \margcomb{functional pattern}{n \geq 1}
\alt \term{(} ConsPattern QFunOp Pattern \term{)}          \margtext{infix functional pattern}
}
\alt \extension{QDataConstr} \term{\{} \gseq{FieldPat}{,}{n} \term{\}} \margcomb{labeled pattern}{n \geq 0}
}\\
\production{FieldPat}{\extension{QLabel} \term{=} Pattern}

% Expressions
\production{Expr}{
     InfixExpr \term{::} \extension{QualTypeExpr} \margtext{expression with type signature}
\alt InfixExpr
}\\
\production{InfixExpr}{
     NoOpExpr QOp InfixExpr \margtext{infix operator application}
\alt \term{-}  InfixExpr    \margtext{\extension{unary minus}}%
\alt NoOpExpr
}\\
\production{NoOpExpr}{
     \term{\bs} \gseq{SimplePat}{}{n} \term{->} Expr
     \margcomb{lambda expression}{n \geq 1}
\alt \term{let} LocalDecls \term{in} Expr
     \margtext{let expression}
\alt \term{if} Expr \term{then} Expr \term{else} Expr
     \margtext{conditional}
\alt \term{case} Expr \term{of} \offside{Alt}{;}{n}
     \margcomb{case expression}{n \geq 1}
\alt \term{fcase} Expr \term{of} \offside{Alt}{;}{n}
     \margcomb{fcase expression}{n \geq 1}
\alt \term{do} \term{\{} \gseq{Stmt}{;}{n} \term{;} Expr \term{\}}
     \margcomb{do expression}{n \geq 0}
\alt FuncExpr
}\\
\production{FuncExpr}{\opt{FuncExpr} BasicExpr \margtext{application}}\\
\production{BasicExpr}{
      Variable   \margtext{variable}
\alt \term{\us}  \margtext{anonymous free variable}%
\alt QFunction   \margtext{qualified function}
\extension{
\alt GDataConstr \margtext{general constructor}
}
\alt Literal     \margtext{literal}
\alt \term{(} Expr \term{)}
     \margtext{parenthesized expression}
\alt \term{(} \gseq{Expr}{,}{n} \term{)}
     \margcomb{tuple}{n \geq 2}
\alt \term{[} \gseq{Expr}{,}{n} \term{]}
     \margcomb{finite list}{\extension{n \geq 1}}
\alt \term{[} Expr \opt{\term{,} Expr} \term{..} \opt{Expr} \term{]}
     \margtext{arithmetic sequence}
\alt \term{[} Expr \term{|} \gseq{Qual}{,}{n} \term{]}
     \margcomb{list comprehension}{n\geq 1}
\alt \term{(} \extension{InfixExpr QOp} \term{)}
     \margtext{left section}
\alt \term{(} \extension{\without{\nonterm{QOp}}{\term{-}} InfixExpr} \term{)}
     \margtext{right section}%
\alt \extension{QDataConstr} \term{\{} \gseq{FBind}{,}{n} \term{\}}
     \margcomb{record construction}{n \geq 0}
\alt \without{BasicExpr}{\extension{QDataConstr}} \term{\{} \gseq{FBind}{,}{n} \term{\}}
     \margcomb{record update}{n \geq 1}
}

\production{Alt}{
       Pattern \term{->} Expr \opt{\term{where} LocalDecls}
  \alt Pattern GdAlts         \opt{\term{where} LocalDecls}
}\\
\production{GdAlts}{\term{|} InfixExpr \term{->} Expr \opt{GdAlts}}

\production{FBind}{\extension{QLabel} \term{=} Expr}

\production{Qual}{
      Pattern \term{<-} Expr \margtext{generator}
\alt \term{let} LocalDecls  \margtext{local declarations}
\alt Expr                   \margtext{guard}
}

\production{Stmt}{
      Pattern \term{<-} Expr
\alt \term{let} LocalDecls
\alt Expr
}

\production{Literal}{Int \sor{} Float \sor{} Char \sor{} String}

\extension{
\production{GDataConstr}{
     \term{()} \margtext{unit}
\alt \term{[]} \margtext{empty list}
\alt \term{(,}\many{\term{,}}\term{)} \margtext{tuple}
\alt QDataConstr
}

% Identifier
\production{Variable   }{VariableID    \sor{} \gparen{InfixOpID}  \margtext{variable}}\\
\production{Function   }{FunctionID    \sor{} \gparen{InfixOpID}  \margtext{function}}\\
\production{QFunction  }{QFunctionID   \sor{} \gparen{QInfixOpID} \margtext{qualified function}}\\
\production{DataConstr }{DataConstrID  \sor{} \gparen{InfixOpID}  \margtext{constructor}}\\
\production{QDataConstr}{QDataConstrID \sor{} \gparen{QInfixOpID} \margtext{qualified constructor}}\\
\production{Label      }{LabelID       \sor{} \gparen{InfixOpID}  \margtext{label}}\\
\production{QLabel     }{QLabelID      \sor{} \gparen{QInfixOpID} \margtext{qualified label}}

% Operator
\production{VarOp   }{InfixOpID  \sor{} \gbackquote{VariableID}    \margtext{variable operator}}\\
\production{FunOp   }{InfixOpID  \sor{} \gbackquote{FunctionID}    \margtext{function operator}}\\
\production{QFunOp  }{QInfixOpID \sor{} \gbackquote{QFunctionID}   \margtext{qualified function operator}}\\
\production{ConOp   }{InfixOpID  \sor{} \gbackquote{DataConstrID}  \margtext{constructor operator}}\\
\production{QConOp  }{GConSym    \sor{} \gbackquote{QDataConstrID} \margtext{qualified constructor operator}}\\
\production{LabelOp }{InfixOpID  \sor{} \gbackquote{LabelID}       \margtext{label operator}}\\
\production{QLabelOp}{QInfixOpID \sor{} \gbackquote{QLabelID}      \margtext{qualified label operator}}

\production{Op     }{FunOp \sor{} ConOp  \sor{} LabelOp \margtext{operator}} \\
\production{QOp    }{VarOp \sor{} QFunOp \sor{} QConOp \sor{} QLabelOp \margtext{qualified operator}}\\
\production{GConSym}{\term{:} \sor{} QInfixOpID \margtext{general constructor symbol}}
}
\end{grammar}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: "manual"
%%% End:
