简体   繁体   English

使用DCG解析表达式

[英]parsing an expression using DCG

I try to parse a list of identifiers with DCG but I fail to do it, 我尝试使用DCG解析标识符列表,但是我做不到,

example

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

- -

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

example of identifier to verify 要验证的标识符示例

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

code edit 代码编辑

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

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

someone tell me where is the problem ? 有人告诉我问题出在哪里?

Let us first see what you are actually currently describing with (for example) id//1 , using the most general query: 让我们先看看你实际上目前与描述(例如) id//1 ,采用最一般的查询:

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

Trying out the most general query is often a good way to find out more about a relation. 尝试最一般的查询通常是了解关系的好方法。 In this case, we already note two very important things: 在这种情况下,我们已经注意到了两个非常重要的事情:

  1. Regarding the list Ls of tokens, the first solution is clearly more general than intended. 关于令牌列表Ls ,第一种解决方案显然比预期的更通用 No clause that you add to this program (while preserving ) can remove this flaw. 您添加到该程序中的子句(在保留 )不能消除此缺陷。 Therefore, you need to make the first rule more specific . 因此,您需要使第一个规则更具体
  2. The tokens described by the second answer do not actually match the grammar, because they contain the concrete token ids(_) . 第二个答案描述的标记实际上与语法不匹配,因为它们包含具体的标记ids(_) This points you to the fact that you are intermingling DCG rule names with the tokens you want to describe. 这表明您将DCG规则名称与要描述的标记混合在一起的事实。

For a start, let us first focus an describing the list of tokens that we want to describe. 首先,让我们首先关注一个要描述的令牌列表的描述。 This simplifies the code somewhat, since we do not have to deal with so many things at once. 因为我们不必一次处理那么多事情,所以这在某种程度上简化了代码。

I suggest you start with the following: 我建议您从以下内容开始:

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

ids_ --> ids, more_ids_.

more_ids_ --> [].
more_ids_ --> [,], ids_.

Notice the helpful pattern that allows us to specify "more of the same", which is either nothing or a comma and then "the same". 注意有用的模式,它使我们可以指定“更多相同”,它既可以是空也不逗号 ,然后可以是 “相同”。

I suppose you will eventually make this more general, and for example accept also other identifiers besides the concrete token id . 我想您最终将使它更加通用,例如,除了具体的令牌id之外,还接受其他标识符。 The place to do this is clear from the code above, and I leave it as an easy exercise. 从上面的代码中可以清楚地了解到这一点,我将其作为一个简单的练习。

Notice that we can already use this to see whether we are describing only intended lists of tokens: 请注意,我们已经可以使用它来查看是否在描述标记的预期列表:

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

I am using length/2 for fair enumeration. 我正在使用length/2进行公平枚举。

Once you have made sure that you are describing all and only lists of tokens you intended, you can then start to relate such lists of tokens to other Prolog terms. 一旦确定要描述的只是所有想要的标记列表,然后就可以将这些标记列表与其他Prolog术语相关联。 This will often involve (=..)/2 and other relations between terms. 这通常涉及项之间的(=..)/2和其他关系。

I think you're missing that a DCG, when translated to Prolog, handles symbols enclosed between squares as terminals . 我认为您会丢失DCG,当将其转换为Prolog时,会将正方形之间的符号作为终端处理

So, your clauses like 所以,你的子句就像

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

are deemed to fail, except when a specific pattern of terminals is given. 被认为是失败的,除非给出了特定的终端模式。 Let's try, in SWI-Prolog: 让我们在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].

you can see that ids/1 is not handled as a non -terminal. 您会看到ids / 1没有作为终端处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM