123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162openLogic.Abstract_syntaxmoduleLog=UtilsLib.Xlog.Make(structletname="Term_sequence"end)typetoken=|Termof(Abstract_syntax.term*Abstract_syntax.location)|Opof(Abstract_syntax.term*Abstract_syntax.syntactic_behavior*Abstract_syntax.location)letrecabs_term_to_string_=function|Abstract_syntax.Var(x,_)|Abstract_syntax.Const(x,_)->x|Abstract_syntax.Abs(x,_,t,_)->Printf.sprintf"(Lambda %s. %a)"xabs_term_to_stringt|Abstract_syntax.LAbs(x,_,t,_)->Printf.sprintf"(lambda %s. %a)"xabs_term_to_stringt|Abstract_syntax.App(t1,t2,_)->Printf.sprintf"(%a %a)"abs_term_to_stringt1abs_term_to_stringt2letto_string=abs_term_to_string()lettok_to_string=functionTerm(t,_)|Op(t,_,_)->to_stringtletis_infix=functionAbstract_syntax.Infix_->true|_->falseletis_prefix=functionAbstract_syntax.Prefix->true|_->falseletlower_thanf1f2=match(f1,f2)with|Abstract_syntax.Infix(_,p1),Abstract_syntax.Infix(_,p2)->p1<p2|_->falseletnext=function[]->(None,[])|a::tl->(Somea,tl)letnew_loc(s,_)(_,e)=(s,e)letrecparse_sequence_auxstacktokenstreamsg=Log.debug(funm->m"stack: '%s', token: '%s', stream: '%s'\n"(UtilsLib.Utils.string_of_list" ; "tok_to_stringstack)(matchtokenwithSomet->tok_to_stringt|None->"None")(UtilsLib.Utils.string_of_list" ; "tok_to_stringstream));match(stack,token)with|[],Somet->(* shift to initiate the process *)lettoken',stream'=nextstreaminparse_sequence_aux(t::stack)token'stream'sg|[Term(t,loc)],None->(* sucessful parse *)(t,loc)|[Term_],Sometok->(* shift *)lettoken',stream'=nextstreaminparse_sequence_aux(tok::stack)token'stream'sg|Term(t,loc_t)::Op(t_op,f,loc_o)::tl,_whenis_prefixf->(* reduce: prefix operators have the highest precedence *)letloc=new_locloc_oloc_tinletnew_term=Abstract_syntax.App(t_op,t,loc)inparse_sequence_aux(Term(new_term,loc)::tl)tokenstreamsg(* | (Term _)::(Term _)::tl,Some ((Op _) as tok) ->
(* shift: prefix operators have higher precedence than application *)
(* application has higher precedence than infix operators *)
let token',stream' = next stream in
parse_sequence_aux (tok::stack) token' stream' sg *)|Term(t2,l2)::Term(t1,l1)::tl,_->(* reduce: application can be perfomed *)(* prefix operators have higher precedence than application *)(* application has higher precedence than infix operators *)letloc=new_locl1l2inletterm=Abstract_syntax.App(t1,t2,loc)inparse_sequence_aux(Term(term,loc)::tl)tokenstreamsg|Op(_,f1,_)::Op(_,f2,_)::_,Sometokwhenis_prefixf2&&is_prefixf1->(* shift *)lettoken',stream'=nextstreaminparse_sequence_aux(tok::stack)token'stream'sg|Op(o1,_f1,l_o1)::Op(_,f2,_)::_,_whenis_prefixf2->Errors.(ParsingErrors.emit(Parsing_l.InfixMissingFirstArg(to_stringo1))~loc:l_o1)(* | (Op (_,f1,_))::(Op (o2,f2,l_o2))::_,_ when (is_prefix f2) && (is_infix f1) ->
raise (Old_error.(Error (Parse_error (Infix_missing_second_arg (to_string o2),l_o2)))) *)|Op_::_,Sometok->(* shift. It makes sense to shift *)lettoken',stream'=nextstreaminparse_sequence_aux(tok::stack)token'stream'sg|(Term(t2,l2)::Op(o1,f1,l_o1)::Term(t1,l1)::tl,Some(Op(_o2,f2,_l_o2)))whenis_infixf1&&is_infixf2&&lower_thanf2f1->(* reduce: there are two different operators, *)(* and the first one has the highest precedence *)letloc=new_locl1l_o1inletpartial_term=Abstract_syntax.App(o1,t1,loc)inletloc=new_loclocl2inletnew_term=Abstract_syntax.App(partial_term,t2,loc)inparse_sequence_aux(Term(new_term,loc)::tl)tokenstreamsg|Term_::Op(_,f1,_)::Term_::_,Some(Op(_,f2,_)astok)whenis_infixf1&&is_infixf2&&lower_thanf1f2->(* shift: there are two different operators, *)(* and the second one has the highest precedence *)lettoken',stream'=nextstreaminparse_sequence_aux(tok::stack)token'stream'sg|(Term(t2,l2)::Op(o1,f1,l_o1)::Term(t1,l1)::tl,Some(Op(_,f2,_)astok))whenis_infixf1&&f1=f2->((* there is a sequence with the same operator *)matchf1with|Abstract_syntax.Infix(Abstract_syntax.Left,_)->(* reduce: it is left associative *)letloc=new_locl1l_o1inletpartial_term=Abstract_syntax.App(o1,t1,loc)inletloc=new_loclocl2inletnew_term=Abstract_syntax.App(partial_term,t2,loc)inparse_sequence_aux(Term(new_term,loc)::tl)tokenstreamsg|Abstract_syntax.Infix(Abstract_syntax.Right,_)->(* shift: it is right associative *)lettoken',stream'=nextstreaminparse_sequence_aux(tok::stack)token'stream'sg|Abstract_syntax.Infix(Abstract_syntax.NonAss,_)->(* error: since it is not associative, there *)(* should not be such a sequence *)Errors.(ParsingErrors.emit(Parsing_l.NotAssociative(to_stringo1))~loc:l_o1)|_->failwith"Bug: shouldn't happen")|(Term(_t2,_l2)::Op(_o1,f1,_l_o1)::Term(_t1,_l1)::_,Some(Term_ast))whenis_infixf1->(* shift: application has precedence over the operator *)(* let loc = new_loc l1 l_o1 in
let partial_term = Abstract_syntax.App (o1,t1,loc) in
let loc = new_loc loc l2 in
let new_term = Abstract_syntax.App (partial_term,t2,loc) in
parse_sequence_aux ((Term (new_term,loc))::tl) token stream sg *)lettoken',stream'=nextstreaminparse_sequence_aux(t::stack)token'stream'sg|Term(t2,l2)::Op(o1,f1,l_o1)::Term(t1,l1)::tl,Nonewhenis_infixf1->(* reduce *)letloc=new_locl1l_o1inletpartial_term=Abstract_syntax.App(o1,t1,loc)inletloc=new_loclocl2inletnew_term=Abstract_syntax.App(partial_term,t2,loc)inparse_sequence_aux(Term(new_term,loc)::tl)tokenstreamsg(* failwith (Printf.sprintf "Parse error on \"%s\"" o1) *)(* raise (Old_error.(Error (Parse_error (Not_infix (to_string o1),l_o1))))*)|Term_::Op_::Term_::_,Some(Op_)->failwith"Bug: Should not happen"|Term_::Op(o1,_,l_o1)::Term_::_,_->(* o1 is not infix *)Errors.(ParsingErrors.emit(Parsing_l.NotInfix(to_stringo1))~loc:l_o1)|Term_::Op(o1,_,l_o1)::Op_::_,_->(* failwith (Printf.sprintf "Parse error on \"%s\"" o1) *)Errors.(ParsingErrors.emit(Parsing_l.InfixMissingFirstArg(to_stringo1))~loc:l_o1)|Term_::[Op(o1,_,l_o1)],_->(* the case where o1 is infox is already matched. Then o1 is infix *)Errors.(ParsingErrors.emit(Parsing_l.InfixMissingFirstArg(to_stringo1))~loc:l_o1)|Op(o,f,l)::_,Nonewhenis_infixf->Errors.(ParsingErrors.emit(Parsing_l.InfixMissingSecondArg(to_stringo))~loc:l)|Op(o,_f,l)::_,None->(* Op is necesseraly prefix *)Errors.(ParsingErrors.emit(Parsing_l.PrefixMissingArg(to_stringo))~loc:l)|[],None->failwith"Bug: an empty list should not be parsed"letparse_sequencestream=lettok,stream'=nextstreaminparse_sequence_aux[]tokstream'