使用 Python 的漂亮打印 Lisp
Pretty-print Lisp using Python
有没有办法在 Python 中漂亮地打印 Lisp 风格的代码字符串(换句话说,一堆平衡的括号和其中的文本)而无需重新发明轮子?
我认为最简单的方法是使用三引号。如果你说:
print """
(((This is some lisp code))) """
应该可以。
您可以在三重引号内以任何您喜欢的方式格式化您的代码,它会以您想要的方式出现。
祝你好运,编码愉快!
简答
我认为一个合理的方法是生成 Python 列表或自定义对象而不是字符串,并使用 pprint 模块,正如@saulspatz 所建议的那样。
长答案
整个问题看起来像是 XY-problem 的一个实例。为什么?因为您正在使用 Python(为什么不是 Lisp?)来操作 strings(为什么不是数据结构?)表示生成的 Lisp-style 代码,其中 Lisp-style 定义为 "a bunch of parentheses and text within"。
对于"how to pretty-print?"这个问题,我会这样回答"I wouldn't start from here!"。
除了使用现有的轮子之外,不重新发明轮子的最佳方法是坚持使用简单的输出格式。
但首先,为什么你需要漂亮的打印?谁会查看生成的代码?
根据您使用的确切 Lisp 方言和代码的预期用途,您可以采用非常不同的方式来格式化代码。例如,考虑文本的换行符、缩进和最大宽度。 Common Lisp pretty-printer 是特别进化的,我怀疑你想拥有相同级别的可配置性。
如果你使用 Lisp,一个简单的调用 pprint
就可以解决你的问题,但是你使用的是 Python,所以暂时坚持最合理的输出,因为漂亮的打印是一堆蠕虫。
如果您的代码是为人类读者准备的,请:
- 不要在自己的行上加上右括号
- 不要垂直对齐左括号和右括号
- 不要在左括号之间添加空格
这很丑:
( * ( + 3 x )
(f
x
y
)
)
这个比较好:
(* (+ 3 x)
(f x y))
或者简单地说:
(* (+ 3 x) (f x y))
See here了解更多详情。
但在打印之前,您必须解析输入的字符串并确保其格式正确。由于生成表单的方式,您可能确定它的格式正确,但我认为印刷商应该忽略这一点,不要做出太多假设。如果你向漂亮打印机传递了一个由 Python 对象表示的 AST 而不仅仅是字符串,这会更容易,如评论中所建议的那样。您可以构建数据结构或自定义 类 并使用 pprint (python) 模块。如上所述,如果您可以更改生成 Lisp 样式代码的方式,这似乎是您的情况。
对于字符串,您应该处理任何可能的输入并拒绝无效的输入。
这意味着检查括号和引号是否平衡(提防转义字符)等。
实际上,您 不需要 真正构建用于打印的中间树(尽管它可能对程序的 其他 部分有所帮助),因为Lisp 风格的代码由易于嵌套并使用前缀表示法的形式组成:您可以从左到右扫描输入字符串,并在看到括号时根据需要打印(左括号:递归;右括号,return 来自递归)。当您第一次遇到未转义的双引号 "
时,请阅读直到下一个 "
,...
加上简单的打印方法,就可以满足您的需求了。
有没有办法在 Python 中漂亮地打印 Lisp 风格的代码字符串(换句话说,一堆平衡的括号和其中的文本)而无需重新发明轮子?
我认为最简单的方法是使用三引号。如果你说:
print """
(((This is some lisp code))) """
应该可以。 您可以在三重引号内以任何您喜欢的方式格式化您的代码,它会以您想要的方式出现。
祝你好运,编码愉快!
简答
我认为一个合理的方法是生成 Python 列表或自定义对象而不是字符串,并使用 pprint 模块,正如@saulspatz 所建议的那样。
长答案
整个问题看起来像是 XY-problem 的一个实例。为什么?因为您正在使用 Python(为什么不是 Lisp?)来操作 strings(为什么不是数据结构?)表示生成的 Lisp-style 代码,其中 Lisp-style 定义为 "a bunch of parentheses and text within"。 对于"how to pretty-print?"这个问题,我会这样回答"I wouldn't start from here!"。 除了使用现有的轮子之外,不重新发明轮子的最佳方法是坚持使用简单的输出格式。
但首先,为什么你需要漂亮的打印?谁会查看生成的代码?
根据您使用的确切 Lisp 方言和代码的预期用途,您可以采用非常不同的方式来格式化代码。例如,考虑文本的换行符、缩进和最大宽度。 Common Lisp pretty-printer 是特别进化的,我怀疑你想拥有相同级别的可配置性。
如果你使用 Lisp,一个简单的调用 pprint
就可以解决你的问题,但是你使用的是 Python,所以暂时坚持最合理的输出,因为漂亮的打印是一堆蠕虫。
如果您的代码是为人类读者准备的,请:
- 不要在自己的行上加上右括号
- 不要垂直对齐左括号和右括号
- 不要在左括号之间添加空格
这很丑:
( * ( + 3 x )
(f
x
y
)
)
这个比较好:
(* (+ 3 x)
(f x y))
或者简单地说:
(* (+ 3 x) (f x y))
See here了解更多详情。
但在打印之前,您必须解析输入的字符串并确保其格式正确。由于生成表单的方式,您可能确定它的格式正确,但我认为印刷商应该忽略这一点,不要做出太多假设。如果你向漂亮打印机传递了一个由 Python 对象表示的 AST 而不仅仅是字符串,这会更容易,如评论中所建议的那样。您可以构建数据结构或自定义 类 并使用 pprint (python) 模块。如上所述,如果您可以更改生成 Lisp 样式代码的方式,这似乎是您的情况。
对于字符串,您应该处理任何可能的输入并拒绝无效的输入。
这意味着检查括号和引号是否平衡(提防转义字符)等。
实际上,您 不需要 真正构建用于打印的中间树(尽管它可能对程序的 其他 部分有所帮助),因为Lisp 风格的代码由易于嵌套并使用前缀表示法的形式组成:您可以从左到右扫描输入字符串,并在看到括号时根据需要打印(左括号:递归;右括号,return 来自递归)。当您第一次遇到未转义的双引号 "
时,请阅读直到下一个 "
,...
加上简单的打印方法,就可以满足您的需求了。