26:- module(pPEGutilities,[
27 ptree_json_term/2, 28 ptree_pratt/2, 29 ptree_printstring/2, 30 ptree_printstring/3 31]). 32
33:-set_prolog_flag(optimise,true). 34
41ptree_json_term(PTree,[Name, Value]) :-
42 (string(Name)
43 -> atom_string(PName,Name), 44 PTree =.. [PName, PVal]
45 ; PTree =.. [PName, PVal], 46 atom_string(PName,Name)
47 ),
48 ptree_val_json_value(PVal,Value).
49
50ptree_val_json_value(Value,Value) :-
51 string(Value), !.
52ptree_val_json_value([], []) :- !. 53ptree_val_json_value([PNode|PNodes], [JNode|Jnodes]) :-
54 ptree_json_term(PNode, JNode),
55 ptree_val_json_value(PNodes, Jnodes).
56
83
84ptree_pratt(Tree, Pratt) :-
85 Tree =.. [PFunc,Args], 86 (string(Args) 87 -> Pratt = Tree
88 ; pratt_flatten_(Args,PFunc,T/T,List/[]),
89 pratt_(List,[Pratt]) 90 ).
91
92pratt_flatten_([],_PFunc,List,List).
93pratt_flatten_([Op|Ex],PFunc,LIn/[Pratt_op|Ts],LOut) :- 94 pratt_op(Op,Pratt_op), !,
95 pratt_flatten_(Ex,PFunc,LIn/Ts,LOut).
96pratt_flatten_([Tree|Ex],PFunc,LIn,LOut) :- 97 Tree =.. [PFunc,Args], !,
98 pratt_flatten_(Args,PFunc,LIn,LNxt),
99 pratt_flatten_(Ex,PFunc,LNxt,LOut).
100pratt_flatten_([ValIn|Ex],PFunc,LIn/[ValOut|Ts],LOut) :- 101 ValIn =.. [F,ArgsIn],
102 (string(ArgsIn)
103 -> ValOut = ValIn
104 ; pratt_args_(ArgsIn,PFunc,ArgsOut),
105 ValOut =.. [F,ArgsOut]
106 ),
107 pratt_flatten_(Ex,PFunc,LIn/Ts,LOut).
108
109pratt_args_([],_PFunc,[]).
110pratt_args_([Arg|ArgsIn],PFunc,[Arg|ArgsOut]) :-
111 atomic(Arg), !,
112 pratt_args_(ArgsIn,PFunc,ArgsOut).
113pratt_args_([ArgIn|ArgsIn],PFunc,[ArgOut|ArgsOut]) :-
114 ArgIn =.. [F,FArgsIn],
115 (F = PFunc
116 -> ptree_pratt(ArgIn,ArgOut) 117 ; pratt_args_(FArgsIn,PFunc,FArgsOut), 118 ArgOut =.. [F,FArgsOut]
119 ),
120 pratt_args_(ArgsIn,PFunc,ArgsOut).
121
123pratt_(['$pratt_op'(OpSym,_,_), V], [Term]) :- 124 not_op(V),
125 !,
126 Term =.. [OpSym,[V]].
127
128pratt_([V, '$pratt_op'(OpSym,_,_)], [Term]) :- 129 not_op(V),
130 !,
131 Term =.. [OpSym,[V]].
132
133pratt_([V1, '$pratt_op'(OpSym,_,_), V2], [Term]) :- 134 not_op(V1), not_op(V2),
135 !,
136 Term =.. [OpSym,[V1,V2]].
137
138pratt_(['$pratt_op'(OpSym1,OpL1,OpR1), '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term) :- 139 OpL2 > OpR1, 140 !,
141 pratt_right_(['$pratt_op'(OpSym2,OpL2,OpR2) |Etc], RHS),
142 pratt_(['$pratt_op'(OpSym1,OpL1,OpR1) |RHS], Term).
143
144pratt_([V, '$pratt_op'(OpSym1,OpL1,OpR1), '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term) :- 145 not_op(V),
146 !,
147 (OpL2 > OpR1
148 -> pratt_right_(['$pratt_op'(OpSym2,OpL2,OpR2) |Etc], RHS),
149 pratt_([V, '$pratt_op'(OpSym1,OpL1,OpR1) |RHS], Term)
150 ; pratt_([V, '$pratt_op'(OpSym1,OpL1,OpR1)], [LHS]),
151 pratt_([LHS, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term)
152 ).
153
154pratt_(['$pratt_op'(OpSym1,OpL1,OpR1), V, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term) :- 155 not_op(V),
156 !,
157 (OpL2 > OpR1
158 -> pratt_right_([V, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc],RHS),
159 pratt_(['$pratt_op'(OpSym1,OpL1,OpR1) |RHS], Term)
160 ; pratt_(['$pratt_op'(OpSym1,OpL1,OpR1), V], [LHS]),
161 pratt_([LHS, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term)
162 ).
163
164pratt_([V1, '$pratt_op'(OpSym1,OpL1,OpR1), V2, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term) :- 165 not_op(V1), 166 !,
167 (OpL2 > OpR1
168 -> pratt_right_([V2, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], RHS),
169 pratt_([V1, '$pratt_op'(OpSym1,OpL1,OpR1) |RHS], Term)
170 ; pratt_([V1, '$pratt_op'(OpSym1,OpL1,OpR1), V2], [LHS]),
171 pratt_([LHS, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term)
172 ).
173
174pratt_(Exp, _Term) :-
175 print_message(informational, prolog_parser(op_conflict(Exp))),
176 fail.
177
179pratt_right_(['$pratt_op'(OpSym1,OpL1,OpR1), '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term) :-
180 !,
181 OpL2 > OpR1, 182 pratt_right_(['$pratt_op'(OpSym2,OpL2,OpR2) |Etc], RHS),
183 Term = ['$pratt_op'(OpSym1,OpL1,OpR1) |RHS].
184
185pratt_right_(['$pratt_op'(OpSym1,OpL1,OpR1), V, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term) :-
186 !,
187 (OpL2 > OpR1
188 -> pratt_right_([V, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], RHS),
189 Term = ['$pratt_op'(OpSym1,OpL1,OpR1) |RHS]
190 ; pratt_(['$pratt_op'(OpSym1,OpL1,OpR1), V], [LHS]),
191 Term = [LHS,'$pratt_op'(OpSym2,OpL2,OpR2) |Etc]
192 ).
193
194pratt_right_([V, '$pratt_op'(OpSym1,OpL1,OpR1), '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term) :-
195 !,
196 (OpL2 > OpR1
197 -> pratt_right_(['$pratt_op'(OpSym2,OpL2,OpR2) |Etc], RHS),
198 Term = [V, '$pratt_op'(OpSym1,OpL1,OpR1) |RHS]
199 ; pratt_([V, '$pratt_op'(OpSym1,OpL1,OpR1)], [LHS]),
200 Term = [LHS,'$pratt_op'(OpSym2,OpL2,OpR2) |Etc]
201 ).
202
203pratt_right_([V1, '$pratt_op'(OpSym1,OpL1,OpR1), V2, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], Term) :-
204 !,
205 (OpL2 > OpR1
206 -> pratt_right_([V2, '$pratt_op'(OpSym2,OpL2,OpR2) |Etc], RHS),
207 Term = [V1, '$pratt_op'(OpSym1,OpL1,OpR1) |RHS]
208 ; pratt_([V1, '$pratt_op'(OpSym1,OpL1,OpR1), V2], [LHS]),
209 Term = [LHS,'$pratt_op'(OpSym2,OpL2,OpR2) |Etc]
210 ).
211
212pratt_right_(Exp, Term) :- pratt_(Exp, Term).
213
214
215prolog:message(prolog_parser(op_conflict(Exp))) --> 216 ['Error, operator clash in: ~p\n' - [Exp]].
217
218not_op(V) :- \+functor(V,'$pratt_op',_).
219
222pratt_op(Op, '$pratt_op'(OpSym,OpL,OpR)) :-
223 Op =.. [OpRule,SOp],
224 sub_atom(OpRule,_,3,0,PSfx), 225 atom_codes(PSfx,[95,P,A]),
226 OpL is P*2, 227 (A = 76 -> OpR is OpL+1 228 ;A = 82 -> OpR is OpL-1 229 ), 230 atom_string(OpSym,SOp). 231
232
253ptree_printstring(PTree, PPstring) :- 254 ptree_printstring(PTree, "", PPstring). 255
256ptree_printstring(PTree, Indent, PPstring) :- 257 ptree_printstring(PTree, [Indent], T/T, PPlist/[]),
258 atomics_to_string(PPlist, PPstring). 259
260ptree_printstring(PTree, Indent, StrIn, StrOut) :- 261 PTree =.. [Name, Val], 262 ptree_printstring_(Name, Val, Indent, StrIn, StrOut).
263
264ptree_printstring_(Name, AString, Indent, Str/Tail, Str/Etc) :- 265 string(AString), !,
266 format(string(OString),"~p",[AString]), 267 indent_term(Indent,[Name," ",OString,"\n"|Etc],Tail).
268ptree_printstring_(Name, Children, Indent, Str/Tail, Str/Etc) :- 269 270 indent_term(Indent,[Name,"\n"|Nxt],Tail),
271 new_indent(Indent,NxtIndent),
272 ptree_children(Children,NxtIndent,Str/Nxt,Str/Etc). 273
274ptree_children([], _, Str, Str). 275ptree_children([Term], [_|Indent], Str/Nxt, Str/Etc) :- !, 276 left_crn(LC),
277 ptree_printstring(Term, [LC|Indent], Str/Nxt, Str/Etc).
278ptree_children([Term|Terms], Indent, Str/Nxt1, Str/Etc) :-
279 ptree_printstring(Term, Indent, Str/Nxt1, Str/Nxt2),
280 ptree_children(Terms, Indent, Str/Nxt2, Str/Etc).
281
282indent_term([],Tail,Tail).
283indent_term([I|Is],In,Tail) :-
284 indent_term(Is,[I|In],Tail).
285
286new_indent([LT|Indent], New) :- left_tee(LT), !, 287 vertical(Vrt), New = [LT,Vrt|Indent].
288new_indent([LC|Indent], New) :- left_crn(LC), !, 289 left_tee(LT), space(SP), New = [LT,SP|Indent].
290new_indent(Indent,[LT|Indent]) :- 291 left_tee(LT).
292
293left_tee("\u251C\u2500"). 294left_crn("\u2514\u2500"). 295vertical("\u2502 "). 296space(" ").