使用DCG解析Prolog变量

使用DCG解析Prolog变量,prolog,grammar,dcg,dpll,Prolog,Grammar,Dcg,Dpll,我想在Prolog中使用DCG解析逻辑表达式 逻辑术语表示为列表,例如x的['x','&&&','y']∧ y结果应该是解析树和(X,y)(wereX和y是未分配的Prolog变量) 我实现了它,一切正常,但我有一个问题: 我不知道如何解析变量'x'和'y'来获得真正的Prolog变量x和y,以便以后分配真值 我尝试了以下规则变体: v(X)-->[X]。: 当然,这不起作用,它只返回和('x','y') 但是我可以用Prolog变量统一替换这个术语中的逻辑变量吗?我知道谓词术语\u to \

我想在Prolog中使用DCG解析逻辑表达式

逻辑术语表示为列表,例如
x的
['x','&&&','y']
∧ y
结果应该是解析树
和(X,y)
(were
X
y
是未分配的Prolog变量)

我实现了它,一切正常,但我有一个问题:
我不知道如何解析变量
'x'
'y'
来获得真正的Prolog变量
x
y
,以便以后分配真值

我尝试了以下规则变体:

  • v(X)-->[X]。

    当然,这不起作用,它只返回
    和('x','y')

    但是我可以用Prolog变量统一替换这个术语中的逻辑变量吗?我知道谓词
    术语\u to \u atom
    (它是作为a的解决方案提出的),但我认为它不能在这里用于实现期望的结果

  • v(Y)-->[X],{nonvar(Y)}。

    这确实会返回一个未绑定的变量,但当然每次都会返回一个新变量,即使逻辑变量('x','y',…)已经在术语so中
    ['X'、'&&'、'X']
    的计算结果为
    和(X,Y)
    ,这也不是期望的结果

这个问题有什么优雅或惯用的解决方法吗

非常感谢


编辑:

这个问题的背景是我试图在Prolog中实现。我认为将逻辑术语直接解析为Prolog术语会很聪明,这样可以方便地使用Prolog回溯功能:

  • 输入:一些逻辑术语,例如T=
    [x',&&',y]
  • 解析后的术语:
    [G_123',&&',G_456]
    (现在具有“real”Prolog变量)
  • 将{boolean(t),boolean(f)}中的值赋给t中的第一个未绑定变量
  • 简化术语
  • 。。。重复或回溯,直到找到赋值
    v
    ,从而
    v(T)=T
    或搜索空间耗尽

我对Prolog很陌生,老实说,我想不出更好的方法。我对更好的选择很感兴趣!(所以我有点像舒尔,这就是我想要的;-)非常感谢您到目前为止的支持…

您想将基本术语,如
x
(无需编写
'x'
)与未实例化的变量相关联。当然,这并不构成纯粹的关系。所以我不太清楚你是否真的想要这个

那么您首先从哪里获得列表
[x,&&,x]
?你可能有某种标记器。如果可能,尝试在实际解析之前将变量名与变量关联。如果您坚持在解析过程中执行该关联,则必须在整个语法中执行一对变量。那是,而不是类似的

你现在必须写作了

power(P, D0,D) --> factor(F, D0,D1), power_r(F, P, D1,D).
%        ^^^^                ^^^^^                 ^^^^
因为您正在将上下文引入一个与上下文无关的语法中

解析Prolog文本时,也会出现同样的问题。变量名和具体变量之间的关联已在标记化期间建立。实际的解析器不必处理它

在标记化过程中,基本上有两种方法来执行此操作:

1在列表中收集所有出现的
Name=Variable
,稍后统一:

v(N-V, [N-V|D],D) --> [N], {maybesometest(N)}.

unify_nvs(NVs) :-
   keysort(NVs, NVs2),
   uniq(NVs2).

uniq([]).
uniq([NV|NVs]) :-
   head_eq(NVs, NV).
   uniq(NVs).

head_eq([], _).
head_eq([N-V|_],N-V).
head_eq([N1-_|_],N2-_) :-
   dif(N1,N2).
2在早期使用一些显式字典来合并它们


有些关联。

不确定你是否真的想按你的要求去做。您可以通过保存变量关联列表来实现这一点,以便知道何时重用变量以及何时使用新变量

这是贪婪下降解析器的一个示例,它将使用
&&
|
解析表达式:

parse(Exp, Bindings, NBindings)-->
  parseLeaf(LExp, Bindings, MBindings),
  parse_cont(Exp, LExp, MBindings, NBindings).

parse_cont(Exp, LExp, Bindings, NBindings)-->
  parse_op(Op, LExp, RExp),
  {!},
  parseLeaf(RExp, Bindings, MBindings),
  parse_cont(Exp, Op, MBindings, NBindings).
parse_cont(Exp, Exp, Bindings, Bindings)-->[].

parse_op(and(LExp, RExp), LExp, RExp)--> ['&&'].
parse_op(or(LExp, RExp), LExp, RExp)--> ['||'].

parseLeaf(Y, Bindings, NBindings)-->
  [X],
  {
    (member(bind(X, Var), Bindings)-> Y-NBindings=Var-Bindings ; Y-NBindings=Var-[bind(X, Var)|Bindings])
  }.
它解析表达式并返回变量绑定

样本输出:

?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'y']).
Exp = and(_G683, _G696),
Bindings = [bind(y, _G696), bind(x, _G683)].

?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'x']).
Exp = and(_G683, _G683),
Bindings = [bind(x, _G683)].

?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'y', '&&', 'x', '||', 'z']).
Exp = or(and(and(_G839, _G852), _G839), _G879),
Bindings = [bind(z, _G879), bind(y, _G852), bind(x, _G839)].

您希望在什么时候查看
X
Y
?您是否坚持要将
'x'
映射到
x
?或者只是想让所有的
'x'
在最终的解析树中引用同一个变量?@Boris我编辑这个问题是为了提供更多的上下文-我不关心变量名,只要始终引用同一个变量。非常感谢您的详细解释。。。我还添加了一些背景知识,以便在某些情况下解决这个问题;现在我想我必须重新考虑我的整个方法。非常感谢,我希望我能接受两个答案!我还为这个问题添加了一些背景知识,以将其置于上下文中。
?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'y']).
Exp = and(_G683, _G696),
Bindings = [bind(y, _G696), bind(x, _G683)].

?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'x']).
Exp = and(_G683, _G683),
Bindings = [bind(x, _G683)].

?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'y', '&&', 'x', '||', 'z']).
Exp = or(and(and(_G839, _G852), _G839), _G879),
Bindings = [bind(z, _G879), bind(y, _G852), bind(x, _G839)].