Python 用来在 >> 之间做出决定的算法和...在交互式控制台中提示?

发布于 2024-10-01 21:10:35 字数 316 浏览 8 评论 0原文

我正在实现一个自定义 (Iron)Python 控制台。

一般情况下,我需要显示 >>> 提示,但是当语句不完整时,我需要将提示更改为 ... 并收集更多行在执行它们之前。

我如何知道用户输入的行是否完整或者我是否需要阅读更多行?

一种简单的方法似乎是检查 : 是否存在。但我不确定我是否错过了 : 不存在的其他情况。

我查看了 IronPython 源代码来弄清楚它是如何做到这一点的,但是涉及很多步骤,我的简单复制未能完全工作。

I'm implementing a custom (Iron)Python console.

I need to display a >>> prompt in general, but when a statement is incomplete, I need to change the prompt to ... and gather more lines before executing them.

How do I know if a line entered by a user is complete or if I need to read more lines?

A simple way seems to be checking if : is present. But I'm not sure if I'm not missing other cases where : is not present.

I looked into the IronPython source code to figure how it does this, but there are many steps involved and my simple reproduction failed to completely work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

世界等同你 2024-10-08 21:10:35

仅通过查看代码字符串中的冒号和括号来尝试猜测是不切实际的。您最终需要实现一半的 Python 解析器才能做到这一点。

标准库 code 模块重现了交互式 Python 解释器的行为,我相信它是IronPython 使用此模块来实现其控制台。 (CPython 本身并未在 Python 中实现。)

您感兴趣的行继续逻辑来自 codeop.compile_command 函数。

这有点像黑客。本质上,它尝试使用晦涩的 PyCF_DONT_IMPLY_DEDENT 标志来 compile() 给定的代码,这意味着它不会假设任何开放缩进在块末尾自动关闭。然后它尝试再次编译它并添加换行符(导致显式的 DEDENT)。如果第二个有效但第一个无效,则您有一个潜在的延续,可以在块中输入更多内容。

It's impractical to try to guess from just looking at the code string for colons and brackets. You would end up needing to implement half the Python parser to get that right.

The standard library code module reproduces the behaviour of the interactive Python interpreter, and I believe it is this module that IronPython uses to implement its console. (The CPython one isn't implemented in Python itself.)

The line-continuation logic you're interested in comes from the codeop.compile_command function.

It's a bit of a hack. Essentially it tries to compile() the given code using the obscure PyCF_DONT_IMPLY_DEDENT flag, which means it doesn't assume that any open indents are closed automatically at the end of the block. It then tries to compile it again with newlines added (causing explicit DEDENTs). If the second works but the first doesn't, you've got a potential continuation, more can be typed into the block.

洒一地阳光 2024-10-08 21:10:35

我可以想到几种不同的方法来获取 ... 提示。

  • 开始(或继续)一个块
    • def foo():
  • 未闭合的括号、大括号、方括号(并注意嵌套)
    • x = (
    • x = {
    • x = [
  • 未闭合的三重引号字符串
    • x = '''
  • 行尾有反斜杠:
    • x = \

There are a few different ways I can think of to get the ... prompt.

  • Starting (or continuing) a block
    • def foo():
  • Unclosed parenthesis, brace, square bracket (and watch out for nesting)
    • x = (
    • x = {
    • x = [
  • Unclosed triple quoted string
    • x = '''
  • Backslash at end of line:
    • x = \
不气馁 2024-10-08 21:10:35

repl 循环具有完整的知识并可以访问解析器。如果解析器状态需要语句以外的任何内容,则 repl 循环会生成 ...。在未闭合括号的情况下,下一行的语句将是非法的,因为没有可能的子表达式可以包含语句。在 : 之后,下一个预期的标记始终是缩进,同样,语句始终是非法的。这就是为什么总是需要在 repl 循环的缩进块末尾键入一个空行,因为您必须为语句提供结束缩进以成为下一个预期的生产规则。

The repl loop has full knowledge and access to the parser. If the parser state is such that it expects anything other than a statement, then the repl loop produces a .... In the case of unclosed parentheses, a statement would be illegal on the next line, because there's no possible subexpression which can contain a statement. Following a :, the next expected token is always an indent, once again a statement would always be illegal. Thats why it's always necessary to type a blank line at the end of an indented block at the repl loop, because you must provide the closing dedent for a statement to become the next expected production rule.

娇纵 2024-10-08 21:10:35

您是否使用了 :\ (或未闭合的分隔符,如方括号或括号)?交互式解释器显示 ...

实际的逻辑可能有点复杂,但这是基本规则。

Did you use a : or a \ (or an unclosed delimiter, like brackets or parens)? The interactive interpreter shows a ....

The actual logic might be a bit more complicated, but that's the basic rule.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文