2015-09-30 10 views
2

Я пытаюсь указать 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

Выполняется задача 'Number = Number' * always *. Вы можете удалить его. – mat

+0

Взгляните на [это] (http://www.swi-prolog.org/pldoc/doc/swi/library/dcg/basics.pl?show=src#number/3) для вдохновения. –

ответ

4

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

 
:- 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. 

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

+2

Не было бы неплохо написать это так, чтобы он работал с 'double_quoted', установленным в' chars', тоже? – false

+1

@false. 'dqch_code/2' на помощь? , ! – repeat

+1

Поскольку 'code_type/2' не является стандартным предикатом, даже не общим, вы можете вместо этого использовать цифру (D) -> [D], {D> = 0'0, D = <0'9} .' для более портативного решения. –

2

Вот 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" 

Поскольку нет левой рекурсии в этой грамматике, это поддающееся непосредственно рекурсивный спуск парсер, например, производство по Прологу 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'] .