syntax.mli 6.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
(* The type [partial_grammar] describes the abstract syntax that is produced
   by the parsers (yacc-parser and fancy-parser).

   The type [grammar] describes the abstract syntax that is obtained after one
   or more partial grammars are joined (see [PartialGrammar]). It differs in
   that declarations are organized in a more useful way and a number of
   well-formedness checks have been performed. *)

(* ------------------------------------------------------------------------ *)

11 12 13 14 15 16 17 18
(* Terminals and nonterminal symbols are strings. Identifiers
   (which are used to refer to a symbol's semantic value) are
   strings. A file name is a string. *)

type terminal =
    string

type nonterminal =
19
    string
20 21

type symbol =
22
    string
23

24 25
type identifier =
    string
26

27
type filename =
28 29
    string

30 31
(* ------------------------------------------------------------------------ *)

32
(* A postlude is a source file fragment. *)
33

34
type postlude =
35
    Stretch.t
36

37 38
(* ------------------------------------------------------------------------ *)

39
(* OCaml semantic actions are represented as stretches. *)
40 41 42 43

type action =
    Action.t

44 45
(* ------------------------------------------------------------------------ *)

POTTIER Francois's avatar
POTTIER Francois committed
46
(* Information about tokens. (Only after joining.) *)
47

48 49
type token_associativity =
    LeftAssoc
50 51 52 53
  | RightAssoc
  | NonAssoc
  | UndefinedAssoc

54 55
type precedence_level =
    UndefinedPrecedence
56 57

  (* Items are incomparable when they originate in different files. A
58
     value of type [input_file] is used to record an item's origin. The
59 60
     positions allow locating certain warnings. *)

61
  | PrecedenceLevel of InputFile.input_file * int * Lexing.position * Lexing.position
62

63 64
type token_properties =
    {
65 66 67
               tk_filename      : filename;
               tk_ocamltype     : Stretch.ocamltype option;
               tk_position      : Positions.t;
68
      mutable  tk_associativity : token_associativity;
69
      mutable  tk_precedence    : precedence_level;
70
      mutable  tk_is_declared   : bool;
71 72
    }

73 74
(* ------------------------------------------------------------------------ *)

75
(* A [%prec] annotation is optional. A production can carry at most one.
76
   If there is one, it is a symbol name. See [ParserAux]. *)
77 78

type branch_prec_annotation =
79 80
    symbol Positions.located option

POTTIER Francois's avatar
POTTIER Francois committed
81 82
(* ------------------------------------------------------------------------ *)

83 84 85 86
(* A "production level" is used to solve reduce/reduce conflicts. It reflects
   which production appears first in the grammar. See [ParserAux]. *)

type branch_production_level =
87
  | ProductionLevel of InputFile.input_file * int
88

POTTIER Francois's avatar
POTTIER Francois committed
89 90
(* ------------------------------------------------------------------------ *)

91 92 93 94 95 96 97 98 99
(* A level is attached to every [%on_error_reduce] declaration. It is used
   to decide what to do when several such declarations are applicable in a
   single state. *)

type on_error_reduce_level =
  branch_production_level (* we re-use the above type, to save code *)

(* ------------------------------------------------------------------------ *)

100 101 102 103 104 105 106 107 108 109 110 111 112 113
(* A parameter is either just a symbol or an application of a symbol to a
   nonempty tuple of parameters. Before anonymous rules have been eliminated,
   it can also be an anonymous rule, represented as a list of branches. *)

type parameter =
  | ParameterVar of symbol Positions.located
  | ParameterApp of symbol Positions.located * parameters
  | ParameterAnonymous of parameterized_branch list Positions.located

and parameters =
    parameter list

(* ------------------------------------------------------------------------ *)

POTTIER Francois's avatar
POTTIER Francois committed
114 115 116
(* A producer is a pair of identifier and a parameter. In concrete syntax,
   it could be [e = expr], for instance. *)

117
and producer =
118
    identifier Positions.located * parameter
119

POTTIER Francois's avatar
POTTIER Francois committed
120 121 122 123
(* ------------------------------------------------------------------------ *)

(* A branch contains a series of producers and a semantic action. *)

124
and parameterized_branch =
125
    {
126 127
      pr_branch_position           : Positions.t;
      pr_producers                 : producer list;
128
      pr_action                    : action;
129
      pr_branch_prec_annotation    : branch_prec_annotation;
130
      pr_branch_production_level   : branch_production_level
131 132
    }

POTTIER Francois's avatar
POTTIER Francois committed
133 134 135 136
(* ------------------------------------------------------------------------ *)

(* A rule has a header and several branches. *)

137 138
type parameterized_rule =
    {
139 140 141 142 143 144
      pr_public_flag       : bool;
      pr_inline_flag       : bool;
      pr_nt                : nonterminal;
      pr_positions         : Positions.t list;
      pr_parameters        : symbol list;
      pr_branches          : parameterized_branch list;
145 146
    }

POTTIER Francois's avatar
POTTIER Francois committed
147 148
(* ------------------------------------------------------------------------ *)

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
(* A declaration. (Only before joining.) *)

type declaration =

    (* Raw OCaml code. *)

  | DCode of Stretch.t

    (* Raw OCaml functor parameter. *)

  | DParameter of Stretch.ocamltype (* really a stretch *)

    (* Terminal symbol (token) declaration. *)

  | DToken of Stretch.ocamltype option * terminal

    (* Start symbol declaration. *)

  | DStart of nonterminal

    (* Priority and associativity declaration. *)

  | DTokenProperties of terminal * token_associativity * precedence_level

    (* Type declaration. *)

  | DType of Stretch.ocamltype * parameter

    (* On-error-reduce declaration. *)

179
  | DOnErrorReduce of parameter * on_error_reduce_level
180 181 182

(* ------------------------------------------------------------------------ *)

POTTIER Francois's avatar
POTTIER Francois committed
183 184
(* A partial grammar. (Only before joining.) *)

185
type partial_grammar =
186 187
    {
      pg_filename          : filename;
188
      pg_postlude           : postlude option;
189 190 191
      pg_declarations      : declaration Positions.located list;
      pg_rules             : parameterized_rule list;
    }
192

POTTIER Francois's avatar
POTTIER Francois committed
193 194 195 196 197 198
(* ------------------------------------------------------------------------ *)

(* A grammar. (Only after joining.) *)

(* The differences with partial grammars (above) are as follows:
   1. the file name is gone (there could be several file names, anyway).
199
   2. there can be several postludes.
POTTIER Francois's avatar
POTTIER Francois committed
200 201 202 203 204
   3. declarations are organized by kind: preludes, functor %parameters,
      %start symbols, %types, %tokens, %on_error_reduce.
   4. rules are stored in a map, indexed by symbol names, instead of a list.
 *)

205 206 207
type grammar =
    {
      p_preludes           : Stretch.t list;
208
      p_postludes          : postlude list;
209 210 211 212
      p_parameters         : Stretch.t list;
      p_start_symbols      : Positions.t StringMap.t;
      p_types              : (parameter * Stretch.ocamltype Positions.located) list;
      p_tokens             : token_properties StringMap.t;
213
      p_on_error_reduce    : (parameter * on_error_reduce_level) list;
POTTIER Francois's avatar
POTTIER Francois committed
214
      p_rules              : parameterized_rule StringMap.t;
215
    }