compilerlibs: expose parsers for 'Longident.t's
parent
e667d9fb8d
commit
40e40a9c20
12
.depend
12
.depend
|
@ -346,7 +346,8 @@ parsing/parse.cmx : \
|
||||||
parsing/docstrings.cmx \
|
parsing/docstrings.cmx \
|
||||||
parsing/parse.cmi
|
parsing/parse.cmi
|
||||||
parsing/parse.cmi : \
|
parsing/parse.cmi : \
|
||||||
parsing/parsetree.cmi
|
parsing/parsetree.cmi \
|
||||||
|
parsing/longident.cmi
|
||||||
parsing/parser.cmo : \
|
parsing/parser.cmo : \
|
||||||
parsing/syntaxerr.cmi \
|
parsing/syntaxerr.cmi \
|
||||||
parsing/parsetree.cmi \
|
parsing/parsetree.cmi \
|
||||||
|
@ -371,6 +372,7 @@ parsing/parser.cmx : \
|
||||||
parsing/parser.cmi
|
parsing/parser.cmi
|
||||||
parsing/parser.cmi : \
|
parsing/parser.cmi : \
|
||||||
parsing/parsetree.cmi \
|
parsing/parsetree.cmi \
|
||||||
|
parsing/longident.cmi \
|
||||||
parsing/location.cmi \
|
parsing/location.cmi \
|
||||||
parsing/docstrings.cmi \
|
parsing/docstrings.cmi \
|
||||||
parsing/camlinternalMenhirLib.cmi
|
parsing/camlinternalMenhirLib.cmi
|
||||||
|
@ -1407,6 +1409,7 @@ typing/typemod.cmo : \
|
||||||
typing/printtyp.cmi \
|
typing/printtyp.cmi \
|
||||||
typing/path.cmi \
|
typing/path.cmi \
|
||||||
parsing/parsetree.cmi \
|
parsing/parsetree.cmi \
|
||||||
|
parsing/parse.cmi \
|
||||||
typing/mtype.cmi \
|
typing/mtype.cmi \
|
||||||
utils/misc.cmi \
|
utils/misc.cmi \
|
||||||
parsing/longident.cmi \
|
parsing/longident.cmi \
|
||||||
|
@ -1439,6 +1442,7 @@ typing/typemod.cmx : \
|
||||||
typing/printtyp.cmx \
|
typing/printtyp.cmx \
|
||||||
typing/path.cmx \
|
typing/path.cmx \
|
||||||
parsing/parsetree.cmi \
|
parsing/parsetree.cmi \
|
||||||
|
parsing/parse.cmx \
|
||||||
typing/mtype.cmx \
|
typing/mtype.cmx \
|
||||||
utils/misc.cmx \
|
utils/misc.cmx \
|
||||||
parsing/longident.cmx \
|
parsing/longident.cmx \
|
||||||
|
@ -5787,7 +5791,6 @@ driver/makedepend.cmo : \
|
||||||
parsing/parser.cmi \
|
parsing/parser.cmi \
|
||||||
parsing/parse.cmi \
|
parsing/parse.cmi \
|
||||||
utils/misc.cmi \
|
utils/misc.cmi \
|
||||||
parsing/longident.cmi \
|
|
||||||
parsing/location.cmi \
|
parsing/location.cmi \
|
||||||
parsing/lexer.cmi \
|
parsing/lexer.cmi \
|
||||||
parsing/depend.cmi \
|
parsing/depend.cmi \
|
||||||
|
@ -5801,7 +5804,6 @@ driver/makedepend.cmx : \
|
||||||
parsing/parser.cmx \
|
parsing/parser.cmx \
|
||||||
parsing/parse.cmx \
|
parsing/parse.cmx \
|
||||||
utils/misc.cmx \
|
utils/misc.cmx \
|
||||||
parsing/longident.cmx \
|
|
||||||
parsing/location.cmx \
|
parsing/location.cmx \
|
||||||
parsing/lexer.cmx \
|
parsing/lexer.cmx \
|
||||||
parsing/depend.cmx \
|
parsing/depend.cmx \
|
||||||
|
@ -5934,9 +5936,11 @@ toplevel/expunge.cmx : \
|
||||||
bytecomp/bytesections.cmx
|
bytecomp/bytesections.cmx
|
||||||
toplevel/genprintval.cmo : \
|
toplevel/genprintval.cmo : \
|
||||||
typing/types.cmi \
|
typing/types.cmi \
|
||||||
|
parsing/syntaxerr.cmi \
|
||||||
typing/printtyp.cmi \
|
typing/printtyp.cmi \
|
||||||
typing/predef.cmi \
|
typing/predef.cmi \
|
||||||
typing/path.cmi \
|
typing/path.cmi \
|
||||||
|
parsing/parse.cmi \
|
||||||
typing/outcometree.cmi \
|
typing/outcometree.cmi \
|
||||||
typing/oprint.cmi \
|
typing/oprint.cmi \
|
||||||
utils/misc.cmi \
|
utils/misc.cmi \
|
||||||
|
@ -5949,9 +5953,11 @@ toplevel/genprintval.cmo : \
|
||||||
toplevel/genprintval.cmi
|
toplevel/genprintval.cmi
|
||||||
toplevel/genprintval.cmx : \
|
toplevel/genprintval.cmx : \
|
||||||
typing/types.cmx \
|
typing/types.cmx \
|
||||||
|
parsing/syntaxerr.cmx \
|
||||||
typing/printtyp.cmx \
|
typing/printtyp.cmx \
|
||||||
typing/predef.cmx \
|
typing/predef.cmx \
|
||||||
typing/path.cmx \
|
typing/path.cmx \
|
||||||
|
parsing/parse.cmx \
|
||||||
typing/outcometree.cmi \
|
typing/outcometree.cmi \
|
||||||
typing/oprint.cmx \
|
typing/oprint.cmx \
|
||||||
utils/misc.cmx \
|
utils/misc.cmx \
|
||||||
|
|
3
Changes
3
Changes
|
@ -111,6 +111,9 @@ Working version
|
||||||
- #9060: ensure that Misc.protect_refs preserves backtraces
|
- #9060: ensure that Misc.protect_refs preserves backtraces
|
||||||
(Gabriel Scherer, review by Guillaume Munch-Maccagnoni and David Allsopp)
|
(Gabriel Scherer, review by Guillaume Munch-Maccagnoni and David Allsopp)
|
||||||
|
|
||||||
|
- #9061: expose compiler Longident.t parsers
|
||||||
|
(Florian Angeletti, review by Gabriel Scherer)
|
||||||
|
|
||||||
- #9078: make all compilerlibs/ available to ocamltest.
|
- #9078: make all compilerlibs/ available to ocamltest.
|
||||||
(Gabriel Scherer, review by Sébastien Hinderer)
|
(Gabriel Scherer, review by Sébastien Hinderer)
|
||||||
|
|
||||||
|
|
11042
boot/menhir/parser.ml
11042
boot/menhir/parser.ml
File diff suppressed because one or more lines are too long
|
@ -136,12 +136,24 @@ val use_file: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.toplevel_p
|
||||||
|
|
||||||
val toplevel_phrase: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.toplevel_phrase)
|
val toplevel_phrase: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.toplevel_phrase)
|
||||||
|
|
||||||
|
val parse_val_longident: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Longident.t)
|
||||||
|
|
||||||
val parse_pattern: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.pattern)
|
val parse_pattern: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.pattern)
|
||||||
|
|
||||||
|
val parse_mty_longident: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Longident.t)
|
||||||
|
|
||||||
|
val parse_mod_longident: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Longident.t)
|
||||||
|
|
||||||
|
val parse_mod_ext_longident: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Longident.t)
|
||||||
|
|
||||||
val parse_expression: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.expression)
|
val parse_expression: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.expression)
|
||||||
|
|
||||||
val parse_core_type: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.core_type)
|
val parse_core_type: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.core_type)
|
||||||
|
|
||||||
|
val parse_constr_longident: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Longident.t)
|
||||||
|
|
||||||
|
val parse_any_longident: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Longident.t)
|
||||||
|
|
||||||
val interface: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.signature)
|
val interface: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.signature)
|
||||||
|
|
||||||
val implementation: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.structure)
|
val implementation: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (Parsetree.structure)
|
||||||
|
@ -163,12 +175,24 @@ module Incremental : sig
|
||||||
|
|
||||||
val toplevel_phrase: Lexing.position -> (Parsetree.toplevel_phrase) MenhirInterpreter.checkpoint
|
val toplevel_phrase: Lexing.position -> (Parsetree.toplevel_phrase) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
|
val parse_val_longident: Lexing.position -> (Longident.t) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
val parse_pattern: Lexing.position -> (Parsetree.pattern) MenhirInterpreter.checkpoint
|
val parse_pattern: Lexing.position -> (Parsetree.pattern) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
|
val parse_mty_longident: Lexing.position -> (Longident.t) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
|
val parse_mod_longident: Lexing.position -> (Longident.t) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
|
val parse_mod_ext_longident: Lexing.position -> (Longident.t) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
val parse_expression: Lexing.position -> (Parsetree.expression) MenhirInterpreter.checkpoint
|
val parse_expression: Lexing.position -> (Parsetree.expression) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
val parse_core_type: Lexing.position -> (Parsetree.core_type) MenhirInterpreter.checkpoint
|
val parse_core_type: Lexing.position -> (Parsetree.core_type) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
|
val parse_constr_longident: Lexing.position -> (Longident.t) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
|
val parse_any_longident: Lexing.position -> (Longident.t) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
val interface: Lexing.position -> (Parsetree.signature) MenhirInterpreter.checkpoint
|
val interface: Lexing.position -> (Parsetree.signature) MenhirInterpreter.checkpoint
|
||||||
|
|
||||||
val implementation: Lexing.position -> (Parsetree.structure) MenhirInterpreter.checkpoint
|
val implementation: Lexing.position -> (Parsetree.structure) MenhirInterpreter.checkpoint
|
||||||
|
|
|
@ -45,7 +45,8 @@ utils_modules := $(addprefix utils/,\
|
||||||
|
|
||||||
parsing_modules := $(addprefix parsing/,\
|
parsing_modules := $(addprefix parsing/,\
|
||||||
location longident docstrings syntaxerr ast_helper ast_mapper ast_iterator \
|
location longident docstrings syntaxerr ast_helper ast_mapper ast_iterator \
|
||||||
attr_helper builtin_attributes pprintast)
|
attr_helper builtin_attributes pprintast \
|
||||||
|
lexer camlinternalMenhirLib parser parse)
|
||||||
|
|
||||||
typing_modules := $(addprefix typing/,\
|
typing_modules := $(addprefix typing/,\
|
||||||
ident path type_immediacy types btype primitive typedtree subst predef \
|
ident path type_immediacy types btype primitive typedtree subst predef \
|
||||||
|
|
|
@ -310,7 +310,12 @@ let read_parse_and_extract parse_function extract_function def ast_kind
|
||||||
let bound_vars =
|
let bound_vars =
|
||||||
List.fold_left
|
List.fold_left
|
||||||
(fun bv modname ->
|
(fun bv modname ->
|
||||||
Depend.open_module bv (Longident.parse modname))
|
let lid =
|
||||||
|
let lexbuf = Lexing.from_string modname in
|
||||||
|
Location.init lexbuf
|
||||||
|
(Printf.sprintf "command line argument: -open %S" modname);
|
||||||
|
Parse.simple_module_path lexbuf in
|
||||||
|
Depend.open_module bv lid)
|
||||||
!module_map ((* PR#7248 *) List.rev !Clflags.open_modules)
|
!module_map ((* PR#7248 *) List.rev !Clflags.open_modules)
|
||||||
in
|
in
|
||||||
let r = extract_function bound_vars ast in
|
let r = extract_function bound_vars ast in
|
||||||
|
|
|
@ -30,6 +30,7 @@ let last = function
|
||||||
| Ldot(_, s) -> s
|
| Ldot(_, s) -> s
|
||||||
| Lapply(_, _) -> Misc.fatal_error "Longident.last"
|
| Lapply(_, _) -> Misc.fatal_error "Longident.last"
|
||||||
|
|
||||||
|
|
||||||
let rec split_at_dots s pos =
|
let rec split_at_dots s pos =
|
||||||
try
|
try
|
||||||
let dot = String.index_from s pos '.' in
|
let dot = String.index_from s pos '.' in
|
||||||
|
|
|
@ -27,8 +27,34 @@ type t =
|
||||||
|
|
||||||
val flatten: t -> string list
|
val flatten: t -> string list
|
||||||
val unflatten: string list -> t option
|
val unflatten: string list -> t option
|
||||||
|
(** For a non-empty list [l], [unflatten l] is [Some lid] where [lid] is
|
||||||
|
the long identifier created by concatenating the elements of [l]
|
||||||
|
with [Ldot].
|
||||||
|
[unflatten []] is [None].
|
||||||
|
*)
|
||||||
|
|
||||||
val last: t -> string
|
val last: t -> string
|
||||||
val parse: string -> t
|
val parse: string -> t
|
||||||
|
[@@deprecated "this function may misparse its input,\n\
|
||||||
|
use \"Parse.longident\" or \"Longident.unflatten\""]
|
||||||
|
(**
|
||||||
|
|
||||||
|
This function is broken on identifiers that are not just "Word.Word.word";
|
||||||
|
for example, it returns incorrect results on infix operators
|
||||||
|
and extended module paths.
|
||||||
|
|
||||||
|
If you want to generate long identifiers that are a list of
|
||||||
|
dot-separated identifiers, the function {!unflatten} is safer and faster.
|
||||||
|
{!unflatten} is available since OCaml 4.06.0.
|
||||||
|
|
||||||
|
If you want to parse any identifier correctly, use the long-identifiers
|
||||||
|
functions from the {!Parse} module, in particular {!Parse.longident}.
|
||||||
|
They are available since OCaml 4.11, and also provide proper
|
||||||
|
input-location support.
|
||||||
|
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(** To print a longident, see {!Pprintast.longident}, using
|
(** To print a longident, see {!Pprintast.longident}, using
|
||||||
{!Format.asprintf} to convert to a string. *)
|
{!Format.asprintf} to convert to a string. *)
|
||||||
|
|
|
@ -121,7 +121,13 @@ and core_type = wrap_menhir Parser.Incremental.parse_core_type
|
||||||
and expression = wrap_menhir Parser.Incremental.parse_expression
|
and expression = wrap_menhir Parser.Incremental.parse_expression
|
||||||
and pattern = wrap_menhir Parser.Incremental.parse_pattern
|
and pattern = wrap_menhir Parser.Incremental.parse_pattern
|
||||||
|
|
||||||
|
let longident = wrap_menhir Parser.Incremental.parse_any_longident
|
||||||
|
let val_ident = wrap_menhir Parser.Incremental.parse_val_longident
|
||||||
|
let constr_ident= wrap_menhir Parser.Incremental.parse_constr_longident
|
||||||
|
let extended_module_path =
|
||||||
|
wrap_menhir Parser.Incremental.parse_mod_ext_longident
|
||||||
|
let simple_module_path = wrap_menhir Parser.Incremental.parse_mod_longident
|
||||||
|
let type_ident = wrap_menhir Parser.Incremental.parse_mty_longident
|
||||||
|
|
||||||
(* Error reporting for Syntaxerr *)
|
(* Error reporting for Syntaxerr *)
|
||||||
(* The code has been moved here so that one can reuse Pprintast.tyvar *)
|
(* The code has been moved here so that one can reuse Pprintast.tyvar *)
|
||||||
|
|
|
@ -27,3 +27,82 @@ val use_file : Lexing.lexbuf -> Parsetree.toplevel_phrase list
|
||||||
val core_type : Lexing.lexbuf -> Parsetree.core_type
|
val core_type : Lexing.lexbuf -> Parsetree.core_type
|
||||||
val expression : Lexing.lexbuf -> Parsetree.expression
|
val expression : Lexing.lexbuf -> Parsetree.expression
|
||||||
val pattern : Lexing.lexbuf -> Parsetree.pattern
|
val pattern : Lexing.lexbuf -> Parsetree.pattern
|
||||||
|
|
||||||
|
(** The functions below can be used to parse Longident safely. *)
|
||||||
|
|
||||||
|
val longident: Lexing.lexbuf -> Longident.t
|
||||||
|
(**
|
||||||
|
The function [longident] is guaranted to parse all subclasses
|
||||||
|
of {!Longident.t} used in OCaml: values, constructors, simple or extended
|
||||||
|
module paths, and types or module types.
|
||||||
|
|
||||||
|
However, this function accepts inputs which are not accepted by the
|
||||||
|
compiler, because they combine functor applications and infix operators.
|
||||||
|
In valid OCaml syntax, only value-level identifiers may end with infix
|
||||||
|
operators [Foo.( + )].
|
||||||
|
Moreover, in value-level identifiers the module path [Foo] must be simple
|
||||||
|
([M.N] rather than [F(X)]): functor applications may only appear in
|
||||||
|
type-level identifiers.
|
||||||
|
As a consequence, a path such as [F(X).( + )] is not a valid OCaml
|
||||||
|
identifier; but it is accepted by this function.
|
||||||
|
*)
|
||||||
|
|
||||||
|
(** The next functions are specialized to a subclass of {!Longident.t} *)
|
||||||
|
|
||||||
|
val val_ident: Lexing.lexbuf -> Longident.t
|
||||||
|
(**
|
||||||
|
This function parses a syntactically valid path for a value. For instance,
|
||||||
|
[x], [M.x], and [(+.)] are valid. Contrarily, [M.A], [F(X).x], and [true]
|
||||||
|
are rejected.
|
||||||
|
|
||||||
|
Longident for OCaml's value cannot contain functor application.
|
||||||
|
The last component of the {!Longident.t} is not capitalized,
|
||||||
|
but can be an operator [A.Path.To.(.%.%.(;..)<-)]
|
||||||
|
*)
|
||||||
|
|
||||||
|
val constr_ident: Lexing.lexbuf -> Longident.t
|
||||||
|
(**
|
||||||
|
This function parses a syntactically valid path for a variant constructor.
|
||||||
|
For instance, [A], [M.A] and [M.(::)] are valid, but both [M.a]
|
||||||
|
and [F(X).A] are rejected.
|
||||||
|
|
||||||
|
Longident for OCaml's variant constructors cannot contain functor
|
||||||
|
application.
|
||||||
|
The last component of the {!Longident.t} is capitalized,
|
||||||
|
or it may be one the special constructors: [true],[false],[()],[[]],[(::)].
|
||||||
|
Among those special constructors, only [(::)] can be prefixed by a module
|
||||||
|
path ([A.B.C.(::)]).
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
|
val simple_module_path: Lexing.lexbuf -> Longident.t
|
||||||
|
(**
|
||||||
|
This function parses a syntactically valid path for a module.
|
||||||
|
For instance, [A], and [M.A] are valid, but both [M.a]
|
||||||
|
and [F(X).A] are rejected.
|
||||||
|
|
||||||
|
Longident for OCaml's module cannot contain functor application.
|
||||||
|
The last component of the {!Longident.t} is capitalized.
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
|
val extended_module_path: Lexing.lexbuf -> Longident.t
|
||||||
|
(**
|
||||||
|
This function parse syntactically valid path for an extended module.
|
||||||
|
For instance, [A.B] and [F(A).B] are valid. Contrarily,
|
||||||
|
[(.%())] or [[]] are both rejected.
|
||||||
|
|
||||||
|
The last component of the {!Longident.t} is capitalized.
|
||||||
|
|
||||||
|
*)
|
||||||
|
|
||||||
|
val type_ident: Lexing.lexbuf -> Longident.t
|
||||||
|
(**
|
||||||
|
This function parse syntactically valid path for a type or a module type.
|
||||||
|
For instance, [A], [t], [M.t] and [F(X).t] are valid. Contrarily,
|
||||||
|
[(.%())] or [[]] are both rejected.
|
||||||
|
|
||||||
|
In path for type and module types, only operators and special constructors
|
||||||
|
are rejected.
|
||||||
|
|
||||||
|
*)
|
||||||
|
|
|
@ -787,6 +787,18 @@ The precedences must be listed from low to high.
|
||||||
%type <Parsetree.expression> parse_expression
|
%type <Parsetree.expression> parse_expression
|
||||||
%start parse_pattern
|
%start parse_pattern
|
||||||
%type <Parsetree.pattern> parse_pattern
|
%type <Parsetree.pattern> parse_pattern
|
||||||
|
%start parse_constr_longident
|
||||||
|
%type <Longident.t> parse_constr_longident
|
||||||
|
%start parse_val_longident
|
||||||
|
%type <Longident.t> parse_val_longident
|
||||||
|
%start parse_mty_longident
|
||||||
|
%type <Longident.t> parse_mty_longident
|
||||||
|
%start parse_mod_ext_longident
|
||||||
|
%type <Longident.t> parse_mod_ext_longident
|
||||||
|
%start parse_mod_longident
|
||||||
|
%type <Longident.t> parse_mod_longident
|
||||||
|
%start parse_any_longident
|
||||||
|
%type <Longident.t> parse_any_longident
|
||||||
%%
|
%%
|
||||||
|
|
||||||
/* macros */
|
/* macros */
|
||||||
|
@ -1128,6 +1140,35 @@ parse_pattern:
|
||||||
{ $1 }
|
{ $1 }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
parse_mty_longident:
|
||||||
|
mty_longident EOF
|
||||||
|
{ $1 }
|
||||||
|
;
|
||||||
|
|
||||||
|
parse_val_longident:
|
||||||
|
val_longident EOF
|
||||||
|
{ $1 }
|
||||||
|
;
|
||||||
|
|
||||||
|
parse_constr_longident:
|
||||||
|
constr_longident EOF
|
||||||
|
{ $1 }
|
||||||
|
;
|
||||||
|
|
||||||
|
parse_mod_ext_longident:
|
||||||
|
mod_ext_longident EOF
|
||||||
|
{ $1 }
|
||||||
|
;
|
||||||
|
|
||||||
|
parse_mod_longident:
|
||||||
|
mod_longident EOF
|
||||||
|
{ $1 }
|
||||||
|
;
|
||||||
|
|
||||||
|
parse_any_longident:
|
||||||
|
any_longident EOF
|
||||||
|
{ $1 }
|
||||||
|
;
|
||||||
(* -------------------------------------------------------------------------- *)
|
(* -------------------------------------------------------------------------- *)
|
||||||
|
|
||||||
(* Functor arguments appear in module expressions and module types. *)
|
(* Functor arguments appear in module expressions and module types. *)
|
||||||
|
@ -3374,13 +3415,16 @@ ident:
|
||||||
UIDENT { $1 }
|
UIDENT { $1 }
|
||||||
| LIDENT { $1 }
|
| LIDENT { $1 }
|
||||||
;
|
;
|
||||||
val_ident:
|
val_extra_ident:
|
||||||
LIDENT { $1 }
|
|
||||||
| LPAREN operator RPAREN { $2 }
|
| LPAREN operator RPAREN { $2 }
|
||||||
| LPAREN operator error { unclosed "(" $loc($1) ")" $loc($3) }
|
| LPAREN operator error { unclosed "(" $loc($1) ")" $loc($3) }
|
||||||
| LPAREN error { expecting $loc($2) "operator" }
|
| LPAREN error { expecting $loc($2) "operator" }
|
||||||
| LPAREN MODULE error { expecting $loc($3) "module-expr" }
|
| LPAREN MODULE error { expecting $loc($3) "module-expr" }
|
||||||
;
|
;
|
||||||
|
val_ident:
|
||||||
|
LIDENT { $1 }
|
||||||
|
| val_extra_ident { $1 }
|
||||||
|
;
|
||||||
operator:
|
operator:
|
||||||
PREFIXOP { $1 }
|
PREFIXOP { $1 }
|
||||||
| LETOP { $1 }
|
| LETOP { $1 }
|
||||||
|
@ -3421,59 +3465,68 @@ index_mod:
|
||||||
| { "" }
|
| { "" }
|
||||||
| SEMI DOTDOT { ";.." }
|
| SEMI DOTDOT { ";.." }
|
||||||
;
|
;
|
||||||
constr_ident:
|
|
||||||
UIDENT { $1 }
|
%inline constr_extra_ident:
|
||||||
|
| LPAREN COLONCOLON RPAREN { "::" }
|
||||||
|
;
|
||||||
|
constr_extra_nonprefix_ident:
|
||||||
| LBRACKET RBRACKET { "[]" }
|
| LBRACKET RBRACKET { "[]" }
|
||||||
| LPAREN RPAREN { "()" }
|
| LPAREN RPAREN { "()" }
|
||||||
| LPAREN COLONCOLON RPAREN { "::" }
|
|
||||||
| FALSE { "false" }
|
| FALSE { "false" }
|
||||||
| TRUE { "true" }
|
| TRUE { "true" }
|
||||||
;
|
;
|
||||||
|
constr_ident:
|
||||||
val_longident:
|
UIDENT { $1 }
|
||||||
val_ident { Lident $1 }
|
| constr_extra_ident { $1 }
|
||||||
| mod_longident DOT val_ident { Ldot($1, $3) }
|
| constr_extra_nonprefix_ident { $1 }
|
||||||
;
|
;
|
||||||
constr_longident:
|
constr_longident:
|
||||||
mod_longident %prec below_DOT { $1 }
|
mod_longident %prec below_DOT { $1 } /* A.B.x vs (A).B.x */
|
||||||
| mod_longident DOT LPAREN COLONCOLON RPAREN { Ldot($1,"::") }
|
| mod_longident DOT constr_extra_ident { Ldot($1,$3) }
|
||||||
| LBRACKET RBRACKET { Lident "[]" }
|
| constr_extra_ident { Lident $1 }
|
||||||
| LPAREN RPAREN { Lident "()" }
|
| constr_extra_nonprefix_ident { Lident $1 }
|
||||||
| LPAREN COLONCOLON RPAREN { Lident "::" }
|
;
|
||||||
| FALSE { Lident "false" }
|
mk_longident(prefix,final):
|
||||||
| TRUE { Lident "true" }
|
| final { Lident $1 }
|
||||||
|
| prefix DOT final { Ldot($1,$3) }
|
||||||
|
;
|
||||||
|
val_longident:
|
||||||
|
mk_longident(mod_longident, val_ident) { $1 }
|
||||||
;
|
;
|
||||||
label_longident:
|
label_longident:
|
||||||
LIDENT { Lident $1 }
|
mk_longident(mod_longident, LIDENT) { $1 }
|
||||||
| mod_longident DOT LIDENT { Ldot($1, $3) }
|
|
||||||
;
|
;
|
||||||
type_longident:
|
type_longident:
|
||||||
LIDENT { Lident $1 }
|
mk_longident(mod_ext_longident, LIDENT) { $1 }
|
||||||
| mod_ext_longident DOT LIDENT { Ldot($1, $3) }
|
|
||||||
;
|
;
|
||||||
mod_longident:
|
mod_longident:
|
||||||
UIDENT { Lident $1 }
|
mk_longident(mod_longident, UIDENT) { $1 }
|
||||||
| mod_longident DOT UIDENT { Ldot($1, $3) }
|
|
||||||
;
|
;
|
||||||
mod_ext_longident:
|
mod_ext_longident:
|
||||||
UIDENT { Lident $1 }
|
mk_longident(mod_ext_longident, UIDENT) { $1 }
|
||||||
| mod_ext_longident DOT UIDENT { Ldot($1, $3) }
|
|
||||||
| mod_ext_longident LPAREN mod_ext_longident RPAREN
|
| mod_ext_longident LPAREN mod_ext_longident RPAREN
|
||||||
{ lapply ~loc:$sloc $1 $3 }
|
{ lapply ~loc:$sloc $1 $3 }
|
||||||
| mod_ext_longident LPAREN error
|
| mod_ext_longident LPAREN error
|
||||||
{ expecting $loc($3) "module path" }
|
{ expecting $loc($3) "module path" }
|
||||||
;
|
;
|
||||||
mty_longident:
|
mty_longident:
|
||||||
ident { Lident $1 }
|
mk_longident(mod_ext_longident,ident) { $1 }
|
||||||
| mod_ext_longident DOT ident { Ldot($1, $3) }
|
|
||||||
;
|
;
|
||||||
clty_longident:
|
clty_longident:
|
||||||
LIDENT { Lident $1 }
|
mk_longident(mod_ext_longident,LIDENT) { $1 }
|
||||||
| mod_ext_longident DOT LIDENT { Ldot($1, $3) }
|
|
||||||
;
|
;
|
||||||
class_longident:
|
class_longident:
|
||||||
LIDENT { Lident $1 }
|
mk_longident(mod_longident,LIDENT) { $1 }
|
||||||
| mod_longident DOT LIDENT { Ldot($1, $3) }
|
;
|
||||||
|
|
||||||
|
/* For compiler-libs: parse all valid longidents and a little more:
|
||||||
|
final identifiers which are value specific are accepted even when
|
||||||
|
the path prefix is only valid for types: (e.g. F(X).(::)) */
|
||||||
|
any_longident:
|
||||||
|
| mk_longident (mod_ext_longident,
|
||||||
|
ident | constr_extra_ident | val_extra_ident { $1 }
|
||||||
|
) { $1 }
|
||||||
|
| constr_extra_nonprefix_ident { Lident $1 }
|
||||||
;
|
;
|
||||||
|
|
||||||
/* Toplevel directives */
|
/* Toplevel directives */
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
include ocamlcommon
|
include ocamlcommon
|
||||||
* expect
|
* expect
|
||||||
*)
|
*)
|
||||||
|
[@@@alert "-deprecated"]
|
||||||
|
|
||||||
module L = Longident
|
module L = Longident
|
||||||
|
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
module L = Longident
|
module L = Longident
|
||||||
|}]
|
|}]
|
||||||
|
@ -56,32 +58,113 @@ let last_dot_apply = L.last
|
||||||
val last_dot_apply : string = "foo"
|
val last_dot_apply : string = "foo"
|
||||||
|}];;
|
|}];;
|
||||||
|
|
||||||
|
type parse_result = { flat: L.t; spec:L.t; any_is_correct:bool }
|
||||||
|
let test specialized s =
|
||||||
|
let spec = specialized (Lexing.from_string s) in
|
||||||
|
{ flat = L.parse s;
|
||||||
|
spec;
|
||||||
|
any_is_correct = Parse.longident (Lexing.from_string s) = spec;
|
||||||
|
}
|
||||||
|
|
||||||
let parse_empty = L.parse ""
|
let parse_empty = L.parse ""
|
||||||
|
let parse_empty_val = Parse.longident (Lexing.from_string "")
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
|
type parse_result = { flat : L.t; spec : L.t; any_is_correct : bool; }
|
||||||
|
val test : (Lexing.lexbuf -> L.t) -> string -> parse_result = <fun>
|
||||||
val parse_empty : L.t = L.Lident ""
|
val parse_empty : L.t = L.Lident ""
|
||||||
|
Exception:
|
||||||
|
Syntaxerr.Error
|
||||||
|
(Syntaxerr.Other
|
||||||
|
{Location.loc_start =
|
||||||
|
{Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 0};
|
||||||
|
loc_end =
|
||||||
|
{Lexing.pos_fname = ""; pos_lnum = 1; pos_bol = 0; pos_cnum = 0};
|
||||||
|
loc_ghost = false}).
|
||||||
|}]
|
|}]
|
||||||
let parse_ident = L.parse "foo"
|
let parse_ident = test Parse.val_ident "foo"
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
val parse_ident : L.t = L.Lident "foo"
|
val parse_ident : parse_result =
|
||||||
|
{flat = L.Lident "foo"; spec = L.Lident "foo"; any_is_correct = true}
|
||||||
|}]
|
|}]
|
||||||
let parse_dot = L.parse "M.foo"
|
let parse_dot = test Parse.val_ident "M.foo"
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
val parse_dot : L.t = L.Ldot (L.Lident "M", "foo")
|
val parse_dot : parse_result =
|
||||||
|
{flat = L.Ldot (L.Lident "M", "foo"); spec = L.Ldot (L.Lident "M", "foo");
|
||||||
|
any_is_correct = true}
|
||||||
|}]
|
|}]
|
||||||
let parse_path = L.parse "M.N.foo"
|
let parse_path = test Parse.val_ident "M.N.foo"
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
val parse_path : L.t = L.Ldot (L.Ldot (L.Lident "M", "N"), "foo")
|
val parse_path : parse_result =
|
||||||
|
{flat = L.Ldot (L.Ldot (L.Lident "M", "N"), "foo");
|
||||||
|
spec = L.Ldot (L.Ldot (L.Lident "M", "N"), "foo"); any_is_correct = true}
|
||||||
|}]
|
|}]
|
||||||
let parse_complex = L.parse "M.F(M.N).N.foo"
|
let parse_complex = test Parse.type_ident "M.F(M.N).N.foo"
|
||||||
(* the result below is a known misbehavior of Longident.parse
|
(* the result below is a known misbehavior of Longident.parse
|
||||||
which does not handle applications properly. Fixing it
|
which does not handle applications properly. *)
|
||||||
would be nice, but we soo no convenient way to do it without
|
|
||||||
introducing unpleasant dependencies. *)
|
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
val parse_complex : L.t =
|
val parse_complex : parse_result =
|
||||||
L.Ldot (L.Ldot (L.Ldot (L.Ldot (L.Lident "M", "F(M"), "N)"), "N"), "foo")
|
{flat =
|
||||||
|
L.Ldot (L.Ldot (L.Ldot (L.Ldot (L.Lident "M", "F(M"), "N)"), "N"), "foo");
|
||||||
|
spec =
|
||||||
|
L.Ldot
|
||||||
|
(L.Ldot
|
||||||
|
(L.Lapply (L.Ldot (L.Lident "M", "F"), L.Ldot (L.Lident "M", "N")),
|
||||||
|
"N"),
|
||||||
|
"foo");
|
||||||
|
any_is_correct = true}
|
||||||
|}]
|
|}]
|
||||||
|
|
||||||
|
let parse_op = test Parse.val_ident "M.(.%.()<-)"
|
||||||
|
(* the result below is another known misbehavior of Longident.parse. *)
|
||||||
|
[%%expect {|
|
||||||
|
val parse_op : parse_result =
|
||||||
|
{flat = L.Ldot (L.Ldot (L.Ldot (L.Lident "M", "("), "%"), "()<-)");
|
||||||
|
spec = L.Ldot (L.Lident "M", ".%.()<-"); any_is_correct = true}
|
||||||
|
|}]
|
||||||
|
|
||||||
|
|
||||||
|
let parse_let_op = test Parse.val_ident "M.(let+*!)"
|
||||||
|
[%%expect {|
|
||||||
|
val parse_let_op : parse_result =
|
||||||
|
{flat = L.Ldot (L.Lident "M", "(let+*!)");
|
||||||
|
spec = L.Ldot (L.Lident "M", "let+*!"); any_is_correct = true}
|
||||||
|
|}]
|
||||||
|
|
||||||
|
let constr = test Parse.constr_ident "true"
|
||||||
|
[%%expect{|
|
||||||
|
val constr : parse_result =
|
||||||
|
{flat = L.Lident "true"; spec = L.Lident "true"; any_is_correct = true}
|
||||||
|
|}]
|
||||||
|
|
||||||
|
let prefix_constr = test Parse.constr_ident "A.B.C.(::)"
|
||||||
|
[%%expect{|
|
||||||
|
val prefix_constr : parse_result =
|
||||||
|
{flat = L.Ldot (L.Ldot (L.Ldot (L.Lident "A", "B"), "C"), "(::)");
|
||||||
|
spec = L.Ldot (L.Ldot (L.Ldot (L.Lident "A", "B"), "C"), "::");
|
||||||
|
any_is_correct = true}
|
||||||
|
|}]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let mod_ext = test Parse.extended_module_path "A.F(B.C(X)).G(Y).D"
|
||||||
|
[%%expect{|
|
||||||
|
val mod_ext : parse_result =
|
||||||
|
{flat =
|
||||||
|
L.Ldot (L.Ldot (L.Ldot (L.Ldot (L.Lident "A", "F(B"), "C(X))"), "G(Y)"),
|
||||||
|
"D");
|
||||||
|
spec =
|
||||||
|
L.Ldot
|
||||||
|
(L.Lapply
|
||||||
|
(L.Ldot
|
||||||
|
(L.Lapply (L.Ldot (L.Lident "A", "F"),
|
||||||
|
L.Lapply (L.Ldot (L.Lident "B", "C"), L.Lident "X")),
|
||||||
|
"G"),
|
||||||
|
L.Lident "Y"),
|
||||||
|
"D");
|
||||||
|
any_is_correct = true}
|
||||||
|
|}]
|
||||||
|
|
||||||
|
|
||||||
let string_of_longident lid = Format.asprintf "%a" Pprintast.longident lid
|
let string_of_longident lid = Format.asprintf "%a" Pprintast.longident lid
|
||||||
[%%expect{|
|
[%%expect{|
|
||||||
val string_of_longident : Longident.t -> string = <fun>
|
val string_of_longident : Longident.t -> string = <fun>
|
||||||
|
@ -90,15 +173,15 @@ let str_empty = string_of_longident parse_empty
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
val str_empty : string = ""
|
val str_empty : string = ""
|
||||||
|}]
|
|}]
|
||||||
let str_ident = string_of_longident parse_ident
|
let str_ident = string_of_longident parse_ident.flat
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
val str_ident : string = "foo"
|
val str_ident : string = "foo"
|
||||||
|}]
|
|}]
|
||||||
let str_dot = string_of_longident parse_dot
|
let str_dot = string_of_longident parse_dot.flat
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
val str_dot : string = "M.foo"
|
val str_dot : string = "M.foo"
|
||||||
|}]
|
|}]
|
||||||
let str_path = string_of_longident parse_path
|
let str_path = string_of_longident parse_path.flat
|
||||||
[%%expect {|
|
[%%expect {|
|
||||||
val str_path : string = "M.N.foo"
|
val str_path : string = "M.N.foo"
|
||||||
|}]
|
|}]
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
File "tool-ocamlc-open-error.ml", line 1:
|
||||||
|
Warning 24: bad source file name: "Tool-ocamlc-open-error" is not a valid module name.
|
||||||
|
File "command line argument: -open "F("", line 1, characters 1-2:
|
||||||
|
Error: Syntax error
|
|
@ -0,0 +1,7 @@
|
||||||
|
(* TEST
|
||||||
|
* setup-ocamlc.byte-build-env
|
||||||
|
** ocamlc.byte
|
||||||
|
flags = "-open F("
|
||||||
|
ocamlc_byte_exit_status = "2"
|
||||||
|
*** check-ocamlc.byte-output
|
||||||
|
*)
|
|
@ -668,6 +668,19 @@ let y = x (* Prints Bar and part of Foo (which has been shadowed) *)
|
||||||
val y : exn * exn = (Foo (3, _), Bar (Some 5))
|
val y : exn * exn = (Foo (3, _), Bar (Some 5))
|
||||||
|}]
|
|}]
|
||||||
|
|
||||||
|
module Empty = struct end
|
||||||
|
module F(X:sig end) = struct
|
||||||
|
type t = ..
|
||||||
|
type t += A
|
||||||
|
end
|
||||||
|
let x = let open F(Empty) in (A:F(Empty).t) (* A is not printed *)
|
||||||
|
[%%expect {|
|
||||||
|
module Empty : sig end
|
||||||
|
module F : functor (X : sig end) -> sig type t = .. type t += A end
|
||||||
|
val x : F(Empty).t = <extension>
|
||||||
|
|}]
|
||||||
|
|
||||||
|
|
||||||
(* Test Obj functions *)
|
(* Test Obj functions *)
|
||||||
|
|
||||||
type foo = ..
|
type foo = ..
|
||||||
|
|
|
@ -547,10 +547,15 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
|
||||||
else O.field bucket 0
|
else O.field bucket 0
|
||||||
in
|
in
|
||||||
let name = (O.obj(O.field slot 0) : string) in
|
let name = (O.obj(O.field slot 0) : string) in
|
||||||
let lid = Longident.parse name in
|
|
||||||
try
|
try
|
||||||
(* Attempt to recover the constructor description for the exn
|
(* Attempt to recover the constructor description for the exn
|
||||||
from its name *)
|
from its name *)
|
||||||
|
let lid =
|
||||||
|
try Parse.longident (Lexing.from_string name) with
|
||||||
|
(* The syntactic class for extension constructor names
|
||||||
|
is an extended form of constructor "Longident.t"s
|
||||||
|
that also includes module application (e.g [F(X).A]) *)
|
||||||
|
| Syntaxerr.Error _ | Lexer.Error _ -> raise Not_found in
|
||||||
let cstr = Env.find_constructor_by_name lid env in
|
let cstr = Env.find_constructor_by_name lid env in
|
||||||
let path =
|
let path =
|
||||||
match cstr.cstr_tag with
|
match cstr.cstr_tag with
|
||||||
|
|
|
@ -150,8 +150,11 @@ let initial_env ~loc ~safe_string ~initially_opened_module
|
||||||
in
|
in
|
||||||
let open_module env m =
|
let open_module env m =
|
||||||
let open Asttypes in
|
let open Asttypes in
|
||||||
let lid = {loc; txt = Longident.parse m } in
|
let lexbuf = Lexing.from_string m in
|
||||||
snd (type_open_ Override env lid.loc lid)
|
let txt =
|
||||||
|
Location.init lexbuf (Printf.sprintf "command line argument: -open %S" m);
|
||||||
|
Parse.simple_module_path lexbuf in
|
||||||
|
snd (type_open_ Override env loc {txt;loc})
|
||||||
in
|
in
|
||||||
let add_units env units =
|
let add_units env units =
|
||||||
String.Set.fold
|
String.Set.fold
|
||||||
|
|
Loading…
Reference in New Issue