我需要从DCG形式的无上下文语法中获取非确定性下推自动机的delta函数,并且执行此操作的算法非常简单:
对于语法中的每个规则A --> B
,请向delta函数添加转换[q1, lambda, A] --> [B]
。
对于语法中的每个规则E --> c
,请向delta函数添加转换[q1, c, c] --> [lambda]
。
将转换[q0, lambda, z0] --> [q1, S*z0]
和[q1, lambda, z0] --> [q2, z0]
添加到delta函数。
每个大写字母都是非终端符号,每个小写字母都是终端符号。 lambda
是空字符串,S
是语法的初始符号,*
是连接运算符,z0
是堆栈顶部的符号。
这意味着语法
S --> A*b | B | y
A --> w*x | x
B --> A*b
生成具有delta函数的下推自动机
[q0, lambda, z0] --> [q1, S*z0]
[q1, lambda, S] --> [q1, A*b]
[q1, lambda, S] --> [q1, B]
[q1, lambda, S] --> [q1, y]
[q1, lambda, A] --> [q1, w*x]
[q1, lambda, A] --> [q1, x]
[q1, lambda, B] --> [q1, A*b]
[q1, b, b] --> [q1, lambda]
[q1, w, w] --> [q1, lambda]
[q1, x, x] --> [q1, lambda]
[q1, y, y] --> [q1, lambda]
[q1, lambda, z0] --> [q2, z0]
我必须在Prolog中实现这个算法(从用户那里获取语法并返回delta函数),我很困惑,因为这是我第一次使用逻辑编程语言。
我认为我可以将语法翻译成谓词形式,然后在所有谓词上“迭代”,并以某种方式将已经“遍历”的谓词添加到列表中,这样我就可以处理这个列表并返回delta函数。但我认为这是一种非常复杂的必要的做事方式,而使用Prolog是没有意义的。
也许这个问题有一个更优雅的解决方案,所以我想知道这种解决方案是否存在。
答案 0 :(得分:2)
这是一个可能的编码
g2nfa(Grammar, Delta) :-
maplist(transitions, Grammar, DeltaT),
append(DeltaT, DeltaF),
Initial = (q0, lambda, z0 --> q1, 'S'*z0),
Final = (q1, lambda, z0 --> q2, z0),
append([[Initial], DeltaF, [Final]], Delta).
transitions(Sym --> Alternatives, Transitions) :-
phrase(transition(Sym, Alternatives), Transitions).
transition(Sym, A|As) --> state(Sym, A), !, transition(Sym, As).
transition(Sym, A) --> state(Sym, A).
state(Sym, A) --> [(q1, lambda, Sym --> q1, A)].
test :-
g2nfa([( 'S' --> 'A'*b | 'B' | y ),
( 'A' --> w*x | x ),
( 'B' --> 'A'*b )
], T), maplist(writeln, T).
似乎满足您的要求
?- test.
q0,lambda,z0-->q1,S*z0
q1,lambda,S-->q1,A*b
q1,lambda,S-->q1,B
q1,lambda,S-->q1,y
q1,lambda,A-->q1,w*x
q1,lambda,A-->q1,x
q1,lambda,B-->q1,A*b
q1,lambda,z0-->q2,z0
true.
这样你就可以搞清楚句法细节了。请注意第二次重写规则(对于语法中的每个规则E - > c,将过渡[q1,c,c] - > gt; [lambda]添加到delta函数。)尚未应用于您的样本中。