123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392moduleError=Odoc_model.ErrormoduleLocation_=Odoc_model.Location_modulePaths=Odoc_model.Pathsletdeprecated_reference_kindwarningslocationkindreplacement=Parse_error.deprecated_reference_kindkindreplacementlocation|>Error.warningwarnings(* http://caml.inria.fr/pub/docs/manual-ocaml/ocamldoc.html#sec359. *)letmatch_ocamldoc_reference_kind(_warningsasw)(_locationasloc)s:(Odoc_model.Paths_types.Reference.tag_any)option=letd=deprecated_reference_kindinmatchswith|Some"module"->Some`TModule|Some"modtype"->dwloc"modtype""module-type";Some`TModuleType|Some"class"->Some`TClass|Some"classtype"->dwloc"classtype""class-type";Some`TClassType|Some"val"->Some`TValue|Some"type"->Some`TType|Some"exception"->Some`TException|Some"attribute"->None|Some"method"->Some`TMethod|Some"section"->Some`TLabel|Some"const"->dwloc"const""constructor";Some`TConstructor|Some"recfield"->dwloc"recfield""field";Some`TField|_->Noneletmatch_extra_odoc_reference_kind(_warningsasw)(_locationasloc)s:(Odoc_model.Paths_types.Reference.tag_any)option=letd=deprecated_reference_kindinmatchswith|Some"class-type"->Some`TClassType|Some"constructor"->Some`TConstructor|Some"exn"->dwloc"exn""exception";Some`TException|Some"extension"->Some`TExtension|Some"field"->Some`TField|Some"instance-variable"->Some`TInstanceVariable|Some"label"->dwloc"label""section";Some`TLabel|Some"module-type"->Some`TModuleType|Some"page"->Some`TPage|Some"value"->dwloc"value""val";Some`TValue|_->None(* Ideally, [tokenize] would call this on every reference kind annotation during
tokenization, when generating the token list. However, that constrains the
phantom tag type to be the same for all tokens in the list (because lists are
homogeneous). So, the parser stores kinds as strings in the token list
instead, and this function is called on each string at the latest possible
time to prevent typing issues.
A secondary reason to delay parsing, and store strings in the token list, is
that we need the strings for user-friendly error reporting. *)letmatch_reference_kindwarningslocations:Odoc_model.Paths_types.Reference.tag_any=matchswith|None->`TUnknown|Somesaswrapped->letresult=matchmatch_ocamldoc_reference_kindwarningslocationwrappedwith|Somekind->Somekind|None->match_extra_odoc_reference_kindwarningslocationwrappedinmatchresultwith|Somekind->kind|None->Parse_error.unknown_reference_qualifierslocation|>Error.raise_exception(* The string is scanned right-to-left, because we are interested in right-most
hyphens. The tokens are also returned in right-to-left order, because the
traversals that consume them prefer to look at the deepest identifier
first. *)lettokenizelocations=letrecscan_identifierstarted_atopen_parenthesis_countindextokens=matchs.[index]with|exceptionInvalid_argument_->letidentifier,location=identifier_endedstarted_atindexin(None,identifier,location)::tokens|'-'whenopen_parenthesis_count=0->letidentifier,location=identifier_endedstarted_atindexinscan_kindidentifierlocationindex(index-1)tokens|'.'whenopen_parenthesis_count=0->letidentifier,location=identifier_endedstarted_atindexinscan_identifierindex0(index-1)((None,identifier,location)::tokens)|')'->scan_identifierstarted_at(open_parenthesis_count+1)(index-1)tokens|'('whenopen_parenthesis_count>0->scan_identifierstarted_at(open_parenthesis_count-1)(index-1)tokens|_->scan_identifierstarted_atopen_parenthesis_count(index-1)tokensandidentifier_endedstarted_atindex=letoffset=index+1inletlength=started_at-offsetinletidentifier=String.trim(String.subsoffsetlength)inletlocation=Location_.in_strings~offset~lengthlocationinifidentifier=""thenbeginParse_error.should_not_be_empty~what:"Identifier in reference"location|>Error.raise_exceptionend;(identifier,location)andscan_kindidentifieridentifier_locationstarted_atindextokens=matchs.[index]with|exceptionInvalid_argument_->letkind,location=kind_endedidentifier_locationstarted_atindexin(kind,identifier,location)::tokens|'.'->letkind,location=kind_endedidentifier_locationstarted_atindexinscan_identifierindex0(index-1)((kind,identifier,location)::tokens)|_->scan_kindidentifieridentifier_locationstarted_at(index-1)tokensandkind_endedidentifier_locationstarted_atindex=letoffset=index+1inletlength=started_at-offsetinletkind=Some(String.subsoffsetlength)inletlocation=Location_.in_strings~offset~lengthlocationinletlocation=Location_.span[location;identifier_location]in(kind,location)inscan_identifier(String.lengths)0(String.lengths-1)[]|>List.revletexpectedallowedlocation=letunqualified="or an unqualified reference"inletallowed=matchallowedwith|[one]->Printf.sprintf"'%s-' %s"oneunqualified|_->String.concat", "((List.map(Printf.sprintf"'%s-'")allowed)@[unqualified])inParse_error.expectedallowedlocationletparsewarningswhole_reference_locations:(Paths.Reference.t,Error.t)Result.result=letopenPaths.ReferenceinletopenOdoc_model.Namesinletrecsignature(kind,identifier,location)tokens:Signature.t=letkind=match_reference_kindwarningslocationkindinmatchtokenswith|[]->beginmatchkindwith|`TUnknown|`TModule|`TModuleTypeaskind->`Root(UnitName.of_stringidentifier,kind)|_->expected["module";"module-type"]location|>Error.raise_exceptionend|next_token::tokens->beginmatchkindwith|`TUnknown->`Dot((parentnext_tokentokens:>LabelParent.t),identifier)|`TModule->`Module(signaturenext_tokentokens,ModuleName.of_stringidentifier)|`TModuleType->`ModuleType(signaturenext_tokentokens,ModuleTypeName.of_stringidentifier)|_->expected["module";"module-type"]location|>Error.raise_exceptionendandparent(kind,identifier,location)tokens:Parent.t=letkind=match_reference_kindwarningslocationkindinmatchtokenswith|[]->beginmatchkindwith|`TUnknown|`TModule|`TModuleType|`TType|`TClass|`TClassTypeaskind->`Root(UnitName.of_stringidentifier,kind)|_->expected["module";"module-type";"type";"class";"class-type"]location|>Error.raise_exceptionend|next_token::tokens->beginmatchkindwith|`TUnknown->`Dot((parentnext_tokentokens:>LabelParent.t),identifier)|`TModule->`Module(signaturenext_tokentokens,ModuleName.of_stringidentifier)|`TModuleType->`ModuleType(signaturenext_tokentokens,ModuleTypeName.of_stringidentifier)|`TType->`Type(signaturenext_tokentokens,TypeName.of_stringidentifier)|`TClass->`Class(signaturenext_tokentokens,ClassName.of_stringidentifier)|`TClassType->`ClassType(signaturenext_tokentokens,ClassTypeName.of_stringidentifier)|_->expected["module";"module-type";"type";"class";"class-type"]location|>Error.raise_exceptionendinletclass_signature(kind,identifier,location)tokens:ClassSignature.t=letkind=match_reference_kindwarningslocationkindinmatchtokenswith|[]->beginmatchkindwith|`TUnknown|`TClass|`TClassTypeaskind->`Root(UnitName.of_stringidentifier,kind)|_->expected["class";"class-type"]location|>Error.raise_exceptionend|next_token::tokens->beginmatchkindwith|`TUnknown->`Dot((parentnext_tokentokens:>LabelParent.t),identifier)|`TClass->`Class(signaturenext_tokentokens,ClassName.of_stringidentifier)|`TClassType->`ClassType(signaturenext_tokentokens,ClassTypeName.of_stringidentifier)|_->expected["class";"class-type"]location|>Error.raise_exceptionendinletdatatype(kind,identifier,location)tokens:DataType.t=letkind=match_reference_kindwarningslocationkindinmatchtokenswith|[]->beginmatchkindwith|`TUnknown|`TTypeaskind->`Root(UnitName.of_stringidentifier,kind)|_->expected["type"]location|>Error.raise_exceptionend|next_token::tokens->beginmatchkindwith|`TUnknown->`Dot((parentnext_tokentokens:>LabelParent.t),identifier)|`TType->`Type(signaturenext_tokentokens,TypeName.of_stringidentifier)|_->expected["type"]location|>Error.raise_exceptionendinletreclabel_parent(kind,identifier,location)tokens:LabelParent.t=letkind=match_reference_kindwarningslocationkindinmatchtokenswith|[]->beginmatchkindwith|`TUnknown|`TModule|`TModuleType|`TType|`TClass|`TClassType|`TPageaskind->`Root(UnitName.of_stringidentifier,kind)|_->expected["module";"module-type";"type";"class";"class-type";"page"]location|>Error.raise_exceptionend|next_token::tokens->beginmatchkindwith|`TUnknown->`Dot(label_parentnext_tokentokens,identifier)|`TModule->`Module(signaturenext_tokentokens,ModuleName.of_stringidentifier)|`TModuleType->`ModuleType(signaturenext_tokentokens,ModuleTypeName.of_stringidentifier)|`TType->`Type(signaturenext_tokentokens,TypeName.of_stringidentifier)|`TClass->`Class(signaturenext_tokentokens,ClassName.of_stringidentifier)|`TClassType->`ClassType(signaturenext_tokentokens,ClassTypeName.of_stringidentifier)|_->expected["module";"module-type";"type";"class";"class-type"]location|>Error.raise_exceptionendinletstart_from_last_component(kind,identifier,location)old_kindtokens=letnew_kind=match_reference_kindwarningslocationkindinletkind=matchold_kindwith|None->new_kind|Some(old_kind_string,old_kind_location)->letold_kind=match_reference_kindwarningsold_kind_location(Someold_kind_string)inmatchnew_kindwith|`TUnknown->old_kind|_->ifold_kind<>new_kindthenbeginletnew_kind_string=matchkindwith|Somes->s|None->""inParse_error.reference_kinds_do_not_matchold_kind_stringnew_kind_stringwhole_reference_location|>Error.warningwarningsend;new_kindinmatchtokenswith|[]->`Root(UnitName.of_stringidentifier,kind)|next_token::tokens->matchkindwith|`TUnknown->`Dot(label_parentnext_tokentokens,identifier)|`TModule->`Module(signaturenext_tokentokens,ModuleName.of_stringidentifier)|`TModuleType->`ModuleType(signaturenext_tokentokens,ModuleTypeName.of_stringidentifier)|`TType->`Type(signaturenext_tokentokens,TypeName.of_stringidentifier)|`TConstructor->`Constructor(datatypenext_tokentokens,ConstructorName.of_stringidentifier)|`TField->`Field(parentnext_tokentokens,FieldName.of_stringidentifier)|`TExtension->`Extension(signaturenext_tokentokens,ExtensionName.of_stringidentifier)|`TException->`Exception(signaturenext_tokentokens,ExceptionName.of_stringidentifier)|`TValue->`Value(signaturenext_tokentokens,ValueName.of_stringidentifier)|`TClass->`Class(signaturenext_tokentokens,ClassName.of_stringidentifier)|`TClassType->`ClassType(signaturenext_tokentokens,ClassTypeName.of_stringidentifier)|`TMethod->`Method(class_signaturenext_tokentokens,MethodName.of_stringidentifier)|`TInstanceVariable->`InstanceVariable(class_signaturenext_tokentokens,InstanceVariableName.of_stringidentifier)|`TLabel->`Label(label_parentnext_tokentokens,LabelName.of_stringidentifier)|`TPage->letsuggestion=Printf.sprintf"'page-%s' should be first."identifierinParse_error.not_allowed~what:"Page label"~in_what:"the last component of a reference path"~suggestionlocation|>Error.raise_exceptioninletold_kind,s,location=letrecfind_old_reference_kind_separatorindex=matchs.[index]with|':'->index|')'->beginmatchString.rindex_fromsindex'('with|index->find_old_reference_kind_separator(index-1)|exception(Not_foundasexn)->raiseexnend|_->find_old_reference_kind_separator(index-1)|exceptionInvalid_argument_->raiseNot_foundinmatchfind_old_reference_kind_separator(String.lengths-1)with|index->letold_kind=String.trim(String.subs0index)inletold_kind_location=Location_.set_end_as_offset_from_startindexwhole_reference_locationinlets=String.subs(index+1)(String.lengths-(index+1))inletlocation=Location_.nudge_start(index+1)whole_reference_locationin(Some(old_kind,old_kind_location),s,location)|exceptionNot_found->(None,s,whole_reference_location)inError.catchbeginfun()->matchtokenizelocationswith|last_token::tokens->start_from_last_componentlast_tokenold_kindtokens|[]->Parse_error.should_not_be_empty~what:"reference target"whole_reference_location|>Error.raise_exceptionendletread_path_longidentlocations=letopenPaths.Pathinletrecloop:string->int->Module.toption=funspos->tryletidx=String.rindex_fromspos'.'inletname=String.subs(idx+1)(pos-idx)inifString.lengthname=0thenNoneelsematchloops(idx-1)with|None->None|Someparent->Some(`Dot(parent,name))withNot_found->letname=String.subs0(pos+1)inifString.lengthname=0thenNoneelseSome(`Rootname)inmatchloops(String.lengths-1)with|Somer->Result.Okr|None->Result.Error(Parse_error.expected"a valid path"location)letread_mod_longidentwarningslocationlid:(Paths.Reference.Module.t,Error.t)Result.result=matchparsewarningslocationlidwith|Error_ase->e|Okp->matchpwith|`Root(_,(`TUnknown|`TModule))|`Dot(_,_)|`Module(_,_)asr->Result.Okr|_->Result.Error(Parse_error.expected"a reference to a module"location)