Skip to main content
 首页 » 编程设计

python之简单的解析器,但不是计算器

2025年05月04日21bluestorm

我正在尝试编写一个非常简单的解析器。我在 SO 和互联网上阅读了类似的问题,但我能找到的只是“类似算术”的东西。

我有一个非常简单的 DSL,例如:

ELEMENT TYPE<TYPE> elemName { 
    TYPE<TYPE> memberName; 
} 

哪里<TYPE>部分是可选的,仅对某些类型有效。

根据我的阅读,我尝试用 Python 编写一个递归下降解析器,但有几件事我似乎无法理解:

  1. 如何查找超过 1 个字符的标记?
  2. 如何将文本拆分成不同的部分?例如,在 TYPE 之后我可以有一个空格或一个 <或空格后跟 < .我该如何解决?

请您参考如下方法:

简答

您所有的问题都归结为您在解析字符串之前没有对其进行标记。

长答案

解析过程实际上分为两个不同的部分:词法分析和解析。

乐行

在您考虑解析的方式中似乎缺少的是标记化或词法分析。这是将字符串转换为标记流(即单词)的过程。这就是您在询问我如何将文本分成不同部分时要寻找的内容?

您可以通过使用 re 根据正则表达式列表检查您的字符串来自行完成,或者您可以使用一些众所周知的库,例如 PLY .尽管如果您使用的是 Python3,我会偏向于我编写的词法分析库,即 ComPyl。 .

因此继续使用 ComPyl,您正在寻找的语法似乎如下所示。

from compyl.lexer import Lexer 
 
rules = [ 
    (r'\s+', None), 
    (r'\w+', 'ID'), 
    (r'< *\w+ *>', 'TYPE'), # Will match your <TYPE> token with inner whitespaces 
    (r'{', 'L_BRACKET'), 
    (r'}', 'R_BRACKET'), 
] 
 
lexer = Lexer(rules=rules, line_rule='\n') 
# See ComPyl doc to figure how to proceed from here 

请注意,第一条规则 (r'\s+', None) 实际上是解决空白问题的方法。它基本上告诉词法分析器匹配任何空白字符并忽略它们。当然,如果您不想使用词法分析工具,您可以简单地在您自己的 re 实现中添加类似的规则。

解析

您似乎想编写自己的LL(1) 解析器,所以我将简要介绍一下这部分。只要知道有很多工具可以为你做这件事(PLY 和 ComPyl 库提供 LR(1) 解析器,它们更强大但更难手写,请参阅 LL(1) 和 LR(1) 之间的区别) here ).

请注意,现在您知道如何标记字符串,我如何查找长度超过 1 个字符的标记? 问题已经解决。您现在正在解析的不是字符流,而是封装匹配的单词的标记流。