Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 简单的解析器,但不是计算器_Python_Parsing_Compiler Construction - Fatal编程技术网

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

Python 简单的解析器,但不是计算器,python,parsing,compiler-construction,Python,Parsing,Compiler Construction,我正在尝试编写一个非常简单的解析器。我在某某网站和互联网上读到了类似的问题,但我能找到的只是类似算术的东西 我有一个非常简单的DSL,例如: ELEMENT TYPE<TYPE> elemName { TYPE<TYPE> memberName; } 其中零件是可选的,仅对某些类型有效 根据我所读的内容,我尝试用Python编写递归下降解析器,但有几件事我似乎不明白: 如何查找长度超过1个字符的令牌? 我怎样把课文分成不同的部分?例如,在一个类型之后,我可以有一

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

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

ELEMENT TYPE<TYPE> elemName {
    TYPE<TYPE> memberName;
}
其中零件是可选的,仅对某些类型有效

根据我所读的内容,我尝试用Python编写递归下降解析器,但有几件事我似乎不明白:

如何查找长度超过1个字符的令牌? 我怎样把课文分成不同的部分?例如,在一个类型之后,我可以有一个空格或一个简短的答案 您所有的问题都归结为这样一个事实:在解析字符串之前,您没有对其进行标记

长话短说 解析过程实际上分为两个不同的部分:词法分析和解析

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

您可以通过使用re检查您的字符串与regexp列表,或者使用一些著名的库,例如。虽然如果您使用的是Python3,我会倾向于使用我编写的词法分析库,这就是

因此,继续使用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匹配任何空格字符并忽略它们。当然,如果您不想使用词法分析工具,您可以简单地在自己的重新实现中添加类似的规则

解析 您似乎想编写自己的LL1解析器,因此我将简要介绍这一部分。只需知道有很多工具可以为您做到这一点,PLY和ComPyl Libraries提供了更强大但更难手工编写的LR1解析器,请参见LL1和LR1之间的区别

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

简短回答 您所有的问题都归结为这样一个事实:在解析字符串之前,您没有对其进行标记

长话短说 解析过程实际上分为两个不同的部分:词法分析和解析

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

您可以通过使用re检查您的字符串与regexp列表,或者使用一些著名的库,例如。虽然如果您使用的是Python3,我会倾向于使用我编写的词法分析库,这就是

因此,继续使用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匹配任何空格字符并忽略它们。当然,如果您不想使用词法分析工具,您可以简单地在自己的重新实现中添加类似的规则

解析 您似乎想编写自己的LL1解析器,因此我将简要介绍这一部分。只需知道有很多工具可以为您做到这一点,PLY和ComPyl Libraries提供了更强大但更难手工编写的LR1解析器,请参见LL1和LR1之间的区别


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

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

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

使用parsy为您的语法类型完成的解析器示例如下:。 它比你的要复杂得多,但它显示了什么是可能的。如果允许但不需要空白,则使用顶部定义的lexeme实用程序使用可选空白


您可能需要进一步了解哪些地方需要空白,哪些地方可以选择空白,以及您真正指的是什么类型的空白。

Olivier关于词法分析/标记化和解析的回答很有帮助

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

使用parsy为您的语法类型完成的解析器示例如下:。 它比你的要复杂得多,但它显示了什么是可能的。如果允许但不需要空白,则使用顶部定义的lexeme实用程序使用可选空白


您可能需要进一步了解哪些地方需要空白,哪些地方可以选择空白,以及您真正的意思是什么类型的空白。

听起来像是在寻找正则表达式听起来像是在寻找正则表达式