Search code examples
pythongrammarebnf

Python EBNF how to read


So I came across the grammar for the Python language (https://docs.python.org/3/reference/grammar.html) and I cannot fully understand how it works. Especially, I'm interested in this snipped about if statements.

if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)* ['else' ':' suite]
[...]
namedexpr_test: test [':=' test]
test: or_test ['if' or_test 'else' test] | lambdef
test_nocond: or_test | lambdef_nocond
lambdef: 'lambda' [varargslist] ':' test
lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison
comparison: expr (comp_op expr)*
# <> isn't actually a valid comparison operator in Python. It's here for the
# sake of a __future__ import described in PEP 401 (which really works :-)
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'

There is a certain style here. Defining or_test in terms of and_test and and_test again in terms of not_test. What is the advantage of this style? (Because I saw it used also in the grammar for C++, and most likely many other languages too).


Solution

  • It encodes precedence. With this grammar, you can unambiguously parse the expression

    not x and y or z
    

    as

                        or_test
                       /       \
                      /         z
                    and_test
                   /        \
                  /          y
              not_test
                 |
                 x
    

    in the "expected" manner, without needing parentheses.