In fact, there are several uses of parenthesis in the OCaml grammar for different grammatical rules, and not all of them can be used with begin..end. Parenthesis and begin..end can be used as semantics-free expression delimiters for disambiguation purpose (as you said, expr ::= '(' expr ')'
). ()
also represents the constant of type unit
and, as a pun, begin end
is also allowed there -- but this last one is not specified in the manual, only consistently supported by the implementation.
But parentheses can also be used
- to delimit patterns:
function (_::_)::_ -> ...
- as syntactic sugar for
Array.get
and Array.set
: t.(i)
t.(i) <- e
- for type annotations
(e : t)
both in expressions and patterns (this is not a special case of the disambiguating delimiters because it is not valid without parenthesis)
- for subtyping coercions:
(e :> t)
and (e : s :> t)
- to form labelled pattern compounds:
fun ~(x:int) ..
and fun ?(x=10) ..
- in various related places (coercions, annotations, etc.) in the module, signature and class/objects parts of the syntax
For none of this use can begin..end used instead, so it would definitely not be valid to replace (
with begin
and )
with end
systematically (while the converse is correct).
Sorry for the pedantic answer, but the question was itself quite precise. I'm not sure begin..end handling is the most elegant part of OCaml grammar (which has it lots of warts). One could wish that they really were equivalent, but then there is little point in insisting on writing begin x : int end
instead of (x : int)
.