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