X-Comment1: #############################################################
X-Comment2: #     uk.ac.glasgow.cs has changed to uk.ac.glasgow.dcs     #
X-Comment3: #     If this address does not work please ask your mail    #
X-Comment4: #     administrator to update your NRS & mailer tables.     #
X-Comment5: #############################################################

[Joe, this overrides my earlier, private message...]

I try to keep out of syntax debates, but we need to sort this
out soon and Simon's asked me to delve in :-(  We don't have
much time, so please respond as soon as possible if you feel
strongly about this.  The final decision rests with Paul, our
benign syntax Czar...


POLEMIC
=======

I feel that making if/let/case bind more tightly than function
application would be a mistake -- for keywords, this form is liable to
reduce program legibility by requiring the reader to scan the input
from left-to-right.  While this is easy for a machine to do, it is much
slower for a human reader (who will initially break a text on *strong*
visual symbols, such as operators or parentheses rather than on equally
weighted keywords/identifiers).

For consistency, I would argue that both \ and case should have the
same precedence as let/if.  Even though a machine can distinguish
syntactic rules for case from those for let, this requires explicit
recognition of the exception in a human reader/programmer, which slows
perception.  To my eye, in the following expression, \ looks much like
an operator (e.g. \\).  The -> isn't as strong a clue as it might be in
this particular context:

                        case x of
                                C | f \ y -> y
                                  -> x

[equivalent to]         case x of
                                C | f (\ y -> y)
                                  -> x

(I deliberately haven't emphasised keywords in the paragraph above :-)


I have no argument with "let"/"case"/"if"/"\" binding tighter than
operators -- operators have a much greater lexical "weight" than
function application -- there's no danger of losing the keywords
amongst the function arguments -- they always appear either:

        i)      to the right of an "="
        ii)     to the right of a "("
        iii)    to the right of an operator
        iv)     to the right of a keyword

All of these are strong visual clues which will not be overlooked when
reading a program.  Here are some important examples of legal/illegal
expressions under the scheme proposed here.


EXAMPLES
========

        LEGAL
        -----

        1 + if c then 2 else 3          1 + (if c then 2 else 3)
        1 + let x = f y in x + x        1 + (let x = f y in x + x)


        ILLEGAL
        -------

        f is it if ic g x y then x else y
        g case x of 1 -> 'a'; 2 -> 'b'



I've rewritten the syntax Joe proposed for expressions (eliminating a
couple of minor bugs) to reflect the above suggestions.  At Simon's
urging, a third superscript (which makes the syntax explicit, but hard
to read) is replaced by a new meta-rule: "Expressions introduced by a
keyword or '\' extend as far to the right as possible".  This catches:

        \ x -> x + y
        let x = fib 10 in x * x / 2
        ...


RULES
=====

The syntax includes Joe's fixes for unary minus, and explicit
precedence parsing. His notes on notation follow (edited slightly to
reflect my changes):

In order to avoid a large increase in the number of productions, an
extension to the superscript notation is employed.  The syntactic
category  exp  is now indexed by two superscripts:

        A _precedence_level_ from 0 to 9.  (10 and 11 are also used
        at the top of the precedence hierarchy for function
        application.)

        An _associativity_, which is a letter n, l, or r, meaning that
        the expression is not associated, left-associated, or
        right-associated at the given precedence level.

To avoid clutter, we no longer write quantifications for superscript
variables.  A precedence level variable is understood to range over 0
to 9, and other variables over all possibilities.  We use 'i' for a
precedence variable, and 'a' for associativity.  In the report,
variables will be in italics and ground indices in Roman.


----------------------------- SYNTAX RULES BEGIN ----------------------------

exp             ->  exp(0,n) [ :: [ context => ] atype]


exp(i,n)        ->  [exp(i+1,n) op(i,n)] exp(i+1,n)             (unassoc lev i)
                |   exp(i,l)
                |   exp(i,r)

exp(i,l)        ->  (exp(i,l) | exp(i+1,n)) op(i,l) exp(i+1,n)  (left-assoc)

exp(6,l)        ->  - exp(7,n)                                  (unary -)

exp(i,r)        ->  exp(i+1,n) op(i,r) (exp(i,r) | exp(i+1,n))  (right-assoc)


exp(10,a)       ->  \ apat1 ... apatk -> exp
                |   let { decls [;]} in exp
                |   if exp then exp else exp
                |   case exp of { alts [;] }
                |   fexp


fexp            ->  fexp aexp
                |   aexp


---------------------------- SYNTAX RULES END -------------------------------

Kevin

Reply via email to