开发者

Algorithm Python uses to decide between >>> and ... prompt in interactive console?

开发者 https://www.devze.com 2023-01-24 11:26 出处:网络
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 befor

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 开发者_JAVA技巧code to figure how it does this, but there are many steps involved and my simple reproduction failed to completely work.


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.


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 = \


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号