123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188(**************************************************************************)(* This file is part of the Codex semantics library. *)(* *)(* Copyright (C) 2013-2025 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file LICENSE). *)(* *)(**************************************************************************)moduletypeLETTER=sigtypetvalequal:t->t->boolvalpretty:Format.formatter->t->unitvalhash:t->intendmoduletypeS=sigtypelettertypetvalempty:tvalepsilon:tvaljoin:t->t->tvalappend:t->letter->tvalappend_star:t->t->tvalequal:t->t->boolvalhash:t->intvalpretty:Format.formatter->t->unitvalpretty_reverse:Format.formatter->t->unitend(** Tagged regular expressions. The tag is used for cons-hashing and share as
many data structures as possibles. Tags should not be used outside of the
implementation. *)type'ltagged_regex=|Empty|Epsilon|Joinofint*'ltagged_regex*'ltagged_regex|Appendofint*'ltagged_regex*'l|AppendStarofint*'ltagged_regex*'ltagged_regexmoduleMake(L:LETTER):Swithtypeletter=L.tandtypet=L.ttagged_regex=structtypeletter=L.ttypet=L.ttagged_regexletempty=Emptyletepsilon=EpsilonmoduleHashedRegex=structtypet=L.ttagged_regexlettag=function|Empty->0|Epsilon->1|Join(x,_,_)->x|Append(x,_,_)->x|AppendStar(x,_,_)->xletshallow_equalxy=tagx=tagyletequalxy=matchx,ywith|Empty,Empty->true|Epsilon,Epsilon->true|Join(_,x1,y1),Join(_,x2,y2)->shallow_equalx1x2&&shallow_equaly1y2|Append(_,x1,l1),Append(_,x2,l2)->shallow_equalx1x2&&L.equall1l2|AppendStar(_,x1,y1),AppendStar(_,x2,y2)->shallow_equalx1x2&&shallow_equaly1y2|_->falselethashx=letempty_h=Hashtbl.hash0inletepsilon_h=Hashtbl.hash1inmatchxwith|Empty->empty_h|Epsilon->epsilon_h|Join(_,x,y)->Hashtbl.hash(0,tagx,tagy)|Append(_,r,l)->Hashtbl.hash(1,tagr,L.hashl)|AppendStar(_,prefix,body)->Hashtbl.hash(2,tagprefix,tagbody)endmoduleRegexHashSet=Weak.Make(HashedRegex)letequal=(==)lethash=HashedRegex.taglethash_set_init_size=2000lethash_set=RegexHashSet.createhash_set_init_sizelettag_counter=ref2letmaybe_sharenew_regex=letret=RegexHashSet.mergehash_setnew_regexinifret==new_regexthenbeginincrtag_counterend;retletjoinxy=ifx==ythenxelsematchx,ywith|Empty,_->y|_,Empty->x|_->maybe_share(Join(!tag_counter,x,y))letappendrl=matchrwith|Empty->empty|_->maybe_share(Append(!tag_counter,r,l))letappend_starrx=matchrwith|Empty->empty|_->maybe_share(AppendStar(!tag_counter,r,x))letprettyfmtr=letrecauxprecedencefmtr=letopenFormatinletppformat=fprintffmtformatinmatchrwith|Empty->pp"<empty>"|Epsilon->pp"<epsilon>"|Join(_,x,y)->(ifprecedence>0thenfprintffmt"(%a@ +@ %a)"elsefprintffmt"%a@ +@ %a")(aux0)x(aux0)y|Append(_,r,l)->(ifprecedence>1thenfprintffmt"@[<v>(%a@,%a)@]"elsefprintffmt"@[<v>%a@,%a@]")(pp_if_not_epsilon1)rL.prettyl|AppendStar(_,r,x)->(ifprecedence>1thenfprintffmt"@[<v>(%a@,%a*)@]"elsefprintffmt"@[<v>%a@,%a*@]")(pp_if_not_epsilon1)r(aux2)xandpp_if_not_epsilonprecedencefmtr=matchrwith|Epsilon->()|_->auxprecedencefmtrinaux0fmtrletpretty_reversefmtr=letrecauxprecedencefmtr=letopenFormatinletppformat=fprintffmtformatinmatchrwith|Empty->pp"<empty>"|Epsilon->pp"<epsilon>"|Join(_,x,y)->(ifprecedence>0thenpp"(%a@ +@ %a)"elsepp"%a@ +@ %a")(aux0)x(aux0)y|Append(_,r,l)->(ifprecedence>1thenpp"@[<v>(%a@,%a)@]"elsepp"@[<v>%a@,%a@]")L.prettyl(aux1)r|AppendStar(_,r,x)->(ifprecedence>1thenpp"@[<v>(%a*@,%a)@]"elsepp"@[<v>%a*@,%a@]")(aux2)x(aux1)rinaux0fmtrend