【问题标题】:Grammar in prolog序言中的语法
【发布时间】:2018-04-28 09:38:25
【问题描述】:

我希望能够使用语法将 [int(2), sep(<), int(1), sep(-), id(N)] 之类的数组转换为条件(在本例中为 [int(2) < int(1)-id(N)] )。我的语法如下:

cond(_, A > B) --> expr(_,A), [sep(>)], expr(_,B).
cond(_, A < B) --> expr(_,A), [sep(<)], expr(_,B).
expr(_, int(X)) --> [int(X)].
expr(_, id(X)) --> [id(X)].
expr(_, X + Y) --> expr(_,X), [sep(+)], expr(_,Y).
expr(_, X - Y) --> expr(_,X), [sep(-)], expr(_,Y).

我不明白的是,如果我有数组:[int(2), sep(&gt;), int(1), sep(+), id(N)] 一切都很好,则条件被正确翻译。然后我进行了一些更改,将+ 替换为-&gt; 替换为&lt;(考虑到在我的语法中&gt;&lt; 高一行,与+ 和@ 相同987654332@),这个没有翻译,陷入无限循环:

Call:  (18)  ? [sep(-), id(N)]=[sep(+)|_G2290032]creep
Fail:  (18)  ? [sep(-), id(N)]=[sep(+)|_G2290032]creep

它总是与sep(+) 比较。这个语法有什么问题?

--编辑添加跟踪

phrase(cond(_, X), [int(2), sep(<), int(1), sep(-),id(N)]).
   Call:  (10)  ? cond(_G2313, _G2314, [int(2), sep(<), int(1), sep(-), id(_G2336)], [])creep
   Call:  (11)  ? expr(_L254, _G2482, [int(2), sep(<), int(1), sep(-), id(_G2336)], _L235)creep
   Exit:  (11)  ? expr(_L254, int(2), [int(2), sep(<), int(1), sep(-), id(_G2336)], [sep(<), int(1), sep(-), id(_G2336)])creep
   Call:  (11)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(>)|_G2488]creep
   Fail:  (11)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(>)|_G2488]creep
   Redo:  (11)  ? expr(_L254, _G2482, [int(2), sep(<), int(1), sep(-), id(_G2336)], _L235)creep
   Call:  (12)  ? expr(_L279, _G2485, [int(2), sep(<), int(1), sep(-), id(_G2336)], _L260)creep
   Exit:  (12)  ? expr(_L279, int(2), [int(2), sep(<), int(1), sep(-), id(_G2336)], [sep(<), int(1), sep(-), id(_G2336)])creep
   Call:  (12)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(+)|_G2491]creep
   Fail:  (12)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(+)|_G2491]creep
   Redo:  (12)  ? expr(_L279, _G2485, [int(2), sep(<), int(1), sep(-), id(_G2336)], _L260)creep
   Call:  (13)  ? expr(_L304, _G2488, [int(2), sep(<), int(1), sep(-), id(_G2336)], _L285)creep
   Exit:  (13)  ? expr(_L304, int(2), [int(2), sep(<), int(1), sep(-), id(_G2336)], [sep(<), int(1), sep(-), id(_G2336)])creep
   Call:  (13)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(+)|_G2494]creep
   Fail:  (13)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(+)|_G2494]creep
   Redo:  (13)  ? expr(_L304, _G2488, [int(2), sep(<), int(1), sep(-), id(_G2336)], _L285)creep
   Call:  (14)  ? expr(_L329, _G2491, [int(2), sep(<), int(1), sep(-), id(_G2336)], _L310)creep
   Exit:  (14)  ? expr(_L329, int(2), [int(2), sep(<), int(1), sep(-), id(_G2336)], [sep(<), int(1), sep(-), id(_G2336)])creep
   Call:  (14)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(+)|_G2497]creep
   Fail:  (14)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(+)|_G2497]creep
   Redo:  (14)  ? expr(_L329, _G2491, [int(2), sep(<), int(1), sep(-), id(_G2336)], _L310)creep
   Call:  (15)  ? expr(_L354, _G2494, [int(2), sep(<), int(1), sep(-), id(_G2336)], _L335)creep
   Exit:  (15)  ? expr(_L354, int(2), [int(2), sep(<), int(1), sep(-), id(_G2336)], [sep(<), int(1), sep(-), id(_G2336)])creep
   Call:  (15)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(+)|_G2500]creep
   Fail:  (15)  ? [sep(<), int(1), sep(-), id(_G2336)]=[sep(+)|_G2500]
   ...

【问题讨论】:

  • 可能是expr/2中的左递归。如果您发布可以直接复制并运行的完整代码,则更容易找到问题。
  • @TomasBy 刚刚添加了跟踪

标签: prolog grammar


【解决方案1】:

正如@TomasBy 所建议的,非终端 expr//2 中的左递归导致非终止。在 SWI-Prolog 中有库(tabling),只需导入它并将 expr//2 声明为 tabled。

:- use_module(library(tabling)).
:- table expr//2.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    • 2017-08-14
    相关资源
    最近更新 更多