This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: PEG discrepancy on 'if {x} {a}: pass'
Type: behavior Stage: resolved
Components: Versions: Python 3.10, Python 3.9
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: lys.nikolaou Nosy List: gvanrossum, lys.nikolaou, terry.reedy
Priority: low Keywords: patch

Created on 2020-08-28 21:43 by gvanrossum, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 22996 merged lys.nikolaou, 2020-10-26 23:35
PR 23006 merged lys.nikolaou, 2020-10-27 19:04
Messages (5)
msg376048 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-08-28 21:43
I just noticed a subtle discrepancy between the old parser and the PEG parser.

Consider this syntax error:
```
if x {a}: pass
```
The old parser places the caret at the '{':
```
$ python3.8 -c 'if x { a } : pass'
  File "<string>", line 1
    if x { a } : pass
         ^
SyntaxError: invalid syntax
```
The PEG parser puts it at 'a':
```
$ python3.10 -c 'if x { a } : pass'
  File "<string>", line 1
    if x { a } : pass
           ^
SyntaxError: invalid syntax
```

I don't think we should put much effort into fixing it -- it's just a curiosity. I suspect it's got to do with some lookahead.
msg376065 - (view) Author: Lysandros Nikolaou (lys.nikolaou) * (Python committer) Date: 2020-08-29 14:41
I had a look at this. I have been testing with the input a{x}, which faces the same problem. 

It's actually because of an invalid_* rule. The call stack looks like this:

...
invalid_comprehension_rule(Parser * p) (/home/lysnikolaou/repos/cpython/Parser/parser.c:15065)
genexp_rule(Parser * p) (/home/lysnikolaou/repos/cpython/Parser/parser.c:11381)
primary_raw(Parser * p) (/home/lysnikolaou/repos/cpython/Parser/parser.c:10361)
primary_rule(Parser * p) (/home/lysnikolaou/repos/cpython/Parser/parser.c:10285)
await_primary_rule(Parser * p) (/home/lysnikolaou/repos/cpython/Parser/parser.c:10240)
...

The invalid_comprehension rule acecpts an LBRACE as the starting token and only fails after it's parsed it, which means that the parser fails with three tokens in the tokens array, the NAME which is valid, the LBRACE which is parsed for the invalid_comprehension rule and the NAME thereafter, upon which the parser fails and backs out of everything. Then, we look at the last token we've parsed and that's where we're placing the caret.

Because of invalid_comprehension, we can even go as far as making the parser show a completely different error, for example:

➜  cpython git:(master) ✗ cat a.py
a{*x for x in a}
➜  cpython git:(master) ✗ ./python a.py
  File "/home/lysnikolaou/repos/cpython/a.py", line 1
    a{*x for x in a}
      ^
SyntaxError: iterable unpacking cannot be used in comprehension

Or place the caret even further:

➜  cpython git:(master) ✗ cat a.py     
a{*x + a + b + c}
➜  cpython git:(master) ✗ ./python a.py
  File "/home/lysnikolaou/repos/cpython/a.py", line 1
    a{*x + a + b + c}
                    ^
SyntaxError: invalid syntax

There's a simple fix, which is adding an alternative to the primary rule, that parses something along the lines of `primary set` and then call RAISE_SYNTAX_ERROR_KNOWN_LOCATION there, but that would have to come before the genexp alternative, which worries me because of the performance implications. `primary` is a left recursive rule that gets called VERY often, probably more than a few times even when parsing a single NAME.
msg376412 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2020-09-04 22:47
Minimal example
>>> a{ # or
>>> a {
In 3.8, this is immediately flagged as a SyntaxError.  In 3.9 and master, a continuation prompt is issued.  This strikes me as a parsing buglet that should preferably be fixed, as it implies that something valid *could* follow '{', thus misleading beginners.  On the other hand, after scanning my keyboard, '{' seems unique in being a legal symbol, unlike `, $, and ?, or combinations like +*, that can AFAIK never follow a name.  So it would need special handling.


Side note: for the same reason I dislike the { change, I like the generic 3.9 change for legal operators without a second operand. 
>>> a *
Both flag as SyntaxError, but in 3.8, the caret is under '*', falsely implying that '*' cannot follow a name, while in 3.9, it is under the whitespace following, correct implying that the * is legal and that the problem is lack of a second expression (on the same line without continuation).
msg379792 - (view) Author: Lysandros Nikolaou (lys.nikolaou) * (Python committer) Date: 2020-10-27 18:54
New changeset 15acc4eaba8519d7d5f2acaffde65446b44dcf79 by Lysandros Nikolaou in branch 'master':
bpo-41659: Disallow curly brace directly after primary (GH-22996)
https://github.com/python/cpython/commit/15acc4eaba8519d7d5f2acaffde65446b44dcf79
msg379809 - (view) Author: Lysandros Nikolaou (lys.nikolaou) * (Python committer) Date: 2020-10-27 22:38
New changeset c4b58cea4771afc0ddfdb857b0fb5115b9f4bc9f by Lysandros Nikolaou in branch '3.9':
[3.9] bpo-41659: Disallow curly brace directly after primary (GH-22996) (#23006)
https://github.com/python/cpython/commit/c4b58cea4771afc0ddfdb857b0fb5115b9f4bc9f
History
Date User Action Args
2022-04-11 14:59:35adminsetgithub: 85825
2020-10-27 22:39:15lys.nikolaousetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2020-10-27 22:38:48lys.nikolaousetmessages: + msg379809
2020-10-27 19:04:02lys.nikolaousetpull_requests: + pull_request21921
2020-10-27 18:54:29lys.nikolaousetmessages: + msg379792
2020-10-26 23:35:29lys.nikolaousetpull_requests: + pull_request21910
2020-10-26 22:46:06lys.nikolaousetpull_requests: - pull_request21195
2020-09-05 13:42:33lys.nikolaousetkeywords: + patch
stage: needs patch -> patch review
pull_requests: + pull_request21195
2020-09-04 22:47:56terry.reedysetnosy: + terry.reedy
messages: + msg376412
2020-08-29 14:41:50lys.nikolaousetmessages: + msg376065
2020-08-29 01:01:30chromesetversions: - Python 3.5, Python 3.6, Python 3.7, Python 3.8
2020-08-29 01:01:04chromesetversions: + Python 3.5, Python 3.6, Python 3.7, Python 3.8
2020-08-28 21:43:15gvanrossumcreate