在其他抽象语法歧义删除写DCG分析器的Prolog(Remove Ambiguity in abst

2019-07-03 10:57发布

P =>程序K =>块

S =>单命令

C =>命令

E =>表达式

B =>布尔EXPR

I =>标识符

N>标号

P :: = K.

ķ:: =开始Ç端

Ç:: = C1; C2 | 小号

与s :: = I:= E | 如果(B),则S | 如果(B),然后S1 S2其他| (B)是做S | 重复℃直至(B)| K | 打印E

:: = E - E | E1 + E2 | E1 - E2 | E1 E2 | 格E1 E2 | E1 E2模| (E)| 我| ñ

B :: = E1 = E2 | E1> E2 | E1 <E2 | E1 = E2!| 不是B | B1和B2 | B1或B2 | (B)

我应该消除含糊在E和B,这样我可以写在序言一DCG分析器。

Answer 1:

Prolog的评估自上而下,然后LL 语法技术可以适应。 DCG比LL(1)功能更强大,但左递归仍然必须被淘汰。

B更容易处理: 左因子生产。

B ::= E Bx | not B | (B)
Bx ::= = E | > E | < E | != E | and B | or B

E是很难的,因为思念mul令牌介绍更加模糊性。 姑且

E ::= − E | (E) | I | N | El
El ::= Ex E | epsilon
Ex ::= + El | − El | div El | mod El

小量(空生产)的DCG可以这样写

epsilon --> [].

如果您需要处理优先级和结合(在B和E),您将需要更多的工作。 您可以参考这个旧的答案工作模式。



Answer 2:

@chac已经给你相当不错的答案,显示你解决这个通常的方式。

让我采取另一种方式来阅读你的问题:你是“应该去掉了E歧义和B,使”你“可以在序言写DCG分析器”。 这意味着,你只需要那么远,你可以写在序言一DCG分析器删除歧义。 有个好消息: 你并不需要在所有以消除任何含糊之处写DCG分析器! 方法如下:

歧义的源像制作

Ç:: = C; C

或其他运营商+ - 并置DIV MOD和

让我坚持一个简化的语法:

Ë:: = E + E | “1”

我们可以编码这是

e --> "1".
e --> e, "+", e.

不幸的是,序言不终止查询像

?- L = "1+1+1", phrase(e,L).
L = "1+1+1" ;
ERROR: Out of local stack

事实上,它终止,但只是因为我的电脑的内存是有限的...

甚至不是:

?- L = "1", phrase(e,L).
L = "1" ;
ERROR: Out of local stack

这是含糊不清的问题? 没有! 这是序言的只是程序问题,不能直接处理左递归。 这里有一个方法,使Prolog的处理:

e([_|S],S) --> "1".
e([_|S0],S) --> e(S0,S1), "+", e(S1,S).

?- L = "1+1+1", phrase(e(L,[]),L).
L = "1+1+1" ;
L = "1+1+1" ;
false.

?- L = "1", phrase(e(L,[]),L).
L = "1" ;
false.

因为我们只定义语法的时刻,大部分的时间,你也有兴趣看到相应的语法树:

e(integer(1), [_|S],S) --> "1".
e(plus(L,R), [_|S0],S) --> e(L, S0,S1), "+", e(R, S1,S).

?- L = "1+1+1", phrase(e(Tree, L,[]),L).
L = "1+1+1",
Tree = plus(integer(1),plus(integer(1),integer(1))) ;
L = "1+1+1",
Tree = plus(plus(integer(1),integer(1)),integer(1)) ;
false.

现在,我们看到,有歧义与plus ! 您的原始语法既接受它作为(1 + 1)+1和1+(1 + 1),其本身不是问题,只要对应的语义保证关联是观察。 大部分时间,这是消除歧义被左结合的,因此表示(1 + 1)+1,但这不是对所有中缀运算符的情况。



文章来源: Remove Ambiguity in abstract syntax in other to write DCG parser Prolog