一个python解析器,它在502行python中构建python ast而不使用模块

pymetaterp的Python项目详细描述


侏儒虫

这是一个不使用python模块的python ast构建器。更长的无堆栈版本可用于更容易的移植。single_file.py是一个独立的502行脚本。

它(也)只是另一个基于解析表达式语法(peg)的解析器,有一个主要区别。解析的语法将被解释而不是编译。这使得修改语言(通过编辑其语法)和编写语法的语言(以及编写语法的语言)变得很容易。

[这是一种预发布的类型。可能有一些错误和信息丢失。]

下载并运行

git clone https://github.com/asrp/pymetaterp
cd pymetaterp
python single_file.py

python single_file.py filename.py

这将打印出给定文件的ast(或single_file.py自己的ast)。输出的示例开头:

file_input
  regular_assign
    testlist
      NAME
        str 'NAME'
      NAME
        str 'FLAGS'

从库中运行文件

python test/boot_test.py 
python test/python_parse_test.py 

文件

single_file.py主要用于演示。否则,此模块将被分为多个文件。有许多文件,但大多是分开的。导入依赖项是

util.py
  boot.py
  boot_stackless.py
    python.py

其他文件没有导入。要获得有用的信息,必须导入多个文件。有关一些示例,请参见test/python_parse_test.pytest/boot_test.py

回复

很明显,缺少语法读取评估打印循环(repl),因此可以一次为解释器提供一条规则,使用目前看到的规则解析子序列输入。

源读取顺序

我建议首先阅读boot_grammar.py中的boot.pybootstrap。这两个函数构成核心,它们与boot-tree.py一起可以重新生成boot-tree。

然后boot_stacklessboot.py相同,但不使用python调用堆栈/递归进行解析。

python.pyboot.py解释器添加功能。diffboot_grammar.py中添加这些语法。

最后,python_grammar.py包含要最终解析的python语法。

已分析Python语言

模块为Python2.x程序构建AST。它能够解析所有的Python2.x(事实上,它包含了Python2.x语法的一个稍微修改过的版本),但是对空白的处理不够宽容。例如,解析

from my_module import (var1, var2,
                       var3, var4)

出现错误。

因为这是一个预发行版,所以我不经常使用的部分语言可能有错误。它可以为这里包含的所有文件构建ast。

Gramamr语言差异

boot_grammar.py的开头自描述语法。它是一个peg-so all"or"()返回第一个匹配和"and"和"quantified"(*,+,?)贪婪。

name = (letter | '_') (letter | digit | '_')*
expr = apply | exactly | token | parenthesis | output

exactly! = "'" {(escaped_char | ~'\'' anything)*} "'"
token! = "\"" {(escaped_char | ~'"' anything)*} "\""
escaped_char! = '\\' {'n'|'r'|'t'|'b'|'f'|'"'|'\''|'\\'}
apply! = ('\t'|' ')* {name}
parenthesis = "(" {or} ")"
output! = "{" {or} "}"

not = "~" {expr=negation} | expr
quantified = not (('*' | '+' | '?')=quantifier)?
bound = quantified ('=' {name=inline})?
and = bound*
or = and ("|" {and})*

rule = spaces {name=rule_name '!'?=flags and=args ("=" {or})}
grammar = {rule*} spaces

与其他销钉的主要区别。

  • 输出规则:a{b c}d将匹配a b c d的连接,但只返回匹配的b c
  • 量词折叠:letter letter*返回一个列表,而不是第二个元素与letter*匹配的列表对
  • 嵌套和折叠:a(b(c d))ea b c d e具有相同的输出(如果某些对需要显式分组,请参见下面的内联部分)。
  • 节点折叠:输出中只有一个子节点被其父节点替换,除非("不要折叠")标志已为该节点设置。
  • 内联:不知羞耻地接受了欧姆,但解释略有不同。expression=name创建名为name的节点包装expression的输出
  • 规则替换:使用第二个规则名称=表达式行替换规则名称的第一个定义(而不是附加到或中)。
  • 两种基本令牌:有两种基本令牌类型:'a'(单引号)和"a"(双引号)。双引号标记允许在匹配前使用空格。

重新生成引导树.py

使用解释器创建一些树匹配树并对结果调用保存

match_tree.save("tree.py")

左递归

虽然"peg/packrat解析器可以支持左递归",但树输出不是我们想要的。python函数reformat_binaryreformat_atom修复解析树的输出。

来源奇怪

两个硬编码规则

        if root[NAME] == "anything":
            return pop(self.input)
        elif root[NAME] == "void":
            return

标记的硬编码语义

git clone https://github.com/asrp/pymetaterp
cd pymetaterp
python single_file.py
0

优化

为了缩短这些文件(特别是single_file.py)做了一些努力,但没有做太多。仍然有一些断言和注释的打印语句可用于调试。当然,最终的目标是减少程序的复杂性和冗长性,而不是行数。

缺少功能

此程序较长版本的功能/膨胀尚未(尚未?)移过去:

  • 已访问节点的调试树及其输入和输出
  • 函数参数(在语法中,但不在解释器中)
  • 嵌套列表输入(也在语法中,但不在解释器中)
  • 名称、参数、标志、正文作为参数而不是位置子项
  • 备忘录
  • 匹配的输入开始和结束位置
  • 谓词、操作和规则值的精确python表达式匹配。平衡的目前被用作更简单的启发式方法。

删除功能

只需要一些基本知识就可以得到一个较小的文件。

git clone https://github.com/asrp/pymetaterp
cd pymetaterp
python single_file.py
1

读数

其他类似项目

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
选项卡内的java 安卓工具栏   java接口VS API VS公共类   无法解析java。lang.ClassNotFoundException:在安卓 studio中找不到类“com.example.安卓.camera2basic.AutoFitTextureView”?   java等待线程正常完成   java在JTable中的prepareRenderer方法中编辑单元格数据是否可行?   java SessionNotCreatedException selenium webdriver   java Android Studio Gradle CreateProcess错误=2   java找不到适用于异常(int)的构造函数   javascript如何在不使用正则表达式的情况下检查输入是否为表情符号?   从JAVA运行ant时,JAVA_HOME变量不正确   long的java min值引发异常   java如何在这段代码中实现侦听器?   带有透明文本的java Android按钮   图像Java扫描仪问题(JFrame)   java模拟输入蒸汽似乎在Junit测试的第一次输入中就被吃掉了   压缩Java Deflater,现在和将来的结果相同(确定性)   java JTable getModel()。setValueAt从数组中删除第一个元素   java我有不同于编译器和计算器的价值   使用C#客户端调用基本身份验证java webservice   java相同类型的多个@Embedded字段在持久化后始终为空