/** * Module containing the strategies used to post-process a * parsed PHP-source. * Post-processing includes: * - Rewriting HereDoc an DoubleQuoted-parts to lists * * @author Eric Bouwers */ module php/parse/postprocess strategies /** * Rewrites all the structures of DQ- and HereDoc strings to lists. * This is needed because a follow-restriction cannot prevent ambiguity */ post-process-structures = bottomup(try( content-to-list <+ fix-heredoc ) ) ; bottomup(try(check-heredoc)) // needs seperate phase, incorrect heredoc can exists intermediately strategies /** * Fixes the ambigious HereDoc when multiple HereDocs occur in a program. */ fix-heredoc = ?amb(lst) ; lst' := <map(fix-and-length)> lst ; list-accum(tup-min) fix-and-length = try(fix-conc) ; !(<length>,<id>) fix-conc = ?Conc(a,b) ; <conc> (<try(fix-heredoc)> a,<try(fix-heredoc)> b) tup-min = ?((l1,xs1),(l2,xs2)) ; if <gt> (l1,l2) then !xs1 else !xs2 end strategies /** * Checks whether the HereDoc start-tag is equal to the end-tag. * We can just check if it ends-with the start-tag because otherwise * the HereDoc would not parse. * * @type HereDoc(_,_,_) -> exit */ check-heredoc = ?HereDoc(HereDocStart(starttag),_,endtag) ; <not(string-ends-with(|starttag))> endtag ; !(starttag,endtag) ; debug(!"There exist a HereDoc without matching start- and endtag.\n") ; <exit> 1 rules /** * Transforms the content of a DoubleQuoted string into a * list. * TODO: Integrate both HereDoc- and DQ-content * * @type DQContent() -> List() */ content-to-list : DQContent(lit) -> list where list := <make-list> lit content-to-list : HereDocContent(lit) -> list where list := <make-list> lit content-to-list : DQContent(lit1,esc,lit2) -> list where lit1' := <make-list> lit1 ; lit2' := <make-list> lit2 ; esc' := <maybe-wrap-in-list> esc ; list := <conc> (lit1',esc',lit2') content-to-list : HereDocContent(lit1,esc,lit2) -> list where lit1' := <make-list> lit1 ; lit2' := <make-list> lit2 ; esc' := <maybe-wrap-in-list> esc ; list := <conc> (lit1',esc',lit2') content-to-list : DQContent(esc1,lit,esc2) -> list where lit' := <make-list> lit ; esc1' := <maybe-wrap-in-list> esc1 ; esc2' := <maybe-wrap-in-list> esc2 ; list := <conc> (esc1',lit',esc2') content-to-list : HereDocContent(esc1,lit,esc2) -> list where lit' := <make-list> lit ; esc1' := <maybe-wrap-in-list> esc1 ; esc2' := <maybe-wrap-in-list> esc2 ; list := <conc> (esc1',lit',esc2') /** * Utility function to transform a (possible transformed) * */ make-list: Some(s) -> [Literal(s)] make-list: None() -> [] make-list: [x | xs ] -> [x | xs] make-list: [] -> [] strategies /** * Wraps a certain term in a list when it is not a list. * @type _ -> List(_) */ maybe-wrap-in-list= ?esc ; if <?[x | xs]> esc then esc' := esc else esc' := [esc] end