36
37:- module('$dcg',
38 [ dcg_translate_rule/2, 39 dcg_translate_rule/4, 40 phrase/2, 41 phrase/3, 42 call_dcg/3 43 ]).
58dcg_translate_rule(Rule, Clause) :-
59 dcg_translate_rule(Rule, _, Clause, _).
60
61dcg_translate_rule((LP,MNT-->RP), Pos0, Clause, Pos) =>
62 Clause = (H:-B0,B1),
63 f2_pos(Pos0, PosH0, PosRP0, Pos, PosH, PosRP),
64 f2_pos(PosH0, PosLP0, PosMNT0, PosH, PosLP, PosMNT),
65 '$current_source_module'(M),
66 Qualify = q(M,M,_),
67 dcg_extend(LP, PosLP0, S0, SR, H, PosLP),
68 dcg_body(RP, PosRP0, Qualify, S0, S1, B0, PosRP),
69 dcg_body(MNT, PosMNT0, Qualify, SR, S1, B1, PosMNT).
70dcg_translate_rule((LP-->RP), Pos0, Clause, Pos) =>
71 Clause = (H:-B),
72 f2_pos(Pos0, PosLP0, PosRP0, Pos, PosLP, PosRP),
73 dcg_extend(LP, PosLP0, S0, S, H, PosLP),
74 '$current_source_module'(M),
75 Qualify = q(M,M,_),
76 dcg_body(RP, PosRP0, Qualify, S0, S, B, PosRP).
77dcg_translate_rule((LP,MNT==>RP), Pos0, Clause, Pos), is_list(MNT) =>
78 Clause = (H=>B0,B1),
79 f2_pos(Pos0, PosH0, PosRP0, Pos, PosH, PosRP),
80 f2_pos(PosH0, PosLP0, PosMNT0, PosH, PosLP, PosMNT),
81 '$current_source_module'(M),
82 Qualify = q(M,M,_),
83 dcg_extend(LP, PosLP0, S0, SR, H, PosLP),
84 dcg_body(RP, PosRP0, Qualify, S0, S1, B0, PosRP),
85 dcg_body(MNT, PosMNT0, Qualify, SR, S1, B1, PosMNT).
86dcg_translate_rule((LP,Grd==>RP), Pos0, Clause, Pos) =>
87 Clause = (H,Grd=>B),
88 f2_pos(Pos0, PosH0, PosRP0, Pos, PosH, PosRP),
89 f2_pos(PosH0, PosLP0, PosGrd, PosH, PosLP, PosGrd),
90 dcg_extend(LP, PosLP0, S0, S, H, PosLP),
91 '$current_source_module'(M),
92 Qualify = q(M,M,_),
93 dcg_body(RP, PosRP0, Qualify, S0, S, B, PosRP).
94dcg_translate_rule((LP==>RP), Pos0, Clause, Pos) =>
95 Clause = (H=>B),
96 f2_pos(Pos0, PosLP0, PosRP0, Pos, PosLP, PosRP),
97 dcg_extend(LP, PosLP0, S0, S, H, PosLP),
98 '$current_source_module'(M),
99 Qualify = q(M,M,_),
100 dcg_body(RP, PosRP0, Qualify, S0, S, B, PosRP).
106dcg_body(Var, P0, Q, S, SR, phrase(QVar, S, SR), P) :-
107 var(Var),
108 !,
109 qualify(Q, Var, P0, QVar, P).
110dcg_body(M:X, Pos0, q(_,C,_), S, SR, Ct, Pos) :-
111 !,
112 f2_pos(Pos0, _, XP0, _, _, _),
113 dcg_body(X, XP0, q(M,C,Pos0), S, SR, Ct, Pos).
114dcg_body([], P0, _, S, SR, S=SR, P) :- 115 !,
116 dcg_terminal_pos(P0, P).
117dcg_body(List, P0, _, S, SR, C, P) :-
118 ( List = [_|_]
119 -> !,
120 ( is_list(List)
121 -> '$append'(List, SR, OL), 122 C = (S = OL)
123 ; '$type_error'(list, List)
124 )
125 ; string(List) 126 -> !,
127 string_codes(List, Codes),
128 '$append'(Codes, SR, OL),
129 C = (S = OL)
130 ),
131 dcg_terminal_pos(P0, P).
132dcg_body(!, P0, _, S, SR, (!, SR = S), P) :-
133 !,
134 dcg_cut_pos(P0, P).
135dcg_body({}, P, _, S, S, true, P) :- !.
136dcg_body({T}, P0, Q, S, SR, (QT, SR = S), P) :-
137 !,
138 dcg_bt_pos(P0, P1),
139 qualify(Q, T, P1, QT, P).
140dcg_body((T,R), P0, Q, S, SR, (Tt, Rt), P) :-
141 !,
142 f2_pos(P0, PA0, PB0, P, PA, PB),
143 dcg_body(T, PA0, Q, S, SR1, Tt, PA),
144 dcg_body(R, PB0, Q, SR1, SR, Rt, PB).
145dcg_body((T;R), P0, Q, S, SR, (Tt;Rt), P) :-
146 !,
147 f2_pos(P0, PA0, PB0, P, PA, PB),
148 dcg_body(T, PA0, Q, S, S1, T1, PA), or_delay_bind(S, SR, S1, T1, Tt),
149 dcg_body(R, PB0, Q, S, S2, R1, PB), or_delay_bind(S, SR, S2, R1, Rt).
150dcg_body((T|R), P0, Q, S, SR, (Tt;Rt), P) :-
151 !,
152 f2_pos(P0, PA0, PB0, P, PA, PB),
153 dcg_body(T, PA0, Q, S, S1, T1, PA), or_delay_bind(S, SR, S1, T1, Tt),
154 dcg_body(R, PB0, Q, S, S2, R1, PB), or_delay_bind(S, SR, S2, R1, Rt).
155dcg_body((C->T), P0, Q, S, SR, (Ct->Tt), P) :-
156 !,
157 f2_pos(P0, PA0, PB0, P, PA, PB),
158 dcg_body(C, PA0, Q, S, SR1, Ct, PA),
159 dcg_body(T, PB0, Q, SR1, SR, Tt, PB).
160dcg_body((C*->T), P0, Q, S, SR, (Ct*->Tt), P) :-
161 !,
162 f2_pos(P0, PA0, PB0, P, PA, PB),
163 dcg_body(C, PA0, Q, S, SR1, Ct, PA),
164 dcg_body(T, PB0, Q, SR1, SR, Tt, PB).
165dcg_body((\+ C), P0, Q, S, SR, (\+ Ct, SR = S), P) :-
166 !,
167 f1_pos(P0, PA0, P, PA),
168 dcg_body(C, PA0, Q, S, _, Ct, PA).
169dcg_body(T, P0, Q, S, SR, QTt, P) :-
170 dcg_extend(T, P0, S, SR, Tt, P1),
171 qualify(Q, Tt, P1, QTt, P).
172
173or_delay_bind(S, SR, S1, T, (T, SR=S)) :-
174 S1 == S,
175 !.
176or_delay_bind(_S, SR, SR, T, T).
184qualify(q(M,C,_), X0, Pos0, X, Pos) :-
185 M == C,
186 !,
187 X = X0,
188 Pos = Pos0.
189qualify(q(M,_,MP), X, Pos0, M:X, Pos) :-
190 dcg_qualify_pos(Pos0, MP, Pos).
200:- dynamic dcg_extend_cache/4. 201:- volatile dcg_extend_cache/4. 202
203dcg_no_extend([]).
204dcg_no_extend([_|_]).
205dcg_no_extend({_}).
206dcg_no_extend({}).
207dcg_no_extend(!).
208dcg_no_extend((\+_)).
209dcg_no_extend((_,_)).
210dcg_no_extend((_;_)).
211dcg_no_extend((_|_)).
212dcg_no_extend((_->_)).
213dcg_no_extend((_*->_)).
214dcg_no_extend((_-->_)).
223dcg_extend(V, _, _, _, _, _) :-
224 var(V),
225 !,
226 throw(error(instantiation_error,_)).
227dcg_extend(M:OldT, Pos0, A1, A2, M:NewT, Pos) :-
228 !,
229 f2_pos(Pos0, MPos, P0, Pos, MPos, P),
230 dcg_extend(OldT, P0, A1, A2, NewT, P).
231dcg_extend(OldT, P0, A1, A2, NewT, P) :-
232 dcg_extend_cache(OldT, A1, A2, NewT),
233 !,
234 extended_pos(P0, P).
235dcg_extend(OldT, P0, A1, A2, NewT, P) :-
236 ( callable(OldT)
237 -> true
238 ; throw(error(type_error(callable,OldT),_))
239 ),
240 ( dcg_no_extend(OldT)
241 -> throw(error(permission_error(define,dcg_nonterminal,OldT),_))
242 ; true
243 ),
244 ( compound(OldT)
245 -> compound_name_arity(OldT, Name, Arity),
246 compound_name_arity(CopT, Name, Arity)
247 ; CopT = OldT,
248 Name = OldT,
249 Arity = 0
250 ),
251 NewArity is Arity+2,
252 functor(NewT, Name, NewArity),
253 copy_args(1, Arity, CopT, NewT),
254 A1Pos is Arity+1,
255 A2Pos is Arity+2,
256 arg(A1Pos, NewT, A1C),
257 arg(A2Pos, NewT, A2C),
258 assert(dcg_extend_cache(CopT, A1C, A2C, NewT)),
259 OldT = CopT,
260 A1C = A1,
261 A2C = A2,
262 extended_pos(P0, P).
263
264copy_args(I, Arity, Old, New) :-
265 I =< Arity,
266 !,
267 arg(I, Old, A),
268 arg(I, New, A),
269 I2 is I + 1,
270 copy_args(I2, Arity, Old, New).
271copy_args(_, _, _, _).
272
273
274 277
278extended_pos(Pos0, Pos) :-
279 '$expand':extended_pos(Pos0, 2, Pos).
280f2_pos(Pos0, A0, B0, Pos, A, B) :- '$expand':f2_pos(Pos0, A0, B0, Pos, A, B).
281f1_pos(Pos0, A0, Pos, A) :- '$expand':f1_pos(Pos0, A0, Pos, A).
287dcg_bt_pos(Var, Var) :-
288 var(Var),
289 !.
290dcg_bt_pos(brace_term_position(F,T,P0),
291 term_position(F,T,F,F,
292 [ P0,
293 term_position(T,T,T,T,_)
294 ])) :- !.
295dcg_bt_pos(Pos, _) :-
296 expected_layout(brace_term, Pos).
297
298dcg_cut_pos(Var, Var) :-
299 var(Var),
300 !.
301dcg_cut_pos(F-T, term_position(F,T,F,T,
302 [ F-T,
303 term_position(T,T,T,T,_)
304 ])).
305dcg_cut_pos(Pos, _) :-
306 expected_layout(atomic, Pos).
310dcg_terminal_pos(Pos, _) :-
311 var(Pos),
312 !.
313dcg_terminal_pos(list_position(F,T,_Elms,_Tail),
314 term_position(F,T,_,_,_)).
315dcg_terminal_pos(F-T,
316 term_position(F,T,_,_,_)).
317dcg_terminal_pos(string_position(F,T),
318 term_position(F,T,_,_,_)).
319dcg_terminal_pos(Pos, _) :-
320 expected_layout(terminal, Pos).
324dcg_qualify_pos(Var, _, _) :-
325 var(Var),
326 !.
327dcg_qualify_pos(Pos,
328 term_position(F,T,FF,FT,[MP,_]),
329 term_position(F,T,FF,FT,[MP,Pos])) :- !.
330dcg_qualify_pos(_, Pos, _) :-
331 expected_layout(f2, Pos).
332
333expected_layout(Expected, Found) :-
334 '$expand':expected_layout(Expected, Found).
335
336
337
346:- meta_predicate
347 phrase(//, ?),
348 phrase(//, ?, ?),
349 call_dcg(//, ?, ?). 350:- noprofile((phrase/2,
351 phrase/3,
352 call_dcg/3)). 353:- '$iso'((phrase/2, phrase/3)). 354
355phrase(RuleSet, Input) :-
356 phrase(RuleSet, Input, []).
357phrase(RuleSet, Input, Rest) :-
358 phrase_input(Input),
359 phrase_input(Rest),
360 call_dcg(RuleSet, Input, Rest).
361
362call_dcg(RuleSet, Input, Rest) :-
363 ( strip_module(RuleSet, M, Plain),
364 nonvar(Plain),
365 dcg_special(Plain)
366 -> dcg_body(Plain, _, q(M,M,_), S0, S, Body, _),
367 Input = S0, Rest = S,
368 call(M:Body)
369 ; call(RuleSet, Input, Rest)
370 ).
371
372phrase_input(Var) :- var(Var), !.
373phrase_input([_|_]) :- !.
374phrase_input([]) :- !.
375phrase_input(Data) :-
376 throw(error(type_error(list, Data), _)).
377
378dcg_special(S) :-
379 string(S).
380dcg_special((_,_)).
381dcg_special((_;_)).
382dcg_special((_|_)).
383dcg_special((_->_)).
384dcg_special(!).
385dcg_special({_}).
386dcg_special([]).
387dcg_special([_|_]).
388dcg_special(\+_)
Grammar rule (DCG) compiler
This module provides the term-expansion rules for DCGs as well as phrase/2,3 and call_dcg/3 for calling DCGs. The original code was copied from C-Prolog and written by Fernando Pereira, EDCAAD, Edinburgh, 1984. Since then many people have modified and extended this code.
DCGs have for a long time been a moving target, notably when it comes to dealing with cuts and unification delaying for calls to non-DCG code. This has slowly converged. This implementation attempts to be closely compatible to the pending ISO standard for DCGs. */