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.
2777 lines
66 KiB
2777 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 { } |
|
; |
|
%%
|
|
|