5.1 句法和词法文法

5.1.1 上下文无关的文法

一个上下文无关文法是由一定数量的产生式组成的。每个产生式的左边都有一个称为非终结符的抽象符号。右边(right-hand side) 是零或多个非终结符和终结符(terminal symbols)的有序排列。任何文法,它的终结符都来自指定的字母集。

一个链式产生式是那种右边只有一个非终结符和0个或多个终结符的产生式

当从一个叫做 目标符 (goal symbol) 的特殊非终端符组成的句子起始,那么给出的上下文无关文法就表示 语言 (language),即,将产生式右边序列的非终结符当作左边,进行反复替换的结果就成为可能的终结符序列集合(可能无限)。

5.1.2 词法和正则的文法

第11章中给出了ECMAScript的词法文法。这个文法的终结符是Unicode代码单元,其符合10.1中规定的源代码规则。它定义了一序列的产生式,从目标符InputElementDiv,InputElementTemplateTail,InputElementRegExp,或者InputElementRegExpOrTemplateTail开始,描述了如何将代码单元序列转译为输入元素序列。

空白和注释之外的输入元素构成 ECMAScript 语法文法的终结符,它们被称为 ECMAScript 的 tokens。这些 tokens 是ECMAScript 语言中的保留字,标识符,字面量,标点符号。此外,行结束符虽然不被视为 tokens,但会成为输入元素流的一部分,用于指导处理自动插入分号机制(11.9)。空白和单行注释会被丢弃,不会出现在语法文法的输入元素流中。如果一个 多行注释 (MultiLineComment)(即形式为“/ … /”的注释,不管是否跨越多行)不包含行结束符也会简单地丢弃,但如果一个 多行注释 包含一个或多个结束符,那么,注释会被替换为一个行结束符,成为语法文法输入元素流的一部分。

21.2.1给出了 ECMAScript 的 正则文法 (RegExp grammar)。此文法的终结符字符也由 SourceCharacter 定义。它定义了一套产生式,从目标符 Pattern 起始,描述了如何将这样的字符序列翻译成一个正则表达式模式。

两个冒号“::”作为分隔符分割词法和正则的文法产生式。词法和正则的文法共享某些产生式。

5.1.3 数字字符串文法

另一个将字符串转换为数字值的一种文法,此文法与词法文法的一部分(和数字字面量相关的)类似,并且有终结符 SourceCharacter。此文法出现在 7.1.3.1 。

三个冒号“:::”作为分隔符分割数字字符串文法的产生式。

5.1.4 语法文法

第11、12、13、14、15章给出了ECMAScript语法文法的定义,这个文法把词法文法定义的ECMAScript tokens作为其终结符。其定义了一组产生式,从Script或者Module这两个目标符号开始。其描述了怎样的token序列才是语法正确的,从而组成ECMAScript程序。

当一个字符流被解析为 ECMAScript 的Script或者Module,它首先会反复应用词法文法将其转换为一个输入元素流;然后再应用语法文法解析这个输入元素流为单应用。当输入元素流没有更多 tokens 时,如果 tokens 不能解析为单实例的目标非终结符(Script或者Module)的单一实例,那么意味着程序在语法上存在错误。

只用一个冒号“:”作为分隔符分割语法词法的产生式。

事实上第 11、12、13 、14、15 章给出的语法语法,并不能完全说明一个正确的 ECMAScript 程序能接受的 token 序列。一些额外的 token 序列也能被接受,即某些特殊位置(如行结束符前)加入分号可以被文法接受。此外,文法描述的某些 token 序列也可能不被文法接受,如一个行结束符出现在“尴尬”的位置。

在某些情况下,为了避免出现歧义,语法文法使用广义产生式允许token序列不构成一个有效的ECMAScript Script或者Module。比如,这个技术运用在对象字面量和对象解构赋值模式中,在这种情况下会有一个更严格的补充语法,从而更严格的限制可接受的token序列。在某些上下文中,当明确的定义了这个产生式的输入元素,会再次被补充语法的目标符号解析。当输入流中没有剩余token,并且其token不能被文法解析为相应的补充文法目标符号单例时,说明输入流中有语法错误。

