
% convert expression to function-like term
expr2term(Str, Rpn) :-
	string_chars(Str,Cs),
	add2term(Rpn,Cs,[]).

%integer parsing with accumulator (without rev)
pInteger(I) --> pInteger1(I,0).
pInteger1(I,A) --> pNextDigit(I,A). % parse an integer of at least one digit
pInteger(I,A) --> pInteger1(I,A); {I=A}. % parse an integer of 0-inf digits

% parse a digit and continue with parsing pInteger
pNextDigit(I,A) -->
	[Digit],
	{atom_number(Digit,N), A1 is 10*A+N},
	pInteger(I,A1).

% expression is either right-associative additive expression, or a single
% multiplicative term. mult2term(A) is only called once to avoid unnecessary
% backtrakcing.
add2term(R) -->
	mult2term(A), (
		['+'], add2term(B), {R=plus(A,B)};
		['-'], add2term(B), {R=minus(A,B)};
		{A=R}
	).

% multiplicative term is either multiplicative, or a simple expression
mult2term(R) -->
	simple2term(A), (
		['*'], mult2term(B), {R=krat(A,B)};
		['/'], mult2term(B), {R=deleno(A,B)};
		{A=R}
	).

% simple expression is either something large in parentheses, or an integer
simple2term(R) -->
	['('], add2term(R), [')'];
	pInteger(R).

demo :-
	expr2term("((((1-1)*1+1/4)))", X),
	writeln(X).
