Ошибка Prolog DCG Sytnax: ожидается оператор - PullRequest
0 голосов
/ 17 октября 2019

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

123.234   {true}
123..124  {false}
+123.123  {true}
-123.1    {true}
+-123.42  {false}

Мой код выглядит так:

isFloat(Num) :- float(Num).

sign --> "", "+", "-".

float --> sign, number, ".", number.

number --> digit.
number --> digit, number.

digit --> [0,1,2,3,4,5,6,7,8,9].

По большей части это работает, но иногда я получаю сообщение об ошибке вместо false всякий раз, когда есть что-то, что не соответствует грамматике.

output:

?- ['practice.pro'].
true.

?- isFloat(+12.234).
true.

?- isFloat(+12).
false.

?- isFloat(++12).
ERROR: Syntax error: Operator expected
ERROR: isFloat(+
ERROR: ** here **
ERROR: +12) . 

?- isFloat(123.345..).
ERROR: Syntax error: Operator expected
ERROR: isFloat(123.34
ERROR: ** here **
ERROR: 5..) . 

?- isFloat(+12.567).
true.

Я предполагал, что если это не соответствует грамматике правильно, DCG вернет false, но вместо этогоЯ получаю синтаксическую ошибку, если переданное число не соответствует грамматике. Кто-нибудь может объяснить, что я делаю не так? Спасибо.

Редактировать: форматировать вопрос лучше.

1 Ответ

0 голосов
/ 18 октября 2019

Боюсь, вам на самом деле не удалось использовать определенную вами DCG. float/1 - это встроенная функция, которую вы вызываете, и, не цитируя ничего, вы фактически не передали строку во что-либо для анализа. Пролог анализирует ваш вклад как литерал;если это не удастся из-за синтаксической проблемы, больше ничего не произойдет. Кроме того, чтобы задействовать систему DCG, вы должны использовать phrase/2, а это не так, поэтому даже когда вы передаете вещи в isFloat/2, они просто передают их напрямую float/1.

Кроме того, имейте в виду, что DCG магически не возвращают то, что они проанализировали. Если ваше правило DCG не имеет ничего перед стрелкой, из phrase/2 вам ничего не вернется. Таким образом, код, который у вас есть, это принятие операций с плавающей запятой (или с изменениями ниже), но на самом деле парсинг операций с плавающей запятой из строки в фактическое представление с плавающей запятой не выполняется.

Фактический вызов вашего кода будет выглядеть примерно так:

phrase(float, `+12.234`).

Это не удастся по нескольким причинам, наиболее очевидным из которых является то, что ваше правило digit//0 не выполняет то, что вы думаете, оно делает. На самом деле он ожидает точно список цифр от 0 до 9. Вероятно, вы захотите сделать что-то похожее на это:

digit --> "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9".

Как только вы это сделаете, вы сможетеразобрать "номер". Но вы делаете аналогичную ошибку в sign//0, потому что запятая в Прологе означает и , а не или . Фиксированный код выглядит следующим образом:

sign --> "" | "+" | "-".
float --> sign, number, ".", number.
number --> digit.
number --> digit, number.

digit --> "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9".

И его использование выглядит следующим образом:

?- phrase(float, `-923.23`).
true

Обратите внимание, что теперь вы получаете ожидаемые ошибки разбора:

?- phrase(float, `-923..23`).
false.

Обратите внимание, что это не вернет вам поплавок. Вам придется проделать больше работы, чтобы достичь этого.

...