Как мне указать DCG для действительного номера?

Я пытаюсь указать DCG для действительного числа, которое будет использоваться следующим образом:

value(Number) --> valid_number(Number).

В основном, проверка, является ли указанное значение числовым (это также может быть переменная, поэтому необходимо проверить).

Я не знаю как это построить valid_number DCG/ предикат, хотя.

Прямо сейчас у меня просто есть:

valid_number('1') --> ['1'].
valid_number('2') --> ['2'].
...

Который работает, но это, очевидно, ужасно. Попытка что-то вроде:

valid_number(Number) --> { integer(Number), Number = Number }.

И то, и другое не работает и, по общему признанию, выглядит довольно грубо (извините, я новичок в Прологе и пытаюсь изучить лучшие практики)

Как бы я начал создавать этот DCG/ предикат, который проверяет, является ли он числом?

2 ответа

Решение

Я даю вам пример кода, который описывает натуральные числа:

: - set_prolog_flag (двойные кавычки, символы). натуральный номер (N) -> число_(Cs), {число_кодов (N, Cs) }.

число _([D|Ds]) -> цифра (D), число_ (Ds).
номер _([D])    -> цифра (D).

цифра (D) -> [D], {тип_значения (D, цифра)}.

Пример использования:

?- phrase(natural_number(N), "123").
N = 123 ;
false.

Я оставляю обобщение этого на другие числа в качестве упражнения.

Вот грамматика ABNF для числового литерала, такого как вы можете найти на компьютерном языке:

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'] .
Другие вопросы по тегам