ECMAScript:词汇语法与句法语法

Posted

技术标签:

【中文标题】ECMAScript:词汇语法与句法语法【英文标题】:ECMAScript: Lexical Grammar vs Syntactic Grammar 【发布时间】:2018-09-16 15:19:53 【问题描述】:

我在理解ECMAScript 2017 规范中Lexical GrammarSyntactic Grammar 之间的具体区别时遇到了一些困难。


ECMAScript 2017 节选

5.1.2 词法和正则表达式语法

ECMAScript 的词汇语法在第 11 节中给出。这个语法 终结符 Unicode 代码点 符合 10.1 中定义的 SourceCharacter 规则。它定义了一组 产生式,从目标符号 InputElementDiv 开始, InputElementTemplateTail,或 InputElementRegExp,或 InputElementRegExpOrTemplateTail,描述这样的序列如何 代码点被转换为一系列输入元素

除空格和 cmets 以外的输入元素构成终端 ECMAScript 句法文法的符号,被称为 ECMAScript 令牌。这些标记是保留字、标识符、 ECMAScript 语言的文字和标点符号。

5.1.4 句法语法

将代码点流解析为 ECMAScript 脚本时 或模块,它首先通过以下方式转换为输入元素流 词汇语法的重复应用;这个输入流 元素然后由句法的单个应用程序解析 语法。


问题

    词汇语法 这里说终端符号是 Unicode 代码点(单个字符) 它还说它产生输入元素(又名令牌) 这些如何调和?终端符号要么是令牌,因此它会产生令牌。或者,终端符号是单独的代码点,这就是它产生的。 句法语法 我对这个语法和词汇语法有同样的问题 好像说这里的终端符号是记号 那么通过应用句法语法规则,产生了有效的标记,然后可以将其发送到解析器?或者,此语法是否接受令牌作为输入,然后测试整个令牌流的有效性?

我的最佳猜测

    词法分析阶段 输入:代码点(源代码) 输出:应用词法产生式产生有效的标记(词位类型+值)作为输出 解析阶段 输入:令牌 输出:应用语法产生式 (CFG) 来确定所有标记是否一起表示有效流(即源代码作为一个整体是有效的Script / Module

【问题讨论】:

当它说 "... 以 Unicode 码点为终端符号..." 时,我认为它们的意思是传达一个或多个码点的“分组”如本段其余部分所述。它的编写方式有点令人困惑。 Crazy Train:不,每个终端符号都是一个 Unicode 代码点。 @Magnus 你真的应该接受Bergi的回答。它就在这个问题上,只是坐在这里,没有正确的答案被接受。 【参考方案1】:

我认为您对 terminal symbol 的含义感到困惑。事实上,它们是解析器的输入,而不是输出(它是一个解析树 - 包括列表的退化情况)。

另一方面,生产规则确实有终端符号作为输出,目标符号作为输入 - 它是倒退的,这就是术语“终端”的来源。非终结符可以扩展(以不同的方式,这就是规则所描述的)为一系列终结符。

例子:

Language:
   S -> T | S '_' T
   T -> D | T D
   D -> '0' | '1' | '2' | … | '9'

String:
   12_45

Production:
     S          // start: the goal
   = S '_' T
   = T '_' T
   = T D ' ' T
   = T '2 ' T
   = D '2 ' T
   = '12 ' T
   = '12 ' T D
   = '12 ' T '5'
   = '12 ' D '5'
   = '12_45'     // end: the terminals

Parse tree:
   S
    S
     T
      T
       D
        '1'
      D
       '2'
    ' '
    T
     T
      D
       '4'
     D
      '5'

Parser output (generating a sequence of items from top-level Ts):
   '12'
   '45'

所以

词法分析阶段将代码点作为输入,将标记作为输出。代码点是词法文法的终结符。 句法阶段将标记作为输入,将程序作为输出。记号是句法文法的终结符。

【讨论】:

是的,谢谢Bergi,我明白了。在词法分析阶段,我假设我们重复应用词法文法,以产生一组仅终端符号。在词法分析阶段之后,这些代表什么?输出(即剩余的终端符号)现在是否完成了标记?同样,在解析阶段开始时,我们将词法分析器提供给我们的内容并应用一次句法语法,以测试脚本/模块的有效性。这个阶段有什么进/出? (假设对于每种语法,输入都有终端符号和非终端符号,输出只有终端符号。我不明白的是每个输入/输出对于词汇语法的含义阶段与句法语法阶段。) @Magnus 不,从产生式派生的终端符号将是 input。当我们说“一个文法从一个起始符号产生终结符号”时,“Produce”这个词并不意味着“输出”,它的意思是“由……组成”。词汇阶段的输出是记号,由语法中的非终结符号组成。 词汇语法告诉您从给定的代码点流中创建哪些标记(实际上是输入元素)。词汇阶段产生的每个标记都是词汇语法的非终结符的一个实例(具体来说,是 InputElement 开始符号之一)。 @Magnus 是的。在词汇阶段,我们从作为词汇语法的终结符号的代码点开始。然后将它们解析为令牌流,由语法中的非终结符号表示。【参考方案2】:

您的“最佳猜测”对于第一个近似值是正确的。主要更正是将“令牌”更改为“输入元素”。也就是说,词法层面产生输入元素(只有其中一些被指定为'tokens'),而句法层面以输入元素作为输入。

句法级别可以几乎忽略不是标记的输入元素,除非自动分号插入规则要求它注意空格和 cmets 中的行终止符。

您的“这些如何调和?”问题似乎源于对“终端符号”或“产生”的误解,但我不清楚是哪个。

【讨论】:

太好了,谢谢迈克尔。是的,我想我不知道在词法分析阶段如何使用词法语法来创建标记。句法语法/分析阶段也是如此。 语法本身不会创建标记。相反,您需要一个基于语法的解析器 来执行此操作。请注意,至少在理论上,您需要两个不同的解析器:一个基于词汇语法来处理词汇级别,另一个基于句法语法来处理句法级别。 (实际上,两者可能并没有那么明显。) 是的,明白了。据我了解,通常所说的解析器实际上是编译器/解释器的第二阶段。第一阶段称为lexical analysis(由lexer 使用lexical grammar 完成)。此阶段创建令牌并进一步分为scannerevaluator 阶段。然后lexer 将令牌发送到parser(编译器的第二阶段),它将使用context-free grammar 测试整个代码的有效性,然后生成parse tree。然后编译器的后期阶段可能会产生实际的机器代码......

以上是关于ECMAScript:词汇语法与句法语法的主要内容,如果未能解决你的问题,请参考以下文章

词汇与分词技术

Javascript系列语法关键保留字变量

ECMAScript简介以及es6新增语法

javaScript语法总结

尚融宝06-ECMAScript基本介绍和使用

快速掌握ECMAScript 6中的let语法