RosettaCodeData/Task/IBAN/Logtalk/iban-1.logtalk
2015-11-18 06:14:39 +00:00

129 lines
2.7 KiB
Text

:- object(iban).
:- info([
version is 0.1,
author is 'Paulo Moura',
date is 2015/10/11,
comment is 'IBAN validation example using DCG rules.'
]).
:- public(valid/1).
valid(IBAN) :-
phrase(iban, IBAN), !.
iban -->
country_code(Code), check_digits(Check), bban(BBAN),
{(BBAN*1000000 + Code*100 + Check) mod 97 =:= 1}.
country_code(Code) -->
letter_digits(L1, D3, D2), letter_digits(L0, D1, D0),
{country_code([L1, L0]), Code is D3*1000 + D2*100 + D1*10 + D0}.
check_digits(Check) -->
digit(D1), digit(D0),
{Check is D1*10 + D0}.
bban(BBAN) -->
bban_codes(Digits),
{digits_to_integer(Digits, BBAN, Count), Count =< 30}.
bban_codes(Ds) -->
" ", bban_codes(Ds).
bban_codes([D| Ds]) -->
digit(D), bban_codes(Ds).
bban_codes([D1, D0| Ds]) -->
letter_digits(_, D1, D0), bban_codes(Ds).
bban_codes([]) -->
[].
digit(D) -->
[C],
{0'0 =< C, C =< 0'9, D is C - 0'0}.
letter_digits(C, D1, D0) -->
[C],
{ ( 0'A =< C, C =< 0'Z ->
D is C - 0'A + 10
; 0'a =< C, C =< 0'z,
D is C - 0'a + 10
),
D1 is D div 10,
D0 is D mod 10
}.
digits_to_integer(Digits, BBAN, Count) :-
digits_to_integer(Digits, 0, BBAN, 0, Count).
digits_to_integer([], BBAN, BBAN, Count, Count).
digits_to_integer([Digit| Digits], BBAN0, BBAN, Count0, Count) :-
BBAN1 is BBAN0 * 10 + Digit,
Count1 is Count0 + 1,
digits_to_integer(Digits, BBAN1, BBAN, Count1, Count).
country_code("AL").
country_code("AD").
country_code("AT").
country_code("AZ").
country_code("BE").
country_code("BH").
country_code("BA").
country_code("BR").
country_code("BG").
country_code("CR").
country_code("HR").
country_code("CY").
country_code("CZ").
country_code("DK").
country_code("DO").
country_code("EE").
country_code("FO").
country_code("FI").
country_code("FR").
country_code("GE").
country_code("DE").
country_code("GI").
country_code("GR").
country_code("GL").
country_code("GT").
country_code("HU").
country_code("IS").
country_code("IE").
country_code("IL").
country_code("IT").
country_code("KZ").
country_code("KW").
country_code("LV").
country_code("LB").
country_code("LI").
country_code("LT").
country_code("LU").
country_code("MK").
country_code("MT").
country_code("MR").
country_code("MU").
country_code("MC").
country_code("MD").
country_code("ME").
country_code("NL").
country_code("NO").
country_code("PK").
country_code("PS").
country_code("PL").
country_code("PT").
country_code("RO").
country_code("SM").
country_code("SA").
country_code("RS").
country_code("SK").
country_code("SI").
country_code("ES").
country_code("SE").
country_code("CH").
country_code("TN").
country_code("TR").
country_code("AE").
country_code("GB").
country_code("VG").
:- end_object.