nonterminalType.ml 2.25 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
open UnparameterizedSyntax
open IL

(* This is the conventional name of the nonterminal GADT, which describes the
   nonterminal symbols. *)

let tcnonterminalgadt =
  "nonterminal"

let tnonterminalgadt a =
  TypApp (tcnonterminalgadt, [ a ])

(* This is the conventional name of the data constructors of the nonterminal
   GADT. *)

let tnonterminalgadtdata nt =
  "N_" ^ Misc.normalize nt

(* This is the definition of the nonterminal GADT. Here, the data
   constructors have no value argument, but have a type index. *)

22
exception MissingOCamlType of string
23 24

let nonterminalgadtdef grammar =
25 26 27
  assert Settings.inspection;
  let comment, datadefs =
    try
28

29
      "The indexed type of nonterminal symbols.",
30 31 32 33 34 35
      List.fold_left (fun defs nt ->
        let index =
          match ocamltype_of_symbol grammar nt with
          | Some t ->
              TypTextual t
          | None ->
36
              raise (MissingOCamlType nt)
37 38 39 40 41 42 43
        in
        {
          dataname = tnonterminalgadtdata nt;
          datavalparams = [];
          datatypeparams = Some [ index ]
        } :: defs
      ) [] (nonterminals grammar)
44 45

    with MissingOCamlType nt ->
46 47 48 49
      (* If the type of some nonterminal symbol is unknown, give up
         and define ['a nonterminal] as an abstract type. This is
         useful when we are in [--(raw)-depend] mode and we do not
         wish to fail. Instead, we produce a mock [.mli] file that
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
         is an approximation of the real [.mli] file. When we are
         not in [--(raw)-depend] mode, though, this is a problem.
         We display an error message and stop. *)
      match Settings.depend with
      | Settings.OMRaw
      | Settings.OMPostprocess ->
          "The indexed type of nonterminal symbols (mock!).",
          []
      | Settings.OMNone ->
          Error.error [] (Printf.sprintf "\
            the type of the nonterminal symbol %s is unknown.\n\
            When --inspection is set, the type of every nonterminal symbol must be known.\n\
            Please use --infer or specify the type of every symbol via %%type declarations."
            nt
          )

66 67 68 69 70 71 72 73 74 75
  in
  [
    IIComment comment;
    IITypeDecls [{
      typename = tcnonterminalgadt;
      typeparams = [ "_" ];
      typerhs = TDefSum datadefs;
      typeconstraint = None
    }]
  ]