1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2%% parseDomain.pl
    3%%   Simple parser of PDDL domain file into prolog syntax.
    4%% Author: Robert Sasak, Charles University in Prague
    5%%
    6%% Example: 
    7%% ?-parseDomain('blocks_world.pddl', O).
    8%%   O = domain(blocks,
    9%%        [strips, typing, 'action-costs'],
   10%%        [block],
   11%%        _G4108,
   12%%        [ on(block(?x), block(?y)),
   13%%	         ontable(block(?x)),
   14%%	         clear(block(?x)),
   15%%	         handempty,
   16%%	         holding(block(?x)) ],
   17%%        [number(f('total-cost', []))],
   18%%        _G4108,
   19%%        [ action('pick-up', [block(?x)],       %parameters
   20%%		      [clear(?x), ontable(?x), handempty], %preconditions
   21%%		      [holding(?x)],                       %positiv effects
   22%%          [ontable(?x), clear(?x), handempty], %negativ effects
   23%%          [increase('total-cost', 2)]),        %numeric effects
   24%%         ...],
   25%%       ...)
   26%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   27
   28
   29% parseDomain(+File, -Output).
   30% Parse PDDL domain File and return it rewritten prolog syntax.   
   31parseDomain(F, O):- parseDomain(F, O, _).
   32% parseDomain(+File, -Output, -RestOfFile)
   33% The same as above and also return rest of file. Can be useful when domain and problem are in one file.
   34parseDomain(File, Output, R) :-
   35		read_file(File, List),
   36		domainBNF(Output, List, R).
   37
   38% Support for reading file as a list.
   39:-[readFile].   40
   41% Defining operator ?. It is a syntax sugar for marking variables: ?x
   42:-op(300, fy, ?).   43
   44% List of DCG rules describing structure of domain file in language PDDL.
   45% BNF description was obtain from http://www.cs.yale.edu/homes/dvm/papers/pddl-bnf.pdf
   46% This parser do not fully NOT support PDDL 3.0
   47% However you will find comment out lines ready for futher development.
   48domainBNF(domain(N, R, T, C, P, F, C, S, Slack))
   49			--> ['(','define', '(','domain'], name(N), [')'], 
   50                             (require_def(R)	; []),
   51                             (types_def(T)    	; []), %:typing
   52                             (constants_def(C) 	; []),
   53                             (predicates_def(P)	; []),
   54                             (functions_def(F)	; []), %:fluents
   55%                             (constraints(C)	; []),    %:constraints
   56                             zeroOrMore(structure_def, S),
   57                             zeroOrMore(anythings, Slack),
   58			     [')'].
   59
   60require_def(R)		--> ['(',':','requirements'], oneOrMore(require_key, R), [')'].
   61require_key(strips)								--> [':strips'].
   62require_key(typing)								--> [':typing'].
   63%require_key('negative-preconditions')		--> [':negative-preconditions'].
   64%require_key('disjunctive-preconditions')	--> [':disjunctive-preconditions'].
   65require_key(equality)							--> [':equality'].
   66require_key('existential-preconditions')	--> [':existential-preconditions'].
   67require_key('universal-preconditions')		--> [':universal-preconditions'].
   68require_key('quantified-preconditions')	--> [':quantified-preconditions'].
   69require_key('conditional-effects')			--> [':conditional-effects'].
   70require_key(fluents)								--> [':fluents'].
   71require_key(adl)									--> [':adl'].
   72require_key('durative-actions')				--> [':durative-actions'].
   73require_key('derived-predicates')			--> [':derived-predicates'].
   74require_key('timed-initial-literals')		--> [':timed-initial-literals'].
   75require_key(preferences)						--> [':preferences'].
   76require_key(constraints)						--> [':constraints'].
   77% Universal requirements
   78require_key(R)		--> [':', R].
   79require_key(A)		--> [R],{atom_concat(':',A,R)}.
   80require_key(_)		--> [')'],!,{fail}.
   81require_key(R)		--> [R].
   82
   83anythings(R)		--> [R].
   84
   85types_def(L)			--> ['(',':',types],      typed_list(name, L), [')'].
   86constants_def(L)		--> ['(',':',constants],  typed_list(name, L), [')'].
   87predicates_def(P)		--> ['(',':',predicates], oneOrMore(atomic_formula_skeleton, P), [')'].
   88
   89atomic_formula_skeleton(F)
   90				--> ['('], predicate(P), typed_list(variable, L), [')'], {F =.. [P|L]}.
   91predicate(P)			--> name(P).
   92
   93variable(V)			--> ['?'], name(N), {V =.. [?, N]}.
   94atomic_function_skeleton(f(S, L))
   95				--> ['('], function_symbol(S), typed_list(variable, L), [')'].
   96function_symbol(S)		--> name(S).
   97functions_def(F)		--> ['(',':',functions], function_typed_list(atomic_function_skeleton, F), [')'].	%:fluents
   98%constraints(C)		--> ['(',':',constraints], con_GD(C), [')'].	%:constraints
   99structure_def(A)		--> action_def(A).
  100%structure_def(D)		--> durative_action_def(D).	%:durativeactions
  101%structure_def(D)		--> derived_def(D).		%:derivedpredicates
  102%typed_list(W, G)		--> oneOrMore(W, N), ['-'], type(T), {G =.. [T, N]}.
  103typed_list(W, [G|Ns])		--> oneOrMore(W, N), ['-'], type(T), !, typed_list(W, Ns), {G =.. [T|N]}.
  104typed_list(W, N)		--> zeroOrMore(W, N).
  105
  106primitive_type(N)		--> name(N).
  107type(either(PT))		--> ['(',either], !, oneOrMore(primitive_type, PT), [')'].
  108type(PT)			--> primitive_type(PT).
  109function_typed_list(W, [F|Ls])
  110				--> oneOrMore(W, L), ['-'], !, function_type(T), function_typed_list(W, Ls), {F =.. [T|L]}.	%:typing
  111function_typed_list(W, L)	--> zeroOrMore(W, L).
  112
  113function_type(number)		--> [number].
  114emptyOr(_)			--> ['(',')'].
  115emptyOr(W)			--> W.
  116
  117% Actions definitons
  118action_def(action(S, L, Precon, Pos, Neg, Assign))
  119				--> ['(',':',action], action_symbol(S),
  120						[':',parameters,'('], typed_list(variable, L), [')'],{!},
  121						(action_def_body(Precon, Pos, Neg, Assign)),
  122					[')'].
  123action_symbol(N)		--> name(N).
  129action_def_body(P, Pos, Neg, Assign)
  130				--> (([':',precondition], zeroOrMore(pre_GD,P)) /*	; []*/),
  131				    (([':',effect],      (emptyOr(effect(Pos, Neg, Assign))))	; []).
  137pre_GD(_)			--> [:,effect],{!,fail}.
  138
  139pre_GD(P)			--> pref_GD(P).
  140pre_GD(P)			--> ['(',and], pre_GD(P), [')'].
  141pre_GD(forall(L, P))		--> ['(',forall,'('], typed_list(variable, L), [')'], pre_GD(P), [')'].		%:universal-preconditions
  142pref_GD(preference(N, P))	--> ['(',preference], (pref_name(N); []), gd(P), [')'].				%:preferences
  143pref_GD(P)			--> gd(P).
  144pref_name(N)			--> name(N).
  145gd(L)				--> literal(term, L).								%:negative-preconditions
  146gd(F)				--> atomic_formula(term, F).	%: this option is covered by gd(L)
  147gd(P)				--> ['(',and],  zeroOrMore(gd, P), [')'].
  148%gd(or(P))			--> ['(',or],   zeroOrMore(gd ,P), [')'].					%:disjuctive-preconditions
  149%gd(not(P))			--> ['(',not],  gd(P), [')'].							%:disjuctive-preconditions
  150%gd(imply(P1, P2))		--> ['(',imply], gd(P1), gd(P2), [')'].						%:disjuctive-preconditions
  151%gd(exists(L, P))		--> ['(',exists,'('], typed_list(variable, L), [')'], gd(P), [')'].		%:existential-preconditions
  152%gd(forall(L, P))		--> ['(',forall,'('], typed_list(variable, L), [')'], gd(P), [')'].		%:universal-preconditions
  153gd(F)				--> f_comp(F).	%:fluents
  154f_comp(compare(C, E1, E2))	--> ['('], binary_comp(C), f_exp(E1), f_exp(E2), [')'].
  155literal(T, F)			--> atomic_formula(T, F).
  156literal(T, not(F))		--> ['(',not], atomic_formula(T, F), [')'].
  157atomic_formula(_, F)		--> ['('], predicate(P), zeroOrMore(term, T), [')'], {F =.. [P|T]}.		% cheating, maybe wrong
  158
  159
  160term(N)				--> name(N).
  161term(V)				--> variable(V).
  162f_exp(N)			--> number(N).
  163f_exp(op(O, E1, E2))		--> ['('],binary_op(O), f_exp(E1), f_exp(E2), [')'].
  164f_exp('-'(E))			--> ['(','-'], f_exp(E), [')'].
  165f_exp(H)			--> f_head(H).
  166f_head(F)			--> ['('], function_symbol(S), zeroOrMore(term, T), [')'], { F =.. [S|T] }.
  167f_head(S)				--> function_symbol(S).
  168binary_op(O)			--> multi_op(O).
  169binary_op('-')			--> ['−'].
  170binary_op('/')			--> ['/'].
  171multi_op('*')			--> ['*'].
  172multi_op('+')			--> ['+'].
  173binary_comp('>')		--> ['>'].
  174binary_comp('<')		--> ['<'].
  175binary_comp('=')		--> ['='].
  176binary_comp('>=')		--> ['>='].
  177binary_comp('<=')		--> ['<='].
  178number(N)			--> [N], {integer(N)}.
  179number(N)			--> [N], {float(N)}.
  180effect(P, N, A)			--> ['(',and], c_effect(P, N, A), [')'].
  181effect(P, N, A)			--> c_effect(P, N, A).
  182%c_effect(forall(E))		--> ['(',forall,'('], typed-list(variable)∗) effect(E), ')'.	%:conditional-effects
  183%c_effect(when(P, E))		--> ['(',when], gd(P), cond_effect(E), [')'].			%:conditional-effects
  184c_effect(P, N, A)		--> p_effect(P, N, A).
  185p_effect([], [], [])		--> [].
  186p_effect(Ps, Ns, [F|As])
  187				--> ['('], assign_op(O), f_head(H), f_exp(E), [')'], p_effect(Ps, Ns, As), {F =.. [O, H, E]}.
  188p_effect(Ps, [F|Ns], As)	--> ['(',not], atomic_formula(term,F), [')'], p_effect(Ps, Ns, As).
  189p_effect([F|Ps], Ns, As)	--> atomic_formula(term, F), p_effect(Ps, Ns, As).
  190%p_effect(op(O, H, E))		--> ['('], assign_op(O), f_head(H), f_exp(E), [')'].	%:fluents , What is difference between rule 3 lines above???
  191%cond_effect(E)		--> ['(',and], zeroOrMore(p_effect, E), [')'].				%:conditional-effects
  192%cond_effect(E)			--> p_effect(E).						%:conditional-effects
  193assign_op(assign)		--> [assign].
  194assign_op(scale_up)		--> [scale_up].
  195assign_op(scale_down)		--> [scale_down].
  196assign_op(increase)		--> [increase].
  197assign_op(decrease)		--> [decrease].
  198
  199
  200% BNF description include operator <term>+ to mark zero or more replacements.
  201% This DCG extension to overcome this. 
  202oneOrMore(W, [R|Rs], A, C) :- F =.. [W, R, A, B], F, (
  203					oneOrMore(W, Rs, B, C) ;
  204					(Rs = [] , C = B) 
  205				).
  206% BNF operator <term>*
  207zeroOrMore(W, R)		--> oneOrMore(W, R).
  208zeroOrMore(_, [])		--> [].
  209
  210% Name is everything that is not number, bracket or question mark.
  211% Those rules are not necessary, but rapidly speed up parsing process.
  212name(N)				--> [N], {integer(N), !, fail}.
  213name(N)				--> [N], {float(N), !, fail}.
  214name(N)				--> [N], {N=')', !, fail}.
  215name(N)				--> [N], {N='(', !, fail}.
  216name(N)				--> [N], {N='?', !, fail}.
  217name(N)				--> [N].
  218
  219
  220dcgMust(X)--> X.
  221dcgMust(X)--> {trace}, X