ECMAScript程序的源代码,首先会被分转化为一系列的输入元素(input elements),包括:标记或记号(tokens), 行终结符(line terminators), 注释(comments),或空白(white space).
词法文法(lexical grammar)有两个目标符号(goal symbols).
.其中除法的输入元素符(The InputElementDiv symbol),是在那些,允许使用(/)符号,或(/=)符号的,语法文法(syntactic grammar contexts)上下文中使用的.
.输入元素正则表达式符(InputElementRegExp symbol),则是在其它语法文法上下文中使用的.
Note : Edition3
需要注意的是,语法文法上下文中,同时出现(/)符号和正则表达式直接量( 如/\d/).且都被语法文法所允许的情况. 当除法输入元素这一目标符号,存在于此种情况下时,则斜杠符号(/),不能被当做该上下文中,一个正则表达式直接量的起始位置. 那么作为变通的办法.可以把真正的正则表达式直接量用括号括起来.
Note : Edition5
同时允许除号(/)或除等于(/=),和正则表达式符号(/),存在的语法文法上下文.是不存在的.
下面的例子中,也不受自动分号补全机制所影响 : (所谓不受影响就是指,此类情况不发生自动分号补全)
a = b
/hi/g.exec(c)/map(d);
当一个行终结符后面是一个斜杠(/)(包括空白符或注释后面紧跟的是/的情况.),并且其所在语法上下文中,允许除号(/)或 除等于号(/=)时,不会发生分号自动补全.所以上面与下面的代码是等价的:
a = b/hi/ g.exec(c).map(d); // 抛出异常...
语法 :
InputElementDiv ::
WhiteSpace
LineTerminator
Comment
Token
DivPunctuator
InputElementRegExp ::
WhiteSpace
LineTerminator
Comment
Token
RegularExpressionLiteral
空白(WhiteSpace)
空白符,可以提高源代码的可读性,以及分割项链的的两个标记(token,即不可分割的,文法单位).除此之外,没有其他别的作用了. 空白符,可以存在于两个标记(token)之间.也可以存在于一个字符串直接量内部.这时候空白符,仅仅当做字符串的一部分. 但是空白符永远不能出现在任何一种标记(token)内部.
uncode编码 |
空白符名称 |
正式名称 |
转意表示 |
\u0009 |
Tab(制表符) |
<TAB> |
\t |
\u000B |
Vertical Tab(垂直制表符) |
<VT> |
\v |
\u000C |
Form Feed(换页符,打印用.) |
<FF> |
\f |
\u0020 |
Space(空格) |
<SP> |
不知道... |
\u00A0 |
No-break space(无间断空格) |
<NBSP> |
不知道... |
其他种类"Zs". |
任何其他 Unicode空白分隔符. |
<USP> |
\s 正则表示 |
语法:
<TAB>
<VT>
<FF>
<SP>
<NBSP>
<USP>
行终结符(Line Terminators)
和空白符类似,行终结符也是用于提高可读性,和分割两个标记(token,即不可分割的文法单位). 和空白符不同的是,行终结符,会对语法文法(syntactic grammar)的行为有影响. 一般来说,行终结符,可以出现在两个标记(token)之间.但是在某些地方.行终结符,被语法文法所禁用. 一个行终结符,也不能出现在任何一种记号(token) 内部.甚至连一个字符串内也不允许出现.行符,还会影响分号自动插入(补全)的过程.
行终结符表:
uncode编码 |
终结符名称 |
正式名称 |
转义表示 |
\u000A |
Line Feed(换行符) |
<LF> |
\n |
\u000D |
Carriage Return(回车符) |
<CR> |
\r |
\u2028 |
Line separator(行分隔符) |
<LS> |
不知道... |
\u2029 |
Paragraph separator(段落分隔符) |
<PS> |
不知道... |
语法:
<LF>
<CR>
<LS>
<PS>
注释(Comments)
注释分单行和多行两种.多行注释不允许嵌套.因为单行注释,可以包含除行终结符外的任何字符. 还有一个原因是标记(token)都是尽可能长的.
一个单行注释总是包含所有从 //开始一直到行尾的所有字符. 不过从词法文法上看,行尾的行终结符,不应该被认为是单行注释的一部分.而从语法文法上来说,亦是如此.且行终结符,因被看做是输入元素流的一部分.这一点是非常重要的,因为这意味着,有没有单行注释.都不会影响 分号自动插入(补全)的过程.
注释的行为总是像空白符那样被忽略或抛弃.仅当一个多行注释内部包含一个行终结符.时,才会在语法文法上当成一个 行符来对待.
语法
Comment::
MultiLineComment(多行注释)
SingleLineComment(单行注释)
MultiLineComment ::
/* MultiLineCommentChars-opt (多行注释字符,opt下标即本项存在性是可选的.即可有可无的) */
MultiLineCommentChars ::
MultiLineNotAsteriskChar(多行,非星号"*"字符) MultiLineCommentChars-opt(可选多行字符)
* PostAsteriskCommentChars-opt(可选星号字符)
PostAsteriskCommentChars(星号字符) ::
MultiLineNotForwardSlashOrAsteriskChar(多行非斜线(/)、非星号字符) MultiLineCommentChars-opt(可选多行字符)
* PostAsteriskCommentChars-opt(可选星号字符)
MultiLineNotAsteriskChar (多行非星号字符)::
SourceCharacter but not asterisk * (不包括 星号 "*"的字符)
MultiLineNotForwardSlashOrAsteriskChar(多行非斜杠和星号的字符) ::
SourceCharacter but not forward-slash / or asterisk * (不包括斜杠"/"和星号"*"的字符)
(个人觉得都是废话,总结起来一句话/* 此注释部分,不允许出现"*/".... */ )
SingleLineComment ::
// SingleLineCommentChars-opt (单行注释字符-可选)
SingleLineCommentChars ::
SingleLineCommentChar SingleLineCommentChars-opt
SingleLineCommentChar ::
SourceCharacter but not LineTerminator
(好吧甭废话,总结起来就一句. // 单行注释部分,不能包含换行符.)
标记 ,语言符号(Tokens)
语法
标记(Token)::
ReservedWord(保留字)(Edition 5中,保留字并没有算做Token大项的一种,而是算作一种标识符了.....定义:保留字是不能像标识符那样使用的一个标识符名.)
Identifier(标识符) (IdentifierName ES5改变, 与Identifier的区别是,IdentifierName允许保留字出现)
Punctuator(标点符号)
NumericLiteral(数字直接量)
StringLiteral(字符串直接量)
保留字(ReservedWord):
解释 : 那些不能当做标识符来使用的词汇(标识符名).
ReservedWord::
Keyword(关键字)
FutureReservedWord(预保留字)
NullLiteral (null直接量) (null)
BooleanLiteral(Boolean直接量) (true,false)
(权威指南第四版中,把null, true,false 归结为关键字.但准确来说.仅应属于保留字.当然关键字是保留字的子集.)
Keywords(关键字):
下列标记(tokens) 即就是ECMAScript-edition 3的25个关键字.以及edtion5 额外追加的 debugger 关键字.共26个关键字.
break else new var case finally return void catch for switch while continue function this with default if throw delete in try do instanceof typeof [debugger]
Future Reserved Words(预保留字):
预保留字是,用作将来的扩展而预留的.也作为关键字使用的一些单词.
下列单词为edtion 3的 31个预保留字:
abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws const goto private
transient debugger implements protected volatile double import public
下列单词为edition5的 7个预保留字:
class enum extends super const export import
下列标记(tokens)为edition5中 严格模式下,任何上下文中不允许出现的9个预保留字,一但出现,必须抛出异常:
implements let private public yield interface package protected static
标识符(Identifiers)
解释 :
标识符定义,是在5.16章节所描述的,即将发布的 Unicode 3.0标准(注1)所给出的文法,基础上做了少部分修改而成. 此文法同时基于文法约定和 Unicode标准所定义的字符类信息规范.
而之前的Unicode2.1标准所定义的字符类信息也必须,在遵守ECMAScript实现的语言中,也被视为符合当前字符类信息规范的.
然而基于今后发布的Unicode标准,而附加的标识符也应该被依照ECMASCript实现的语言所承认.
本标准在,违背Unicode标准所给出文法的前提下定义有, 美元符号($)和下划线(_),可以存在于一个标志符的任何位置.其中美元符号,应该只出现在机器生成的代码中.(注2)
标识符中允许出现,Unicode转义序列(会被转意为一个字符的)(注3).转换方式参见 7.8.4章节的关于Unicode转义序列的CV(character values)转换算法部分.
在一个Unicode转义序列(UnicodeEscapeSequence)(注4)前面出现的斜杠(\),不会被当做一个字符处理.
而一个Unicode转义序列,转意后的结果,对于标识符是非法的.那么 "\Unicode" 也是非法的.(注5)
按照Unicode标准相同的两个标识符是不等价的
(注6),除非它们是通过完完全全相同的一系列code points
(注7)表示的(换句话说,ECMA实现只需要在标识符上做按位比较),这意味着传入的源代码在到达编译器之前,已经转换成了规范C格式
(注8)
语法:
IdentifierName
but not ReservedWord
IdentifierStart
IdentifierName IdentifierPart
IdentifierStart:: (标识符起始位置,即一个标识符职能用一下4种字符作为标识符的第一个字符.)
Unicode Letter
$
_
\ UnicodeEscapeSequence (即\ + Unicode转意序列,如\u0001)
IdentifierPart::
IdentifierStart
UnicodeCombiningMark
UnicodeDigit
UnicodeConnectorPunctuation
\ UnicodeEscapeSequence
UnicodeLetter (Unicode文字)
Titlecase letter (首字母大写字母、标题字母)
Modifier letter (修饰符字母)(注9)
Other letter (其他字母.如中国汉字...)
UnicodeCombiningMark (Unicode合并记号) (注11) 所有被称作 Non-spacing mark 或 Combining spacing mark的字符.
UnicodeDigit (就是常说的数字啦) Unicode被定义为普通十进制数字的那些字符.
UnicodeEscapeSequence (见 7.8.4章节关于 Unicode转意序列的描述.) (注12)
u
HexDigit ::
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
Punctuator(标点符号) :: one of
{ |
} |
( |
) |
[ |
] |
. |
; |
, |
< |
> |
<= |
>= |
== |
!= |
=== |
!== |
|
+ |
- |
* |
% |
++ |
-- |
<< |
>> |
>>> |
& |
| |
^ |
! |
~ |
&& |
|| |
? |
: |
= |
+= |
-= |
*= |
%= |
<<= |
>>= |
>>>= |
&= |
|= |
^= |
|
DivPunctuator(除法符号) :: one of
/ /=
(所以单独拿出来,请参考词法约定中,关于词法文法中两种目标符号(goal symbols)部分的说明.)
直接量(Literals)
语法
Literal ::
NullLiteral (null 直接量)- null
BooleanLiteral (布尔直接量)- true,false
NumericLiteral (数字直接量)
StringLiteral (字符串直接量)
RegularExpressionLiteral (正则表达式直接量) (Edition 5才放到此处)
语法
NumericLiteral ::
DecimaLiteral (十进制直接量)
HexIntegerLiteral (十六进制整数直接量)
DecimalLiteral ::
DecimalIntegerLiteral(十进制整数直接量) .DecimalDigits-opt(可选十进制数字) ExponentPart-opt(可选指数部分) (注13)
.DecimalDigits(十进制数字) ExponentPart-opt(可选指数部分) (注14)
DecimalIntegerLiteral(十进制整数直接量) ExponentPart-opt(可选指数部分) (注15)
0 - 0
NonZeroDigit(单个非零数字) DecimalDigits-opt(多个可选数字) - 1,10,123 etc...
DecimalDigits(十进制数字,视情况也可视为,十进制小数.) ::
DecimalDigit(单个十进制数字)
DecimalDigits(多个十进制数字) DecimalDigit(单个十进制数字) (我靠,这类式子好纠结.)
DecimalDigit(单个十进制数字) :: one of
0 1 2 3 4 5 6 7 8 9
NonZeroDigit(单个非零十进制数字) :: one of
1 2 3 4 5 6 7 8 9
ExponentPart(指数部分) ::
ExponentIndicator(指数指示符) SignedIneger(有符号整数) (e1,E-1,部分构成指数部分)
ExponetIndicator :: one of
e E
SignedInteger(有符号整数) ::
DecimalDigits(单个或多个十进制数字)
+DecimalDigits(+单个或多个十进制数字)
-DecimalDigits(-单个或多个十进制数字)
HexIntegerLiteral(十六进制整数直接量) ::
0xHexDigit(0小写x十六进制数字)
0XHexDigit(0大写X十六进制数字)
HexIntegerLiteral(十六进制整数直接量) HexDigit(十六进制数字) (如0xff)
HexDigit :: one of (摘自Edition 5,Edition 3则在unicodeEscapeSequence 中已说明.)
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
对于数字直接量来说,紧跟其后的字符,不能是一个标识符起始位置,或另一个数字.
note 比如:
3in
这里会有一个异常, 3in不会被解析成两个元素,而如果是一个元素.它又不是一个合法的token.
Semantics(语义)
一个数字直接量可以代替(代表)一个 Number类型的值. 这个值取决于两个步骤:
1. 根据直接量推演出的,数学角度上的值(mathematical value - MV).
2. 根据下面所描述的方式,舍入这个数学值.
. NumericLiteral 的 MV(数学值) ::
DecimalLiteral 就是其自身的数学值.
HexIntegerLiteral 就是其自身的数学值.
. DecimalLiteral 的数学值 ::
DecimalIntegerLiteral(如 123) 就是其自身的数学值.
DecimalIntegerLiteral.DecimalDigits (指浮点数,如1.23) 其数学值就是 DecimalIntegerLiteral的数学值,加上DecimalDigits的数学值,乘以10的-n次方, n等于DecimalDigits的位数.
DecimalIntegerLiteral.ExponentPart (如 123.e2 实际等价于123e2) 其数学值是DecimalIntegerLiteral的数学值,乘以10的e次方, e即ExponentPart部分的数学值(E2的数学值是指数2).
.DecimalIntegerLiteral.DecimalDigits ExpontPart(如 123.4e5)其数学值就是 123.4*10的5次方.(此处未直接按原文翻译,原文太罗嗦.参考上面两项.)
.DecimalDigits(如 .123 相当于0.123)的数学值,就是DecimalDigits的数学值,乘以10的-n次方,其中n是DecimalDigits的位数.
.DecimalDigits ExponentPart(如 .123e4 相当于 0.123e4)的数学值,就是DecimalDigits的数学值,乘以10的n-e次方,其中n是DecimalDigits的位数,e是ExponentPart的数学值.
.DecimalIntegerLiteral ExponentPart(如 123e4)的数学值,就是DecimalIntegerLiteral的数学值,乘以10的e次方,其中e即ExponentPart部分的数学值.
0的数学值就是0.
NonZeroDigit(首个非零数字,如000123中的1) DecimalDigits 的数学值是,NonZeroDigit的数学值,乘以10的n次方,加上DecimalDigits的数学值.其中n是DecimalDigits的位数