[英]How to Remove the ambiguity from the following grammar?
消除以下语法中的歧义
S −−> 如果 E 则 S | 如果 E 则 S 否则 S | 其他
您可以消除悬空-其他歧义。 《编译器:原理、技术和工具》第 2 版,第 211-212 页中有这样的语法。 不过书里有语法,只是没有解释(或者我没找到)。
在 ABNF 元语法中,语法是:
statement = matched / open
matched = "if" expr "then" matched "else" matched
/ other
open = "if" expr "then" statement
/ "if" expr "then" matched "else" open
expr = ...
other = ...
这里的想法是通过使用非确定性来避免歧义(无论如何已经提出,因为每个歧义语法也是非确定性的;最后我写了关于差异,我发现(太)经常被误解) . 这意味着在成功解析之后,任何输入都只有一个语法树(意味着您要求的非歧义)。 但是您将需要一个解析器,它可以使用比确定性 LL(1) 解析器更复杂的机制。
规则matched
确保子树中每个直接嵌套的 if 语句都有else
。 换句话说, then
将有一个匹配的else
。
规则open
确保每个子if语句没有else
本身,或者如果确实如此,那么其别的语句是open
反过来。 与其他词,排除open
保证会减少else
比使用的关键字then
关键字使用。 而与其他词,数量else
子树内将小于的数量then
(或者if
■如果你喜欢)。 这与确保两者数量相等的matched
规则形成对比。 这意味着在解析器中实现的matched
和open
永远不会接受相同的输入,从第一次使用规则statement
。
此外,由于matched "else" open
在规则open
, else
将“附加”到最近的if
。 这在解析器识别第一个使用的statement
之前解决了悬空-其他歧义。
为了说明将要发生的步骤,我升级了语法以允许更多“自然”输入。 这意味着更多的标点符号和空格。 首先是词法分析器:
keyword = %s"if" / %s"then" / %s"else"
它尽可能将输入字符分组,而未分组的字符则自行成为标记。 对于输入:
if(x)then if(x)then y else y
然后你有解析器语法,允许解析器接受这些标记(区分大小写)并显式放置空格。 还是可以看原版的,整体流程是一样的。 解析器语法:
statement = matched / open
matched = {keyword, %s"if"} *ws "(" *ws expr *ws ")" *ws {keyword, %s"then"} 1*ws matched {keyword, %s"else"} 1*ws matched
/ other *ws
open = {keyword, %s"if"} *ws "(" *ws expr *ws ")" *ws {keyword, %s"then"} 1*ws statement
/ {keyword, %s"if"} *ws "(" *ws expr *ws ")" *ws {keyword, %s"then"} 1*ws matched {keyword, %s"else"} 1*ws open
expr = %s"x"
other = %s"y"
ws = %s" "
开始解析后,深入探究语法规则的解析机,会这样执行:
statement
matched
的引用的第一个串联。if(x)then
字符的第一个标记matched
规则if(x)then y else y
。matched
规则并期望其匹配else
,但没有这样的,因为输入已经结束。 这意味着解析器必须返回以寻找另一种方式。 此时,您将拥有这个(部分构建的)语法树: statement
进行第二个连接,即一个引用规则open
。决定论、非决定论、歧义和非歧义常常被误解。 我想每个人都举一个例子,因为我认为写的对每个人来说都不是很清楚。
从解析器的角度来看,确定性与给定状态下可能的操作数量有关。 当对于解析器中的所有可能状态至多一个动作是可能的时,解析器是确定性的。 我在很多地方都看到过这样的说法:“语法主要是确定性的,只有少数地方是非确定性的”。 这是误导,因为文法的确定性是基于整个文法——更准确地说是最坏的确定性情况。 例如,下一个语法是确定性的,当被解析器使用时,解析器也将是确定性的:
rule = "a" / "b"
非确定性意味着有解析器,其中一个以上的动作是可能的,对于至少一个输入序列中的至少一个可能的状态。 例如,以下语法是不确定的:
rule = "a" / "a"
显然,您可以将其重写为仅rule = "a"
但这不是相同的语法。 两种语法都生成相同的语言。 语法正在生成一种语言的有效字符串。 这种语言包括其有效的字符串。 解析器正在接受有效的语言字符串并拒绝无效的语言字符串。
歧义是指输入可以在一个以上的方式来识别。 这反过来意味着对于至少一个有效输入可能有不止一种语法树。 例如,前面的语法( rule = "a" / "a"
)是不明确的,因为两个连接都有a
.
非歧义意味着任何有效输入都将以完全一种方式被识别。 这又意味着,只有一个语法树存在于每个有效的输入。 显然,对于无效输入,没有语法树。
您可能有一个非确定性和非歧义的语法,如下所示:
rule = "a" "b" / "a" "c"
您在输入字符a
的规则开头有一个不确定的选择,但在下一个输入字符中,哪个连接是正确的将变得清晰。 这是不可能的,在输入被完全处理,有一个以上的语法树:这意味着语法是不明确的。
显然,每一个对应确定的语法也无歧义的,因为没有状态,其中第二个动作是可能的,可能会导致第二个树。
此外,每一个暧昧的语法不确定性,因为能够有一个以上的语法树,某处的状态,即有超过一个动作可能的,至少一个输入序列。
在这本书的语法的“绝招”是,非决定论是让到存在(它实际上是“就业”),但它不会让到外面传播statement
规则,有效防止语法变得暧昧。
现在,当解析器一次处理一个字符时,所有这些都是有效的。 但我不会离这里很远。 也有不同类型的歧义。 有些你可以数,有些你不能。 但我也不会去那里。
免责声明:我使用了截图和我开发的工具的语法语法:Tunnel Grammar Studio。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.