5.1.6 文法标记

词法文法、正则表达式文法、数字字符串文法无论是在文法的产生式还是贯穿本规范的所有文本直接给出的终结符,都用 等宽 (fixed width) 字体显示。他们表示程序书写正确。所有以这种方式指定的终结符字符,可以理解为 Unicode 字符的完整的 ASCII 范围,不是任何其他类似的 Unicode 范围字符。

非终结符以 斜体 (italic) 显示。一个非终结符的定义由非终结符名称和其后定义的一个或多个冒号给出。(冒号的数量表示产生式所属的文法。)非终结符的右侧有一个或多个可选项紧跟在下一行。 例如,语法定义:

  1. WhileStatement:
  2. while (Expression) Statement

这个表示这个非终结符 WhileStatement 代表 while token,其后跟左括号 token,其后跟 Expression,其后跟右括号 token,其后跟 Statement。这里出现的 Expression 和 Statement 本身是非终结符。另一个例子,语法定义:

  1. ArgumentList:
  2. AssignmentExpression
  3. ArgumentList, AssignmentExpression

这个表示这个 ArgumentList 可以代表一个 AssignmentExpression,或 ArgumentList,其后跟一个逗号,其后跟一个 AssignmentExpression。这个 ArgumentList 的定义是递归的,也就是说,它定义它自身。其结果是,一个 ArgumentList 可能包含用逗号隔开的任意正数个参数,每个参数表达式是一个 AssignmentExpression。这样,非终结符共用了递归的定义。

终结符或非终结符可能会出现后缀下标“ opt ”,表示它是可选符号。实际上包含可选符号的可选项包含两种情况的右边,一个是省略可选元素的,另一个是包含可选元素的。这意味着:

  1. VariableDeclaration:
  2. BindingIdentifier Initializer opt

这个可以被翻译为

  1. VariableDeclaration:
  2. BindingIdentifier
  3. BindingIdentifier Initializer

还有这样:

  1. IterationStatement :
  2. for ( LexicalDeclaration Expression opt; Expression opt ) Statement

是以下的一种缩写:

  1. IterationStatement :
  2. for ( LexicalDeclaration ; Expression opt ) Statement
  3. for ( LexicalDeclaration ; Expression Expression opt ) Statement

是以下的一种缩写 :

  1. IterationStatement:
  2. for ( LexicalDeclaration ;) Statement
  3. for ( LexicalDeclaration ; Expression ) Statement
  4. for ( LexicalDeclaration Expression ; ) Statement
  5. for ( LexicalDeclaration Expression ; Expression ) Statement

所以在这个例子中,非终结符 IterationStatement 事实上有4种可选项在右侧。

一个产生式可能会以”[parameters]“这样的下标形式参数化,这意味着这个产生式的非终结符会有一个后缀。‘parameteters’可能是单个单词,或者以逗号分隔的多个单词。一个参数化的产生式是一序列产生式参数合并后的的简写,会有一个下划线在参数之前来表示参数化的产生式。如下所示:

  1. StatementList[Return]:
  2. ReturnStatement
  3. ExpressionStatement

是如下的简写:

  1. StatementList:
  2. ReturnStatement
  3. ExpressionStatement
  4. StatementList_Return:
  5. ReturnStatement
  6. ExpressionStatement

还有这样:

  1. StatementList[Return, In]:
  2. ReturnStatement
  3. ExpressionStatement

是以下的简写:

  1. StatementList:
  2. ReturnStatement
  3. ExpressionStatement
  4. StatementList_Return:
  5. ReturnStatement
  6. ExpressionStatement
  7. StatementList_In:
  8. ReturnStatement
  9. ExpressionStatement
  10. StatementList_Return_In:
  11. ReturnStatement
  12. ExpressionStatement

多个参数可以组合成多个产生式,在一个完整的文法中,并不是所有参数都会被使用。产生式的右侧的非终结符也可以被参数化,比如:

  1. StatementList:
  2. ReturnStatement
  3. ExpressionStatement[In]

