使用DCG解析Prolog变量
我想在Prolog中使用DCG解析逻辑表达式 逻辑术语表示为列表,例如使用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 \
x的['x','&&&','y']
∧ y
结果应该是解析树和(X,y)
(wereX
和y
是未分配的Prolog变量)
我实现了它,一切正常,但我有一个问题:我不知道如何解析变量
'x'
和'y'
来获得真正的Prolog变量x
和y
,以便以后分配真值
我尝试了以下规则变体:
:v(X)-->[X]。
当然,这不起作用,它只返回和('x','y')
但是我可以用Prolog变量统一替换这个术语中的逻辑变量吗?我知道谓词
(它是作为a的解决方案提出的),但我认为它不能在这里用于实现期望的结果术语\u to \u atom
:v(Y)-->[X],{nonvar(Y)}。
这确实会返回一个未绑定的变量,但当然每次都会返回一个新变量,即使逻辑变量('x','y',…)已经在术语so中
的计算结果为['X'、'&&'、'X']
,这也不是期望的结果和(X,Y)
编辑: 这个问题的背景是我试图在Prolog中实现。我认为将逻辑术语直接解析为Prolog术语会很聪明,这样可以方便地使用Prolog回溯功能:
- 输入:一些逻辑术语,例如T=
[x',&&',y]
- 解析后的术语:
(现在具有“real”Prolog变量)[G_123',&&',G_456]
- 将{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)].