Closed davidweichiang closed 2 years ago
I think the crux of this issue was that there is no way to know if we should parse
case e₁ of Unit -> case e₂ of False -> e₃ | True -> e₄
as case e₁ of Unit -> (case e₂ of False -> e₃ | True -> e₄)
or case e₁ of Unit -> (case e₂ of False -> e₃) | True -> e₄
So with our current syntax, we can't nest case-of
s without parentheses. Similarly, we can't parse any term that could end with a case-of
inside a case (e.g. case e₁ of Unit -> let x = e₂ in case e₃ of False -> e₄ | True -> e₅
). The same goes for lambda
-terms and if-then-else
-terms too.
—————
In general though, I think I could really iron out some parsing precedence details. Currently, we have the following precedence levels:
TERM1 :=
| case TERM1 of VAR VAR* -> TERM2 \| ...
| if TERM1 then TERM1 else TERM1
| \ VAR : TYPE1. TERM1
| let (VAR, ...) = TERM1 in TERM1
| let VAR = TERM1 in TERM1
| TERM2
TERM2 :=
| sample DIST : TYPE1
| amb TERM5*
| TERM3
TERM3 :=
| TERM4 . NUM (* e.2 *)
| TERM4
TERM4 :=
| TERM5 == TERM5 == ...
| TERM5 TERM5* (* application *)
| TERM5
TERM5 :=
| VAR
| (TERM1)
| <TERM1, ...>
| error
TYPE1 :=
| TYPE2 -> TYPE1
| TYPE2
TYPE2 :=
| TYPE3 * TYPE3 * ...
| TYPE3 & TYPE3 & ...
| TYPE3
TYPE3 :=
| VAR
| (TYPE1)
| error
Do ML and Haskell make the same decision for these cases, and can we do the same?
I know in Haskell you must either do
case e₁ of { False -> e₂; True -> e₃ }
or
case e₁ of
False -> e₂
True -> e₃
For the latter syntax, I think that indentation does matter.
I haven't really used ML much, but at least in Standard ML it looks like you must use parentheses to nest case-of
s (source)
It seems like OCaml is the opposite of SML, so this parses:
match true with
true -> true
| false -> match [] with
[] -> true
| x::xs -> false
and
match true with
true -> true
| false ->
let y = 0 in
match [] with
[] -> true
| x::xs -> false
Haskell (and SML as well?) "attempt to maximally consume potential clauses", like OCaml (and also like C with if...then if...then...else
). Basically this is favoring shift over reduce when there's a shift/reduce conflict. I'm ok with that but I'm also ok with requiring disambiguating parentheses.
An expression like
case e of Unit -> let x = e in e
currently can't parse. The error message is very clear (it says to add parentheses) but would it be better to make it parseable?