最简单的方法是使用 DCG 语法来指定虚线四边形的外观。 IPv4 地址是 4 个八位字节,以十进制表示,并用“.”分隔。我们可以将其表达为这样的 DCG 规则:
dotted_quad --> octet, dot, octet, dot, octet, dot, octet.
. 的规则很简单:
dot --> ['.'].
八位字节的规则更复杂。一个八位字节被限制在域 0-255 中。可以用十进制表示
- 0-9:
一个十进制数字0–9
- 10-99:
两位十进制数字,第一个在域1–9,第二个在域0–9。
- 100-199:
三位小数。第一个是1,第二个和第三个在域0–9。
- 200-249:
三位小数。第一个是2,第二个是域0–4,第三个是0–9。
- 250–255:
三位小数。第一个是2,第二个是5,第三个约束为0–5。
我们可以编写很多特殊的规则来涵盖这一点,或者为十进制数字的规则添加一些上下文。让我们为该规则添加一些上下文(因为为什么输入的内容超出了您的需要):
digit(D) --> [D].
digit(Min,Max) --> [D], { D @>= Min, D @=< Max }.
这些让我们说像digit('0','5') 表示允许域0-5 中的数字,或digit('2') 表示只允许数字2。
现在我们可以定义八位字节的规则了:
octet --> digit('0','9') .
octet --> digit('1','9') , digit('0','9').
octet --> digit('1') , digit('0','9') , digit('0','9').
octet --> digit('2') , digit('0','4') , digit('0','9').
octet --> digit('2') , digit('5') , digit('0','5').
现在我们可以定义我们的测试谓词了。它所要做的就是调用我们定义的 DCG:
is_dotted_quad(Cs) :- phrase(dotted_quad, Cs).
但是因为输入类似的东西
[ '1','2','3', '.', '2','3','4', '.', '7','8', '.', '9' ]`
很繁琐且容易出错,让我们添加一些便利来让我们使用字符串或原子:
is_dotted_quad(X) :- atom(X) , atom_chars(X,Cs) , is_dotted_quad(Cs) .
is_dotted_quad(X) :- string(X) , atom_chars(X,Cs) , is_dotted_quad(Cs) .
is_dotted_quad(Cs) :- phrase(dotted_quad, Cs).
把它们放在一起,你会得到这个:
is_dotted_quad(X) :- atom(X) , atom_chars(X,Cs) , is_dotted_quad(Cs).
is_dotted_quad(X) :- string(X) , string_chars(X,Cs) , is_dotted_quad(Cs).
is_dotted_quad(Cs) :- phrase(dotted_quad, Cs).
dotted_quad --> octet, dot, octet, dot, octet, dot, octet.
dot --> ['.'].
octet --> digit('0','9') .
octet --> digit('1','9') , digit('0','9') .
octet --> digit('1') , digit('0','9') , digit('0','9').
octet --> digit('2') , digit('0','4') , digit('0','9').
octet --> digit('2') , digit('5') , digit('0','5').
digit(V) --> [V].
digit(Min,Max) --> [D], { D @>= Min, D @=< Max }.
您可以在https://swish.swi-prolog.org/p/dotted-quad-dcg.pl 使用它
或者,如果您不想使用 DCG,那么 @Dudas 的答案的这种即兴表演也可以 - 但应该知道这本质上就是上述 DCG 的内容(DCG 本质上是一个简单的vanilla prolog 之上的语法糖),只是对意图的声明少了一点:
is_dotted_quad(X) :- atom(X) , atom_chars(X,Cs) , is_dotted_quad(Cs).
is_dotted_quad(X) :- string(X) , string_chars(X,Cs) , is_dotted_quad(Cs).
is_dotted_quad(Cs) :- octet(Cs,T1),
dot(T1,T2), octet(T2,T3),
dot(T3,T4), octet(T4,T5),
dot(T5,T6), octet(T6,[]).
chars( [] , [] ) .
chars( [C|Cs] , [C|Cs] ) .
chars( X , Cs ) :- atom(X) , atom_chars(X,Cs) .
chars( X , Cs ) :- string(X) , string_chars(X,Cs) .
dot(['.'|T],T).
octet( [ Z | T ], T ) :- range(Z,'0','9') .
octet( [ Y , Z | T ], T ) :- range(Y,'1','9') , range(Z,'0','9') .
octet( [ '1' , Y , Z | T ], T ) :- range(Y,'0','9') , range(Z,'0','9') .
octet( [ '2' , Y , Z | T ], T ) :- range(Y,'0','4') , range(Z,'0','9') .
octet( [ '2' , '5' , Z | T ], T ) :- range(Z,'0','5') .
range(X,Min,Max) :- X @>= Min, X @=< Max .