我尝试使用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).
有人告诉我问题出在哪里?
答案 0 :(得分:2)
让我们首先使用最常规的查询来查看您实际当前描述的内容(例如)id//1
:
?- phrase(id(Is), Ls).
Is = Ls, Ls = [_G884] ;
Is = [_G884|_G885],
Ls = [_G884, '(', ids(_G885), ')'].
尝试最常见的查询通常是了解关系的更多信息的好方法。在这种情况下,我们已经注意到两件非常重要的事情:
Ls
列表,第一个解决方案明显更通用。您添加到此程序中的任何子句(在保留logical-purity时)都可以消除此缺陷。因此,您需要制定第一条规则更具体。ids(_)
。这表明您正在将DCG规则名称与要描述的标记混合在一起。首先,让我们首先集中描述我们想要描述的令牌列表。这有点简化了代码,因为我们不必同时处理这么多事情。
我建议你从以下开始:
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未被处理为非 - 终端。