JavaScript 是上下文无关语言吗?
Is JavaScript a Context Free Language?
how browsers work 上的这篇文章解释了 CSS 如何是上下文无关的,而 HTML 不是 。但是 JavaScript 呢,JavaScript 是上下文无关的吗?
我正在学习 CFG 和形式证明,但离理解如何解决这个问题还有很长的路要走。有谁知道 JavaScript 是否是上下文无关的?
没有一种编程语言是(完全)上下文无关的(我想说包括 CSS)。即使上下文无关文法 (CFG) 可用于 define/generate compilers/parsers 语言。
一个简单的事实(例如)变量需要在使用之前首先定义,或者涉及标识符的声明应该是独一无二,使语言“上下文敏感”。
一种(编程)语言的语法应该描述(并生成)字符串,这些字符串只是该语言中的有效程序(在句法上,但在语义上)。然而,CFG 可以描述和生成不是有效程序的字符串(给定语言语义和规范)。描述有效程序的条件(例如:1. class
需要在使用 new class()
之前定义,2. ids
必须匹配等)需要 context-sensitivity。
没有 CFG(具有任何有限数量的产生式)可以正确地表示只有这种语言的有效字符串:{
a
n
b
n
c
n
: n >= 1
}
, where n
should be the same for a
, b
, c
(it should match). Note one can indeed define a CFG for (a superset of) this language, but it will accept also non-valid strings along with valid ones (and then by other means filter them out), this is not what a grammar specification for a language is supposed to do. It should accept only the valid strings and reject the non-valid. In an analogy with statistics,可以说语法规范一种语言应该 eliminate/minimise Type-I(拒绝有效字符串)和 Type-II(接受无效字符串)错误,不只是其中之一。
让我在 JavaScript 的上下文中举一个简单的例子(因为变量似乎对 JavaScript 没有问题)。
在JavaScript(在strict mode)中,重复的命名函数声明无效。所以这是无效的:
function duplicateFunc(){}
function duplicateFunc(){} // duplicate named function declaration
所以程序不正确,但CFG无法处理这种情况。
甚至开启严格模式本身也是上下文相关的
严格模式规则的一个子集可以通过在案例中拆分 CFG 并根据 (删除严格模式示例)
进行相应解析来处理
[更新]
我将尝试给出几个 JavaScript 非上下文无关代码的示例,这些代码 不需要 "strict mode"(对 suggestions/corrections).
reserved words/keywords的使用是对语法的扩展(或限制)。这是一个无关的功能,因此以下示例应算作非 CF 行为的示例。
var var; // identifier using reserved name
var function; // identifier using reserved name
obj.var; // reserved name used as (explicit) property
obj["var"]; // this is fine!!
Object++; // built-in type used as numeric variable
[/更新]
所以上下文在程序的正确解析中起着重要作用。俗话说“上下文就是一切”!
然而,这种 上下文敏感度 可以(希望)通过对上下文无关语法的轻微扩展(例如 Attribute Grammars, Affix Grammars, TAG Grammars 等)来处理,这仍然可以进行有效的解析(意味着在多项式时间内)。
[更新]
"我会说包括 CSS"
详细说明一下这个说法。 CSS1
将是 CF
,但由于 CSS
规范添加了更多功能,包括 variable
支持(例如 css-counters
),它使 CSS
代码上下文-上述意义上的敏感(例如变量需要在使用前定义)。所以下面的 css
代码将被浏览器解析(并被忽略,因为它无效)但它不能用 CFG
来描述
body { }
h3::before {
counter-increment: section; /* no counter section has been defined, not valid css code */
content: "Section" counter(section) ": "; /* Display the counter */
}
[/更新]
我很确定 JS 不是 上下文无关的 — 给定任意代码人工制品,在不知道其上下文的情况下不一定能确定其确切含义。
第一个想到的例子是{}
——这代表一个空的对象字面量还是一个空的语句块?没有上下文是不可能决定的,但是因为该语言允许从以 '}' 结尾的语句中省略分号(就像大多数具有类似 C 语法的语言一样)它也可能是不可决定的 with语境!考虑 {x: {}}
——这可能是一个对象字面量,其 "x" 字段包含一个空对象,或者是一个带有标签子语句的语句块(其中标签是 'x' 和子-语句是 {}
)。也许语言规范有一些规则可以在这种情况下选择正确的解释,但无论如何,仅通过这些示例来判断,语言似乎并不是上下文无关的。
JavaScript的'automatic semicolon insertion'特征当然不能帮助区分表达式和语句。
还有一个要考虑的问题:function x() {}
— 这有什么作用?如果它是一条语句,它会声明一个新的提升变量 'x' 并将此函数作为其值。如果它是一个表达式,它只是计算一个函数,该函数的上值 'x' 绑定到同一函数(用于自引用)。
不,JavaScript 不是上下文无关语言。
非常接近一,ECMAScript 5 规范确实做到了use a context-free grammar1 to describe the language's syntax (you can find all productions in Annex A)。
当然,它确实对纯上下文无关语法产生式做了一些扩展,并描述了解析器的额外行为。一个特别的事情是 lookahead 的使用,它仍然是一种上下文无关的语言,但如果它不能用于某些规则,会使语法复杂化很多。不允许某些东西出现在严格模式代码中是类似的——它可以通过调整语法来完成(有更多的产品),但是通过离开 BNF 更容易表达规则。
但是,也有一些2 规则确实使语言不是上下文无关的。您会在 description of early errors 中找到一个概述,它可以使程序代码无效。对象字面量不能包含重复的 属性 名称,函数参数列表不能包含重复的标识符,这两个规则不能使用(有限的)上下文无关语法来表达。
我的直觉告诉我 the automatic semicolon insertion 属于同一个盒子,但我认为它的规则太复杂了,甚至无法在这里尝试证明。
1:实际上它使用两个语法,一个 lexical and a syntactical 一个,其中第一个消除除法表达式和正则表达式之间的歧义,并产生作为第二个语法输入的标记.
2:与其他编程语言相比,实际上相当少
how browsers work 上的这篇文章解释了 CSS 如何是上下文无关的,而 HTML 不是 。但是 JavaScript 呢,JavaScript 是上下文无关的吗?
我正在学习 CFG 和形式证明,但离理解如何解决这个问题还有很长的路要走。有谁知道 JavaScript 是否是上下文无关的?
没有一种编程语言是(完全)上下文无关的(我想说包括 CSS)。即使上下文无关文法 (CFG) 可用于 define/generate compilers/parsers 语言。
一个简单的事实(例如)变量需要在使用之前首先定义,或者涉及标识符的声明应该是独一无二,使语言“上下文敏感”。
一种(编程)语言的语法应该描述(并生成)字符串,这些字符串只是该语言中的有效程序(在句法上,但在语义上)。然而,CFG 可以描述和生成不是有效程序的字符串(给定语言语义和规范)。描述有效程序的条件(例如:1. class
需要在使用 new class()
之前定义,2. ids
必须匹配等)需要 context-sensitivity。
没有 CFG(具有任何有限数量的产生式)可以正确地表示只有这种语言的有效字符串:{
a
n
b
n
c
n
: n >= 1
}
, where n
should be the same for a
, b
, c
(it should match). Note one can indeed define a CFG for (a superset of) this language, but it will accept also non-valid strings along with valid ones (and then by other means filter them out), this is not what a grammar specification for a language is supposed to do. It should accept only the valid strings and reject the non-valid. In an analogy with statistics,可以说语法规范一种语言应该 eliminate/minimise Type-I(拒绝有效字符串)和 Type-II(接受无效字符串)错误,不只是其中之一。
让我在 JavaScript 的上下文中举一个简单的例子(因为变量似乎对 JavaScript 没有问题)。
在JavaScript(在strict mode)中,重复的命名函数声明无效。所以这是无效的:
function duplicateFunc(){}
function duplicateFunc(){} // duplicate named function declaration
所以程序不正确,但CFG无法处理这种情况。
甚至开启严格模式本身也是上下文相关的
严格模式规则的一个子集可以通过在案例中拆分 CFG 并根据
[更新]
我将尝试给出几个 JavaScript 非上下文无关代码的示例,这些代码 不需要 "strict mode"(对 suggestions/corrections).
reserved words/keywords的使用是对语法的扩展(或限制)。这是一个无关的功能,因此以下示例应算作非 CF 行为的示例。
var var; // identifier using reserved name
var function; // identifier using reserved name
obj.var; // reserved name used as (explicit) property
obj["var"]; // this is fine!!
Object++; // built-in type used as numeric variable
[/更新]
所以上下文在程序的正确解析中起着重要作用。俗话说“上下文就是一切”!
然而,这种 上下文敏感度 可以(希望)通过对上下文无关语法的轻微扩展(例如 Attribute Grammars, Affix Grammars, TAG Grammars 等)来处理,这仍然可以进行有效的解析(意味着在多项式时间内)。
[更新]
"我会说包括 CSS"
详细说明一下这个说法。 CSS1
将是 CF
,但由于 CSS
规范添加了更多功能,包括 variable
支持(例如 css-counters
),它使 CSS
代码上下文-上述意义上的敏感(例如变量需要在使用前定义)。所以下面的 css
代码将被浏览器解析(并被忽略,因为它无效)但它不能用 CFG
body { }
h3::before {
counter-increment: section; /* no counter section has been defined, not valid css code */
content: "Section" counter(section) ": "; /* Display the counter */
}
[/更新]
我很确定 JS 不是 上下文无关的 — 给定任意代码人工制品,在不知道其上下文的情况下不一定能确定其确切含义。
第一个想到的例子是{}
——这代表一个空的对象字面量还是一个空的语句块?没有上下文是不可能决定的,但是因为该语言允许从以 '}' 结尾的语句中省略分号(就像大多数具有类似 C 语法的语言一样)它也可能是不可决定的 with语境!考虑 {x: {}}
——这可能是一个对象字面量,其 "x" 字段包含一个空对象,或者是一个带有标签子语句的语句块(其中标签是 'x' 和子-语句是 {}
)。也许语言规范有一些规则可以在这种情况下选择正确的解释,但无论如何,仅通过这些示例来判断,语言似乎并不是上下文无关的。
JavaScript的'automatic semicolon insertion'特征当然不能帮助区分表达式和语句。
还有一个要考虑的问题:function x() {}
— 这有什么作用?如果它是一条语句,它会声明一个新的提升变量 'x' 并将此函数作为其值。如果它是一个表达式,它只是计算一个函数,该函数的上值 'x' 绑定到同一函数(用于自引用)。
不,JavaScript 不是上下文无关语言。
非常接近一,ECMAScript 5 规范确实做到了use a context-free grammar1 to describe the language's syntax (you can find all productions in Annex A)。
当然,它确实对纯上下文无关语法产生式做了一些扩展,并描述了解析器的额外行为。一个特别的事情是 lookahead 的使用,它仍然是一种上下文无关的语言,但如果它不能用于某些规则,会使语法复杂化很多。不允许某些东西出现在严格模式代码中是类似的——它可以通过调整语法来完成(有更多的产品),但是通过离开 BNF 更容易表达规则。
但是,也有一些2 规则确实使语言不是上下文无关的。您会在 description of early errors 中找到一个概述,它可以使程序代码无效。对象字面量不能包含重复的 属性 名称,函数参数列表不能包含重复的标识符,这两个规则不能使用(有限的)上下文无关语法来表达。
我的直觉告诉我 the automatic semicolon insertion 属于同一个盒子,但我认为它的规则太复杂了,甚至无法在这里尝试证明。
1:实际上它使用两个语法,一个 lexical and a syntactical 一个,其中第一个消除除法表达式和正则表达式之间的歧义,并产生作为第二个语法输入的标记.
2:与其他编程语言相比,实际上相当少