一个上下文无关文法由一定数量的产生式组成。每个产生式的左边部分 是一个被称为非终结符的抽象符号,右边部分是零或多个非终结符和终结符的有序排列。任何文法,它的终结符都来自指定的字母集。
当从一个叫做目标符的特殊非终结符组成的句子起始,那么给出的上下文无关文法就表示语言,即:将产生式右边序列的非终结符当作左边,进行反复替换的结果就成为可能的终结符序列集合(可能无限)。
第7章给出了 ECMAScript 的词法。此文法的终结符字符(Unicode 代码单元)符合第6章定义的 SourceCharacter 的规则。它定义了一套产生式,从目标符 InputElementDiv 或 InputElementRegExp 起始,描述了如何将这样的字符序列转换成一个输入元素序列。
空白字符和注释之外的输入元素构成 ECMAScript 句法的终结符,它们被称为 ECMAScript 的 Token。这些 Token 是,ECMAScript 语言的保留字、标识符、字面量、标点符号。此外,行终止符虽然不被视为 Token,但会成为输入元素流的一部分,用于引导处理 自动插入分号。空白字符和单行注释会被简单地丢弃,不会出现在句法的输入元素流中。如果一个多行注释(即形式为“/*...*/”的注释,不管是否跨越多行)不包含行终止符也会简单地丢弃,但如果一个多行注释包含一个或多个行终止符,那么,注释会被替换为一个行终止符,成为句法的输入元素流的一部分。
15.10 给出了 ECMAScript 的 正则文法。此文法的终结符也由 SourceCharacter 定义。它定义了一套产生式,从目标符 Pattern 起始,描述了如何将这样的字符序列翻译成一个正则表达式模式。
两个冒号“::”作为分隔符分割词法和正则的文法产生式。词法和正则的文法共享某些产生式。
用于将字符串转换为数字值的另一种文法。此文法与词法的一部分类似,都与数字字面量有关,并且它有作为终结符的SourceCharacter。此文法出现在 9.3.1 。
三个冒号“:::”作为分隔符分割数字字符串文法的产生式。
第 11、12、13、14 章给出了 ECMAScript 的句法。词法定义的 ECMAScript Token 是此文法的终结符(5.1.2)。它定义了一组起始于 Program 目标符的产生式,描述了怎样的 Token 序列才能形成句法上正确的 ECMAScript 程序。
当一个字符流被解析为 ECMAScript 程序时,它首先通过词法应用程序反复转换为一个输入元素流;然后再用一个句法应用程序解析这个输入元素流。当输入元素流没有更多 Token 时,如果 Token 不能解析为 Program 目标非终结符的单一实例,那么程序在句法上存在错误。
只用一个冒号“:”作为分隔符分割句法的产生式。
事实上第 11、12、13、14 章给出的句法,并不能完全说明一个正确的 ECMAScript 程序能接受的 Token 序列。一些额外的 Token 序列也被接受,即某些特殊位置(如行结束符前)加入分号可以被文法接受。此外,文法描述的某些 Token 序列不被文法接受,如一个行结束符出现在了“尴尬”的位置。
JSON 文法用于描述 ECMAScript 对象的字符串转换为实际的对象。15.12.1 给出了 JSON 文法 。
JSON 文法由 JSON 词法和 JSON 句法组成。JSON 词法用于将字符序列转换为 Token,类似 ECMAScript 词法。JSON 句法说明 JSON 词法给出怎样的 Token 序列才能转换为句法上是正确的 JSON 对象。
两个冒号“::”作为分隔符分割 JSON 词法的产生式。JSON 词法使用某些 ECMAScript 词法的产生式。JSON 句法与 ECMAScript 句法类似。JSON 句法产生式被一个冒号“:”作为分隔符分割。
词法、正则表达式文法、字符串数字文法,以及一些其它文法,每当这些文法的终结符被文本直接涉及到时,使用等宽字符来显示,它们都在文法产生式 中,并且贯穿这份文档。他们表示程序书写正确。所有以这种方式指定的终结符,都可以理解为 Unicode 字符的完整的 ASCII 范围,不是任何其他乌焉成马的 Unicode 范围字符。
非终结符以斜体显示。一个非终结符的定义由非终结符名称和其后定义的一个或多个冒号给出。(冒号的数量表示产生式所属的文法。)非终结符的右侧有一个或多个替代子紧跟在下一行。 例如,句法定义:
'''''WhileStatement''''' : '''while (''' ''Expression'' ''')''' ''Statement''
表示这个非终结符 WhileStatement 代表 while Token,其后跟左括号 Token,其后跟 Expression,其后跟右括号 Token,其后跟 Statement。这里出现的 Expression 和 Statement 本身是非终结符。另一个例子,句法定义:
'''''ArgumentList''''' : ''AssignmentExpression'' ''ArgumentList'' ''',''' ''AssignmentExpression''
表示这个 ArgumentList 可以代表一个 AssignmentExpression,或 ArgumentList,其后跟一个逗号,其后跟一个 AssignmentExpression。这个 ArgumentList 的定义是递归的,也就是说,它定义它自身。其结果是,一个 ArgumentList 可能包含用逗号隔开的任意正数个参数,每个参数表达式是一个 AssignmentExpression。这样,非终结符共用了递归的定义。
终结符或非终结符可能会出现后缀下标 “opt”,表示它是可选符号。实际上包含可选符号的替代子包含两个右边部分,一个是省略可选元素的,另一个是包含可选元素的。这意味着:
'''''VariableDeclaration''''' : ''Identifier'' ''Initialiser''<sub>opt</sub>
是以下的一种缩写:
'''''VariableDeclaration''''' : ''Identifier'' ''Identifier'' ''Initialiser''
并且:
'''''IterationStatement''''' : '''for''' '''(''' ''ExpressionNoIn''<sub>opt</sub> ''';''' ''Expression''<sub>opt</sub> ''';''' ''Expression''<sub>opt</sub> ''')''' ''Statement''
是以下的一种缩写:
'''''IterationStatement''''' : '''for''' '''(''' ''';''' ''Expression''<sub>opt</sub> ''';''' ''Expression''<sub>opt</sub> ''')''' ''Statement'' '''for''' '''(''' ''ExpressionNoIn'' ''';''' ''Expression''<sub>opt</sub> ''';''' ''Expression''<sub>opt</sub> ''')''' ''Statement''
是以下的一种缩写 :
'''''IterationStatement''''' : '''for''' '''(''' ''';''' ''';''' ''Expression''<sub>opt</sub> ''')''' ''Statement'' '''for''' '''(''' ''';''' ''Expression'' ''';''' ''Expression''<sub>opt</sub>''')''' ''Statement'' '''for''' '''(''' ''ExpressionNoIn'' ''';''' ''';''' ''Expression''<sub>opt</sub>''')''' ''Statement'' '''for''' '''(''' ''ExpressionNoIn'' ''';''' ''Expression'' ''';''' ''Expression''<sub>opt</sub>''')''' ''Statement''
是以下的一种缩写:
'''''IterationStatement''''' : '''for''' '''(''' ''';''' ''';''' ''')''' ''Statement'' '''for''' '''(''' ''';''' ''';''' ''Expression'' ''')''' ''Statement'' '''for''' '''(''' ''';''' ''Expression'' ''';''' ''')''' ''Statement'' '''for''' '''(''' ''';''' ''Expression'' ''';''' ''Expression'' ''')''' ''Statement'' '''for''' '''(''' ''ExpressionNoIn'' ''';''' ''';''' ''')''' ''Statement'' '''for''' '''(''' ''ExpressionNoIn'' ''';''' ''';''' ''Expression'' ''')''' ''Statement'' '''for''' '''(''' ''ExpressionNoIn'' ''';''' ''Expression'' ''';''' ''')''' ''Statement'' '''for''' '''(''' ''ExpressionNoIn'' ''';''' ''Expression'' ''';''' ''Expression'' ''')''' ''Statement''
因此,非终结 IterationStatement 实际上有 8 个右侧替代子。
如果文法定义的冒号后面出现文字 “one of”,那么其后一行或多行出现的每个终结符都是一个选择定义。例如,ECMAScript 包含的词法生产器:
'''''NonZeroDigit''''' :: '''one of''' '''1 2 3 4 5 6 7 8 9'''
这仅仅下面写法的一种缩写:
'''''NonZeroDigit''''' :: '''1''' '''2''' '''3''' '''4''' '''5''' '''6''' '''7''' '''8''' '''9'''
如果产生式的右侧是出现 “[empty]”,它表明,生产器的右侧不包含终结符或非终结符。
如果产生式的右侧出现 “[lookahead]”,它表明,给定 <var>set</var> 的成员不得成为产生式紧随其后的 Token。这个 <var>set</var> 可以写成一个大括号括起来的终结符列表。为方便起见,<var>set</var> 也可以写成一个非终结符,在这种情况下,它代表了这个非终结符 <var>set</var> 可扩展所有终结符。例如,给出定义
'''''DecimalDigit''''' :: '''one of''' '''0 1 2 3 4 5 6 7 8 9'''
'''''DecimalDigits''''' :: ''DecimalDigit'' ''DecimalDigits'' ''DecimalDigit''
再定义
'''''LookaheadExample''''' :: '''n''' [lookahead ? {'''1''' , '''3''' , '''5''' , '''7''' , '''9'''}] ''DecimalDigits'' ''DecimalDigit'' [lookahead ? ''DecimalDigit'']
匹配,字母 n 后跟随由偶数起始的一个或多个十进制数字,或一个十进制数字后面跟随一个非十进制数字。
如果产生式的右侧出现 “[no]”,那么它表示此产生式是个受限的产生式:如果 LineTerminator 在输入流的指定位置出现,那么此产生式将不会被适用。例如,产生式:
'''''ThrowStatement''''' : '''throw''' ''[no [[ES5/lexical#LineTerminator|LineTerminator]] here]'' ''Expression'' ''';'''
表示如果程序中 throw Token 和 Expression 之间的出现 LineTerminator,那么不得使用此产生式。
LineTerminator 除了禁止出现在受限的产生式,可以在输入元素流的任何两个 Token 之间出现任意次数,而不会影响程序的句法验证。
当一个词法产生式或数字字符串文法中出现多字符 Token,它表示此字符序列将注册一个 Token。
使用词组 “but not” 可以指定某些不允许在产生式右侧的扩展,它说明排除这个扩展。例如,产生式:
'''''Identifier''''' :: ''IdentifierName'' '''but not''' ''ReservedWord''
此非终结符 Identifier 可以由可替换成 IdentifierName 的字符序列替换,相同的字符序列不能替换 ReservedWord。
最后,对于实际上不可能列出全部可变元的少量非终结符,我们用普通字体写出描述性的短语来描述它们:
'''''SourceCharacter''''' :: any Unicode code unit
此规范通常使用带编号的列表来指定算法的步骤。这些算法是用来精确地指定 ECMAScript 语言结构所需的语义。该算法无意暗示任何具体实现使用的技术。在实践中,也许可用更有效的算法实现一个给定功能。
为了方便其使用本规范的多个部分,叫做抽象操作的一些算法编写成带名称的可传参函数化形式,所以在其他算法里可以通过名称引用它们。
当一个算法产生返回值 ,“返回 <var>x</var>” 指令说明该算法的返回值是 <var>x</var>,并且算法应该终止。“第 <var>n</var> 步的结果” 的简写是 Result(<var>n</var>) 。
为了表达清晰,算法的步骤可细分为有序的子步骤。子步骤被缩进,可以将自身进一步划分为缩进子步骤。大纲编号约定用于识别分步骤,第一层次的子步骤适用小写字母标记,第二层次的子步骤使用小写罗马数字标记。如果需要超过三个层次,则重复这些规则,第四层次使用数字标记。
例如 :
- Top-level step
- Substep.
- Substep
- Subsubstep.
- Subsubstep.
- Subsubsubstep
- Subsubsubsubstep
- Subsubsubstep
一个步骤可以表示其子步骤的迭代应用可能指定其子步的迭代应用程序。
数学运算,如加法、减法、取反、乘法、除法,以及稍后在本节中定义的数学函数,他们应该总是被理解为对数学实数计算精确的数学结果,其中不包括无穷大,不包括负零区别于正零。本标准中的浮点运算算法模型,包括明确的步骤,在必要情况下处理无穷大和有符号零和执行四舍五入。如果一个数学运算或函数应用一个浮点数,它应该被应用为代表此浮点数的确切的数学值,一个浮点数必须是有限的 ,如果是 +0 或 -0 ,则相应的数学值就是 0。
数学函数 abs(<var>x</var>) 产生 <var>x</var> 的绝对值,如果 <var>x</var> 是负数(小于零),它是这是 -<var>x</var>,否则是 <var>x</var> 本身。
如果 <var>x</var> 是正数,数学函数 sign(<var>x</var>) 产生 1,如果 <var>x</var> 是负数产生 -1。此标准中 <var>x</var> 为零的情况下不使用 sign 函数。
符号 “<var>x</var> modulo <var>y</var>”(<var>y</var> 必须有限且非零)计算一个满足以下条件的 <var>k</var> 值 ,与 <var>y</var> 同号 ( 或是零 ) ,abs(<var>k</var>) < abs(<var>y</var>) ,对一些整数 <var>q</var> 满足 <var>x</var>-<var>k</var> = <var>k</var>×<var>k</var>。
数学函数 floor(<var>x</var>) 产生不大于 <var>x</var> 的最大整数(最大可为正无穷)。
如果算法定义“抛出一个异常”,算法的执行将被终止,且没有返回结果。已调用的算法也被终止,直到算法步骤使用术语“如果一个异常被抛出 ...”明确指出异常处理。一旦遇到这种算法步骤,异常将不再被视已发生过。