Search code examples
prologpredicate

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?


Solution

  • 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.