mkpisk
mkpisk

Reputation: 152

formatting the output with proper paranthesis - Prolog

This question is directly related to first order logic creating terms for arithmetic expressions using prolog. After implementing the logic as per the link I have issues with the formatting of the ourput for printauth/1. It currently results as 8-2+4* -3, how is it possible to get something like ((8-2)+(4* -3)) (notice its not the same as +(-(8,2),*(4,-3))).

I have been trying to using various options (\k,\q) in format/2 predicate but nothing works. even I tried write_canonical and other write predicates, still no success.

printterm(Term) :- arithmetic_expression(Term, Expr), format("(~q)\n", [Expr]).
    %write_canonical(Expr).
    %write_term(Expr, [ignore_ops(true)]).
    %format("(~q)\n", [Expr]) .

current output:

?- printterm(plus((minus(8,2)),(times(4,3)))).
(8-2+4*3)
true .

expected output:


?- printterm(plus((minus(8,2)),(times(4,3)))).
((8-2)+(4*3))
true .

Is it possible to achieve this?

Upvotes: 1

Views: 126

Answers (2)

TA_intern
TA_intern

Reputation: 2422

The term you passed to your printterm:

plus((minus(8,2)),(times(4,3)))

This is conventionally written as:

plus(minus(8, 2), times(4, 3))

The parentheses are not needed and are indeed lost when the term is read. Try:

?- X = plus((minus(8,2)),(times(4,3))).

To get what you want it seems you really need to program it. For example:

print_arithmetic_expression(E) :-
    phrase(parenthesized_expression(E), P),
    format("~s~n", [P]).

parenthesized_expression(E) -->
    atomic_expr(E),
    !.
parenthesized_expression(E) -->
    { expr_op(E, Op, A, B) },
    pexp(A),
    " ", [Op], " ",
    pexp(B).

atomic_expr(E) -->
    { atomic(E),
      format(codes(C), "~w", [E])
    },
    C.

expr_op(plus(A,B), 0'+, A, B).
expr_op(minus(A,B), 0'-, A, B).
expr_op(times(A,B), 0'*, A, B).

pexp(E) -->
    atomic_expr(E),
    !.
pexp(E) -->
    { expr_op(E, Op, A, B) },
    "(",
    pexp(A),
    " ", [Op], " ",
    pexp(B),
    ")".

I get:

?- print_arithmetic_expression(plus(minus(8, 2), times(4, 3))).
(8 - 2) + (4 * 3)
true.

Upvotes: 1

David Tonhofer
David Tonhofer

Reputation: 15316

Why not roll your own printing predicate?

Make it return a String for added flexibility (so you are free to decide whether to pump the String out to the real world immediately, or manipulate it further first).

Something like this for all operations:

printterm(plus(S1,S2),R) :- 
   printterm(S1,RS1),
   printterm(S2,RS2),
   atomic_list_concat(['(',RS1,'+',RS2,')'],R).

printterm(minus(S1,S2),R) :- ...

printterm(times(S1,S2),R) :- ...

Then to use it, call it from printterm/1

printterm(Term) :- 
   arithmetic_expression(Term, Expr), 
   printterm(Expr,R),
   format("~w\n", [R]).

Upvotes: 0

Related Questions