129 lines
2.7 KiB
Text
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.
|