我是否使上下文无关语法上下文敏感并且重要吗?
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] 这种形式的语义反馈通常被认为是一种复杂化,因为它在词法分析和解析之间产生了紧密的耦合,但是许多解析器这样做是为了方便或必要。
但也许您只满足于检测某些上下文。如果是这样,你的语法肯定是可行的,并且不会产生上下文敏感性。 if
和 while
语句肯定提供了句法确定的布尔上下文。算术运算符提供确定的数字上下文(尽管如果您有多种算术类型,则可能需要类型检查。)但是有些上下文在语法上不是类型确定的,例如赋值语句、相等运算符和函数调用。因此,您最终将在步行的各个地方进行特殊情况类型检查。
就我个人而言,我不认为尝试使语法复杂化以尝试进行部分类型检查有什么好处;我更喜欢在解析后进行类型 validation/deduction 传递。但在某些用例中,不太灵活的方法是完全合理的。
备注
有些语言对使用前声明非常严格(例如 C),但其他语言允许程序员按逻辑顺序声明变量,而不必担心对它们的引用(C++ class 声明,例如。)
就我个人而言,我不希望坚持在使用前声明而使程序员的生活复杂化。事实上,作为一名程序员,我很欣赏可以 推导 变量类型而不是坚持冗余声明的语言。但口味不同。无论如何,强制声明并不一定意味着使用前声明,许多强制声明的语言仍然提供声明顺序的灵活性,允许(例如)相互递归函数而无需冗余前向声明。
不,这些更改不会将上下文无关语法变成上下文相关语法。
只要看左手边的产生式就可以看出区别:只要每个 LHS 都是一个符号,它就是一个 CFG。如果任何 LHS 有 多个 符号,那么它就是 CSG。
(这有点过于简单化了,但足以准确回答您的问题。)
那是 grammars,但是当涉及到 languages 时,请注意,您的语法生成的语言与类型语言不同-有效程序。前者是上下文无关的,但后者可能不是。
如果我的语言有基本的东西,比如
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] 这种形式的语义反馈通常被认为是一种复杂化,因为它在词法分析和解析之间产生了紧密的耦合,但是许多解析器这样做是为了方便或必要。
但也许您只满足于检测某些上下文。如果是这样,你的语法肯定是可行的,并且不会产生上下文敏感性。 if
和 while
语句肯定提供了句法确定的布尔上下文。算术运算符提供确定的数字上下文(尽管如果您有多种算术类型,则可能需要类型检查。)但是有些上下文在语法上不是类型确定的,例如赋值语句、相等运算符和函数调用。因此,您最终将在步行的各个地方进行特殊情况类型检查。
就我个人而言,我不认为尝试使语法复杂化以尝试进行部分类型检查有什么好处;我更喜欢在解析后进行类型 validation/deduction 传递。但在某些用例中,不太灵活的方法是完全合理的。
备注
有些语言对使用前声明非常严格(例如 C),但其他语言允许程序员按逻辑顺序声明变量,而不必担心对它们的引用(C++ class 声明,例如。)
就我个人而言,我不希望坚持在使用前声明而使程序员的生活复杂化。事实上,作为一名程序员,我很欣赏可以 推导 变量类型而不是坚持冗余声明的语言。但口味不同。无论如何,强制声明并不一定意味着使用前声明,许多强制声明的语言仍然提供声明顺序的灵活性,允许(例如)相互递归函数而无需冗余前向声明。
不,这些更改不会将上下文无关语法变成上下文相关语法。
只要看左手边的产生式就可以看出区别:只要每个 LHS 都是一个符号,它就是一个 CFG。如果任何 LHS 有 多个 符号,那么它就是 CSG。
(这有点过于简单化了,但足以准确回答您的问题。)
那是 grammars,但是当涉及到 languages 时,请注意,您的语法生成的语言与类型语言不同-有效程序。前者是上下文无关的,但后者可能不是。