在其他文字中删除抽象语法中的歧义,以编写DCG解析器



p =>程序k =>块

s =>单个命令

c =>命令

e =>表达

b => boolean-expr

i =>标识符

n>数字

p :: = k。

k :: = begin c end

c :: = c1;C2 |S

s :: = i:= e |如果(b)然后s |如果(b)则S1 else s2 |而(b)做S |重复C直到(b)|K |打印E

e :: = - e |E1 E2 |E1 -E2 |E1 E2 |E1 Div E2 |E1 mod E2 |(E)|我|n

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

我应该删除E和B中的歧义,以便我可以在Prolog中编写DCG解析器。

prolog tops downuate tops down,然后可以调整LL语法技术。DCG比LL(1)强大,但仍必须消除左侧递归。

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

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

e更难,因为mul MISS的标记会引入更大的歧义。暂时

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

Epsilon(空生产)可以以这种方式编写

epsilon --> [].

如果您需要处理优先级和关联性(在B和E中),则需要更多的工作。您可以参考工作架构的旧答案。

@chac已经给了您一个很好的答案,向您展示了解决此问题的常见方法。

让我采用另一种方法来阅读您的问题:您是"应该消除E和B中的歧义,这样"您"可以在Prolog"中撰写DCG解析器。这意味着,您只需要消除歧义,只能在Prolog中编写DCG解析器。有个好消息:您根本不需要删除任何歧义来编写DCG解析器!这是:

歧义的来源是

之类的作品

c :: = c;c

或其他操作员 - 并列Div mod和

让我坚持简化的语法:

e :: = e e |&quot" 1&quot

我们可以将其编码为

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

不幸的是,Prolog并未终止

这样的查询
?- L = "1+1+1", phrase(e,L).
   L = "1+1+1"
;  resource_error(_). % ERROR: Out of local stack

实际上,它终止了,但这仅仅是因为我的计算机的内存是有限的...

甚至不是:

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

这是歧义的问题吗?不!这只是序言的程序问题,无法直接处理左回归。这是使序言处理的一种方法:

E([_ | S],S) ->" 1"。e([_ | s0],s) -> e(s0,s1)," ",e(s1,s)。? -  l =" 1 1 1",短语(e(l,[]),l)。   l =" 1 1 1";l =" 1 1 1";错误的。? -  l =" 1",短语(e(l,[]),l)。   L =" 1";错误的。

目前我们只定义了语法,在大多数情况下,您也有兴趣看到相应的语法树:

e( integer(1), [_ | s],s) ->" 1"。e( plus(l,r), [_ | s0],s) -> e( l, s0,s1)," ",e( r, s1,s)。? -  l =" 1 1 1",短语(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),整数(1)),整数(1));错误的。

现在,我们看到plus有歧义!您的原始语法都将其接受为(1 1) 1和1 (1 1),只要相应的语义保证观察到关联性,就不是问题。在大多数情况下,这是歧义为左求的,因此含义(1 1) 1,但这并不是所有Infix Operators的情况。

相关内容

  • 没有找到相关文章

最新更新