unparameterizedSyntax.ml 3.19 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
(* 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 
   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 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
                                    par rapport à syntax.mli; faire un type record au lieu d'une paire? *)
      action			: action;
      branch_shift_precedence	: branch_shift_precedence;
      branch_reduce_precedence  : branch_reduce_precedence
    }

type rule = 
    {
      branches		   : branch list;
      positions            : Positions.t list;
      (* This flag is not relevant after the NonTerminalInlining.inline pass. *)
      inline_flag          : bool;
    }

type grammar = 
    {
      preludes	           : Stretch.t list;
      postludes	           : Syntax.trailer list;
      parameters           : Stretch.t list;
      start_symbols        : StringSet.t;
      types                : Stretch.ocamltype StringMap.t;
      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
(* [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 []

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

let nonterminals grammar : nonterminal list =
69
  StringMap.fold (fun nt _ rules -> nt :: rules) grammar.rules []
70 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