123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158(*****************************************************************************
Liquidsoap, a programmable stream generator.
Copyright 2003-2024 Savonet team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details, fully stated in the COPYING
file at the root of the liquidsoap distribution.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************)(** Helper functions for the parser. *)openParsed_termmoduleTerm=Parsed_termmoduleVars=Term_base.Varstypearglist=Parsed_term.fun_arglisttypepos=Parsed_term.postypelexer_let_decoration=[`None|`Recursive|`Replaces|`Eval|`Json_parse|`Yaml_parse|`Xml_parse|`Sqlite_row|`Sqlite_query]typeexplicit_binding=[`DefofTerm._let|`LetofTerm._let]typebinding=[explicit_binding|`BindingofTerm._let]letrender_string_ref=ref(fun~pos:__->assertfalse)(* This is filled by Lexer to make it possible to use this function in the parser. *)letrender_string~poss=letfn=!render_string_refinfn~possletpending_comments=ref[]letclear_comments()=pending_comments:=[]letappend_comment~posc=letcomments=List.mapString.trim(String.split_on_char'\n'c)inpending_comments:=(pos,comments)::!pending_commentsletcomment_distanceterm_poscomment_pos=if(fstcomment_pos).Lexing.pos_lnum=(sndterm_pos).Lexing.pos_lnumthen(`Before,0)else(letbefore_distance=(fstterm_pos).Lexing.pos_lnum-(sndcomment_pos).Lexing.pos_lnuminletafter_distance=(fstcomment_pos).Lexing.pos_lnum-(sndterm_pos).Lexing.pos_lnuminif0<=after_distance&&(before_distance<0||after_distance<before_distance)then(`After,after_distance)else(`Before,before_distance))letsort_commentscomments=List.sort(fun(p,_)(p',_)->Stdlib.compare(fstp).Lexing.pos_cnum(fstp').Lexing.pos_cnum)commentsletattach_commentsterm=List.iter(fun(comment_pos,c)->letclosest_term=refterminletdistance=ref(comment_distanceterm.poscomment_pos)inParsed_term.iter_term(funterm->match(comment_distanceterm.poscomment_pos,!distance)with|(t,d),(t',d')when0<=d&&(d'<0||ift=`Before&&t'=`Afterthend<=d'elsed<d')->distance:=(t,d);closest_term:=term|_->())term;letcomment=match!distancewith`Before,_->`Beforec|`After,_->`Aftercin!closest_term.comments<-sort_comments((comment_pos,comment)::!closest_term.comments))!pending_comments;pending_comments:=[]letlet_args~decoration~pat?arglist~def?cast()={decoration;pat;arglist;def;cast}letmk_json_assoc_object_ty~pos=function|`Tuple[`Named"string";ty],"as","json","object"->`Json_objectty|_->raise(Term_base.Parse_error(pos,"Invalid type constructor"))typelet_opt_el=string*Term.tletlet_decoration_of_lexer_let_decoration=function|`Json_parse->`Json_parse[]|`Yaml_parse->`Yaml_parse|`Xml_parse->`Xml_parse|`Sqlite_query->`Sqlite_query|`Sqlite_row->`Sqlite_row|`Eval->`Eval|`Recursive->`Recursive|`None->`None|`Replaces->`Replacesletargs_of_json_parse~pos=function|[]->[]|[("json5",v)]->[("json5",v)]|(lbl,_)::_->raise(Term_base.Parse_error(pos,"Invalid argument "^lbl^" for json.parse let constructor"))letmk=Parsed_term.makeletmk_fun~posargumentsbody=mk~pos(`Fun(arguments,body))letmk_try?ensure?handler?errors_list~variable~body~pos()=mk~pos(`Try{try_body=body;try_variable=variable;try_errors_list=errors_list;try_handler=handler;try_finally=ensure;})letmk_let~pos_letbody=letast=match_letwith|`Letv->`Let(v,body)|`Defv->`Def(v,body)|`Bindingv->`Binding(v,body)inmk~posastletmk_encoder~posep=mk~pos(`Encoder(e,p))