我理解两者之间的区别,歧义意味着至少有一个字符串有2个不同的解析树,而在一个明确的树中只有一个。但我似乎无法将一个转换为另一个。
如何将以下含糊不清的语法转换为明确的语法?
S -> aSb
S -> abS
S -> lambda
编辑:好的,我对此的抨击就像是
S -> aSb | lambda
b -> abS | lambda
有什么想法吗?
答案 0 :(得分:1)
语法不明确,不仅因为有两个规则匹配'a'作为下一个标记 - 而是因为'ab'可以通过第一个或第二个规则匹配(用每个规则替换三个S)。
有一种固有的模糊语法,但这不是一种。
着眼于这个具体的例子,我开始枚举将要解析的字符串。我对规则1,2和3进行了编号 - 并考虑了规则1和2可能出现在解析中的所有序列(这些是生成终端的两个规则。)N.B。我假设“lambda”表示空产品。
1,2 => ab
11,12 => abab
21,22 => aabb
111,112 => ababab
121,122 => abaabb
211,212 => aababb
221,222 => aaabbb
1111,1112 => abababab
1121,1122 => ababaabb
1211,1212 => abaababb
1221,1222 => abaaabbb
2111,2112 => aabababb
2121,2122 => aabaabbb
2211,2212 => aaababbb
2221,2222 => aaaabbbb
从这个练习中,很明显我们匹配偶数长度的'a和b'字符串,其中'a'终端的数量与'b'终端的数量完全匹配...此外,两个串联如果前缀匹配使用第二个规则,则只匹配的字符串会产生另一个匹配的字符串。
从这个分析中,我制作了一些新的作品。
S -> a a X
S -> a b S
S -> lambda
X -> S b b
这个新语法不含糊,但它与模糊语法匹配相同的字符串。它通过引入一个新的非终端X来实现这一点。当这个CFG与下推自动机一起使用时,使用S和X产生的附加状态信息足以避免模糊。
如果在使用Yacc或Bison之类的情况下出现此问题,则模糊性通常表明您选择了终端令牌。如果你选择'aa','ab'和'bb'作为终端 - 你就不会遇到困难。当使用(F)lex作为一个标记器时,根据经验,最好使它匹配的标记尽可能大......因为匹配正则表达式(至少在理论上)比一个更快无上下文语法 - 这当然可能产生了双字符令牌方法。