问题
显示无上下文语法" S-> SbS | ScS | a"是暧昧的 为字符串abaca提供两个解析树。
我不知道字符串是多么含糊不清?我正在读一本关于编译器和自学的书,所以我在书中做了这个问题而且我很难过。
可能的解决方案
abaca abaca
a(aba)aca aba(aca)a
任何人都可以确认我的解决方案是否正确,如果没有,有人可以指导我。
答案 0 :(得分:2)
使用笔和纸更容易。在所有可能性中,我通过推导出初始符号S
来列出三种可能性。
S -> SbS -> abS -> abScS -> abacS -> abaca
S -> ScS -> Sca -> SbSca -> abSca -> abaca
S -> SbS -> SbScS -> abScS -> abSca -> abaca
还有其他人,这不难看出。但是,通常更容易将字符串(abaca
)缩减为原始符号(S
)。许多编译器都这样做是为了避免无限递归:
abaca <- Sbaca <- SbSca <- Sca <- ScS <- S
abaca <- abacS <- abScs <- abS <- SbS <- S
这样做的方法是手工选择一种方式(推导或减少),然后通过反复试验你可以根据语法进行的替换,这将导致你进入一棵树。树中通向目标的节点(原始符号或最终字符串)是正确的节点。如果有多条路径,那就不明确了。
现在,这些推导中的每一个以及其他推导都将产生所谓的Parse Tree
。解析树表示能够从初始符号生成终端字符串的派生集。为了更好地可视化解析树,我在网上找到了一个工具来绘制这些树,你可以找到它here。
它使用的格式是[NonTerminal terminal [NonTerminal terminal] terminal]
,几乎是一个类似Lisp的列表,带有方括号而不是括号。例如,我构建的第一个派生S -> SbS -> abS -> abScs -> ...
可以写成[S [S a] b [S [S a] c [S a]]]
,其中[S [S ...] b [S ...]]
表示第一个派生,然后将第一个[S ...]
展开为[S a]
通过二次推导等等。希望这些工具可以帮助您正式学习语法!