cdexpr:
[ "top" RIGHTA
  [ SELF; ";"; SELF ]
| "expr1" LEFTA
  [ "fun"; LIST1 cdpatt; "->"; SELF
  | "fix"; LIDENT; "->"; SELF
  | "match"; SELF; "with"; OPT "|"; LIST1 cd_match_case SEP "|"
  | "let"; "rec"; LIDENT; LIST0 cdpatt; "="; SELF; "in"; SELF
  | "let"; LIST1 cdpatt; "="; SELF; "in"; SELF
  | "if"; SELF; "then"; cdexpr LEVEL "expr1"; "else"; cdexpr LEVEL "expr1"
  | "for"; LIDENT; "="; SELF; [ "to" | "downto" ]; SELF; "do"; SELF; "done"
  | "while"; SELF; "do"; SELF; "done" ]
| "," LEFTA
  [ SELF; ","; LIST1 NEXT SEP "," ]
| ":=" NONA
  [ SELF; ":="; SELF ]
| "||" RIGHTA
  [ SELF; "||"; SELF ]
| "&&" RIGHTA
  [ SELF; "&&"; SELF ]
| "not" NONA
  [ "not"; SELF ]
| "<" LEFTA
  [ SELF; "="; SELF
  | SELF; "<>"; SELF
  | SELF; "=="; SELF
  | SELF; "!="; SELF
  | SELF; [ "<" | ">" | "<=" | ">=" ]; SELF ]
| RIGHTA
  [ SELF; "::"; SELF ]
| "+" LEFTA
  [ SELF; [ "+" | "-" ]; SELF
  | SELF; [ "+." | "-." ]; SELF ]
| "*" LEFTA
  [ SELF; [ "*" | "/" | "land" | "lor" | "lxor" | "mod" ]; SELF
  | SELF; [ "*." | "/." | "%." ]; SELF ]
| "**" LEFTA
  [ SELF; "**"; SELF
  | SELF; [ "lsl" | "lsr" | "asr" ]; SELF ]
| "unary minus" NONA
  [ "-"; SELF
  | "lnot"; SELF
  | "-."; SELF ]
| "apply" LEFTA
  [ SELF; SELF
  | "ref"; SELF
  | UIDENT; cdexpr_constr
  | UIDENT ]
| "." LEFTA
  [ SELF; "."; "("; SELF; ")"; "<-"; SELF
  | SELF; "."; "("; SELF; ")"
  | SELF; "."; "["; SELF; "]"; "<-"; SELF
  | SELF; "."; "["; SELF; "]"
  | SELF; "."; LIST1 value_path SEP "." ]
| "~-" NONA
  [ "!"; SELF
  | "`"; expr LEVEL "simple"
  | "@"; expr LEVEL "simple" ]
| "simple" LEFTA
  [ "true"
  | "false"
  | "^"; SELF
  | "("; SELF; ")"
  | "["; "]"
  | "["; cdexpr1_semi_list; "]"
  | INT
  | FLOAT
  | STRING
  | value_path ] ]
cdpatt:
[ LEFTA
  [ LIST1 [ "_" | LIDENT ] SEP "," ] ]
cd_match_case:
[ LEFTA
  [ patt; OPT [ "when"; expr ]; "->"; cdexpr ] ]
