12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879(* This file is part of Markup.ml, released under the MIT license. See
LICENSE.md for details, or visit https://github.com/aantron/markup.ml. *)(* Tries. These aren't fully functional nor fully mutable. To accumulate a trie,
it is necessary to retain the latest result of [add]. However, previous tries
become invalid after [add]. *)type'atrie=|Empty|Leafof'a|Nodeof'aoption*'atriearrayletlower_limit=Char.code'0'letupper_limit=Char.code'z'letarray_size=upper_limit-lower_limit+1letcreate()=Emptyletedge_indexc=Char.codec-lower_limitletaddkeyvaluetrie=letrectraverseindextrie=ifindex>=String.lengthkeythenmatchtriewith|Empty|Leaf_->Leafvalue|Node(_,children)->Node(Somevalue,children)elseletedge_index=edge_indexkey.[index]inletvalue',children,current_child=matchtriewith|Empty->None,None,Empty|Leafv->Somev,None,Empty|Node(v,children)->v,Somechildren,children.(edge_index)inletchild=traverse(index+1)current_childinletchildren=matchchildrenwith|None->Array.initarray_size(funi->ifi=edge_indexthenchildelseEmpty)|Somechildren->children.(edge_index)<-child;childreninNode(value',children)intraverse0trietype'amatch_=|No|Yesof'a|Prefix|Multipleof'aletmatches=function|Empty->No|Leafv->Yesv|Node(None,_)->Prefix|Node(Somev,_)->Multiplevletadvancec=function|Empty|Leaf_->Empty|Node(_,children)->ifc<lower_limit||c>upper_limitthenEmptyelsechildren.(c-lower_limit)letguess_memory_usagetrie=letrecaccumulatewords=function|Empty->words+1|Leaf_->words+2|Node(_,children)->letwords=words+4+Array.lengthchildreninArray.fold_leftaccumulatewordschildreninaccumulate0trie