[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Priorities of (non)operators.
Original-Via: uk.ac.ukc; Mon, 11 Mar 91 18:43:19 GMT
From: Kent Karlsson <kent@se.chalmers.cs>
Date: Mon, 11 Mar 91 19:34:32 +0100
To: haskell@cs.glasgow.ac.uk
Subject: Priorities of (non)operators.
Original-Sender: kent%se.chalmers.cs@sunic.sunet.se
Sender: haskell-request@cs.glasgow.ac.uk
PRIORITIES OF NONOPERATORS
==========================
The priorities of some nonoperators are not entierly clear
from the report.
E.g. how is if a then b else \x -> c where {...}
supposed to be read:
(i) as (if a then b else \x -> c) where {...}
(ii) or as if a then b else (\x -> c where {...})
(iii) or is it a syntax error, i.e., does one have to
write out the parenthesis? (Remember that
conditional expressions are supposed to bind tighter than where-expressions,
but lambda-abstractions are supposed to bind looser than where-expressions...)
I vote for (iii): it's clearer, and the grammar is easier than
for the other alternatives.
In order to make the priorities entierly clear, they should be
built into the context-free grammar. For convenience a production
exp(k) -> ... is written as exp -> ... (k) below, and any
occurrence of exp in an rhs of a grammar production means exp(-8).
The priorities of operators are sometimes multiplied by 2 below,
that is in order to handle nonassociative operators properly.
Expressions of the form
exp(2i+1) rop(i) exp(2i) lop(i) exp(2i+1)
are ambiguous in the grammar below, and therefore disallowed.
I propose the following grammar for expressions:
lop(i) -> op (if op is left associative of priority i) \
rop(i) -> op (if op is right associative of priority i) } (0 <= i <= 9)
nop(i) -> op (if op is nonassociative of priority i) /
exp -> aexp (21)
| exp(20) exp(21) (20) function application, priority 10
| exp1(2i) lop(i) exp2(2i+1) (2i) operator application
| - exp(13) (12) unary -, priority 6
| exp1(2i+1) rop(i) exp2(2i) (2i) operator application
| exp1(2i+1) nop(i) exp2(2i+1) (2i-1) operator application
| exp(-2) :: [context =>] atype (-2) expression type signature
| case exp of { alts } (-4) case expression
| if exp1 then exp2(-4) else exp3(-4) (-4) conditional expression
| exp(-6) where { decls } (-6) where expression
| \ apat1 ... apatn [gd] -> exp(-8) (-8) lambda abstraction, (n>=0)
| exp(j+1) (j) priority scheme (-8 <= j < 21)
and similarly for pat and lhs.
The restriction in the then-part of a conditional expression
is intentionally the same as in the else-part above, even though there
is no ambiguity that is resolved by the restriction. It is there
just to make the then- and else-parts into the same syntactic category.
I don't know why case e of {...} x y z is a permitted application,
while f case e of {...} is not allowed. I think they are equally ugly,
and so is case e of {...} + 5 etc. I've taken the liberty to disallow them
above (but they can still be written *with* parenthesis).
There are parsing algorithms that implement such a priority scheme
without having the exp(j) -> exp(j+1) productions explicit (e.g. the
one used in Isabelle). (Unfortunately yacc doesn't, but that is yacc's
problem, not a problem in e.g. LR-parsing as such.)
/kent k