.ec e	 epsilon
.am table_of_contents
.  bp
.  em
.appendix "CLU Syntax"
.para
We use an extended BNF grammar to define the syntax.
The general form of a production is:
.show 4
.def nonterminal alternative
.or alternative
.or ```...
.or alternative
.eshow
.para
The following extensions are used:
.nr fff fheight/4
.if
. width "a , etc   "
. sv list_left_margin 800m
. sv list_right_margin
. sv list_indent width!m
. sv list_space
. sv list_spacing 1.5
. ilist
a , etc	stands for a list of one or more 2a*'s separated by commas;
i.e., "a" or "a, a" or "a, a, a" etc.
. next
lcurly!arcurly	stands for a sequence of zero or more 2a*'s;
i.e., " " or "a" or "a a" etc.
. next
lbkt!arbkt	stands for an optional 2a*;
i.e., " " or "a".
. end_list
. en
.para
All semicolons are optional in CLU,
but for simplicity they appear in the syntax as ";" rather than "lbkt!;rbkt".
Nonterminal symbols appear in normal face.
Reserved words appear in bold face.
All other terminal symbols are non-alphabetic,
and appear in normal face.


.eq temp_or or
.eq temp_def def
.de bdef
.be def_block
.nv ls 110
.br
.nv fill 0
.keep ndef
\0
.hp d_stop0!m
def
.hp d_stop2!m
.em
.
.
.de or
.br
.hp d_stop1!m
orbar
.hp d_stop2!m
.em
.
.
.de ndef
.end_keep
.sp .5
.en
.sr fff em  look, ma! a space
.if nargs>0
.sr fff
.en
.\fff!bdef \0
.em
.
.
.de comment
.sp .5
.hp d_stop1!m
% 
.em
.de comment1
.br
.hp d_stop1!m
% 
.em
.
.
.de prec
.hp percent_stop!m
%
.hp prec_stop!m
\curprec
.em
.
.
.de nprec
.nr curprec curprec-1
.nr prec_stop prec_stop+prec_width
.prec
.em
.
.
.width "others_handler  "
.nr d_stop0 width
.width "def"
.nr d_stop1 d_stop0+(width/2)
.width "cluster_body  def  "
.nr d_stop2 width
.width "expression // expression              "
.nr percent_stop d_stop2+width
.width "% "
.nr prec_width width
.
.
.bdef module
lcurly equate rcurly procedure
.or
lcurly equate rcurly iterator
.or
lcurly equate rcurly cluster
.
.
.ndef procedure
idn = s(1)proc lbkt parms rbkt args lbkt returns rbkt lbkt signals rbkt lbkt where rbkt ;
t(1)body
t(1)end idn ;
.
.
.ndef iterator
idn = s(1)iter lbkt parms rbkt args lbkt yields rbkt lbkt signals rbkt lbkt where rbkt ;
t(1)body
t(1)end idn ;
.
.
.ndef cluster
idn = s(1)cluster lbkt parms rbkt is idn , etc lbkt where rbkt ;
t(1)cluster_body
t(1)end idn ;
.
.
.ndef parms
[ parm , etc ]
.
.
.ndef parm
idn , etc : type
.or
idn , etc : type_spec
.
.
.ndef args
( lbkt decl , etc rbkt )
.
.
.ndef decl
idn , etc : type_spec
.
.
.ndef returns
returns ( type_spec , etc )
.
.
.ndef yields
yields ( type_spec , etc )
.
.
.ndef signals
signals ( exception , etc )
.
.
.ndef exception
name lbkt ( type_spec , etc ) rbkt
.
.
.ndef where
where restriction , etc
.
.
.ndef restriction
idn has oper_decl , etc
.or
idn in type_set
.
.
.ndef type_set
{ idn | idn has oper_decl , etc ; lcurly equate rcurly }
.or
idn
.
.
.ndef oper_decl
op_name , etc : type_spec
.
.
.ndef op_name
name lbkt [ constant , etc ] rbkt
.
.
.ndef constant
expression
.or
type_spec
.
.
.ndef body
lcurly equate rcurly lcurly statement rcurly
.
.
.ndef cluster_body
s(1)lcurly equate rcurly  rep = type_spec ;  lcurly equate rcurly
b(1)routine lcurly routine rcurly
.
.
.ndef routine
procedure
.or
iterator
.
.
.ndef equate
idn = constant ;
.or
idn = type_set ;
.
.
.ndef type_spec
null
.or
bool
.or
int
.or
real
.or
char
.or
string
.or
any
.or
rep
.or
cvt
.or
array [ type_spec ]
.or
record [ field_spec , etc ]
.or
oneof [ field_spec , etc ]
.or
proctype ( lbkt type_spec , etc rbkt ) lbkt returns rbkt lbkt signals rbkt
.or
itertype ( lbkt type_spec , etc rbkt ) lbkt yields rbkt lbkt signals rbkt
.or
idn [ constant , etc ]
.or
idn
.
.
.ndef field_spec
name , etc : type_spec
.
.
.ndef statement
decl ;
.or
idn : type_spec := expression ;
.or
decl , etc := invocation ;
.or
idn , etc := invocation ;
.or
idn , etc := expression , etc ;
.or
primary . name := expression ;
.or
primary [ expression ] := expression ;
.or
invocation ;
.or
while expression do body end ;
.or
for lbkt decl , etc rbkt in invocation do body end ;
.or
for lbkt idn , etc rbkt in invocation do body end ;
.or
if s(1)expression then body
t(1)lcurly elseif expression then body rcurly
t(1)lbkt else body rbkt
t(1)end ;
.or
tagcase expression
t(1)tag_arm lcurly tag_arm rcurly
t(1)lbkt others : body rbkt
t(1)end ;
.or
return lbkt ( expression , etc ) rbkt ;
.or
yield lbkt ( expression , etc ) rbkt ;
.or
signal name lbkt ( expression , etc ) rbkt ;
.or
exit name lbkt ( expression , etc ) rbkt ;
.or
break ;
.or
continue ;
.or
begin body end ;
.or
statement except s(1)lcurly when_handler rcurly
t(1)lbkt others_handler rbkt
t(1)end ;
.
.
.ndef tag_arm
tag name , etc lbkt ( idn : type_spec ) rbkt : body
.
.
.ndef when_handler
when name , etc lbkt ( decl , etc )rbkt : body
.or
when name , etc ( * ) : body
.
.
.ndef others_handler
others lbkt ( idn : type_spec ) rbkt : body
.
.
.ndef expression
.nr prec_stop percent_stop+prec_width
.nr curprec 6
primary
.or
( expression )
.or
~ expressionprec()	(precedence)
.or
- expressionprec()
.or
expression ** expressionnprec()
.or
expression // expressionnprec()
.or
expression / expressionprec()
.or
expression * expressionprec()
.or
expression || expressionnprec()
.or
expression + expressionprec()
.or
expression - expressionprec()
.or
expression < expressionnprec()
.or
expression <= expressionprec()
.or
expression = expressionprec()
.or
expression >= expressionprec()
.or
expression > expressionprec()
.or
expression ~< expressionprec()
.or
expression ~<= expressionprec()
.or
expression ~= expressionprec()
.or
expression ~>= expressionprec()
.or
expression ~> expressionprec()
.or
expression & expressionnprec()
.or
expression cand expressionprec()
.or
expression | expressionnprec()
.or
expression cor expressionprec()
.
.
.ndef primary
nil
.or
true
.or
false
.or
int_literal
.or
real_literal
.or
char_literal
.or
string_literal
.or
idn
.or
idn [ constant , etc ]
.or
primary . name
.or
primary [ expression ]
.or
invocation
.or
type_spec $ { field , etc }
.or
type_spec $ [ lbkt expression : rbkt lbkt expression , etc rbkt ]
.or
type_spec $ name lbkt [ constant , etc ] rbkt
.or
force [ type_spec ]
.or
up ( expression )
.or
down ( expression )
.
.
.ndef invocation
primary ( lbkt expression , etc rbkt )
.
.
.ndef field
name , etc : expression
.
.
.ndef


.para
2Reserved word*:
one of the identifiers appearing in bold face in the syntax.
Upper and lower case letters are not distinguished in reserved words.
.para
2Name*, 2idn*:
a sequence of
letters,
digits,
and underscores that begins with a letter or underscore,
and that is not a reserved word.
Upper and lower case letters are not distinguished in names and idns.
.para
2Int_literal*:
a sequence of one or more decimal digits.
.para
2Real_literal*:
a mantissa with an (optional) exponent.
A mantissa is either a sequence of one or more decimal digits,
or two sequences (one of which may be empty) joined by a period.
The mantissa must contain at least one digit.
An exponent is 'E' or 'e',
optionally followed by '+' or '-',
followed by one or more decimal digits.
An exponent is required if the mantissa does not contain a period.
.para
2Char_literal*:
either a printing ASCII character
(octal 40 thru octal 176),
other than single quote or backslash,
enclosed in single quotes,
or one of the following escape characters enclosed in single quotes:
.show
escape sequence        s(1)character
.sp .5
\'t(1)'     s(2)(single quote)
\"t(1)"t(2)(double quote)
\\t(1)\t(2)(backslash)
\nt(1)NLt(2)(newline)
\tt(1)HTt(2)(horizontal tab)
\pt(1)FFt(2)(newpage)
\bt(1)BSt(2)(backspace)
\rt(1)CRt(2)(carriage return)
\vt(1)VTt(2)(vertical tab)
\***t(1)specified by octal value (* is an octal digit)
.eshow
The escape sequences may be written using upper case letters.
.para
2String_literal*:
a sequence of zero or more character representations,
enclosed in double quotes.
A character representation is either
a printing ASCII character other than double quote or backslash,
or one of the escape sequences listed above.
.para
2Comment*:
a sequence of characters that begins with a percent sign,
ends with a newline character,
and contains only printing ASCII characters and horizontal tabs in between.
.para
2Separator*:
a blank character
(space, vertical tab, horizontal tab, carriage return, newline, form feed)
or a comment.
Zero or more separators may appear between any two tokens,
except that at least one separator is required between any two adjacent
non-self-terminating tokens:
reserved words,
identifiers,
integer literals,
and real literals.
.eq or temp_or
.eq def temp_def
