如何在Prolog中捕获语法错误?

时间:2017-03-27 16:14:40

标签: prolog

我已经定义了一个运算符#

:- op(500, yfx, #).

我已经写了以下规则来检查术语是否格式正确:

valid(X):- integer(X).
valid(X # Y):- valid(X), valid(Y).

我想编写一个谓词check/1,如果它的参数有效则返回true,否则返回false。我写了这个:

check(Exp):- catch(valid(Exp), error(syntax_error(_),_), fail), !.

当Exp格式正确时,它返回true。但是,当它不合法时,它不会捕获语法错误:

?- check(5 ## 6).
ERROR: [Thread pdt_console_client_0_Default Process] Syntax error: Operator expected
ERROR: [Thread pdt_console_client_0_Default Process] check(5
ERROR: [Thread pdt_console_client_0_Default Process] ** here **
ERROR: [Thread pdt_console_client_0_Default Process]  ## 6) . 

我正在使用SWI-Prolog version 7.4.1 for amd64

如果出现错误,如何捕获语法错误并使check返回false?

1 个答案:

答案 0 :(得分:3)

在您的情况下,问题是如果首先输入有效的Prolog目标,则check/1仅被称为

因此,当check/1已被调用时,语法肯定至少是一个有效的Prolog术语,即使它从check/1本身的角度来看也没有意义。如果语法有效,则Prolog toplevel 已经引发错误,甚至没有调用check/1

因此,要更好地控制语法问题,您需要自己阅读这些条款。

有几种方法可以做到这一点。一个简单的方法是使用read/1。例如:

?- catch(read(X), Error, true).
|: check(5##6).

Error = error(syntax_error(operator_expected), stream(user_input, 8, 7, 347)).

通过这种方式,您基本上可以构建自己的顶层,从而可以更好地控制此类问题。另请参阅read_term/2以及一些有助于此的相关谓词。

与此类问题相关的一个重要选项是variable_names/1:它产生Prolog变量与其原子名称之间的对应关系,以便您可以报告可读绑定。这是最重要的部分,ISO标准化的最新进展极大地促进了这些功能。也许,在适当的时候,我们将能够在Prolog中编写可移植的toplevels,可用于多个系统。有许多应用程序可以从中受益,你的其中之一就是其中之一。