简单的解析器,但不是计算程序

2024-09-27 00:15:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图编写一个非常简单的解析器。我在网上和网上也读过类似的问题,但我能找到的只是“算术类”的东西。在

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

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

其中<TYPE>部分是可选的,仅对某些类型有效。在

根据我读到的内容,我试图用Python编写一个递归下降解析器,但有一些事情我似乎无法理解:

  1. 如何查找长度超过1个字符的令牌?在
  2. 我怎样把课文分成不同的部分?例如,在一个类型之后,我可以有一个空白或一个<,或者一个后跟<的空白。我该如何解决这个问题?在

Tags: 解析器类型内容type算术element事情dsl
2条回答

Olivier关于词法分析/标记化然后解析的回答很有帮助。在

但是,对于相对简单的情况,一些解析工具能够处理您的需求,而不需要单独的标记化步骤。parsy就是其中之一。您可以从更小的构建块构建解析器-有很好的文档可以帮助您。在

一个用parsy完成的语法分析器的例子如下:http://parsy.readthedocs.io/en/latest/howto/other_examples.html#proto-file-parser。 它比你的复杂得多,但它显示了什么是可能的。如果允许空白(但不是必需的),它使用lexeme实用程序(在顶部定义)来使用可选的空白。在

您可能需要加强对空白的必要性和可选性的理解,以及空白的真正含义。在

简短回答

所有的问题都归结为这样一个事实:在解析字符串之前,没有对字符串进行标记化。在

冗长的回答

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

Lexing

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

您可以通过使用re根据regexp列表检查字符串,也可以使用一些著名的库,如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),实际上是解决空白问题的方法。它基本上告诉lexer匹配任何空白字符并忽略它们。当然,如果您不想使用词法分析工具,只需在您自己的re实现中添加一个类似的规则。在

解析

您似乎想编写自己的LL(1)解析器,因此我将简要介绍这一部分。只需知道,有很多工具可以为您做到这一点(PLY和compyllibraries提供了LR(1)解析器,这些解析器功能更强大,但更难手工编写,请看LL(1)和LR(1)here)之间的区别。在

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

相关问题 更多 >

    热门问题