在 Python 语言的词法分析阶段标记 f 字符串

Tokenizing f string in lexical analysis phase of Python language

最近通过Aho的龙书了解了编译器。据我了解,语言首先通过词法分析进行标记化。对于像 C/C++ 和 Java 这样的语言来说,这个过程似乎很简单。但是对于 Python,特别是 Python3,f 字符串应该如何表现?我不认为单独通过正则表达式或使用 lex 的词法分析可以标记化字符串,例如 f"1+2 = {int(f'{1}') + int(f'{2}')}" 。我不认为正则表达式和状态可以识别 {} 内的部分不是字符串字符。我搜索了一下,发现 python3 使用 antlr https://github.com/antlr/grammars-v4/blob/master/python/python3-py/Python3.g4 的语法。但我不相信它会标记 f 字符串。所以我的问题是如何处理 f 字符串?是否可以使用 lex/flex 来处理它们?或者它们是在其他阶段处理的吗?还是标准解析器技术不适用于它们?

Python 的格式化字符串文字旨在使解析器的工作更轻松,但代价是一些有时会给用户带来不便的限制。特别是,格式化的字符串文字总是在第一次出现打开文字的引号时终止,因为不允许在字符串文字的任何地方使用该引号(或序列),包括嵌入的表达式。此外,文字中不允许使用反斜杠,因此您也不能偷偷使用反斜杠转义引号。

所以词法分析很简单,与任何其他字符串文字没有太大区别。 (主要区别在于没有反斜杠转义。)

当然,一旦确定了文字标记,最终将需要对其进行递归解析,此时将需要基于词法分析器状态的策略来处理嵌入式表达式。

大多数具有类似功能的其他语言——Perl、Javascript、Posix shell 等等——确实允许任意嵌套表达式,包括包含定界引号的表达式。对此类语言进行词法分析的一个简单策略是使用词法状态结合状态堆栈来跟踪递归嵌入。这可能有点混乱,它肯定偏离了 Aho 等人概述的简单模型,但它并不是特别复杂。

通过构建递归 parser/scanner 可以实现更清晰的(在我看来)解决方案,但这需要重构词法扫描器以便将词法分析与输入管理分开。 (f)lex 和 Antlr 架构都没有促进这一点,尽管可以将它们弯曲成这种形式。

顺便说一句,我没有尝试你链接到的 Antlr 解析器,但在我看来它会标记格式化的字符串文字。但是,它错误地允许反斜杠转义,因此它会接受一些标准 Python 拒绝的文字。我认为它不包括在识别文字后分解文字所必需的代码。