可以使用产生式定义词法文法吗?

Can a lexical grammar be defined using productions?

我正在观看一门关于编译器的课程,该课程使用正则表达式为词法分析器 (lexer) 定义语法,词法分析器使用此正则表达式来配​​置有限自动机。只有当课程到达语法分析器(解析器)部分时,才会介绍特定于上下文无关语法的术语,如产生式、终端和非终端。由此得出结论,这些仅在语法分析期间使用。

但是,词法分析器的 EcmaScript 规范 defines productions

Productions of the lexical and RegExp grammars are distinguished by having two colons “::” as separating punctuation. The lexical and RegExp grammars share some productions.

那么词法分析器的语法是否也可以使用带有终结符和非终结符的产生式来指定,而不仅仅是正则表达式?

This grammar tutorial 还提到上下文无关语法 (CFG) 是常规语法的超集,所以我的问题的答案似乎是 "yes"。我会很感激一点解释。提前致谢

这已在评论中得到回答,但除非重复,否则可能值得回答。

就像您自己的 link 一样,是的,任何处理上下文无关语法的解析器也可以处理常规语法。上下文无关语法是由下推自动机 (PDA) 识别的语法,它是有限状态机 (FSM) 识别的语法的严格超集1。例如,关于这个 here 有一个很好的章节。

(请注意,常规语言,我在这里将其称为"RL",虽然这不是一个常见的缩写,但它是一种可以被 FSM 识别的语言。A context free language 或 CFL 是一种可以被 PDA 识别的语言。同时 regular grammar, 或 RG, 是一种可以识别常规语言的语言,上下文无关语法或 CFG 是一种识别上下文无关语言的语法。CFL、CFG、PDA 和 FSM 都是常见的标准缩写;我在这里使用的 RL 和 RG 缩写不是。我们也有 RE 或 R.E.,代表正则表达式,这就是我们编写常规 语言 的方式——我们的 RL——我们用它来构建识别 "words" 在这个 RL.)

我们通常想出一些 RL 并为此编写一个基于正则表达式的小型 FSM 识别器以将输入转换为标记,然后使用上下文无关语法解析标记的原因是,这使得更小,更简单的代码构造。不进行广泛优化的编译器倾向于将大部分时间花在标记化代码上(尽管这显然因语言而异:例如,某些语言具有复杂的类型系统,这可能导致它们将大部分时间花在进行类型匹配上), 所以在我们可以做到小而快的程度上,我们领先。

作为 ,您在 ECMAScript 中看到的具体问题是 源语言用来表达正则表达式的语法 。 (这句话是不是太复杂了?:-))虽然正则表达式可以被 FSM(而不是PDA)识别,但我们使用的语法write 正则表达式本身不需要是 RL——在 ECMAScript 中,它不是。

事实上,混合使用 RL 和 CFL 来编码 RE 是非常典型的。例如,在 C、C++ 和 Python 中,RE 处理在一个库中,我们向库例程发送一个字符串,它 "compiles" 进入某个 FSM。字符串本身在 CFL 中对 RE 进行编码,因此 (运行time) 编译成 FSM 可能会失败。其他一些语言,例如 awk,将 RE 语法提升到语法中,但提出了一个环绕的正则 language 来表达它——例如 /pattern/ 中有任何嵌入的斜杠模式被编码为 \/。通过在 RL 中对 RE 进行编码,这些语言允许其基于 FSM 的分词器将整个 RE 转换为单个令牌,而无需使用 CFG。然后可以在编译时而不是 运行 时编译令牌(使用单独的子例程再次将令牌分开),并且任何编译时语法违规都可以在 awk "compile" 时产生(这无论如何是运行时间)。

ECMAScript 只是选择不同而已。它的 RE 语言不是 RL,而是 CFL,因此只有 PDA 而不是 FSM 可以识别它。它是否可以用类似 awk 的方式处理,我不确定:CFL 部分在 21.2.1 节中定义,并且在 11.8.5 节中有一个周围的 RL。如,嵌入式CFL需要一个PDA/CFG(例如,21.2.1中的语法有平衡括号:析取嵌入额外的析取,之后需要一个右括号)。

(哇!TLA 太多了!2 :-))


1这个严格的超集意味着有许多 CFL 无法被 FSM 识别。一个典型的例子是 FSM 不能平衡任意数量的括号,而 PDA 可以。如果您选择一些上限,例如 "no more than 100 nested parentheses",您可以生成一个(相当大的)FSM,它可以识别所有嵌套括号不超过 100 个但仍然具有平衡括号的输入。

2TLA:三个(或偶尔两个)字母的首字母缩写词。另请参阅 ETLA,扩展三字母首字母缩略词。