123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480(******************************************************************************)(* *)(* Menhir *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under *)(* the terms of the GNU Library General Public License version 2, with a *)(* special exception on linking, as described in the file LICENSE. *)(* *)(******************************************************************************)openCmly_formatopenCmly_apiexceptionErrorofstring(* ------------------------------------------------------------------------ *)(* Reading a .cmly file from a channel. *)letread_channel(ic:in_channel):grammar=(* .cmly file format: CMLY ++ version string ++ grammar *)letmagic="CMLY"^Version.versionintryletm=really_input_stringic(String.lengthmagic)inifm<>magicthenraise(Error(Printf.sprintf"Invalid magic string in .cmly file.\n\
Expecting %S, but got %S."magicm))else(input_valueic:grammar)with|End_of_file(* [really_input_string], [input_value] *)|Failure_->(* [input_value] *)raise(Error(Printf.sprintf"Invalid or damaged .cmly file."))(* Reading a .cmly file based on its filename. *)letread(filename:string):grammar=letic=open_in_binfilenameinmatchread_channelicwith|x->close_in_noerric;x|exceptionexn->close_in_noerric;raiseexn(* ------------------------------------------------------------------------ *)(* Reading a .cmly file whose content is stored in a string. *)letstarts_withprefixs=String.(lengthprefix<=lengths&&prefix=subs0(lengthprefix))letfrom_string(content:string):grammar=(* .cmly file format: CMLY ++ version string ++ grammar *)letmagic="CMLY"^Version.versioninifstarts_withmagiccontentthentryMarshal.from_stringcontent(String.lengthmagic)withFailure_->raise(Error(Printf.sprintf"Invalid or damaged .cmly file."))elseletm=String.(subcontent0(min(lengthmagic)(lengthcontent)))inraise(Error(Printf.sprintf"Invalid magic string in .cmly file.\n\
Expecting %S, but got %S."magicm))(* ------------------------------------------------------------------------ *)(* Packaging the interval [0..count) as a module of type [INDEXED]. *)moduleIndex(P:sigvalname:string(* for error messages only *)valcount:intend):INDEXEDwithtypet=int=structtypet=intletcount=P.countletof_intn=if0<=n&&n<countthennelseinvalid_arg(P.name^".of_int: index out of bounds")letto_intn=nlethashn=nletequal(i:int)(j:int)=i=jletcompare(i:int)(j:int)=i-j(* OK for integers of small magnitude *)letiterf=fori=0tocount-1dofidoneletfoldfx=letr=refxinfori=0tocount-1dor:=fi!rdone;!rlettabulatef=leta=Array.initcountfinArray.getaend(* ------------------------------------------------------------------------ *)(* Packaging a data structure of type [Cmly_format.grammar] as a module
of type [Cmly_api.GRAMMAR]. *)moduleLift(G:sigvalgrammar:grammarend):GRAMMAR=structopenGtypeterminal=inttypenonterminal=inttypeproduction=inttypelr0=inttypelr1=inttypeitem=production*inttypeocamltype=stringtypeocamlexpr=stringtypeidentifier=stringmoduleRange=structtypet=Cmly_format.rangeletstartprange=range.r_startletendprange=range.r_endendtype'alocated='a*Range.tmoduleAttribute=structtypet=Cmly_format.attributeletlabelattr=attr.a_labellethas_labellabelattr=label=attr.a_labelletpayloadattr=attr.a_payloadletpositionattr=attr.a_positionendmoduleAction=structtypet=actionletexprt=t.a_exprletkeywordst=t.a_keywordsendmoduleSurface=structtypefilename=stringtypename=stringmodulePriority_level=structtypet=priority_levelletinput_filet=t.pl_input_fileletlevelt=t.pl_levelendmoduleProducer=structtype'symt='symproducer_defletsymbol(x,_,_)=xletidentifier(_,x,_)=xletattributes(_,_,x)=xendmoduleBranch=structtype'symt='symsurface_branchletpositiont=t.br_positionletproducerst=t.br_producersletactiont=t.br_actionletprec_annotationt=t.br_prec_annotationletproduction_levelt=t.br_production_levelletattributest=t.br_attributesendmoduleParameter=structtypet=parametertypedesc=|Varofname|Appofname*tlist|AnonymousoftBranch.tlistletdesc=function|ParameterVar(x,_)->Varx|ParameterApp((x,_),xs)->App(x,xs)|ParameterAnonymous(x,_)->Anonymousxletlocated(ParameterVar(_,pos)|ParameterApp((_,pos),_)|ParameterAnonymous(_,pos))=posendmoduleRule=structtype('param,'sym)t=('param,'sym)surface_ruleletparameterst=t.r_parametersletbranchest=t.r_branchesletinlinet=t.r_inlineletpositionst=t.r_positionsletpublict=t.r_publicletattributest=t.r_attributesendmoduleToken=structtypet=surface_tokentypeassociativity=Cmly_format.token_associativity=|LeftAssoc|RightAssoc|NonAssoc|UndefinedAssocletocamltypet=t.tk_ocamltypeletpositiont=t.tk_positionletaliast=t.tk_aliasletattributest=t.tk_attributesletassociativityt=t.tk_associativityletprecedencet=t.tk_precedenceletis_declaredt=t.tk_is_declaredendmoduleSyntax=structtype('param,'sym)t=('param,'sym)surface_syntaxlettypest=t.s_typeslettokenst=t.s_tokensletrulest=t.s_rulestypeground=(unit,name)ttypehigher=(namelist,Parameter.t)tendletstart_symbols=grammar.g_start_symbolsleton_error_reduce=grammar.g_on_error_reduceletbefore_expansion=grammar.g_before_expansionletbefore_inlining=grammar.g_before_inliningendmoduleGrammar=structletbasename=grammar.g_basenameletpreludes=grammar.g_preludesletpostludes=grammar.g_postludesletentry_points=grammar.g_entry_pointsletattributes=grammar.g_attributesletparameters=grammar.g_parametersendmoduleTerminal=structlettable=grammar.g_terminalsletnamei=table.(i).t_nameletkindi=table.(i).t_kindlettypi=table.(i).t_typeletattributesi=table.(i).t_attributesincludeIndex(structletname="Terminal"letcount=Array.lengthtableend)endmoduleNonterminal=structlettable=grammar.g_nonterminalsletnamei=table.(i).n_nameletmangled_namei=table.(i).n_mangled_nameletkindi=table.(i).n_kindlettypi=table.(i).n_typeletpositionsi=table.(i).n_positionsletnullablei=table.(i).n_nullableletfirsti=table.(i).n_firstletattributesi=table.(i).n_attributesincludeIndex(structletname="Nonterminal"letcount=Array.lengthtableend)endtypesymbol=Cmly_format.symbol=|Tofterminal|Nofnonterminalletsymbol_name?(mangled=false)=function|Tt->Terminal.namet|Nn->ifmangledthenNonterminal.mangled_namenelseNonterminal.namenmoduleSymbol=structtypet=symbol=|Tofterminal|Nofnonterminallethash=functionTt->t|Nnt->nt(* [t] and [nt] are integers *)letequal=(=)(* OK to use polymorphic equality *)letcompare=compare(* OK to use polymorphic comparison *)letname=symbol_nameendmoduleProduction=structlettable=grammar.g_productionsletkindi=table.(i).p_kindletlhsi=table.(i).p_lhsletrhsi=table.(i).p_rhsletpositionsi=table.(i).p_positionsletactioni=table.(i).p_actionletattributesi=table.(i).p_attributesincludeIndex(structletname="Production"letcount=Array.lengthtableend)endmoduleLr0=structlettable=grammar.g_lr0_statesletincomingi=table.(i).lr0_incomingletitemsi=table.(i).lr0_itemsincludeIndex(structletname="Lr0"letcount=Array.lengthtableend)endmoduleLr1=structlettable=grammar.g_lr1_statesletlr0i=table.(i).lr1_lr0lettransitionsi=table.(i).lr1_transitionsletget_reductionsi=table.(i).lr1_reductionsletdefault_reductioni=table.(i).lr1_default_reductionincludeIndex(structletname="Lr1"letcount=Array.lengthtableend)letreductionsi=List.map(fun(s,p)->(s,[p]))table.(i).lr1_reductionsendmodulePrint=structletterminalppft=Format.pp_print_stringppf(Terminal.namet)letnonterminalppft=Format.pp_print_stringppf(Nonterminal.namet)letsymbolppf=function|Tt->terminalppft|Nn->nonterminalppfnletmangled_nonterminalppft=Format.pp_print_stringppf(Nonterminal.namet)letmangled_symbolppf=function|Tt->terminalppft|Nn->mangled_nonterminalppfnletreclengthslacc=function|[]->ifl=-1then[]elsel::lengths(-1)[]acc|[]::rows->lengthslaccrows|(col::cols)::rows->lengths(maxl(String.lengthcol))(cols::acc)rowsletrecadjust_lengthlengthscols=matchlengths,colswith|l::ls,c::cs->letpad=l-String.lengthcinletc=ifpad=0thencelsec^String.makepad' 'inc::adjust_lengthlscs|_,[]->[]|[],_->assertfalseletalign_tabularrows=letlengths=lengths(-1)[]rowsinList.map(adjust_lengthlengths)rowsletprint_lineppf=function|[]->()|x::xs->Format.fprintfppf"%s"x;List.iter(Format.fprintfppf" %s")xsletprint_tableppftable=lettable=align_tabulartableinList.iter(Format.fprintfppf"%a\n"print_line)tableletannot_itemsetannotsppfitems=letlast_lhs=ref(-1)inletprepare(p,pos)annot=letrhs=Array.map(fun(sym,id,_)->ifid<>""&&id.[0]<>'_'then"("^id^" = "^symbol_namesym^")"elsesymbol_namesym)(Production.rhsp)inifpos>=0&&pos<Array.lengthrhsthenrhs.(pos)<-". "^rhs.(pos)elseifpos>0&&pos=Array.lengthrhsthenrhs.(pos-1)<-rhs.(pos-1)^" .";letlhs=Production.lhspinletrhs=Array.to_listrhsinletrhs=if!last_lhs=lhsthen""::" |"::rhselsebeginlast_lhs:=lhs;Nonterminal.namelhs::"::="::rhsendinifannot=[]then[rhs]else[rhs;(""::""::annot)]inletrecprepare_allxsys=matchxs,yswith|[],_->[]|(x::xs),(y::ys)->letz=preparexyinz::prepare_allxsys|(x::xs),[]->letz=preparex[]inz::prepare_allxs[]inprint_tableppf(List.concat(prepare_allitemsannots))letitemsetppft=annot_itemset[]ppftletannot_itemannotppfitem=annot_itemset[annot]ppf[item]letitemppft=annot_item[]ppftletproductionppft=itemppf(t,-1)endend(* ------------------------------------------------------------------------ *)(* High-level views of the low-level functions [read] and [from_string]. *)moduleRead(X:sigvalfilename:stringend)=Lift(structletgrammar=readX.filenameend)moduleFromString(X:sigvalcontent:stringend)=Lift(structletgrammar=from_stringX.contentend)