:- module(plht,[compile_plht/3,coerce_to_atom/2]). :- use_module(library(sgml)). :- dynamic special_tag. % sort the key/value lists so that % vars with the same name get unified. merge_vars(A,B,Vars):- append(A,B,AB), list_to_set(AB,Vars). merge_vars(A,B,C,Vars):- merge_vars(A,B,AB), merge_vars(AB,C,Vars). merge_vars(A,B,C,D,Vars):- merge_vars(A,B,AB), merge_vars(C,D,CD), merge_vars(AB,CD,Vars). coerce_to_atom(X,X):-atom(X),X\=[]. coerce_to_atom([X],X). coerce_to_atom([X|Rest],A):- coerce_to_atom(Rest,B), atom_concat(X,B,A). special_tag('pl:loop',pl_loop). special_tag('pl:parameter',pl_parameter). special_tag('pl:cond',pl_cond). pl_loop(Attrs,Content,Vars,Form):- memberchk(query=QueryA,Attrs), atom_to_term(QueryA,Term,Vars0), sort(Vars0,Vars1), form_from_tree(Content,Vars2,FormForContent), ( memberchk(counter=VarName,Attrs)-> merge_vars([VarName=Var|Vars1],Vars2,Vars), gensym(loop_counter,LID), Form=(flag(LID,_,1),ignore((Term, flag(LID,Var,Var+1), once(FormForContent),fail))); merge_vars(Vars1,Vars2,Vars), Form=ignore((Term,once(FormForContent),fail))). pl_parameter(Attrs,Content,Vars,Form):- memberchk(var=VarName,Attrs), memberchk(name=ParamName,Attrs), form_from_tree(Content,Vars2,FormForContent), ( memberchk(list=true,Attrs) -> Form=(findall(X,member(ParamName=X,Search),Var), FormForContent) ; once(memberchk(default=Default,Attrs);Default=''), Form=(once(memberchk(ParamName=Var,Search);Var=Default), FormForContent)), sort(['Search'=Search,VarName=Var],Vars1), merge_vars(Vars1,Vars2,Vars). pl_cond(_,[],[],fail). pl_cond(Attrs,[element('pl:if',[test=Test],Content)|Rest],Vars,Form):- !,atom_to_term(Test,TermT,Vars1), form_from_tree(Content,Vars2,FormForContent), pl_cond(Attrs,Rest,Vars3,FormForRest), Form=(TermT->FormForContent;FormForRest), merge_vars(Vars1,Vars2,Vars3,Vars). pl_cond(_,[element('pl:else',_,Content)|_],Vars,Form):- !, form_from_tree(Content,Vars,Form). pl_cond(Attrs,['\n'|Rest],Vars,Form):- !,pl_cond(Attrs,Rest,Vars,Form). pl_cond(Attrs,[Something|Rest],Vars,Form):- form_from_tree1(Something,Vars1,FormS), pl_cond(Attrs,Rest,Vars2,FormForRest), write(user_output,'warning: something in a pl_cond'), Form=(FormS,fail;FormForRest), merge_vars(Vars1,Vars2,Vars). form_for_value(ValA,Vars,Form):- atom_concat('$',VarName,ValA)-> Vars=[VarName=X],Form=(coerce_to_atom(X,X1),xml_quote_attribute(X1,Y),write(Y)); Vars=[],xml_quote_attribute(ValA,Val),Form=write(Val). form_from_attrs([],[],true). form_from_attrs([Name=Value|Rest],Vars,Form):- form_for_value(Value,Vars1,FormForValue), form_from_attrs(Rest,Vars2,FormForRest), Form=(write(' '),write(Name),write('="'),FormForValue,write('"'),FormForRest), merge_vars(Vars1,Vars2,Vars). form_for_tag(Tag,Attrs,Content,Vars,Form):- % special tag special_tag(Tag,Pred)-> call(Pred,Attrs,Content,Vars,Form); % html tag form_from_tree(Content,Vars1,FormForContent), form_from_attrs(Attrs,Vars2,FormForAttrs), merge_vars(Vars1,Vars2,Vars), Form=(write('<'),write(Tag),FormForAttrs,write('>'), FormForContent,write('')). form_from_tree1(element(Tag,Attrs,Content),Vars,Form):- form_for_tag(Tag,Attrs,Content,Vars,Form). form_from_tree1(CDATA,[],Form):- atom(CDATA), xml_quote_cdata(CDATA,Quoted), Form=write(Quoted). form_from_tree1(pi(F0),Vars,Term):- (atom_concat('pl ',F1,F0);atom_concat('pl\n',F1,F0))-> atom_to_term(F1,Term,Vars); atom_concat('pl=',F1,F0)-> atom_to_term(F1,Term0,Vars), Term=(xml_quote_attribute(Term0,Quoted),write(Quoted)); atom_concat('verbatim ',F1,F0)-> Term=write(F1),Vars=[]. form_from_tree([Something|Rest],Vars,Form):- form_from_tree1(Something,Vars1,Form1), form_from_tree(Rest,Vars2,Form2), merge_vars(Vars1,Vars2,Vars), Form=(Form1,Form2). form_from_tree([],[],true). form_from_file(File,Vars,Form):- load_xml_file(File,Tree), form_from_tree(Tree,Vars,Form0), optimize(Form0,Form). compile_plht(PredName,InFile,OutFile):- form_from_file(InFile,Vars,Form), merge_vars(Vars,['Query'=Query,'Search'=Search],_), Pred=..[PredName,Query], tell(OutFile), portray_clause(Pred:-(once(memberchk(search(Search),Query);Search=[]),Form)), told. linearize((A,B))-->!,linearize(A),linearize(B). linearize(A1)-->[A],{optimize(A1,A)}. unlinearize([A],A). unlinearize([A|As],(A,AA)):- unlinearize(As,AA). optimize1([A1,true|As],Bs):-!, optimize1([A1|As],Bs). optimize1([write(T1),write(T2)|Rest],Bs):- atom(T1),atom(T2),!, atom_concat(T1,T2,T3), optimize1([write(T3)|Rest],Bs). optimize1([A|Rest],[A|Bs]):- optimize1(Rest,Bs). optimize1([],[]). optimize((A,A1),B):-linearize((A,A1),As,[]),optimize1(As,Bs), unlinearize(Bs,B),!. optimize(ignore(A),ignore(A1)):-optimize(A,A1). optimize(once(A),once(A1)):-optimize(A,A1). optimize(A,A).