我试图在ECMAScript 2017之后理解字符串文字到最终字符串值(由代码单元值组成)的转换。
5.1.2 Lexical和RegExp Grammars
ECMAScript的词汇语法在第11节中给出。这个语法 具有符合的终端符号Unicode代码点 10.1中定义的SourceCharacter规则。它定义了一组 制作,从目标符号InputElementDiv开始, InputElementTemplateTail,或InputElementRegExp,或 InputElementRegExpOrTemplateTail,描述如何序列 代码点被转换为一系列输入元素。
除了空格和注释之外的输入元素构成终端 ECMAScript语法语法的符号被称为 ECMAScript令牌。这些令牌是保留字,标识符, 文字和ECMAScript语言的标点符号。
5.1.4语法语法
当要将代码点流解析为ECMAScript脚本时 或模块,它首先被转换为输入元素流 重复应用词汇语法;这个输入流 然后,单个元素应用程序解析元素 语法。
和
11 ECMAScript语言:词汇语法
首先转换ECMAScript脚本或模块的源文本 转换为一系列输入元素,它们是令牌,行终止符, 评论或空格。源文本从左侧扫描到 对,重复采用尽可能长的代码点序列 作为下一个输入元素。
11.8.4字符串文字
StringLiteral ::
" DoubleStringCharacters_opt "
' SingleStringCharacters_opt '
SingleStringCharacters ::
SingleStringCharacter SingleStringCharacters_opt
SingleStringCharacter ::
SourceCharacter but not one of ' or \ or LineTerminator
\ EscapeSequence
LineContinuation
EscapeSequence ::
CharacterEscapeSequence
0 [lookahead ∉ DecimalDigit]
HexEscapeSequence
UnicodeEscapeSequence
CharacterEscapeSequence ::
SingleEscapeCharacter
NonEscapeCharacter
NonEscapeCharacter ::
SourceCharacter but not one of EscapeCharacter or LineTerminator
EscapeCharacter ::
SingleEscapeCharacter
DecimalDigit
x
u
11.8.4.3静态语义:SV
字符串文字代表String类型的值。字符串 根据代码单位值描述文字的值(SV) 由字符串文字的各个部分贡献。
和
SingleStringCharacter的SV :: SourceCharacter但不是'要么 \或LineTerminator是代码点值的UTF16Encoding SourceCharacter。
SingleStringCharacter :: \ EscapeSequence的SV是。的SV EscapeSequence。
假设我们有字符串文字'b\ar'
。我现在想要遵循上面的词法语法和语义语法,将字符串文字转换成一组代码单元值。
b\ar
被识别为 CommonToken b\ar
进一步被识别为 StringLiteral \
infront的每个 SingleStringCharacter 都会被转换为 SourceCharacter \a
被识别为\ EscapeSequence any Unicode code point
我遇到的问题是StringLiteral输入元素现在是:
SourceCharacter, \ SourceCharacter, SourceCharacter
\ SourceCharacter 没有SV规则,仅适用于 \ EscapeCharacter 。
这让我想知道我的顺序是否错误,或者误解了如何应用词法和句法语法。
我也对如何完全应用SV规则感到困惑。因为它们被定义为应用于非终结符号,而不是终结符号(应该是应用词法语法后的结果)。
非常感谢任何帮助。
答案 0 :(得分:2)
好吧,假设我们正在使用单个令牌'b\ar'
,就像你说的StringLiteral
令牌一样。应用11.8.4.3 Static Semantics: SV中定义的算法以及10.1.1 Static Semantics: UTF16Encoding(cp),我们遵循SV
规则:
StringLiteral::
'
SingleStringCharacters
'
的SV是SV
的{{1}}。
SingleStringCharacters
部分递归SV
运行,例如SingleStringCharacters
SV(b\ar)
SV
的{{1}}是一个或两个代码单元的序列,SingleStringCharacters::
SingleStringCharacterSingleStringCharacters
后跟所有按顺序SV
SingleStringCharacter
中的代码单元。
这表示“每SV
个附加结果调用SV”。
SingleStringCharacters
SingleStringCharacter
SV(b)
的{{1}}但不是SV
或SingleStringCharacter::
或SourceCharacter
之一是'
的{{1}}代码点值\
。
LineTerminator
,因此这里的结果实际上是一个16位单元的代码单元序列UTF16Encoding
SourceCharacter
\x0062
\x0062
SV(\a)
的{{1}}是SV
的{{1}}。
SingleStringCharacter::
此\
(无EscapeSequence
前缀)SV
EscapeSequence
的{{1}}是SV(EscapeSequence)
的{{1}}。
SV(a)
\
SV
的{{1}}是EscapeSequence::
的{{1}}。
CharacterEscapeSequence
SV
的{{1}}但不是CharacterEscapeSequence
或SV(a)
中的SV
是SourceCharacter代码点值的CharacterEscapeSequence::
。
NonEscapeCharacter
,因此这会产生仅SV
的单个单元序列。NonEscapeCharacter
SV
相同的步骤生成包含NonEscapeCharacter::
的单个单元序列。SourceCharacter
合并在一起,字符串的值是UTF16代码单元EscapeCharacter
的序列。该代码单元序列导致LineTerminator
。我虽然应该首先应用词汇语法并最终使用令牌,然后应用SV规则?
词法分析员的观点中的“标记”是UTF16Encoding
,其中的所有内容都只是有关如何解析的信息。 \x0061
不是一种令牌。
\x0061
定义了如何将StringLiteral标记分解为一系列代码单元。
作为11 ECMAScript Language: Lexical Grammar
中的州ECMAScript脚本或模块的源文本首先转换为一系列输入元素,即标记,行终止符,注释或空格。源文本从左向右扫描,重复使用尽可能长的代码点序列作为下一个输入元素。
这些“输入元素”是解析器语法使用的标记。
假设事件顺序正确,我的第二个问题是SV(\ a)。应用第一个转义序列规则,我们留下SV(a),它应该遵循与SV(b)no相同的路径?
不仅仅是值,还有数据类型。使用Flow / Typescript样式的注释,您可以考虑上面的步骤
SV(r)
SV(b)
\x0072
的{{1}}是SV(b) + SV(\a) + SV(r)
的{{1}}。[\x0062, \x0061, \x0072]
bar
的{{1}}是StringLiteral
的{{1}}。EscapeSequence
SV
的{{1}}是SV
的{{1}}。SingleStringCharacter::
\
的{{1}}但不是EscapeSequence
或SV
中的EscapeSequence
是SourceCharacter代码点值的SV
。 好像它是一个重载函数,例如
EscapeSequence::
所以CharacterEscapeSequence
有点像SV
而CharacterEscapeSequence
有不同的类型。