使用DCG解析表达式

时间:2016-02-07 21:06:26

标签: prolog dcg

我尝试使用DCG解析标识符列表,但我没有做到,

示例

                          ::=
                            |
                          __|____
                         |       |
                        Id     Id,'(',Ids,')'.
                                       _|_
                                      |   |
                                     Id   Id,

-

ids ::= id.
ids ::= id(id1,id2,...).

要验证的标识符示例

  exp1 = 'id_0'
  exp3 = 'id_1(i)'
  exp2 = 'id_2(i1,i2)'

代码编辑

id([Id]) --> [Id].
id([Id|Ids]) --> [Id,'('], ids(Ids), [')'].

ids([Id]) --> [Id].
ids([Id|Ids]) --> [Id], ids(Ids).
有人告诉我问题出在哪里?

2 个答案:

答案 0 :(得分:2)

让我们首先使用最常规的查询来查看您实际当前描述的内容(例如)id//1

?- phrase(id(Is), Ls).
Is = Ls, Ls = [_G884] ;
Is = [_G884|_G885],
Ls = [_G884, '(', ids(_G885), ')'].

尝试最常见的查询通常是了解关系的更多信息的好方法。在这种情况下,我们已经注意到两件非常重要的事情:

  1. 关于令牌的Ls列表,第一个解决方案明显更通用。您添加到此程序中的任何子句(在保留时)都可以消除此缺陷。因此,您需要制定第一条规则更具体
  2. 第二个答案描述的标记实际上与语法不匹配,因为它们包含具体标记ids(_)。这表明您正在将DCG规则名称与要描述的标记混合在一起。
  3. 首先,让我们首先集中描述我们想要描述的令牌列表。这有点简化了代码,因为我们不必同时处理这么多事情。

    我建议你从以下开始:

    ids --> [id].
    ids --> [id,'('], ids_, [')'].
    
    ids_ --> ids, more_ids_.
    
    more_ids_ --> [].
    more_ids_ --> [,], ids_.
    

    请注意有用的模式,允许我们指定“更多相同”,即没有逗号 然后“同样的“。

    我想你最终会使这更加通用,例如,除了具体的标记id之外,还接受其他标识符。从上面的代码中可以清楚地看到这一点,我将其作为一个简单的练习。

    请注意,我们已经可以使用它来查看我们是否只描述了 预定的令牌列表:

    ?- length(Ls, _), phrase(ids, Ls).
    Ls = [id] ;
    Ls = [id, '(', id, ')'] ;
    Ls = [id, '(', id, ',', id, ')'] ;
    Ls = [id, '(', id, '(', id, ')', ')'] ;
    etc.
    

    我使用length/2进行公平查点。

    一旦确定您正在描述您想要的所有和唯一的令牌列表,您就可以开始将这些令牌列表与其他Prolog术语联系起来。这通常涉及(=..)/2以及术语之间的其他关系。

答案 1 :(得分:1)

我认为你错过了一个DCG,当翻译成Prolog时,将方块之间的符号处理为终端

所以,你的条款如

id([Id|Ids]) --> [Id,'(',ids(Ids),')'].
除非给出终端的特定模式,否则

被视为失败。让我们试试SWI-Prolog:

1 ?- [user].
id([Id|Ids]) --> [Id,'(',ids(Ids),')'].
|: 
true.

2 ?- phrase(id(L), [me,'(',ids([1,2,3]),')']).
L = [me, 1, 2, 3].

您可以看到ids / 1未被处理为 - 终端。