这等同于说:

  1. StatementList:
  2. ReturnStatement
  3. ExpressionStatement_In

一个非终结符可能同时有参数列表和‘opt’,比如:

  1. VariableDeclaration:
  2. BindingIdentifierInitializer[In] opt

是如下的简写

  1. VariableDeclaration:
  2. BindingIdentifier
  3. BindingIdentifierInitializer_In

产生式右侧的非终结符参数名前有一个‘?’前缀时,意味着其参数的出现取决于产生式左侧的非终结符的参数是否出现。比如:

  1. VariableDeclaration[In]:
  2. BindingIdentifierInitializer[?In]

是如下的简写

  1. VariableDeclaration:
  2. BindingIdentifierInitializer
  3. VariableDeclaration_In:
  4. BindingIdentifierInitializer_In

如果右侧的可选项有[+parameter]前缀,意味着右侧的参数可选项只有在产生式的左侧已经使用了参数的情况下才会使用。如果右侧的可选项有[~parameter]前缀,意味着右侧的参数可选项只有在产生式的左侧没有使用参数的情况下才会使用。这意味着下面这样:

  1. StatementList[Return]:
  2. [+Return]ReturnStatement
  3. ExpressionStatement

是如下的简写:

  1. StatementList:
  2. ExpressionStatement
  3. StatementList_Return:
  4. ReturnStatement
  5. ExpressionStatement

还有

  1. StatementList[Return]:
  2. [~Return]ReturnStatement
  3. ExpressionStatement

是如下的简写:

  1. StatementList:
  2. ReturnStatement
  3. ExpressionStatement
  4. StatementList_Return:
  5. ExpressionStatement

当词‘one of’在冒号后面出现时,这意味着,接下来的每个终结符都是可选项。比如:

  1. NonZeroDigit::one of
  2. 1 2 3 4 5 6 7 8 9

是如下的简写:

  1. NonZeroDigit::
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9

如果产生式的右侧是出现“[empty]”,它表明,产生式的右侧不包含终结符或非终结符。

如果产生式的右侧出现“[lookahead ∉ set]”,它表明,给定 set 的成员不得成为产生式紧随其后的 token。这个 set 可以写成一个大括号括起来的终结符列表。为方便起见,set 也可以写成一个非终结符,在这种情况下,它代表了这个非终结符 set 可扩展所有终结符。例如,给出定义

  1. DecimalDigit::one of
  2. 0 1 2 3 4 5 6 7 8 9
  3. DecimalDigits::
  4. DecimalDigit
  5. DecimalDigits DecimalDigit
  6. LookaheadExample::
  7. n [lookahead { 1, 3, 5, 7, 9 }] DecimalDigits
  8. DecimalDigit[lookahead DecimalDigit]

能匹配字母 n 后跟随由偶数起始的一个或多个十进制数字,或一个十进制数字后面跟随一个非十进制数字。

如果产生式的右侧出现“[no LineTerminator here]”,那么它表示此产生式是个受限的产生式:如果 行终结符 在输入流的指定位置出现,那么此产生式将不会被适用。例如,产生式:

  1. ThrowStatement:
  2. throw [no LineTerminator here] Expression;

这就指出,如果在throw 和expression中间出现行终结符的话将不能使用这个产生式。
LineTerminator 除了禁止出现在受限的产生式,可以在输入元素流的任何两个 tokens 之间出现任意次数,而不会影响程序的语法验证。

当一个词法文法产生式或数字字符串文法中出现多字符 token,它表示此字符序列将注册一个 token。

使用词组“but not“可以指定某些不允许在产生式右侧的扩展,它说明排除这个扩展。例如,产生式:

  1. Identifier::
  2. IdentifierNamebut not ReservedWord

此非终结符 Identifier 可以由可替换成 IdentifierName 的字符序列替换,相同的字符序列不能替换 ReservedWord。

最后,对于实际上不可能列出全部可变元的少量非终结符,我们用普通字体写出描述性的短语来描述它们:

  1. SourceCharacter::
  2. any Unicode code point