You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2778 lines
66 KiB
2778 lines
66 KiB
(**************************************************************************)
|
|
(* *)
|
|
(* OCaml *)
|
|
(* *)
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
(* *)
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
|
(* en Automatique. *)
|
|
(* *)
|
|
(* All rights reserved. This file is distributed under the terms of *)
|
|
(* the GNU Lesser General Public License version 2.1, with the *)
|
|
(* special exception on linking described in the file LICENSE. *)
|
|
(* *)
|
|
(**************************************************************************)
|
|
|
|
(* The parser definition *)
|
|
|
|
%{
|
|
%}
|
|
|
|
(* Tokens *)
|
|
|
|
%token AMPERAMPER
|
|
%token AMPERSAND
|
|
%token AND
|
|
%token AS
|
|
%token ASSERT
|
|
%token BACKQUOTE
|
|
%token BANG
|
|
%token BAR
|
|
%token BARBAR
|
|
%token BARRBRACKET
|
|
%token BEGIN
|
|
%token CHAR
|
|
%token CLASS
|
|
%token COLON
|
|
%token COLONCOLON
|
|
%token COLONEQUAL
|
|
%token COLONGREATER
|
|
%token COMMA
|
|
%token CONSTRAINT
|
|
%token DO
|
|
%token DONE
|
|
%token DOT
|
|
%token DOTDOT
|
|
%token DOWNTO
|
|
%token ELSE
|
|
%token END
|
|
%token EOF
|
|
%token EQUAL
|
|
%token EXCEPTION
|
|
%token EXTERNAL
|
|
%token FALSE
|
|
%token FLOAT
|
|
%token FOR
|
|
%token FUN
|
|
%token FUNCTION
|
|
%token FUNCTOR
|
|
%token GREATER
|
|
%token GREATERRBRACE
|
|
%token GREATERRBRACKET
|
|
%token IF
|
|
%token IN
|
|
%token INCLUDE
|
|
%token INFIXOP0
|
|
%token INFIXOP1
|
|
%token INFIXOP2
|
|
%token INFIXOP3
|
|
%token INFIXOP4
|
|
%token DOTOP
|
|
%token LETOP
|
|
%token ANDOP
|
|
%token INHERIT
|
|
%token INITIALIZER
|
|
%token INT
|
|
%token LABEL
|
|
%token LAZY
|
|
%token LBRACE
|
|
%token LBRACELESS
|
|
%token LBRACKET
|
|
%token LBRACKETBAR
|
|
%token LBRACKETLESS
|
|
%token LBRACKETGREATER
|
|
%token LBRACKETPERCENT
|
|
%token LBRACKETPERCENTPERCENT
|
|
%token LESS
|
|
%token LESSMINUS
|
|
%token LET
|
|
%token LIDENT
|
|
%token LPAREN
|
|
%token LBRACKETAT
|
|
%token LBRACKETATAT
|
|
%token LBRACKETATATAT
|
|
%token MATCH
|
|
%token METHOD
|
|
%token MINUS
|
|
%token MINUSDOT
|
|
%token MINUSGREATER
|
|
%token MODULE
|
|
%token MUTABLE
|
|
%token NEW
|
|
%token NONREC
|
|
%token OBJECT
|
|
%token OF
|
|
%token OPEN
|
|
%token OPTLABEL
|
|
%token OR
|
|
%token PERCENT
|
|
%token PLUS
|
|
%token PLUSDOT
|
|
%token PLUSEQ
|
|
%token PREFIXOP
|
|
%token PRIVATE
|
|
%token QUESTION
|
|
%token QUOTE
|
|
%token RBRACE
|
|
%token RBRACKET
|
|
%token REC
|
|
%token RPAREN
|
|
%token SEMI
|
|
%token SEMISEMI
|
|
%token HASH
|
|
%token HASHOP
|
|
%token SIG
|
|
%token STAR
|
|
%token STRING
|
|
%token STRUCT
|
|
%token THEN
|
|
%token TILDE
|
|
%token TO
|
|
%token TRUE
|
|
%token TRY
|
|
%token TYPE
|
|
%token UIDENT
|
|
%token UNDERSCORE
|
|
%token VAL
|
|
%token VIRTUAL
|
|
%token WHEN
|
|
%token WHILE
|
|
%token WITH
|
|
%token COMMENT
|
|
%token DOCSTRING
|
|
|
|
%token EOL
|
|
|
|
(* Precedences and associativities.
|
|
|
|
Tokens and rules have precedences. A reduce/reduce conflict is resolved
|
|
in favor of the first rule (in source file order). A shift/reduce conflict
|
|
is resolved by comparing the precedence and associativity of the token to
|
|
be shifted with those of the rule to be reduced.
|
|
|
|
By default, a rule has the precedence of its rightmost terminal (if any).
|
|
|
|
When there is a shift/reduce conflict between a rule and a token that
|
|
have the same precedence, it is resolved using the associativity:
|
|
if the token is left-associative, the parser will reduce; if
|
|
right-associative, the parser will shift; if non-associative,
|
|
the parser will declare a syntax error.
|
|
|
|
We will only use associativities with operators of the kind x * x -> x
|
|
for example, in the rules of the form expr: expr BINOP expr
|
|
in all other cases, we define two precedences if needed to resolve
|
|
conflicts.
|
|
|
|
The precedences must be listed from low to high.
|
|
*)
|
|
|
|
%nonassoc IN
|
|
%nonassoc below_SEMI
|
|
%nonassoc SEMI (* below EQUAL ({lbl=...; lbl=...}) *)
|
|
%nonassoc LET (* above SEMI ( ...; let ... in ...) *)
|
|
%nonassoc below_WITH
|
|
%nonassoc FUNCTION WITH (* below BAR (match ... with ...) *)
|
|
%nonassoc AND (* above WITH (module rec A: SIG with ... and ...) *)
|
|
%nonassoc THEN (* below ELSE (if ... then ...) *)
|
|
%nonassoc ELSE (* (if ... then ... else ...) *)
|
|
%nonassoc LESSMINUS (* below COLONEQUAL (lbl <- x := e) *)
|
|
%right COLONEQUAL (* expr (e := e := e) *)
|
|
%nonassoc AS
|
|
%left BAR (* pattern (p|p|p) *)
|
|
%nonassoc below_COMMA
|
|
%left COMMA (* expr/expr_comma_list (e,e,e) *)
|
|
%right MINUSGREATER (* function_type (t -> t -> t) *)
|
|
%right OR BARBAR (* expr (e || e || e) *)
|
|
%right AMPERSAND AMPERAMPER (* expr (e && e && e) *)
|
|
%nonassoc below_EQUAL
|
|
%left INFIXOP0 EQUAL LESS GREATER (* expr (e OP e OP e) *)
|
|
%right INFIXOP1 (* expr (e OP e OP e) *)
|
|
%nonassoc below_LBRACKETAT
|
|
%nonassoc LBRACKETAT
|
|
%right COLONCOLON (* expr (e :: e :: e) *)
|
|
%left INFIXOP2 PLUS PLUSDOT MINUS MINUSDOT PLUSEQ (* expr (e OP e OP e) *)
|
|
%left PERCENT INFIXOP3 STAR (* expr (e OP e OP e) *)
|
|
%right INFIXOP4 (* expr (e OP e OP e) *)
|
|
%nonassoc prec_unary_minus prec_unary_plus (* unary - *)
|
|
%nonassoc prec_constant_constructor (* cf. simple_expr (C versus C x) *)
|
|
%nonassoc prec_constr_appl (* above AS BAR COLONCOLON COMMA *)
|
|
%nonassoc below_HASH
|
|
%nonassoc HASH (* simple_expr/toplevel_directive *)
|
|
%left HASHOP
|
|
%nonassoc below_DOT
|
|
%nonassoc DOT DOTOP
|
|
(* Finally, the first tokens of simple_expr are above everything else. *)
|
|
%nonassoc BACKQUOTE BANG BEGIN CHAR FALSE FLOAT INT
|
|
LBRACE LBRACELESS LBRACKET LBRACKETBAR LIDENT LPAREN
|
|
NEW PREFIXOP STRING TRUE UIDENT
|
|
LBRACKETPERCENT
|
|
|
|
|
|
(* Entry points *)
|
|
|
|
%start<unit> implementation (* for implementation files *)
|
|
%start<unit> interface (* for interface files *)
|
|
%%
|
|
|
|
(* macros *)
|
|
%inline extra_str(symb): symb { };
|
|
%inline extra_sig(symb): symb { };
|
|
%inline extra_cstr(symb): symb { };
|
|
%inline extra_csig(symb): symb { };
|
|
%inline extra_def(symb): symb { };
|
|
%inline extra_text(symb): symb { };
|
|
%inline extra_rhs(symb): symb { };
|
|
%inline mkrhs(symb): symb { }
|
|
;
|
|
|
|
%inline text_str(symb): symb { }
|
|
%inline text_str_SEMISEMI: SEMISEMI { [] }
|
|
%inline text_sig(symb): symb { }
|
|
%inline text_sig_SEMISEMI: SEMISEMI { [] }
|
|
%inline text_def(symb): symb { }
|
|
%inline top_def(symb): symb { }
|
|
%inline text_cstr(symb): symb { [] }
|
|
%inline text_csig(symb): symb { [] }
|
|
|
|
(* Using this %inline definition means that we do not control precisely
|
|
when [mark_rhs_docs] is called, but I don't think this matters. *)
|
|
%inline mark_rhs_docs(symb): symb { }
|
|
|
|
%inline op(symb): symb { }
|
|
|
|
%inline mkloc(symb): symb { }
|
|
|
|
%inline mkexp(symb): symb { }
|
|
%inline mkpat(symb): symb { }
|
|
%inline mktyp(symb): symb { }
|
|
%inline mkstr(symb): symb { }
|
|
%inline mksig(symb): symb { }
|
|
%inline mkmod(symb): symb { }
|
|
%inline mkmty(symb): symb { }
|
|
%inline mkcty(symb): symb { }
|
|
%inline mkctf(symb): symb { }
|
|
%inline mkcf(symb): symb { }
|
|
%inline mkclass(symb): symb { }
|
|
|
|
%inline wrap_mkstr_ext(symb): symb { }
|
|
%inline wrap_mksig_ext(symb): symb { }
|
|
|
|
%inline mk_directive_arg(symb): symb { }
|
|
|
|
(* Generic definitions *)
|
|
|
|
(* [iloption(X)] recognizes either nothing or [X]. Assuming [X] produces
|
|
an OCaml list, it produces an OCaml list, too. *)
|
|
|
|
%inline iloption(X):
|
|
(* nothing *)
|
|
{ [] }
|
|
| x = X
|
|
{ [] }
|
|
|
|
(* [llist(X)] recognizes a possibly empty list of [X]s. It is left-recursive. *)
|
|
|
|
reversed_llist(X):
|
|
(* empty *)
|
|
{ [] }
|
|
| xs = reversed_llist(X) x = X
|
|
{ [] }
|
|
|
|
%inline llist(X):
|
|
xs = reversed_llist(X)
|
|
{ [] }
|
|
|
|
(* [reversed_nonempty_llist(X)] recognizes a nonempty list of [X]s, and produces
|
|
an OCaml list in reverse order -- that is, the last element in the input text
|
|
appears first in this list. Its definition is left-recursive. *)
|
|
|
|
reversed_nonempty_llist(X):
|
|
x = X
|
|
{ [] }
|
|
| xs = reversed_nonempty_llist(X) x = X
|
|
{ [] }
|
|
|
|
(* [nonempty_llist(X)] recognizes a nonempty list of [X]s, and produces an OCaml
|
|
list in direct order -- that is, the first element in the input text appears
|
|
first in this list. *)
|
|
|
|
%inline nonempty_llist(X):
|
|
xs = reversed_nonempty_llist(X)
|
|
{ [] }
|
|
|
|
(* [reversed_separated_nonempty_llist(separator, X)] recognizes a nonempty list
|
|
of [X]s, separated with [separator]s, and produces an OCaml list in reverse
|
|
order -- that is, the last element in the input text appears first in this
|
|
list. Its definition is left-recursive. *)
|
|
|
|
(* [inline_reversed_separated_nonempty_llist(separator, X)] is semantically
|
|
equivalent to [reversed_separated_nonempty_llist(separator, X)], but is
|
|
marked %inline, which means that the case of a list of length one and
|
|
the case of a list of length more than one will be distinguished at the
|
|
use site, and will give rise there to two productions. This can be used
|
|
to avoid certain conflicts. *)
|
|
|
|
%inline inline_reversed_separated_nonempty_llist(separator, X):
|
|
x = X
|
|
{ []}
|
|
| xs = reversed_separated_nonempty_llist(separator, X)
|
|
separator
|
|
x = X
|
|
{ []}
|
|
|
|
reversed_separated_nonempty_llist(separator, X):
|
|
xs = inline_reversed_separated_nonempty_llist(separator, X)
|
|
{ []}
|
|
|
|
(* [separated_nonempty_llist(separator, X)] recognizes a nonempty list of [X]s,
|
|
separated with [separator]s, and produces an OCaml list in direct order --
|
|
that is, the first element in the input text appears first in this list. *)
|
|
|
|
%inline separated_nonempty_llist(separator, X):
|
|
xs = reversed_separated_nonempty_llist(separator, X)
|
|
{ []}
|
|
|
|
%inline inline_separated_nonempty_llist(separator, X):
|
|
xs = inline_reversed_separated_nonempty_llist(separator, X)
|
|
{ []}
|
|
|
|
(* [reversed_separated_nontrivial_llist(separator, X)] recognizes a list of at
|
|
least two [X]s, separated with [separator]s, and produces an OCaml list in
|
|
reverse order -- that is, the last element in the input text appears first
|
|
in this list. Its definition is left-recursive. *)
|
|
|
|
reversed_separated_nontrivial_llist(separator, X):
|
|
xs = reversed_separated_nontrivial_llist(separator, X)
|
|
separator
|
|
x = X
|
|
{ []}
|
|
| x1 = X
|
|
separator
|
|
x2 = X
|
|
{ []}
|
|
|
|
(* [separated_nontrivial_llist(separator, X)] recognizes a list of at least
|
|
two [X]s, separated with [separator]s, and produces an OCaml list in direct
|
|
order -- that is, the first element in the input text appears first in this
|
|
list. *)
|
|
|
|
%inline separated_nontrivial_llist(separator, X):
|
|
xs = reversed_separated_nontrivial_llist(separator, X)
|
|
{ []}
|
|
|
|
(* [separated_or_terminated_nonempty_list(delimiter, X)] recognizes a nonempty
|
|
list of [X]s, separated with [delimiter]s, and optionally terminated with a
|
|
final [delimiter]. Its definition is right-recursive. *)
|
|
|
|
separated_or_terminated_nonempty_list(delimiter, X):
|
|
x = X ioption(delimiter)
|
|
{ []}
|
|
| x = X
|
|
delimiter
|
|
xs = separated_or_terminated_nonempty_list(delimiter, X)
|
|
{ []}
|
|
|
|
(* [reversed_preceded_or_separated_nonempty_llist(delimiter, X)] recognizes a
|
|
nonempty list of [X]s, separated with [delimiter]s, and optionally preceded
|
|
with a leading [delimiter]. It produces an OCaml list in reverse order. Its
|
|
definition is left-recursive. *)
|
|
|
|
reversed_preceded_or_separated_nonempty_llist(delimiter, X):
|
|
ioption(delimiter) x = X
|
|
{ []}
|
|
| xs = reversed_preceded_or_separated_nonempty_llist(delimiter, X)
|
|
delimiter
|
|
x = X
|
|
{ []}
|
|
|
|
(* [preceded_or_separated_nonempty_llist(delimiter, X)] recognizes a nonempty
|
|
list of [X]s, separated with [delimiter]s, and optionally preceded with a
|
|
leading [delimiter]. It produces an OCaml list in direct order. *)
|
|
|
|
%inline preceded_or_separated_nonempty_llist(delimiter, X):
|
|
xs = reversed_preceded_or_separated_nonempty_llist(delimiter, X)
|
|
{ []}
|
|
|
|
(* [bar_llist(X)] recognizes a nonempty list of [X]'s, separated with BARs,
|
|
with an optional leading BAR. We assume that [X] is itself parameterized
|
|
with an opening symbol, which can be [epsilon] or [BAR]. *)
|
|
|
|
(* This construction may seem needlessly complicated: one might think that
|
|
using [preceded_or_separated_nonempty_llist(BAR, X)], where [X] is *not*
|
|
itself parameterized, would be sufficient. Indeed, this simpler approach
|
|
would recognize the same language. However, the two approaches differ in
|
|
the footprint of [X]. We want the start location of [X] to include [BAR]
|
|
when present. In the future, we might consider switching to the simpler
|
|
definition, at the cost of producing slightly different locations. TODO *)
|
|
|
|
reversed_bar_llist(X):
|
|
(* An [X] without a leading BAR. *)
|
|
x = X(epsilon)
|
|
{ [] }
|
|
| (* An [X] with a leading BAR. *)
|
|
x = X(BAR)
|
|
{ [] }
|
|
| (* An initial list, followed with a BAR and an [X]. *)
|
|
xs = reversed_bar_llist(X)
|
|
x = X(BAR)
|
|
{ [] }
|
|
|
|
%inline bar_llist(X):
|
|
xs = reversed_bar_llist(X)
|
|
{ [] }
|
|
|
|
(* [xlist(A, B)] recognizes [AB*]. We assume that the semantic value for [A]
|
|
is a pair [x, b], while the semantic value for [B*] is a list [bs].
|
|
We return the pair [x, b :: bs]. *)
|
|
|
|
%inline xlist(A, B):
|
|
a = A bs = B*
|
|
{ [] }
|
|
|
|
(* [listx(delimiter, X, Y)] recognizes a nonempty list of [X]s, optionally
|
|
followed with a [Y], separated-or-terminated with [delimiter]s. The
|
|
semantic value is a pair of a list of [X]s and an optional [Y]. *)
|
|
|
|
listx(delimiter, X, Y):
|
|
| x = X ioption(delimiter)
|
|
{ [] }
|
|
| x = X delimiter y = Y delimiter?
|
|
{ [] }
|
|
| x = X
|
|
delimiter
|
|
tail = listx(delimiter, X, Y)
|
|
{ [] }
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Entry points. *)
|
|
|
|
(* An .ml file. *)
|
|
implementation:
|
|
structure EOF
|
|
{ }
|
|
;
|
|
|
|
(* An .mli file. *)
|
|
interface:
|
|
signature EOF
|
|
{ }
|
|
;
|
|
|
|
(* A toplevel phrase. *)
|
|
toplevel_phrase:
|
|
(* An expression with attributes, ended by a double semicolon. *)
|
|
extra_str(text_str(str_exp))
|
|
SEMISEMI
|
|
{ }
|
|
| (* A list of structure items, ended by a double semicolon. *)
|
|
extra_str(flatten(text_str(structure_item)*))
|
|
SEMISEMI
|
|
{ }
|
|
| (* A directive, ended by a double semicolon. *)
|
|
toplevel_directive
|
|
SEMISEMI
|
|
{ }
|
|
| (* End of input. *)
|
|
EOF
|
|
{ }
|
|
;
|
|
|
|
(* An .ml file that is read by #use. *)
|
|
use_file:
|
|
(* An optional standalone expression,
|
|
followed with a series of elements,
|
|
followed with EOF. *)
|
|
extra_def(append(
|
|
optional_use_file_standalone_expression,
|
|
flatten(use_file_element*)
|
|
))
|
|
EOF
|
|
{ }
|
|
;
|
|
|
|
(* An optional standalone expression is just an expression with attributes
|
|
(str_exp), with extra wrapping. *)
|
|
%inline optional_use_file_standalone_expression:
|
|
iloption(text_def(top_def(str_exp)))
|
|
{ [] }
|
|
;
|
|
|
|
(* An element in a #used file is one of the following:
|
|
- a double semicolon followed with an optional standalone expression;
|
|
- a structure item;
|
|
- a toplevel directive.
|
|
*)
|
|
%inline use_file_element:
|
|
preceded(SEMISEMI, optional_use_file_standalone_expression)
|
|
| text_def(top_def(structure_item))
|
|
| text_def(mark_rhs_docs(toplevel_directive))
|
|
{ }
|
|
;
|
|
|
|
parse_core_type:
|
|
core_type EOF
|
|
{ }
|
|
;
|
|
|
|
parse_expression:
|
|
seq_expr EOF
|
|
{ }
|
|
;
|
|
|
|
parse_pattern:
|
|
pattern EOF
|
|
{ }
|
|
;
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Functor arguments appear in module expressions and module types. *)
|
|
|
|
%inline functor_args:
|
|
reversed_nonempty_llist(functor_arg)
|
|
{ }
|
|
(* Produce a reversed list on purpose;
|
|
later processed using [fold_left]. *)
|
|
;
|
|
|
|
functor_arg:
|
|
(* An anonymous and untyped argument. *)
|
|
LPAREN RPAREN
|
|
{ }
|
|
| (* An argument accompanied with an explicit type. *)
|
|
LPAREN x = mkrhs(module_name) COLON mty = module_type RPAREN
|
|
{ }
|
|
;
|
|
|
|
module_name:
|
|
(* A named argument. *)
|
|
x = UIDENT
|
|
{ }
|
|
| (* An anonymous argument. *)
|
|
UNDERSCORE
|
|
{ }
|
|
;
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Module expressions. *)
|
|
|
|
(* The syntax of module expressions is not properly stratified. The cases of
|
|
functors, functor applications, and attributes interact and cause conflicts,
|
|
which are resolved by precedence declarations. This is concise but fragile.
|
|
Perhaps in the future an explicit stratification could be used. *)
|
|
|
|
module_expr:
|
|
| STRUCT attrs = attributes s = structure END
|
|
{ }
|
|
(*| STRUCT attributes structure error
|
|
{ }*)
|
|
| FUNCTOR attrs = attributes args = functor_args MINUSGREATER me = module_expr
|
|
{ }
|
|
| me = paren_module_expr
|
|
{ }
|
|
| me = module_expr attr = attribute
|
|
{ }
|
|
| mkmod(
|
|
(* A module identifier. *)
|
|
x = mkrhs(mod_longident)
|
|
{ }
|
|
| (* In a functor application, the actual argument must be parenthesized. *)
|
|
me1 = module_expr me2 = paren_module_expr
|
|
{ }
|
|
| (* Application to unit is sugar for application to an empty structure. *)
|
|
me1 = module_expr LPAREN RPAREN
|
|
{ }
|
|
| (* An extension. *)
|
|
ex = extension
|
|
{ }
|
|
)
|
|
{ }
|
|
;
|
|
|
|
(* A parenthesized module expression is a module expression that begins
|
|
and ends with parentheses. *)
|
|
|
|
paren_module_expr:
|
|
(* A module expression annotated with a module type. *)
|
|
LPAREN me = module_expr COLON mty = module_type RPAREN
|
|
{ }
|
|
(*| LPAREN module_expr COLON module_type error
|
|
{ }*)
|
|
| (* A module expression within parentheses. *)
|
|
LPAREN me = module_expr RPAREN
|
|
{ }
|
|
(*| LPAREN module_expr error
|
|
{ }*)
|
|
| (* A core language expression that produces a first-class module.
|
|
This expression can be annotated in various ways. *)
|
|
LPAREN VAL attrs = attributes e = expr_colon_package_type RPAREN
|
|
{ }
|
|
(*| LPAREN VAL attributes expr COLON error
|
|
{ }*)
|
|
(*| LPAREN VAL attributes expr COLONGREATER error
|
|
{ }*)
|
|
(*| LPAREN VAL attributes expr error
|
|
{ }*)
|
|
;
|
|
|
|
(* The various ways of annotating a core language expression that
|
|
produces a first-class module that we wish to unpack. *)
|
|
%inline expr_colon_package_type:
|
|
e = expr
|
|
{ }
|
|
| e = expr COLON ty = package_type
|
|
{ }
|
|
| e = expr COLON ty1 = package_type COLONGREATER ty2 = package_type
|
|
{ }
|
|
| e = expr COLONGREATER ty2 = package_type
|
|
{ }
|
|
;
|
|
|
|
(* A structure, which appears between STRUCT and END (among other places),
|
|
begins with an optional standalone expression, and continues with a list
|
|
of structure elements. *)
|
|
structure:
|
|
extra_str(append(
|
|
optional_structure_standalone_expression,
|
|
flatten(structure_element*)
|
|
))
|
|
{ }
|
|
;
|
|
|
|
(* An optional standalone expression is just an expression with attributes
|
|
(str_exp), with extra wrapping. *)
|
|
%inline optional_structure_standalone_expression:
|
|
items = iloption(mark_rhs_docs(text_str(str_exp)))
|
|
{ [] }
|
|
;
|
|
|
|
(* An expression with attributes, wrapped as a structure item. *)
|
|
%inline str_exp:
|
|
e = seq_expr
|
|
attrs = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* A structure element is one of the following:
|
|
- a double semicolon followed with an optional standalone expression;
|
|
- a structure item. *)
|
|
%inline structure_element:
|
|
append(text_str_SEMISEMI, optional_structure_standalone_expression)
|
|
| text_str(structure_item)
|
|
{ [] }
|
|
;
|
|
|
|
(* A structure item. *)
|
|
structure_item:
|
|
let_bindings(ext)
|
|
{ }
|
|
| mkstr(
|
|
item_extension post_item_attributes
|
|
{ }
|
|
| floating_attribute
|
|
{ }
|
|
)
|
|
| wrap_mkstr_ext(
|
|
primitive_declaration
|
|
{ }
|
|
| value_description
|
|
{ }
|
|
| type_declarations
|
|
{ }
|
|
| str_type_extension
|
|
{ }
|
|
| str_exception_declaration
|
|
{ }
|
|
| module_binding
|
|
{ }
|
|
| rec_module_bindings
|
|
{ }
|
|
| module_type_declaration
|
|
{ }
|
|
| open_declaration
|
|
{ }
|
|
| class_declarations
|
|
{ }
|
|
| class_type_declarations
|
|
{ }
|
|
| include_statement(module_expr)
|
|
{ }
|
|
)
|
|
{ }
|
|
;
|
|
|
|
(* A single module binding. *)
|
|
%inline module_binding:
|
|
MODULE
|
|
ext = ext attrs1 = attributes
|
|
name = mkrhs(module_name)
|
|
body = module_binding_body
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* The body (right-hand side) of a module binding. *)
|
|
module_binding_body:
|
|
EQUAL me = module_expr
|
|
{ }
|
|
| mkmod(
|
|
COLON mty = module_type EQUAL me = module_expr
|
|
{ }
|
|
| arg = functor_arg body = module_binding_body
|
|
{ }
|
|
) { }
|
|
;
|
|
|
|
(* A group of recursive module bindings. *)
|
|
%inline rec_module_bindings:
|
|
xlist(rec_module_binding, and_module_binding)
|
|
{ }
|
|
;
|
|
|
|
(* The first binding in a group of recursive module bindings. *)
|
|
%inline rec_module_binding:
|
|
MODULE
|
|
ext = ext
|
|
attrs1 = attributes
|
|
REC
|
|
name = mkrhs(module_name)
|
|
body = module_binding_body
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* The following bindings in a group of recursive module bindings. *)
|
|
%inline and_module_binding:
|
|
AND
|
|
attrs1 = attributes
|
|
name = mkrhs(module_name)
|
|
body = module_binding_body
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Shared material between structures and signatures. *)
|
|
|
|
(* An [include] statement can appear in a structure or in a signature,
|
|
which is why this definition is parameterized. *)
|
|
%inline include_statement(thing):
|
|
INCLUDE
|
|
ext = ext
|
|
attrs1 = attributes
|
|
thing = thing
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* A module type declaration. *)
|
|
module_type_declaration:
|
|
MODULE TYPE
|
|
ext = ext
|
|
attrs1 = attributes
|
|
id = mkrhs(ident)
|
|
typ = preceded(EQUAL, module_type)?
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Opens. *)
|
|
|
|
open_declaration:
|
|
OPEN
|
|
override = override_flag
|
|
ext = ext
|
|
attrs1 = attributes
|
|
me = module_expr
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
open_description:
|
|
OPEN
|
|
override = override_flag
|
|
ext = ext
|
|
attrs1 = attributes
|
|
id = mkrhs(mod_ext_longident)
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
%inline open_dot_declaration: mkrhs(mod_longident)
|
|
{ }
|
|
;
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Module types *)
|
|
|
|
module_type:
|
|
| SIG attrs = attributes s = signature END
|
|
{ }
|
|
(*| SIG attributes signature error
|
|
{ }*)
|
|
| FUNCTOR attrs = attributes args = functor_args
|
|
MINUSGREATER mty = module_type
|
|
%prec below_WITH
|
|
{ }
|
|
| MODULE TYPE OF attributes module_expr %prec below_LBRACKETAT
|
|
{ }
|
|
| LPAREN module_type RPAREN
|
|
{ }
|
|
(*| LPAREN module_type error
|
|
{ }*)
|
|
| module_type attribute
|
|
{ }
|
|
| mkmty(
|
|
mkrhs(mty_longident)
|
|
{ }
|
|
| module_type MINUSGREATER module_type
|
|
%prec below_WITH
|
|
{ }
|
|
| module_type WITH separated_nonempty_llist(AND, with_constraint)
|
|
{ }
|
|
(* | LPAREN MODULE mkrhs(mod_longident) RPAREN
|
|
{ } *)
|
|
| extension
|
|
{ }
|
|
)
|
|
{ }
|
|
;
|
|
(* A signature, which appears between SIG and END (among other places),
|
|
is a list of signature elements. *)
|
|
signature:
|
|
extra_sig(flatten(signature_element*))
|
|
{ }
|
|
;
|
|
|
|
(* A signature element is one of the following:
|
|
- a double semicolon;
|
|
- a signature item. *)
|
|
%inline signature_element:
|
|
text_sig_SEMISEMI
|
|
| text_sig(signature_item)
|
|
{ [] }
|
|
;
|
|
|
|
(* A signature item. *)
|
|
signature_item:
|
|
| item_extension post_item_attributes
|
|
{ }
|
|
| mksig(
|
|
floating_attribute
|
|
{ }
|
|
)
|
|
{ }
|
|
| wrap_mksig_ext(
|
|
value_description
|
|
{ }
|
|
| primitive_declaration
|
|
{ }
|
|
| type_declarations
|
|
{ }
|
|
| type_subst_declarations
|
|
{ }
|
|
| sig_type_extension
|
|
{ }
|
|
| sig_exception_declaration
|
|
{ }
|
|
| module_declaration
|
|
{ }
|
|
| module_alias
|
|
{ }
|
|
| module_subst
|
|
{ }
|
|
| rec_module_declarations
|
|
{ }
|
|
| module_type_declaration
|
|
{ }
|
|
| open_description
|
|
{ }
|
|
| include_statement(module_type)
|
|
{ }
|
|
| class_descriptions
|
|
{ }
|
|
| class_type_declarations
|
|
{ }
|
|
)
|
|
{ }
|
|
|
|
(* A module declaration. *)
|
|
%inline module_declaration:
|
|
MODULE
|
|
ext = ext attrs1 = attributes
|
|
name = mkrhs(module_name)
|
|
body = module_declaration_body
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* The body (right-hand side) of a module declaration. *)
|
|
module_declaration_body:
|
|
COLON mty = module_type
|
|
{ }
|
|
| mkmty(
|
|
arg = functor_arg body = module_declaration_body
|
|
{ }
|
|
)
|
|
{ }
|
|
;
|
|
|
|
(* A module alias declaration (in a signature). *)
|
|
%inline module_alias:
|
|
MODULE
|
|
ext = ext attrs1 = attributes
|
|
name = mkrhs(module_name)
|
|
EQUAL
|
|
body = module_expr_alias
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
%inline module_expr_alias:
|
|
id = mkrhs(mod_longident)
|
|
{ }
|
|
;
|
|
(* A module substitution (in a signature). *)
|
|
module_subst:
|
|
MODULE
|
|
ext = ext attrs1 = attributes
|
|
uid = mkrhs(UIDENT)
|
|
COLONEQUAL
|
|
body = mkrhs(mod_ext_longident)
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
(*| MODULE ext attributes mkrhs(UIDENT) COLONEQUAL error
|
|
{ }*)
|
|
;
|
|
|
|
(* A group of recursive module declarations. *)
|
|
%inline rec_module_declarations:
|
|
xlist(rec_module_declaration, and_module_declaration)
|
|
{ }
|
|
;
|
|
%inline rec_module_declaration:
|
|
MODULE
|
|
ext = ext
|
|
attrs1 = attributes
|
|
REC
|
|
name = mkrhs(module_name)
|
|
COLON
|
|
mty = module_type
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
%inline and_module_declaration:
|
|
AND
|
|
attrs1 = attributes
|
|
name = mkrhs(module_name)
|
|
COLON
|
|
mty = module_type
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Class declarations. *)
|
|
|
|
%inline class_declarations:
|
|
xlist(class_declaration, and_class_declaration)
|
|
{ }
|
|
;
|
|
%inline class_declaration:
|
|
CLASS
|
|
ext = ext
|
|
attrs1 = attributes
|
|
virt = virtual_flag
|
|
params = formal_class_parameters
|
|
id = mkrhs(LIDENT)
|
|
body = class_fun_binding
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
%inline and_class_declaration:
|
|
AND
|
|
attrs1 = attributes
|
|
virt = virtual_flag
|
|
params = formal_class_parameters
|
|
id = mkrhs(LIDENT)
|
|
body = class_fun_binding
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
class_fun_binding:
|
|
EQUAL class_expr
|
|
{ }
|
|
| mkclass(
|
|
COLON class_type EQUAL class_expr
|
|
{ }
|
|
| labeled_simple_pattern class_fun_binding
|
|
{ }
|
|
) { }
|
|
;
|
|
|
|
formal_class_parameters:
|
|
params = class_parameters(type_parameter)
|
|
{ }
|
|
;
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Class expressions. *)
|
|
|
|
class_expr:
|
|
class_simple_expr
|
|
{ }
|
|
| FUN attributes class_fun_def
|
|
{ }
|
|
| let_bindings(no_ext) IN class_expr
|
|
{ }
|
|
| LET OPEN override_flag attributes mkrhs(mod_longident) IN class_expr
|
|
{ }
|
|
| class_expr attribute
|
|
{ }
|
|
| mkclass(
|
|
class_simple_expr nonempty_llist(labeled_simple_expr)
|
|
{ }
|
|
| extension
|
|
{ }
|
|
) { }
|
|
;
|
|
class_simple_expr:
|
|
| LPAREN class_expr RPAREN
|
|
{ }
|
|
(*| LPAREN class_expr error
|
|
{ }*)
|
|
| mkclass(
|
|
tys = actual_class_parameters cid = mkrhs(class_longident)
|
|
{ }
|
|
(*| OBJECT attributes class_structure error
|
|
{ }*)
|
|
| LPAREN class_expr COLON class_type RPAREN
|
|
{ }
|
|
(*| LPAREN class_expr COLON class_type error
|
|
{ }*)
|
|
) { }
|
|
| OBJECT attributes class_structure END
|
|
{ }
|
|
;
|
|
|
|
class_fun_def:
|
|
mkclass(
|
|
labeled_simple_pattern MINUSGREATER e = class_expr
|
|
| labeled_simple_pattern e = class_fun_def
|
|
{ }
|
|
) { }
|
|
;
|
|
%inline class_structure:
|
|
| class_self_pattern extra_cstr(class_fields)
|
|
{ }
|
|
;
|
|
class_self_pattern:
|
|
LPAREN pattern RPAREN
|
|
{ }
|
|
| mkpat(LPAREN pattern COLON core_type RPAREN
|
|
{ })
|
|
{ }
|
|
| (* empty *)
|
|
{ }
|
|
;
|
|
%inline class_fields:
|
|
flatten(text_cstr(class_field)*)
|
|
{ }
|
|
;
|
|
class_field:
|
|
| INHERIT override_flag attributes class_expr
|
|
self = preceded(AS, mkrhs(LIDENT))?
|
|
post_item_attributes
|
|
{ }
|
|
| VAL value post_item_attributes
|
|
{ }
|
|
| METHOD method_ post_item_attributes
|
|
{ }
|
|
| CONSTRAINT attributes constrain_field post_item_attributes
|
|
{ }
|
|
| INITIALIZER attributes seq_expr post_item_attributes
|
|
{ }
|
|
| item_extension post_item_attributes
|
|
{ }
|
|
| mkcf(floating_attribute
|
|
{ })
|
|
{ }
|
|
;
|
|
value:
|
|
no_override_flag
|
|
attrs = attributes
|
|
mutable_ = virtual_with_mutable_flag
|
|
label = mkrhs(label) COLON ty = core_type
|
|
{ }
|
|
| override_flag attributes mutable_flag mkrhs(label) EQUAL seq_expr
|
|
{ }
|
|
| override_flag attributes mutable_flag mkrhs(label) type_constraint
|
|
EQUAL seq_expr
|
|
{ }
|
|
;
|
|
method_:
|
|
no_override_flag
|
|
attrs = attributes
|
|
private_ = virtual_with_private_flag
|
|
label = mkrhs(label) COLON ty = poly_type
|
|
{ }
|
|
| override_flag attributes private_flag mkrhs(label) strict_binding
|
|
{ }
|
|
| override_flag attributes private_flag mkrhs(label)
|
|
COLON poly_type EQUAL seq_expr
|
|
{ }
|
|
| override_flag attributes private_flag mkrhs(label) COLON TYPE lident_list
|
|
DOT core_type EQUAL seq_expr
|
|
{ }
|
|
;
|
|
|
|
(* Class types *)
|
|
|
|
class_type:
|
|
class_signature
|
|
{ }
|
|
| mkcty(
|
|
label = arg_label
|
|
domain = tuple_type
|
|
MINUSGREATER
|
|
codomain = class_type
|
|
{ }
|
|
) { }
|
|
;
|
|
class_signature:
|
|
mkcty(
|
|
tys = actual_class_parameters cid = mkrhs(clty_longident)
|
|
{ }
|
|
| extension
|
|
{ }
|
|
) { }
|
|
| OBJECT attributes class_sig_body END
|
|
{ }
|
|
(*| OBJECT attributes class_sig_body error
|
|
{ }*)
|
|
| class_signature attribute
|
|
{ }
|
|
| LET OPEN override_flag attributes mkrhs(mod_longident) IN class_signature
|
|
{ }
|
|
;
|
|
%inline class_parameters(parameter):
|
|
| (* empty *)
|
|
{ }
|
|
| LBRACKET params = separated_nonempty_llist(COMMA, parameter) RBRACKET
|
|
{ }
|
|
;
|
|
%inline actual_class_parameters:
|
|
tys = class_parameters(core_type)
|
|
{ }
|
|
;
|
|
%inline class_sig_body:
|
|
class_self_type extra_csig(class_sig_fields)
|
|
{ }
|
|
;
|
|
class_self_type:
|
|
LPAREN core_type RPAREN
|
|
{ }
|
|
| mktyp((* empty *) { })
|
|
{ }
|
|
;
|
|
%inline class_sig_fields:
|
|
flatten(text_csig(class_sig_field)*)
|
|
{ }
|
|
;
|
|
class_sig_field:
|
|
INHERIT attributes class_signature post_item_attributes
|
|
{ }
|
|
| VAL attributes value_type post_item_attributes
|
|
{ }
|
|
| METHOD attributes private_virtual_flags mkrhs(label) COLON poly_type
|
|
post_item_attributes
|
|
{ }
|
|
| CONSTRAINT attributes constrain_field post_item_attributes
|
|
{ }
|
|
| item_extension post_item_attributes
|
|
{ }
|
|
| mkctf(floating_attribute
|
|
{ })
|
|
{ }
|
|
;
|
|
%inline value_type:
|
|
flags = mutable_virtual_flags
|
|
label = mkrhs(label)
|
|
COLON
|
|
ty = core_type
|
|
{ }
|
|
;
|
|
%inline constrain:
|
|
core_type EQUAL core_type
|
|
{ }
|
|
;
|
|
constrain_field:
|
|
core_type EQUAL core_type
|
|
{ }
|
|
;
|
|
(* A group of class descriptions. *)
|
|
%inline class_descriptions:
|
|
xlist(class_description, and_class_description)
|
|
{ }
|
|
;
|
|
%inline class_description:
|
|
CLASS
|
|
ext = ext
|
|
attrs1 = attributes
|
|
virt = virtual_flag
|
|
params = formal_class_parameters
|
|
id = mkrhs(LIDENT)
|
|
COLON
|
|
cty = class_type
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
%inline and_class_description:
|
|
AND
|
|
attrs1 = attributes
|
|
virt = virtual_flag
|
|
params = formal_class_parameters
|
|
id = mkrhs(LIDENT)
|
|
COLON
|
|
cty = class_type
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
class_type_declarations:
|
|
xlist(class_type_declaration, and_class_type_declaration)
|
|
{ }
|
|
;
|
|
%inline class_type_declaration:
|
|
CLASS TYPE
|
|
ext = ext
|
|
attrs1 = attributes
|
|
virt = virtual_flag
|
|
params = formal_class_parameters
|
|
id = mkrhs(LIDENT)
|
|
EQUAL
|
|
csig = class_signature
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
%inline and_class_type_declaration:
|
|
AND
|
|
attrs1 = attributes
|
|
virt = virtual_flag
|
|
params = formal_class_parameters
|
|
id = mkrhs(LIDENT)
|
|
EQUAL
|
|
csig = class_signature
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* Core expressions *)
|
|
|
|
seq_expr:
|
|
| expr %prec below_SEMI { }
|
|
| expr SEMI { }
|
|
| mkexp(expr SEMI seq_expr
|
|
{ })
|
|
{ }
|
|
| expr SEMI PERCENT attr_id seq_expr
|
|
{ }
|
|
;
|
|
labeled_simple_pattern:
|
|
QUESTION LPAREN label_let_pattern opt_default RPAREN
|
|
{ }
|
|
| QUESTION label_var
|
|
{ }
|
|
| OPTLABEL LPAREN let_pattern opt_default RPAREN
|
|
{ }
|
|
| OPTLABEL pattern_var
|
|
{ }
|
|
| TILDE LPAREN label_let_pattern RPAREN
|
|
{ }
|
|
| TILDE label_var
|
|
{ }
|
|
| LABEL simple_pattern
|
|
{ }
|
|
| simple_pattern
|
|
{ }
|
|
;
|
|
|
|
pattern_var:
|
|
mkpat(
|
|
mkrhs(LIDENT) { }
|
|
| UNDERSCORE { }
|
|
) { }
|
|
;
|
|
|
|
%inline opt_default:
|
|
preceded(EQUAL, seq_expr)?
|
|
{ }
|
|
;
|
|
label_let_pattern:
|
|
x = label_var
|
|
{ }
|
|
| x = label_var COLON cty = core_type
|
|
{ }
|
|
;
|
|
%inline label_var:
|
|
mkrhs(LIDENT)
|
|
{ }
|
|
;
|
|
let_pattern:
|
|
pattern
|
|
{ }
|
|
| mkpat(pattern COLON core_type
|
|
{ })
|
|
{ }
|
|
;
|
|
|
|
expr:
|
|
simple_expr %prec below_HASH
|
|
{ }
|
|
| expr_attrs
|
|
{ }
|
|
| mkexp(expr_)
|
|
{ }
|
|
| let_bindings(ext) IN seq_expr
|
|
{ }
|
|
| pbop_op = mkrhs(LETOP) bindings = letop_bindings IN body = seq_expr
|
|
{ }
|
|
| expr COLONCOLON expr
|
|
{ }
|
|
| mkrhs(label) LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOT mkrhs(label_longident) LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOT LPAREN seq_expr RPAREN LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOT LBRACKET seq_expr RBRACKET LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOT LBRACE expr RBRACE LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOTOP LBRACKET expr_semi_list RBRACKET LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOTOP LPAREN expr_semi_list RPAREN LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOTOP LBRACE expr_semi_list RBRACE LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOT mod_longident DOTOP LBRACKET expr_semi_list RBRACKET
|
|
LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOT mod_longident DOTOP LPAREN expr_semi_list RPAREN
|
|
LESSMINUS expr
|
|
{ }
|
|
| simple_expr DOT mod_longident DOTOP LBRACE expr_semi_list RBRACE
|
|
LESSMINUS expr
|
|
{ }
|
|
| expr attribute
|
|
{ }
|
|
| UNDERSCORE
|
|
{ }
|
|
;
|
|
%inline expr_attrs:
|
|
| LET MODULE ext_attributes mkrhs(module_name) module_binding_body IN seq_expr
|
|
{ }
|
|
| LET EXCEPTION ext_attributes let_exception_declaration IN seq_expr
|
|
{ }
|
|
| LET OPEN override_flag ext_attributes module_expr IN seq_expr
|
|
{ }
|
|
| FUNCTION ext_attributes match_cases
|
|
{ }
|
|
| FUN ext_attributes labeled_simple_pattern fun_def
|
|
{ }
|
|
| FUN ext_attributes LPAREN TYPE lident_list RPAREN fun_def
|
|
{ }
|
|
| MATCH ext_attributes seq_expr WITH match_cases
|
|
{ }
|
|
| TRY ext_attributes seq_expr WITH match_cases
|
|
{ }
|
|
(*| TRY ext_attributes seq_expr WITH error
|
|
{ }*)
|
|
| IF ext_attributes seq_expr THEN expr ELSE expr
|
|
{ }
|
|
| IF ext_attributes seq_expr THEN expr
|
|
{ }
|
|
| WHILE ext_attributes seq_expr DO seq_expr DONE
|
|
{ }
|
|
| FOR ext_attributes pattern EQUAL seq_expr direction_flag seq_expr DO
|
|
seq_expr DONE
|
|
{ }
|
|
| ASSERT ext_attributes simple_expr %prec below_HASH
|
|
{ }
|
|
| LAZY ext_attributes simple_expr %prec below_HASH
|
|
{ }
|
|
| OBJECT ext_attributes class_structure END
|
|
{ }
|
|
(*| OBJECT ext_attributes class_structure error
|
|
{ }*)
|
|
;
|
|
%inline expr_:
|
|
| simple_expr nonempty_llist(labeled_simple_expr)
|
|
{ }
|
|
| expr_comma_list %prec below_COMMA
|
|
{ }
|
|
| mkrhs(constr_longident) simple_expr %prec below_HASH
|
|
{ }
|
|
| name_tag simple_expr %prec below_HASH
|
|
{ }
|
|
| e1 = expr op = op(infix_operator) e2 = expr
|
|
{ }
|
|
| subtractive expr %prec prec_unary_minus
|
|
{ }
|
|
| additive expr %prec prec_unary_plus
|
|
{ }
|
|
;
|
|
|
|
simple_expr:
|
|
| LPAREN seq_expr RPAREN
|
|
{ }
|
|
(*| LPAREN seq_expr error
|
|
{ }*)
|
|
| LPAREN seq_expr type_constraint RPAREN
|
|
{ }
|
|
| simple_expr DOT LPAREN seq_expr RPAREN
|
|
{ }
|
|
(*| simple_expr DOT LPAREN seq_expr error
|
|
{ }*)
|
|
| simple_expr DOT LBRACKET seq_expr RBRACKET
|
|
{ }
|
|
(*| simple_expr DOT LBRACKET seq_expr error
|
|
{ }*)
|
|
| simple_expr DOTOP LBRACKET expr_semi_list RBRACKET
|
|
{ }
|
|
(*| simple_expr DOTOP LBRACKET expr_semi_list error
|
|
{ }*)
|
|
| simple_expr DOTOP LPAREN expr_semi_list RPAREN
|
|
{ }
|
|
(*| simple_expr DOTOP LPAREN expr_semi_list error
|
|
{ }*)
|
|
| simple_expr DOTOP LBRACE expr_semi_list RBRACE
|
|
{ }
|
|
(*| simple_expr DOTOP LBRACE expr error
|
|
{ }*)
|
|
| simple_expr DOT mod_longident DOTOP LBRACKET expr_semi_list RBRACKET
|
|
{ }
|
|
(*| simple_expr DOT
|
|
mod_longident DOTOP LBRACKET expr_semi_list error
|
|
{ }*)
|
|
| simple_expr DOT mod_longident DOTOP LPAREN expr_semi_list RPAREN
|
|
{ }
|
|
(*| simple_expr DOT
|
|
mod_longident DOTOP LPAREN expr_semi_list error
|
|
{ }*)
|
|
| simple_expr DOT mod_longident DOTOP LBRACE expr_semi_list RBRACE
|
|
{ }
|
|
(*| simple_expr DOT
|
|
mod_longident DOTOP LBRACE expr_semi_list error
|
|
{ }*)
|
|
| simple_expr DOT LBRACE expr RBRACE
|
|
{ }
|
|
(*| simple_expr DOT LBRACE expr error
|
|
{ }*)
|
|
| simple_expr_attrs
|
|
{ }
|
|
| mkexp(simple_expr_)
|
|
{ }
|
|
;
|
|
%inline simple_expr_attrs:
|
|
| BEGIN ext = ext attrs = attributes e = seq_expr END
|
|
{ }
|
|
| BEGIN ext_attributes END
|
|
{ }
|
|
(*| BEGIN ext_attributes seq_expr error
|
|
{ }*)
|
|
| NEW ext_attributes mkrhs(class_longident)
|
|
{ }
|
|
| LPAREN MODULE ext_attributes module_expr RPAREN
|
|
{ }
|
|
| LPAREN MODULE ext_attributes module_expr COLON package_type RPAREN
|
|
{ }
|
|
(*| LPAREN MODULE ext_attributes module_expr COLON error
|
|
{ }*)
|
|
;
|
|
%inline simple_expr_:
|
|
| mkrhs(val_longident)
|
|
{ }
|
|
| constant
|
|
{ }
|
|
| mkrhs(constr_longident) %prec prec_constant_constructor
|
|
{ }
|
|
| name_tag %prec prec_constant_constructor
|
|
{ }
|
|
| op(PREFIXOP) simple_expr
|
|
{ }
|
|
| op(BANG {"!"}) simple_expr
|
|
{ }
|
|
| LBRACELESS object_expr_content GREATERRBRACE
|
|
{ }
|
|
(*| LBRACELESS object_expr_content error
|
|
{ }*)
|
|
| LBRACELESS GREATERRBRACE
|
|
{ }
|
|
| simple_expr DOT mkrhs(label_longident)
|
|
{ }
|
|
| od=open_dot_declaration DOT LPAREN seq_expr RPAREN
|
|
{ }
|
|
| od=open_dot_declaration DOT LBRACELESS object_expr_content GREATERRBRACE
|
|
{ }
|
|
(*| mod_longident DOT LBRACELESS object_expr_content error
|
|
{ }*)
|
|
| simple_expr HASH mkrhs(label)
|
|
{ }
|
|
| simple_expr op(HASHOP) simple_expr
|
|
{ }
|
|
| extension
|
|
{ }
|
|
| od=open_dot_declaration DOT mkrhs(LPAREN RPAREN { })
|
|
{ }
|
|
(*| mod_longident DOT LPAREN seq_expr error
|
|
{ }*)
|
|
| LBRACE record_expr_content RBRACE
|
|
{ }
|
|
(*| LBRACE record_expr_content error
|
|
{ }*)
|
|
| od=open_dot_declaration DOT LBRACE record_expr_content RBRACE
|
|
{ }
|
|
(*| mod_longident DOT LBRACE record_expr_content error
|
|
{ }*)
|
|
| LBRACKETBAR expr_semi_list BARRBRACKET
|
|
{ }
|
|
(*| LBRACKETBAR expr_semi_list error
|
|
{ }*)
|
|
| LBRACKETBAR BARRBRACKET
|
|
{ }
|
|
| od=open_dot_declaration DOT LBRACKETBAR expr_semi_list BARRBRACKET
|
|
{ }
|
|
| od=open_dot_declaration DOT LBRACKETBAR BARRBRACKET
|
|
{ }
|
|
(*| mod_longident DOT
|
|
LBRACKETBAR expr_semi_list error
|
|
{ }*)
|
|
| LBRACKET expr_semi_list RBRACKET
|
|
{ }
|
|
(*| LBRACKET expr_semi_list error
|
|
{ }*)
|
|
| od=open_dot_declaration DOT LBRACKET expr_semi_list RBRACKET
|
|
{ }
|
|
| od=open_dot_declaration DOT mkrhs(LBRACKET RBRACKET { })
|
|
{ }
|
|
(*| mod_longident DOT
|
|
LBRACKET expr_semi_list error
|
|
{ }*)
|
|
| od=open_dot_declaration DOT LPAREN MODULE ext_attributes module_expr COLON
|
|
package_type RPAREN
|
|
{ }
|
|
(*| mod_longident DOT
|
|
LPAREN MODULE ext_attributes module_expr COLON error
|
|
{ }*)
|
|
;
|
|
labeled_simple_expr:
|
|
simple_expr %prec below_HASH
|
|
{ }
|
|
| LABEL simple_expr %prec below_HASH
|
|
{ }
|
|
| TILDE label = LIDENT
|
|
{ }
|
|
| QUESTION label = LIDENT
|
|
{ }
|
|
| OPTLABEL simple_expr %prec below_HASH
|
|
{ }
|
|
;
|
|
%inline lident_list:
|
|
xs = mkrhs(LIDENT)+
|
|
{ }
|
|
;
|
|
%inline let_ident:
|
|
val_ident { }
|
|
;
|
|
let_binding_body:
|
|
let_ident strict_binding
|
|
{ }
|
|
| let_ident type_constraint EQUAL seq_expr
|
|
{ }
|
|
| let_ident COLON typevar_list DOT core_type EQUAL seq_expr
|
|
(* TODO: could replace [typevar_list DOT core_type]
|
|
with [mktyp(poly(core_type))]
|
|
and simplify the semantic action? *)
|
|
{ }
|
|
| let_ident COLON TYPE lident_list DOT core_type EQUAL seq_expr
|
|
{ }
|
|
| pattern_no_exn EQUAL seq_expr
|
|
{ }
|
|
| simple_pattern_not_ident COLON core_type EQUAL seq_expr
|
|
{ }
|
|
;
|
|
(* The formal parameter EXT can be instantiated with ext or no_ext
|
|
so as to indicate whether an extension is allowed or disallowed. *)
|
|
let_bindings(EXT):
|
|
let_binding(EXT) { }
|
|
| let_bindings(EXT) and_let_binding { }
|
|
;
|
|
%inline let_binding(EXT):
|
|
LET
|
|
ext = EXT
|
|
attrs1 = attributes
|
|
rec_flag = rec_flag
|
|
body = let_binding_body
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
and_let_binding:
|
|
AND
|
|
attrs1 = attributes
|
|
body = let_binding_body
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
letop_binding_body:
|
|
pat = let_ident exp = strict_binding
|
|
{ }
|
|
| pat = simple_pattern COLON typ = core_type EQUAL exp = seq_expr
|
|
{ }
|
|
| pat = pattern_no_exn EQUAL exp = seq_expr
|
|
{ }
|
|
;
|
|
letop_bindings:
|
|
body = letop_binding_body
|
|
{ }
|
|
| bindings = letop_bindings pbop_op = mkrhs(ANDOP) body = let_binding_body
|
|
{ }
|
|
;
|
|
fun_binding:
|
|
strict_binding
|
|
{ }
|
|
| type_constraint EQUAL seq_expr
|
|
{ }
|
|
;
|
|
strict_binding:
|
|
EQUAL seq_expr
|
|
{ }
|
|
| labeled_simple_pattern fun_binding
|
|
{ }
|
|
| LPAREN TYPE lident_list RPAREN fun_binding
|
|
{ }
|
|
;
|
|
%inline match_cases:
|
|
xs = preceded_or_separated_nonempty_llist(BAR, match_case)
|
|
{ }
|
|
;
|
|
match_case:
|
|
pattern MINUSGREATER seq_expr
|
|
{ }
|
|
| pattern WHEN seq_expr MINUSGREATER seq_expr
|
|
{ }
|
|
| pattern MINUSGREATER DOT
|
|
{ }
|
|
;
|
|
fun_def:
|
|
MINUSGREATER seq_expr
|
|
{ }
|
|
| mkexp(COLON atomic_type MINUSGREATER seq_expr
|
|
{ })
|
|
{ }
|
|
(* Cf #5939: we used to accept (fun p when e0 -> e) *)
|
|
| labeled_simple_pattern fun_def
|
|
{ }
|
|
| LPAREN TYPE lident_list RPAREN fun_def
|
|
{ }
|
|
;
|
|
%inline expr_comma_list:
|
|
es = separated_nontrivial_llist(COMMA, expr)
|
|
{ }
|
|
;
|
|
record_expr_content:
|
|
eo = ioption(terminated(simple_expr, WITH))
|
|
fields = separated_or_terminated_nonempty_list(SEMI, record_expr_field)
|
|
{ }
|
|
;
|
|
%inline record_expr_field:
|
|
| label = mkrhs(label_longident)
|
|
c = type_constraint?
|
|
eo = preceded(EQUAL, expr)?
|
|
{ }
|
|
;
|
|
%inline object_expr_content:
|
|
xs = separated_or_terminated_nonempty_list(SEMI, object_expr_field)
|
|
{ }
|
|
;
|
|
%inline object_expr_field:
|
|
label = mkrhs(label)
|
|
oe = preceded(EQUAL, expr)?
|
|
{ }
|
|
;
|
|
%inline expr_semi_list:
|
|
es = separated_or_terminated_nonempty_list(SEMI, expr)
|
|
{ }
|
|
;
|
|
type_constraint:
|
|
COLON core_type { }
|
|
| COLON core_type COLONGREATER core_type { }
|
|
| COLONGREATER core_type { }
|
|
(*| COLON error { }*)
|
|
(*| COLONGREATER error { }*)
|
|
;
|
|
|
|
(* Patterns *)
|
|
|
|
(* Whereas [pattern] is an arbitrary pattern, [pattern_no_exn] is a pattern
|
|
that does not begin with the [EXCEPTION] keyword. Thus, [pattern_no_exn]
|
|
is the intersection of the context-free language [pattern] with the
|
|
regular language [^EXCEPTION .*].
|
|
|
|
Ideally, we would like to use [pattern] everywhere and check in a later
|
|
phase that EXCEPTION patterns are used only where they are allowed (there
|
|
is code in typing/typecore.ml to this end). Unfortunately, in the
|
|
definition of [let_binding_body], we cannot allow [pattern]. That would
|
|
create a shift/reduce conflict: upon seeing LET EXCEPTION ..., the parser
|
|
wouldn't know whether this is the beginning of a LET EXCEPTION construct or
|
|
the beginning of a LET construct whose pattern happens to begin with
|
|
EXCEPTION. The conflict is avoided there by using [pattern_no_exn] in the
|
|
definition of [let_binding_body].
|
|
|
|
In order to avoid duplication between the definitions of [pattern] and
|
|
[pattern_no_exn], we create a parameterized definition [pattern_(self)]
|
|
and instantiate it twice. *)
|
|
|
|
pattern:
|
|
pattern_(pattern)
|
|
{ }
|
|
| EXCEPTION ext_attributes pattern %prec prec_constr_appl
|
|
{ }
|
|
;
|
|
|
|
pattern_no_exn:
|
|
pattern_(pattern_no_exn)
|
|
{ }
|
|
;
|
|
|
|
%inline pattern_(self):
|
|
| self COLONCOLON pattern
|
|
{ }
|
|
| self attribute
|
|
{ }
|
|
| pattern_gen
|
|
{ }
|
|
| mkpat(
|
|
self AS mkrhs(val_ident)
|
|
{ }
|
|
(*| self AS error
|
|
{ }*)
|
|
| pattern_comma_list(self) %prec below_COMMA
|
|
{ }
|
|
(*| self COLONCOLON error
|
|
{ }*)
|
|
| self BAR pattern
|
|
{ }
|
|
(*| self BAR error
|
|
{ }*)
|
|
) { }
|
|
;
|
|
|
|
pattern_gen:
|
|
simple_pattern
|
|
{ }
|
|
| mkpat(
|
|
mkrhs(constr_longident) pattern %prec prec_constr_appl
|
|
{ }
|
|
| name_tag pattern %prec prec_constr_appl
|
|
{ }
|
|
) { }
|
|
| LAZY ext_attributes simple_pattern
|
|
{ }
|
|
;
|
|
simple_pattern:
|
|
mkpat(mkrhs(val_ident) %prec below_EQUAL
|
|
{ })
|
|
{ }
|
|
| simple_pattern_not_ident { }
|
|
;
|
|
|
|
simple_pattern_not_ident:
|
|
| LPAREN pattern RPAREN
|
|
{ }
|
|
| simple_delimited_pattern
|
|
{ }
|
|
| LPAREN MODULE ext_attributes mkrhs(module_name) RPAREN
|
|
{ }
|
|
| LPAREN MODULE ext_attributes mkrhs(module_name) COLON package_type RPAREN
|
|
{ }
|
|
| mkpat(simple_pattern_not_ident_)
|
|
{ }
|
|
;
|
|
%inline simple_pattern_not_ident_:
|
|
| UNDERSCORE
|
|
{ }
|
|
| signed_constant
|
|
{ }
|
|
| signed_constant DOTDOT signed_constant
|
|
{ }
|
|
| mkrhs(constr_longident)
|
|
{ }
|
|
| name_tag
|
|
{ }
|
|
| HASH mkrhs(type_longident)
|
|
{ }
|
|
| mkrhs(mod_longident) DOT simple_delimited_pattern
|
|
{ }
|
|
| mkrhs(mod_longident) DOT mkrhs(LBRACKET RBRACKET { })
|
|
{ }
|
|
| mkrhs(mod_longident) DOT mkrhs(LPAREN RPAREN { })
|
|
{ }
|
|
| mkrhs(mod_longident) DOT LPAREN pattern RPAREN
|
|
{ }
|
|
(*| mod_longident DOT LPAREN pattern error
|
|
{ }*)
|
|
(*| mod_longident DOT LPAREN error
|
|
{ }*)
|
|
(*| LPAREN pattern error
|
|
{ }*)
|
|
| LPAREN pattern COLON core_type RPAREN
|
|
{ }
|
|
(*| LPAREN pattern COLON core_type error
|
|
{ }*)
|
|
(*| LPAREN pattern COLON error
|
|
{ }*)
|
|
(*| LPAREN MODULE ext_attributes module_name COLON package_type
|
|
error
|
|
{ }*)
|
|
| extension
|
|
{ }
|
|
;
|
|
|
|
simple_delimited_pattern:
|
|
mkpat(
|
|
LBRACE record_pat_content RBRACE
|
|
{ }
|
|
(*| LBRACE record_pat_content error
|
|
{ }*)
|
|
| LBRACKET pattern_semi_list RBRACKET
|
|
{ }
|
|
(*| LBRACKET pattern_semi_list error
|
|
{ }*)
|
|
| LBRACKETBAR pattern_semi_list BARRBRACKET
|
|
{ }
|
|
| LBRACKETBAR BARRBRACKET
|
|
{ }
|
|
(*| LBRACKETBAR pattern_semi_list error
|
|
{ }*)
|
|
) { }
|
|
|
|
pattern_comma_list(self):
|
|
pattern_comma_list(self) COMMA pattern { }
|
|
| self COMMA pattern { }
|
|
(*| self COMMA error { }*)
|
|
;
|
|
%inline pattern_semi_list:
|
|
ps = separated_or_terminated_nonempty_list(SEMI, pattern)
|
|
{ }
|
|
;
|
|
(* A label-pattern list is a nonempty list of label-pattern pairs, optionally
|
|
followed with an UNDERSCORE, separated-or-terminated with semicolons. *)
|
|
%inline record_pat_content:
|
|
listx(SEMI, record_pat_field, UNDERSCORE)
|
|
{ }
|
|
;
|
|
%inline record_pat_field:
|
|
label = mkrhs(label_longident)
|
|
octy = preceded(COLON, core_type)?
|
|
opat = preceded(EQUAL, pattern)?
|
|
{ }
|
|
;
|
|
|
|
(* Value descriptions *)
|
|
|
|
value_description:
|
|
VAL
|
|
ext = ext
|
|
attrs1 = attributes
|
|
id = mkrhs(val_ident)
|
|
COLON
|
|
ty = core_type
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* Primitive declarations *)
|
|
|
|
primitive_declaration:
|
|
EXTERNAL
|
|
ext = ext
|
|
attrs1 = attributes
|
|
id = mkrhs(val_ident)
|
|
COLON
|
|
ty = core_type
|
|
EQUAL
|
|
prim = raw_string+
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
|
|
(* Type declarations and type substitutions. *)
|
|
|
|
(* Type declarations [type t = u] and type substitutions [type t := u] are very
|
|
similar, so we view them as instances of [generic_type_declarations]. In the
|
|
case of a type declaration, the use of [nonrec_flag] means that [NONREC] may
|
|
be absent or present, whereas in the case of a type substitution, the use of
|
|
[no_nonrec_flag] means that [NONREC] must be absent. The use of [type_kind]
|
|
versus [type_subst_kind] means that in the first case, we expect an [EQUAL]
|
|
sign, whereas in the second case, we expect [COLONEQUAL]. *)
|
|
|
|
%inline type_declarations:
|
|
generic_type_declarations(nonrec_flag, type_kind)
|
|
{ }
|
|
;
|
|
|
|
%inline type_subst_declarations:
|
|
generic_type_declarations(no_nonrec_flag, type_subst_kind)
|
|
{ }
|
|
;
|
|
|
|
(* A set of type declarations or substitutions begins with a
|
|
[generic_type_declaration] and continues with a possibly empty list of
|
|
[generic_and_type_declaration]s. *)
|
|
|
|
%inline generic_type_declarations(flag, kind):
|
|
xlist(
|
|
generic_type_declaration(flag, kind),
|
|
generic_and_type_declaration(kind)
|
|
)
|
|
{ }
|
|
;
|
|
|
|
(* [generic_type_declaration] and [generic_and_type_declaration] look similar,
|
|
but are in reality different enough that it is difficult to share anything
|
|
between them. *)
|
|
|
|
generic_type_declaration(flag, kind):
|
|
TYPE
|
|
ext = ext
|
|
attrs1 = attributes
|
|
flag = flag
|
|
params = type_parameters
|
|
id = mkrhs(LIDENT)
|
|
kind_priv_manifest = kind
|
|
cstrs = constraints
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
%inline generic_and_type_declaration(kind):
|
|
AND
|
|
attrs1 = attributes
|
|
params = type_parameters
|
|
id = mkrhs(LIDENT)
|
|
kind_priv_manifest = kind
|
|
cstrs = constraints
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
%inline constraints:
|
|
llist(preceded(CONSTRAINT, constrain))
|
|
{ }
|
|
;
|
|
(* Lots of %inline expansion are required for [nonempty_type_kind] to be
|
|
LR(1). At the cost of some manual expansion, it would be possible to give a
|
|
definition that leads to a smaller grammar (after expansion) and therefore
|
|
a smaller automaton. *)
|
|
nonempty_type_kind:
|
|
| priv = inline_private_flag
|
|
ty = core_type
|
|
{ }
|
|
| oty = type_synonym
|
|
priv = inline_private_flag
|
|
cs = constructor_declarations
|
|
{ }
|
|
| oty = type_synonym
|
|
priv = inline_private_flag
|
|
DOTDOT
|
|
{ }
|
|
| oty = type_synonym
|
|
priv = inline_private_flag
|
|
LBRACE ls = label_declarations RBRACE
|
|
{ }
|
|
;
|
|
%inline type_synonym:
|
|
ioption(terminated(core_type, EQUAL))
|
|
{ }
|
|
;
|
|
type_kind:
|
|
(*empty*)
|
|
{ }
|
|
| EQUAL nonempty_type_kind
|
|
{ }
|
|
;
|
|
%inline type_subst_kind:
|
|
COLONEQUAL nonempty_type_kind
|
|
{ }
|
|
;
|
|
type_parameters:
|
|
(* empty *)
|
|
{ }
|
|
| p = type_parameter
|
|
{ }
|
|
| LPAREN ps = separated_nonempty_llist(COMMA, type_parameter) RPAREN
|
|
{ }
|
|
;
|
|
type_parameter:
|
|
type_variance type_variable { }
|
|
;
|
|
type_variable:
|
|
mktyp(
|
|
QUOTE tyvar = ident
|
|
{ }
|
|
| UNDERSCORE
|
|
{ }
|
|
) { }
|
|
;
|
|
|
|
type_variance:
|
|
(* empty *) { }
|
|
| PLUS { }
|
|
| MINUS { }
|
|
;
|
|
|
|
(* A sequence of constructor declarations is either a single BAR, which
|
|
means that the list is empty, or a nonempty BAR-separated list of
|
|
declarations, with an optional leading BAR. *)
|
|
constructor_declarations:
|
|
| BAR
|
|
{ }
|
|
| cs = bar_llist(constructor_declaration)
|
|
{ }
|
|
;
|
|
(* A constructor declaration begins with an opening symbol, which can
|
|
be either epsilon or BAR. Note that this opening symbol is included
|
|
in the footprint $sloc. *)
|
|
(* Because [constructor_declaration] and [extension_constructor_declaration]
|
|
are identical except for their semantic actions, we introduce the symbol
|
|
[generic_constructor_declaration], whose semantic action is neutral -- it
|
|
merely returns a tuple. *)
|
|
generic_constructor_declaration(opening):
|
|
opening
|
|
cid = mkrhs(constr_ident)
|
|
args_res = generalized_constructor_arguments
|
|
attrs = attributes
|
|
{ }
|
|
;
|
|
%inline constructor_declaration(opening):
|
|
d = generic_constructor_declaration(opening)
|
|
{ }
|
|
;
|
|
str_exception_declaration:
|
|
sig_exception_declaration
|
|
{ }
|
|
| EXCEPTION
|
|
ext = ext
|
|
attrs1 = attributes
|
|
id = mkrhs(constr_ident)
|
|
EQUAL
|
|
lid = mkrhs(constr_longident)
|
|
attrs2 = attributes
|
|
attrs = post_item_attributes
|
|
{ }
|
|
;
|
|
sig_exception_declaration:
|
|
EXCEPTION
|
|
ext = ext
|
|
attrs1 = attributes
|
|
id = mkrhs(constr_ident)
|
|
args_res = generalized_constructor_arguments
|
|
attrs2 = attributes
|
|
attrs = post_item_attributes
|
|
{ }
|
|
;
|
|
%inline let_exception_declaration:
|
|
mkrhs(constr_ident) generalized_constructor_arguments attributes
|
|
{ }
|
|
;
|
|
generalized_constructor_arguments:
|
|
(*empty*) { }
|
|
| OF constructor_arguments { }
|
|
| COLON constructor_arguments MINUSGREATER atomic_type %prec below_HASH
|
|
{ }
|
|
| COLON atomic_type %prec below_HASH
|
|
{ }
|
|
;
|
|
|
|
constructor_arguments:
|
|
| tys = inline_separated_nonempty_llist(STAR, atomic_type)
|
|
%prec below_HASH
|
|
{ }
|
|
| LBRACE label_declarations RBRACE
|
|
{ }
|
|
;
|
|
label_declarations:
|
|
label_declaration { }
|
|
| label_declaration_semi { }
|
|
| label_declaration_semi label_declarations { }
|
|
;
|
|
label_declaration:
|
|
mutable_flag mkrhs(label) COLON poly_type_no_attr attributes
|
|
{ }
|
|
;
|
|
label_declaration_semi:
|
|
mutable_flag mkrhs(label) COLON poly_type_no_attr attributes SEMI attributes
|
|
{ }
|
|
;
|
|
|
|
(* Type Extensions *)
|
|
|
|
%inline str_type_extension:
|
|
type_extension(extension_constructor)
|
|
{ }
|
|
;
|
|
%inline sig_type_extension:
|
|
type_extension(extension_constructor_declaration)
|
|
{ }
|
|
;
|
|
%inline type_extension(declaration):
|
|
TYPE
|
|
ext = ext
|
|
attrs1 = attributes
|
|
no_nonrec_flag
|
|
params = type_parameters
|
|
tid = mkrhs(type_longident)
|
|
PLUSEQ
|
|
priv = private_flag
|
|
cs = bar_llist(declaration)
|
|
attrs2 = post_item_attributes
|
|
{ }
|
|
;
|
|
%inline extension_constructor(opening):
|
|
extension_constructor_declaration(opening)
|
|
{ }
|
|
| extension_constructor_rebind(opening)
|
|
{ }
|
|
;
|
|
%inline extension_constructor_declaration(opening):
|
|
d = generic_constructor_declaration(opening)
|
|
{ }
|
|
;
|
|
extension_constructor_rebind(opening):
|
|
opening
|
|
cid = mkrhs(constr_ident)
|
|
EQUAL
|
|
lid = mkrhs(constr_longident)
|
|
attrs = attributes
|
|
{ }
|
|
;
|
|
|
|
(* "with" constraints (additional type equations over signature components) *)
|
|
|
|
with_constraint:
|
|
TYPE type_parameters mkrhs(label_longident) with_type_binder
|
|
core_type_no_attr constraints
|
|
{ }
|
|
(* used label_longident instead of type_longident to disallow
|
|
functor applications in type path *)
|
|
| TYPE type_parameters mkrhs(label_longident)
|
|
COLONEQUAL core_type_no_attr
|
|
{ }
|
|
| MODULE mkrhs(mod_longident) EQUAL mkrhs(mod_ext_longident)
|
|
{ }
|
|
| MODULE mkrhs(mod_longident) COLONEQUAL mkrhs(mod_ext_longident)
|
|
{ }
|
|
;
|
|
with_type_binder:
|
|
EQUAL { }
|
|
| EQUAL PRIVATE { }
|
|
;
|
|
|
|
(* Polymorphic types *)
|
|
|
|
%inline typevar:
|
|
QUOTE mkrhs(ident)
|
|
{ }
|
|
;
|
|
%inline typevar_list:
|
|
nonempty_llist(typevar)
|
|
{ [] }
|
|
;
|
|
%inline poly(X):
|
|
typevar_list DOT X
|
|
{ }
|
|
;
|
|
possibly_poly(X):
|
|
X
|
|
{ }
|
|
| mktyp(poly(X))
|
|
{ }
|
|
;
|
|
%inline poly_type:
|
|
possibly_poly(core_type)
|
|
{ }
|
|
;
|
|
%inline poly_type_no_attr:
|
|
possibly_poly(core_type_no_attr)
|
|
{ }
|
|
;
|
|
|
|
(* -------------------------------------------------------------------------- *)
|
|
|
|
(* Core language types. *)
|
|
|
|
(* A core type (core_type) is a core type without attributes (core_type_no_attr)
|
|
followed with a list of attributes. *)
|
|
core_type:
|
|
core_type_no_attr
|
|
{ }
|
|
| core_type attribute
|
|
{ }
|
|
;
|
|
|
|
(* A core type without attributes is currently defined as an alias type, but
|
|
this could change in the future if new forms of types are introduced. From
|
|
the outside, one should use core_type_no_attr. *)
|
|
%inline core_type_no_attr:
|
|
alias_type
|
|
{ }
|
|
;
|
|
|
|
(* Alias types include:
|
|
- function types (see below);
|
|
- proper alias types: 'a -> int as 'a
|
|
*)
|
|
alias_type:
|
|
function_type
|
|
{ }
|
|
| mktyp(
|
|
ty = alias_type AS QUOTE tyvar = ident
|
|
{ }
|
|
)
|
|
{ }
|
|
;
|
|
|
|
(* Function types include:
|
|
- tuple types (see below);
|
|
- proper function types: int -> int
|
|
foo: int -> int
|
|
?foo: int -> int
|
|
*)
|
|
function_type:
|
|
| ty = tuple_type
|
|
%prec MINUSGREATER
|
|
{ }
|
|
| mktyp(
|
|
label = arg_label
|
|
domain = extra_rhs(tuple_type)
|
|
MINUSGREATER
|
|
codomain = function_type
|
|
{ }
|
|
)
|
|
{ }
|
|
;
|
|
%inline arg_label:
|
|
| label = optlabel
|
|
{ }
|
|
| label = LIDENT COLON
|
|
{ }
|
|
| (* empty *)
|
|
{ }
|
|
;
|
|
(* Tuple types include:
|
|
- atomic types (see below);
|
|
- proper tuple types: int * int * int list
|
|
A proper tuple type is a star-separated list of at least two atomic types.
|
|
*)
|
|
tuple_type:
|
|
| ty = atomic_type
|
|
%prec below_HASH
|
|
{ }
|
|
| mktyp(
|
|
tys = separated_nontrivial_llist(STAR, atomic_type)
|
|
{ }
|
|
)
|
|
{ }
|
|
;
|
|
|
|
(* Atomic types are the most basic level in the syntax of types.
|
|
Atomic types include:
|
|
- types between parentheses: (int -> int)
|
|
- first-class module types: (module S)
|
|
- type variables: 'a
|
|
- applications of type constructors: int, int list, int option list
|
|
- variant types: [`A]
|
|
*)
|
|
atomic_type:
|
|
| LPAREN core_type RPAREN
|
|
{ }
|
|
| LPAREN MODULE ext_attributes package_type RPAREN
|
|
{ }
|
|
| mktyp( (* begin mktyp group *)
|
|
QUOTE ident
|
|
{ }
|
|
| UNDERSCORE
|
|
{ }
|
|
| tys = actual_type_parameters
|
|
tid = mkrhs(type_longident)
|
|
{ }
|
|
| LESS meth_list GREATER
|
|
{ }
|
|
| LESS GREATER
|
|
{ }
|
|
| tys = actual_type_parameters
|
|
HASH
|
|
cid = mkrhs(class_longident)
|
|
{ }
|
|
| LBRACKET tag_field RBRACKET
|
|
(* not row_field; see CONFLICTS *)
|
|
{ }
|
|
| LBRACKET BAR row_field_list RBRACKET
|
|
{ }
|
|
| LBRACKET row_field BAR row_field_list RBRACKET
|
|
{ }
|
|
| LBRACKETGREATER BAR? row_field_list RBRACKET
|
|
{ }
|
|
| LBRACKETGREATER RBRACKET
|
|
{ }
|
|
| LBRACKETLESS BAR? row_field_list RBRACKET
|
|
{ }
|
|
| LBRACKETLESS BAR? row_field_list GREATER name_tag_list RBRACKET
|
|
{ }
|
|
| extension
|
|
{ }
|
|
)
|
|
{ } (* end mktyp group *)
|
|
;
|
|
|
|
(* This is the syntax of the actual type parameters in an application of
|
|
a type constructor, such as int, int list, or (int, bool) Hashtbl.t.
|
|
We allow one of the following:
|
|
- zero parameters;
|
|
- one parameter:
|
|
an atomic type;
|
|
among other things, this can be an arbitrary type between parentheses;
|
|
- two or more parameters:
|
|
arbitrary types, between parentheses, separated with commas.
|
|
*)
|
|
%inline actual_type_parameters:
|
|
| (* empty *)
|
|
{ }
|
|
| ty = atomic_type
|
|
{ }
|
|
| LPAREN tys = separated_nontrivial_llist(COMMA, core_type) RPAREN
|
|
{ }
|
|
;
|
|
|
|
%inline package_type:
|
|
mktyp(module_type
|
|
{ })
|
|
{ }
|
|
;
|
|
%inline row_field_list:
|
|
separated_nonempty_llist(BAR, row_field)
|
|
{ }
|
|
;
|
|
row_field:
|
|
tag_field
|
|
{ }
|
|
| core_type
|
|
{ }
|
|
;
|
|
tag_field:
|
|
mkrhs(name_tag) OF opt_ampersand amper_type_list attributes
|
|
{ }
|
|
| mkrhs(name_tag) attributes
|
|
{ }
|
|
;
|
|
opt_ampersand:
|
|
AMPERSAND { }
|
|
| (* empty *) { }
|
|
;
|
|
%inline amper_type_list:
|
|
separated_nonempty_llist(AMPERSAND, core_type_no_attr)
|
|
{ }
|
|
;
|
|
%inline name_tag_list:
|
|
nonempty_llist(name_tag)
|
|
{ }
|
|
;
|
|
(* A method list (in an object type). *)
|
|
meth_list:
|
|
head = field_semi tail = meth_list
|
|
| head = inherit_field SEMI tail = meth_list
|
|
{ }
|
|
| head = field_semi
|
|
| head = inherit_field SEMI
|
|
{ }
|
|
| head = field
|
|
| head = inherit_field
|
|
{ }
|
|
| DOTDOT
|
|
{ }
|
|
;
|
|
%inline field:
|
|
mkrhs(label) COLON poly_type_no_attr attributes
|
|
{ }
|
|
;
|
|
|
|
%inline field_semi:
|
|
mkrhs(label) COLON poly_type_no_attr attributes SEMI attributes
|
|
{ }
|
|
;
|
|
|
|
%inline inherit_field:
|
|
ty = atomic_type
|
|
{ }
|
|
;
|
|
|
|
%inline label:
|
|
LIDENT { }
|
|
;
|
|
|
|
(* Constants *)
|
|
|
|
constant:
|
|
| INT { }
|
|
| CHAR { }
|
|
| STRING { }
|
|
| FLOAT { }
|
|
;
|
|
signed_constant:
|
|
constant { }
|
|
| MINUS INT { }
|
|
| MINUS FLOAT { }
|
|
| PLUS INT { }
|
|
| PLUS FLOAT { }
|
|
;
|
|
|
|
(* Identifiers and long identifiers *)
|
|
|
|
ident:
|
|
UIDENT { }
|
|
| LIDENT { }
|
|
;
|
|
val_ident:
|
|
LIDENT { }
|
|
| LPAREN operator RPAREN { }
|
|
(*| LPAREN operator error { }*)
|
|
(*| LPAREN error { }*)
|
|
(*| LPAREN MODULE error { }*)
|
|
;
|
|
operator:
|
|
PREFIXOP { }
|
|
| LETOP { }
|
|
| ANDOP { }
|
|
| DOTOP LPAREN index_mod RPAREN { }
|
|
| DOTOP LPAREN index_mod RPAREN LESSMINUS { }
|
|
| DOTOP LBRACKET index_mod RBRACKET { }
|
|
| DOTOP LBRACKET index_mod RBRACKET LESSMINUS { }
|
|
| DOTOP LBRACE index_mod RBRACE { }
|
|
| DOTOP LBRACE index_mod RBRACE LESSMINUS { }
|
|
| HASHOP { }
|
|
| BANG { }
|
|
| infix_operator { }
|
|
;
|
|
%inline infix_operator:
|
|
| op = INFIXOP0 { }
|
|
| op = INFIXOP1 { }
|
|
| op = INFIXOP2 { }
|
|
| op = INFIXOP3 { }
|
|
| op = INFIXOP4 { }
|
|
| PLUS { }
|
|
| PLUSDOT { }
|
|
| PLUSEQ { }
|
|
| MINUS { }
|
|
| MINUSDOT { }
|
|
| STAR { }
|
|
| PERCENT { }
|
|
| EQUAL { }
|
|
| LESS { }
|
|
| GREATER { }
|
|
| OR { }
|
|
| BARBAR { }
|
|
| AMPERSAND { }
|
|
| AMPERAMPER { }
|
|
| COLONEQUAL { }
|
|
;
|
|
index_mod:
|
|
| { }
|
|
| SEMI DOTDOT { }
|
|
;
|
|
constr_ident:
|
|
UIDENT { }
|
|
| LBRACKET RBRACKET { }
|
|
| LPAREN RPAREN { }
|
|
| LPAREN COLONCOLON RPAREN { }
|
|
| FALSE { }
|
|
| TRUE { }
|
|
;
|
|
|
|
val_longident:
|
|
val_ident { }
|
|
| mod_longident DOT val_ident { }
|
|
;
|
|
constr_longident:
|
|
mod_longident %prec below_DOT { }
|
|
| mod_longident DOT LPAREN COLONCOLON RPAREN { }
|
|
| LBRACKET RBRACKET { }
|
|
| LPAREN RPAREN { }
|
|
| LPAREN COLONCOLON RPAREN { }
|
|
| FALSE { }
|
|
| TRUE { }
|
|
;
|
|
label_longident:
|
|
LIDENT { }
|
|
| mod_longident DOT LIDENT { }
|
|
;
|
|
type_longident:
|
|
LIDENT { }
|
|
| mod_ext_longident DOT LIDENT { }
|
|
;
|
|
mod_longident:
|
|
UIDENT { }
|
|
| mod_longident DOT UIDENT { }
|
|
;
|
|
mod_ext_longident:
|
|
UIDENT { }
|
|
| mod_ext_longident DOT UIDENT { }
|
|
| mod_ext_longident LPAREN mod_ext_longident RPAREN
|
|
{ }
|
|
(*| mod_ext_longident LPAREN error
|
|
{ }*)
|
|
;
|
|
mty_longident:
|
|
ident { }
|
|
| mod_ext_longident DOT ident { }
|
|
;
|
|
clty_longident:
|
|
LIDENT { }
|
|
| mod_ext_longident DOT LIDENT { }
|
|
;
|
|
class_longident:
|
|
LIDENT { }
|
|
| mod_longident DOT LIDENT { }
|
|
;
|
|
|
|
(* Toplevel directives *)
|
|
|
|
toplevel_directive:
|
|
HASH dir = mkrhs(ident)
|
|
arg = ioption(mk_directive_arg(toplevel_directive_argument))
|
|
{ }
|
|
;
|
|
|
|
%inline toplevel_directive_argument:
|
|
| STRING { }
|
|
| INT { }
|
|
| val_longident { }
|
|
| mod_longident { }
|
|
| FALSE { }
|
|
| TRUE { }
|
|
;
|
|
|
|
(* Miscellaneous *)
|
|
|
|
(* The symbol epsilon can be used instead of an (* empty *) comment. *)
|
|
%inline epsilon:
|
|
(* empty *)
|
|
{ }
|
|
;
|
|
|
|
%inline raw_string:
|
|
s = STRING
|
|
{ }
|
|
;
|
|
|
|
name_tag:
|
|
BACKQUOTE ident { }
|
|
;
|
|
rec_flag:
|
|
(* empty *) { }
|
|
| REC { }
|
|
;
|
|
%inline nonrec_flag:
|
|
(* empty *) { }
|
|
| NONREC { }
|
|
;
|
|
%inline no_nonrec_flag:
|
|
(* empty *) { }
|
|
| NONREC { }
|
|
;
|
|
direction_flag:
|
|
TO { }
|
|
| DOWNTO { }
|
|
;
|
|
private_flag:
|
|
inline_private_flag
|
|
{ }
|
|
;
|
|
%inline inline_private_flag:
|
|
(* empty *) { }
|
|
| PRIVATE { }
|
|
;
|
|
mutable_flag:
|
|
(* empty *) { }
|
|
| MUTABLE { }
|
|
;
|
|
virtual_flag:
|
|
(* empty *) { }
|
|
| VIRTUAL { }
|
|
;
|
|
mutable_virtual_flags:
|
|
(* empty *)
|
|
{ }
|
|
| MUTABLE
|
|
{ }
|
|
| VIRTUAL
|
|
{ }
|
|
| MUTABLE VIRTUAL
|
|
| VIRTUAL MUTABLE
|
|
{ }
|
|
;
|
|
private_virtual_flags:
|
|
(* empty *) { }
|
|
| PRIVATE { }
|
|
| VIRTUAL { }
|
|
| PRIVATE VIRTUAL { }
|
|
| VIRTUAL PRIVATE { }
|
|
;
|
|
(* This nonterminal symbol indicates the definite presence of a VIRTUAL
|
|
keyword and the possible presence of a MUTABLE keyword. *)
|
|
virtual_with_mutable_flag:
|
|
| VIRTUAL { }
|
|
| MUTABLE VIRTUAL { }
|
|
| VIRTUAL MUTABLE { }
|
|
;
|
|
(* This nonterminal symbol indicates the definite presence of a VIRTUAL
|
|
keyword and the possible presence of a PRIVATE keyword. *)
|
|
virtual_with_private_flag:
|
|
| VIRTUAL { }
|
|
| PRIVATE VIRTUAL { }
|
|
| VIRTUAL PRIVATE { }
|
|
;
|
|
%inline no_override_flag:
|
|
(* empty *) { }
|
|
;
|
|
%inline override_flag:
|
|
(* empty *) { }
|
|
| BANG { }
|
|
;
|
|
subtractive:
|
|
| MINUS { }
|
|
| MINUSDOT { }
|
|
;
|
|
additive:
|
|
| PLUS { }
|
|
| PLUSDOT { }
|
|
;
|
|
optlabel:
|
|
| OPTLABEL { }
|
|
| QUESTION LIDENT COLON { }
|
|
;
|
|
|
|
(* Attributes and extensions *)
|
|
|
|
single_attr_id:
|
|
LIDENT { }
|
|
| UIDENT { }
|
|
| AND { }
|
|
| AS { }
|
|
| ASSERT { }
|
|
| BEGIN { }
|
|
| CLASS { }
|
|
| CONSTRAINT { }
|
|
| DO { }
|
|
| DONE { }
|
|
| DOWNTO { }
|
|
| ELSE { }
|
|
| END { }
|
|
| EXCEPTION { }
|
|
| EXTERNAL { }
|
|
| FALSE { }
|
|
| FOR { }
|
|
| FUN { }
|
|
| FUNCTION { }
|
|
| FUNCTOR { }
|
|
| IF { }
|
|
| IN { }
|
|
| INCLUDE { }
|
|
| INHERIT { }
|
|
| INITIALIZER { }
|
|
| LAZY { }
|
|
| LET { }
|
|
| MATCH { }
|
|
| METHOD { }
|
|
| MODULE { }
|
|
| MUTABLE { }
|
|
| NEW { }
|
|
| NONREC { }
|
|
| OBJECT { }
|
|
| OF { }
|
|
| OPEN { }
|
|
| OR { }
|
|
| PRIVATE { }
|
|
| REC { }
|
|
| SIG { }
|
|
| STRUCT { }
|
|
| THEN { }
|
|
| TO { }
|
|
| TRUE { }
|
|
| TRY { }
|
|
| TYPE { }
|
|
| VAL { }
|
|
| VIRTUAL { }
|
|
| WHEN { }
|
|
| WHILE { }
|
|
| WITH { }
|
|
(* mod/land/lor/lxor/lsl/lsr/asr are not supported for now *)
|
|
;
|
|
|
|
attr_id:
|
|
mkloc(
|
|
single_attr_id { }
|
|
| single_attr_id DOT attr_id { }
|
|
) { }
|
|
;
|
|
attribute:
|
|
LBRACKETAT attr_id payload RBRACKET
|
|
{ }
|
|
;
|
|
post_item_attribute:
|
|
LBRACKETATAT attr_id payload RBRACKET
|
|
{ }
|
|
;
|
|
floating_attribute:
|
|
LBRACKETATATAT attr_id payload RBRACKET
|
|
{ }
|
|
;
|
|
%inline post_item_attributes:
|
|
post_item_attribute*
|
|
{ }
|
|
;
|
|
%inline attributes:
|
|
attribute*
|
|
{ }
|
|
;
|
|
ext:
|
|
| (* empty *) { }
|
|
| PERCENT attr_id { }
|
|
;
|
|
%inline no_ext:
|
|
| (* empty *) { }
|
|
| PERCENT attr_id { }
|
|
;
|
|
%inline ext_attributes:
|
|
ext attributes { }
|
|
;
|
|
extension:
|
|
LBRACKETPERCENT attr_id payload RBRACKET { }
|
|
;
|
|
item_extension:
|
|
LBRACKETPERCENTPERCENT attr_id payload RBRACKET { }
|
|
;
|
|
payload:
|
|
structure { }
|
|
| COLON signature { }
|
|
| COLON core_type { }
|
|
| QUESTION pattern { }
|
|
| QUESTION pattern WHEN seq_expr { }
|
|
;
|
|
%%
|