我是否使上下文无关语法上下文敏感并且重要吗?

Am I making a context free grammar context sensitive and does it matter?

如果我的语言有基本的东西,比如

a = expression

if expression then ...

while expression do ...

那么我的语法可能是这样的:(伪代码)

assignment: identifier Equals expression ;
if        : If expression Then ...
while     : While expression Do ...

现在第一个表达式的类型只需要与 'a' 类型兼容,但其他两个表达式必须是布尔类型。

虽然到处都很容易检查表达式的类型,但在我看来,在语法中定义会很方便

boolExpression : expression;

然后我的其他规则将如下所示:

assignment: identifier Equals expression ;
if        : If boolExpression Then ...
while     : While boolExpression Do ...

这将允许我检查 boolExpression returns 是一个 BOOL 类型,这样我就不必添加代码来测试每个表达式。

但是我这样做是否将上下文无关文法变成了上下文相关文法?如果是这样,这重要吗?

如果你有布尔变量,那么你不能在语法上验证一个表达式是否是布尔值。如果你想捕获 all 类型检查,你将需要某种语义反馈,这确实会使语言上下文敏感,并且也使从左到右的解析变得不可能,除非你要求变量在使用前声明。 [见注释 1] 这种形式的语义反馈通常被认为是一种复杂化,因为它在词法分析和解析之间产生了紧密的耦合,但是许多解析器这样做是为了方便或必要。

但也许您只满足于检测某些上下文。如果是这样,你的语法肯定是可行的,并且不会产生上下文敏感性。 ifwhile 语句肯定提供了句法确定的布尔上下文。算术运算符提供确定的数字上下文(尽管如果您有多种算术类型,则可能需要类型检查。)但是有些上下文在语法上不是类型确定的,例如赋值语句、相等运算符和函数调用。因此,您最终将在步行的各个地方进行特殊情况类型检查。

就我个人而言,我不认为尝试使语法复杂化以尝试进行部分类型检查有什么好处;我更喜欢在解析后进行类型 validation/deduction 传递。但在某些用例中,不太灵活的方法是完全合理的。

备注

  1. 有些语言对使用前声明非常严格(例如 C),但其他语言允许程序员按逻辑顺序声明变量,而不必担心对它们的引用(C++ class 声明,例如。)

    就我个人而言,我不希望坚持在使用前声明而使程序员的生活复杂化。事实上,作为一名程序员,我很欣赏可以 推导 变量类型而不是坚持冗余声明的语言。但口味不同。无论如何,强制声明并不一定意味着使用前声明,许多强制声明的语言仍然提供声明顺序的灵活性,允许(例如)相互递归函数而无需冗余前向声明。

不,这些更改不会将上下文无关语法变成上下文相关语法。

只要看左手边的产生式就可以看出区别:只要每个 LHS 都是一个符号,它就是一个 CFG。如果任何 LHS 有 多个 符号,那么它就是 CSG。

(这有点过于简单化了,但足以准确回答您的问题。)

那是 grammars,但是当涉及到 languages 时,请注意,您的语法生成的语言与类型语言不同-有效程序。前者是上下文无关的,但后者可能不是。