如何为有效号码指定 DCG?
How do I specify a DCG for a valid number?
我正在尝试为将像这样使用的有效号码指定 DCG:
value(Number) --> valid_number(Number).
基本上检查指定值是否为数字,(也可能是变量,所以有必要检查)。
虽然我不知道如何构建这个 valid_number
DCG/predicate。
现在我只有:
valid_number('1') --> ['1'].
valid_number('2') --> ['2'].
...
哪个有效,但显然很糟糕。尝试类似的东西:
valid_number(Number) --> { integer(Number), Number = Number }.
两者都不起作用,而且看起来也很恶心(对不起,我对 Prolog 很陌生,正在努力学习最佳实践)。
我将如何构建这个 DCG/predicate 来验证它是否是一个数字?
我给你一个描述自然数字的代码示例:
:- set_prolog_flag(double_quotes, chars).
natural_number(N) --> number_(Cs), { number_codes(N, Cs) }.
number_([D|Ds]) --> digit(D), number_(Ds).
number_([D]) --> digit(D).
digit(D) --> [D], { char_type(D, digit) }.
用法示例:
?- phrase(natural_number(N), "123").
N = 123 ;
false.
我把这个推广到其他数字作为练习。
这里有一个 ABNF grammar 数字文字,例如您可能会在计算机语言中找到的数字文字:
NUMERIC-CONSTANT = INTEGER-PART 0*1(FRACTIONAL-PART) 0*1(EXPONENT)
INTEGER-PART = 0*1(SIGN) 1*(DIGIT)
FRACTIONAL-PART = 0*1( DECIMAL-POINT 1*(DIGIT) )
EXPONENT = EXP 0*1(SIGN) 1*(DIGIT)
EXP = "E" / "e"
DECIMAL-POINT = "."
SIGN = "+" / "-"
DIGIT = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
由于此语法中没有左递归,因此这直接适用于递归下降解析器,例如由 Prolog DCG 生成的:
numeric_constant --> integer , optional_fraction , optional_exponent .
integer --> optional_sign , digits .
optional_sign --> sign .
optional_sign --> [].
digits --> digit , digits .
optional_fraction --> fraction .
optional_fraction --> [].
fraction --> decimal_point , digits .
optional_exponent --> exponent .
optional_exponent --> [].
exponent --> exp , optional_sign , digits .
exp --> ['E'] .
exp --> ['e'] .
decimal_point --> ['.'] .
sign --> ['+'] .
sign --> ['-'] .
digit --> ['0'] .
digit --> ['1'] .
digit --> ['2'] .
digit --> ['3'] .
digit --> ['4'] .
digit --> ['5'] .
digit --> ['6'] .
digit --> ['7'] .
digit --> ['8'] .
digit --> ['9'] .
我正在尝试为将像这样使用的有效号码指定 DCG:
value(Number) --> valid_number(Number).
基本上检查指定值是否为数字,(也可能是变量,所以有必要检查)。
虽然我不知道如何构建这个 valid_number
DCG/predicate。
现在我只有:
valid_number('1') --> ['1'].
valid_number('2') --> ['2'].
...
哪个有效,但显然很糟糕。尝试类似的东西:
valid_number(Number) --> { integer(Number), Number = Number }.
两者都不起作用,而且看起来也很恶心(对不起,我对 Prolog 很陌生,正在努力学习最佳实践)。
我将如何构建这个 DCG/predicate 来验证它是否是一个数字?
我给你一个描述自然数字的代码示例:
:- set_prolog_flag(double_quotes, chars). natural_number(N) --> number_(Cs), { number_codes(N, Cs) }. number_([D|Ds]) --> digit(D), number_(Ds). number_([D]) --> digit(D). digit(D) --> [D], { char_type(D, digit) }.
用法示例:
?- phrase(natural_number(N), "123").
N = 123 ;
false.
我把这个推广到其他数字作为练习。
这里有一个 ABNF grammar 数字文字,例如您可能会在计算机语言中找到的数字文字:
NUMERIC-CONSTANT = INTEGER-PART 0*1(FRACTIONAL-PART) 0*1(EXPONENT)
INTEGER-PART = 0*1(SIGN) 1*(DIGIT)
FRACTIONAL-PART = 0*1( DECIMAL-POINT 1*(DIGIT) )
EXPONENT = EXP 0*1(SIGN) 1*(DIGIT)
EXP = "E" / "e"
DECIMAL-POINT = "."
SIGN = "+" / "-"
DIGIT = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
由于此语法中没有左递归,因此这直接适用于递归下降解析器,例如由 Prolog DCG 生成的:
numeric_constant --> integer , optional_fraction , optional_exponent .
integer --> optional_sign , digits .
optional_sign --> sign .
optional_sign --> [].
digits --> digit , digits .
optional_fraction --> fraction .
optional_fraction --> [].
fraction --> decimal_point , digits .
optional_exponent --> exponent .
optional_exponent --> [].
exponent --> exp , optional_sign , digits .
exp --> ['E'] .
exp --> ['e'] .
decimal_point --> ['.'] .
sign --> ['+'] .
sign --> ['-'] .
digit --> ['0'] .
digit --> ['1'] .
digit --> ['2'] .
digit --> ['3'] .
digit --> ['4'] .
digit --> ['5'] .
digit --> ['6'] .
digit --> ['7'] .
digit --> ['8'] .
digit --> ['9'] .