a.ilchinger
a.ilchinger

Reputation: 432

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).

Upvotes: 0

Views: 433

Answers (1)

chepner
chepner

Reputation: 531808

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.

Upvotes: 1

Related Questions