:- ensure_loaded(typeops).

% use of rule
%
% problem: conversion between code, number or string
% the example shows two solutions with the clauses of number_part/2

%+++++++++++++++++++++++++++++ imports ++++++++++++++++++++++++++++

:- import_type(prolog_types).
:- import_pred(prolog_dcg, '=<'/2).
:- import_pred(prolog_dcg, is/2).
:- import_pred(prolog_dcg, 'C'/3).
:- import_pred(prolog_dcg, '@=<'/2).


%+++++++++++++++++++++++++++++ predicates  +++++++++++++++++++++++ 


:- rule number(int).

number(C) --> "+", number(C).
number(C) --> "-", number(X), {C is -X}.
number(C) --> number_part(C,_).


:- rule number_part(int,int).


number_part(X,Digit) --> [C], {'C'("0",A0,""), 'C'("9",A9,""), % getting code
			       A0=<C, C=<A9, X is C - A0, 
                               Digit is 10}.

number_part(X,Digit2) --> [C], number_part(Y,Digit1),        % code of 0 = 48
                               {"0" @=< [C], [C] @=< "9",
				X is (C - 48) * Digit1 + Y,
				Digit2 is Digit1 * 10}.

%------

:- type numexpr_ext --> [int | empty_list].
:- type empty_list  --> [].
% :- type numexpr_ext --> [int].    % .(int,[])
:- type numexpr > numexpr_ext.


:- rule number_part2(int, int).

number_part2(X,Digit) --> [C], {"0" =< C, C =< "9", X is C - "0", 
                               Digit is 10}.

number_part2(X,Digit2) --> [C], number_part2(Y,Digit1),      
                               {"0" =< [C], [C] =< "9",
				X is (C - "0") * Digit1 + Y,
				Digit2 is Digit1 * 10}.

:- rule number2(int).

number2(C) --> "+", number2(C).
number2(C) --> "-", number2(X), {C is -X}.
number2(C) --> number_part2(C,_).



%+++++++++++++++++++++++++++++ tests +++++++++++++++++++++++++++++ 

?- number(C,"87439","").             % C = 87439

?- number_part(C,Digit,"848","").    % C = 848, Digit = 1000

?- number2(C,"87439","").            % C = 87439


