C ++

我对于情境敏感性和模糊性如何相互影响感到困惑。

我认为是正确的是:

歧义:

模糊的语法导致使用左或右派生来构建多个分析树。 所有可能的语法都不明确的语言是一种模糊的语言。

例如C ++是一种模糊的语言,因为x * y总是可以表示两种不同的东西,如下所述:为什么C ++不能用LR(1)解析器分析?

上下文灵敏度:

上下文敏感语法的规则是,这些规则的左边可能包含除了不同类型语法的所有规则的lhs内所需的一个非终结符之外的(非)终结符号。 这意味着您不能在降序时更换非终端。 相反,你必须先看看周围的非终点。


现在令我困扰的是那些或多或少表示上下文敏感的解析器可以解析像x * y这样的歧义的陈述。 例如,在上面的链接问题中,声明“......创建时装饰语法树的解析器不是上下文无关的,而LR解析器(纯粹的)无上下文。” 在我看来,这意味着上下文敏感的解析器(与上下文无关的解析器相反)可以做到这一点。 另一个例子是C ++语法的任何部分都是敏感的吗? 这个问题的答案是“是...”。 同样在这里:什么是模棱两可的上下文无关语法?

我没有看到这种C ++歧义与上下文敏感性有什么关系。 我不认为有任何可以解决这种歧义的上下文敏感语法。 例如,如果您采用类似于Typedef的虚构规则,<other> *,PointerDeclaration - > Ident“*”Ident

那么您仍然无法确定(使用纯解析)在Typedef期间是否使用了具体的第一个Ident(例如“x”)(例如typedef double x;)。


所以有可能在链接的问题中使用术语“上下文敏感性”,虽然这意味着像上下文相关性那样简单(例如,比简单的解析器所提供的更多信息)。 或者,“真正的”上下文敏感性“与含糊之处之间是否有任何联系。

编辑更多指定的问题:上下文无关语法中是否存在任何可以通过使用上下文相关语法来处理的歧义。 这个问题发生在我身上,因为在链接问题中,它听起来像C ++歧义有时被称为上下文敏感问题。

Edit2附加信息:本书的计算机系统第346页指出,具有相同数量的实际参数和形式参数的要求可以用上下文相关的语法来表示。 但是这很麻烦,因为你需要很多复杂的规则。 但也许这也可能适用于前面提到的C ++歧义。 所以我们有像这样的规则

“Typedef double x”,<other> *,PointerDeclaration - >“x”“*”Ident

当然,这些规则将会非常有限,你需要大量的资金来表达每一种可能性。 至少这可能是一个解决这个问题的方法,是否可以用上下文相关的规则来取代(神经)上下文无关的自由歧义


上下文敏感性和模糊性完全正交。 存在不明确的上下文无关语言和明确的上下文敏感语言。

上下文敏感语言是一种可以通过上下文敏感语法(CSG)解析的形式语言。 由于上下文无关文法是简化的上下文敏感语言,所以每个上下文无关语言也是一种上下文敏感语言。 尽管并非每种正式语言都是上下文敏感的, 甚至有一些CSG无法描述的语言。


如果要使用上下文无关语法分析器分析上下文敏感语言,则可以定义接受上下文敏感语言超集的上下文无关语法(因为它们功能较弱)。 因为您接受超集,您可能会得到含糊不清或错误肯定的结果,这些结果必须在解析后解决。

示例一:允许任何标签名称的XML类语言 。 由于上下文无关语法无法解析由两个重复单词w = {a,b} +组成的句子ww,因此它不能解析<ID></ID> 。 因此,我们定义了一个接受超集的上下文无关语法:

start -> elem
elem  -> open elem* close
open  -> '<' ID '>'
close -> '</' ID '>'
ID    -> ('a' / 'b')+

这显然会解析一个不需要的句子,因此需要在openclose额外检查等效ID。

例二:用一种非常简单的语言描述类C的Typedef 。 设想一种只包含typedef,指针和乘法的语言。 它只有两个ID, ab 。 这种语言的一个例子:

typedef a;
b * a;                    // multiplication
a * b;                    // b is pointer to type a 

上下文无关语法如下:

start                     -> typedef multiplication-or-pointer+
typedef                   -> 'typedef' ID ';'
multiplication-or-pointer -> ID '*' ID ';'
ID                        -> 'a'
ID                        -> 'b'

语法不接受超集,但它不知道它是否看到乘法或指针,因此它是不明确的。 因此,必须经过结果并决定,如果它是乘法或指针,取决于typedef中定义的类型。

有了上下文敏感的语法,人们可以做更多的事情。 非常粗略(并且不精确):

start                                     -> typedef multiplication-or-pointer+
typedef                                   -> 'typedef' ID ';'
multiplication-or-pointer                 -> pointer / multiplication
'typedef' 'a' ';' WHATEVER pointer        -> 'a' '*' ID   
'typedef' 'b' ';' WHATEVER pointer        -> 'b' '*' ID   
'typedef' 'b' ';' WHATEVER multiplication -> 'a' '*' ID
'typedef' 'a' ';' WHATEVER multiplication -> 'b' '*' ID
ID                                        -> 'a'
ID                                        -> 'b'

请注意,我在这里展示的内容并不准确,因为我的ID数量有限。 一般来说,可以有无数的ID。 您可以为一般情况编写上下文敏感的语法(尽管它必须绝对不直观),但不能编写上下文无关语法。

关于你的编辑1:我希望前面的例子能够回答这个问题。

关于你的编辑2:还有另一个技巧如何表达,所以规则不是那么有限,但它们通常令人兴奋,而IMO则是没有人使用CSG形式主义的原因。

注意:上下文敏感语法相当于一个线性有界自动机,上下文无关语法相当于一个下推自动机。 说上下文无关的分析器与上下文相关的分析器是相反的是不正确的。


编译器不使用“纯”(不管这可能意味着什么)语法来解析它们 - 它们是真实世界的程序,它们可以执行所有真实世界的程序 - 在某些情况下应用启发式方法。 这就是为什么不使用编译器生成器生成C ++编译器(以及大多数其他语言的编译器,除了本科生练习)。

链接地址: http://www.djcxy.com/p/74857.html

上一篇: c++

下一篇: Why can't C++ be parsed with a LR(1) parser?