In Python 3.10 we will no longer be burdened by the old
parser (though 3rd party tooling needs to catch up).
One thing that the PEG parser makes possible in about 20
lines of code is something not entirely different from the old
print statement. I have a prototype:
Python 3.10.0a0
(heads/print-statement-dirty:5ed19fcc1a, Jun 9 2020,
16:31:17)
[Clang 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more
information.
Cannot read termcap database;
using dumb terminal settings.
>>> print 2+2
4
>>> print "hello world"
hello world
>>> print "hello", input("Name:")
Name:Guido
hello Guido
>>> print 1, 2, 3, sep=", "
1, 2, 3
>>>
But wait, there's more! The same syntax will make it
possible to call *any* function:
>>> len "abc"
3
>>>
Or any method:
>>> import sys
>>> sys.getrefcount "abc"
24
>>>
Really, *any* method:
>>> class C:
... def foo(self, arg): print arg
...
>>> C().foo 2+2
4
>>>
There are downsides too, though. For example, you can't
call a method without arguments:
>>> print
<built-in function print>
>>>
Worse, the first argument cannot start with a parenthesis
or bracket:
>>> print (1,
2, 3)
1 2 3
>>> C().foo (1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: C.foo() takes 2 positional arguments but 4 were
given
>>> print (2+2), 42
4
(None, 42)
>>> C().foo [0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'method' object is not subscriptable
>>>
No, it's not April 1st. I am seriously proposing this (but
I'll withdraw it if the response is a resounding "boo, hiss").
After all, we currently have a bunch of complexity in the
parser just to give a helpful error message to people used to
Python 2's print statement:
>>> print 1,
2, 3
File "<stdin>", line 1
print 1, 2, 3
^
SyntaxError: Missing parentheses in call to 'print'. Did you
mean print(1, 2, 3)?
>>>
And IIRC there have been a number of aborted attempts at
syntactic hacks to allow people to call functions (like print)
without parentheses, although (I think) none of them made it
into a PEP. The PEG parser makes this much simpler, because it
can simply backtrack -- by placing the grammar rule for this
syntax (tentatively called "call statement") last in the list
of alternatives for "small statement" we ensure that
everything that's a valid expression statement (including
print() calls) is still an expression statement with exactly
the same meaning, while still allowing parameter-less function
calls, without lexical hacks. (There is no code in my
prototype that checks for a space after 'print' -- it just
checks that there's a name, number or string following a name,
which is never legal syntax.)
One possible extension I didn't pursue (yet -- dare me!) is
to allow parameter-less calls inside other expressions. For
example, my prototype does not support things like this:
>>> a = (len
"abc")
File "<stdin>", line 1
a = (len "abc")
^
SyntaxError: invalid syntax
>>>
I think that strikes a reasonable balance between usability
and reduced detection of common errors.
I could also dial it back a bit, e.g. maybe it's too much
to allow 'C().foo x' and we should only allow dotted names
(sufficient to access functions in imported modules and method
calls on variables). Or maybe we should only allow simple
names (allowing 'len x' but disallowing 'sys.getrefcount x'.
Or maybe we should really only bring back print statements.
I believe there are some other languages that support a
similar grammar (Ruby? R? Raku?) but I haven't investigated.
Thoughts?