unparameterizedSyntax.ml 3.29 KB
Newer Older
POTTIER Francois's avatar
POTTIER Francois committed
1 2 3
(* A parameterized branch may instantiate parameterized non terminals.
   If the parameterized branch contributes to the definition of a
   parameterized terminal, then the instantiation of parameterized
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   non terminals that are defined simultaneously must only be done with
   formal parameters.
   Furthermore, all the parameterized non terminals that are in a common
   mutual recursive definition must have the same arity.
   These conditions are sufficient to ensure termination of expansion.
   For example:
   C[x] : ...            // This definition does not involve A or B.
   A[x,y] : B[x,y] C[Y]  // This mutual recursive definition is ok.
   B[x,y] : A[x,y]
   D[x] : E[D[x]]        // This one is incorrect.
   E[y] : D[y]
*)
open Syntax

type branch =
    {
      branch_position           : Positions.t;
21
      producers                 : (symbol * identifier) list; (* TEMPORARY convention renversée
22
                                    par rapport à syntax.mli; faire un type record au lieu d'une paire? *)
23 24
      action                    : action;
      branch_prec_annotation    : branch_prec_annotation;
25
      branch_production_level   : branch_production_level
26 27
    }

POTTIER Francois's avatar
POTTIER Francois committed
28
type rule =
29
    {
30
      branches             : branch list;
31 32 33 34 35
      positions            : Positions.t list;
      (* This flag is not relevant after the NonTerminalInlining.inline pass. *)
      inline_flag          : bool;
    }

POTTIER Francois's avatar
POTTIER Francois committed
36
type grammar =
37
    {
38 39
      preludes             : Stretch.t list;
      postludes            : Syntax.trailer list;
40 41 42
      parameters           : Stretch.t list;
      start_symbols        : StringSet.t;
      types                : Stretch.ocamltype StringMap.t;
43
      on_error_reduce      : on_error_reduce_level StringMap.t;
44 45
      tokens               : Syntax.token_properties StringMap.t;
      rules                : rule StringMap.t;
46
    }
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
(* [tokens grammar] is a list of all (real) tokens in the grammar
   [grammar]. The special tokens "#" and "error" are not included.
   Pseudo-tokens (used in %prec declarations, but never declared
   using %token) are filtered out. *)

let tokens grammar =
  StringMap.fold (fun token properties tokens ->
    if properties.tk_is_declared then token :: tokens else tokens
  ) grammar.tokens []

(* [typed_tokens grammar] is analogous, but includes the OCaml type
   of each token. *)

let typed_tokens grammar =
  StringMap.fold (fun token properties tokens ->
    if properties.tk_is_declared then (token, properties.tk_ocamltype) :: tokens else tokens
  ) grammar.tokens []

66 67 68 69
(* [nonterminals grammar] is a list of all nonterminal symbols in the
   grammar [grammar]. *)

let nonterminals grammar : nonterminal list =
70
  StringMap.fold (fun nt _ rules -> nt :: rules) grammar.rules []
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

(* [ocamltype_of_symbol grammar symbol] produces the OCaml type
   of the symbol [symbol] in the grammar [grammar], if it is known. *)

let ocamltype_of_symbol grammar symbol : Stretch.ocamltype option =
  try
    Some (StringMap.find symbol grammar.types)
  with Not_found ->
    None

(* [ocamltype_of_start_symbol grammar symbol] produces the OCaml type
   of the start symbol [symbol] in the grammar [grammar]. *)

let ocamltype_of_start_symbol grammar symbol : Stretch.ocamltype =
  try
    StringMap.find symbol grammar.types
  with Not_found ->
    (* Every start symbol should have a type. *)
    assert false