Python Assignment statement

193 Views Asked by At

I was going through the python assignment statement docs .

Here python uses below Backus–Naur form for assignment statements.

assignment_stmt ::=  (target_list "=")+ (starred_expression | yield_expression)
target_list     ::=  target ("," target)* [","]
target          ::=  identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | slicing
                     | "*" target

Where as starred_expression is in Backus-Naur Form is

starred_expression ::=  expression | (starred_item ",")* [starred_item]
starred_item       ::=  assignment_expression | "*" or_expr

and yield_expression in Backus-Naur Form is

yield_atom       ::=  "(" yield_expression ")"
yield_expression ::=  "yield" [expression_list | "from" expression]

After recursively going through all those related backnaur form of each sub expression given above. I am still scratching my head how does simple assignment like a=9 can fit into above back naur form. Specially how does the 9, on the RHS of the given statement can fall into yield_expression or starred_exression

1

There are 1 best solutions below

14
user513951 On BEST ANSWER

Isn't it right here?

starred_expression ::=  expression | …

A starred_expression can be just an expression. It must be the case that expression encompasses numeric literals like 9.

(Edited for clarity following comments.)

UPDATE

Here is the full line from starred_expression to 9.

starred_expression     ::=  expression | (starred_item ",")* [starred_item]
expression             ::=  conditional_expression | lambda_expr
conditional_expression ::=  or_test ["if" or_test "else" expression]
or_test                ::=  and_test | or_test "or" and_test
and_test               ::=  not_test | and_test "and" not_test
not_test               ::=  comparison | "not" not_test
comparison             ::=  or_expr (comp_operator or_expr)*
or_expr                ::=  xor_expr | or_expr "|" xor_expr
xor_expr               ::=  and_expr | xor_expr "^" and_expr
and_expr               ::=  shift_expr | and_expr "&" shift_expr
shift_expr             ::=  a_expr | shift_expr ("<<" | ">>") a_expr
a_expr                 ::=  m_expr | a_expr "+" m_expr | a_expr "-" m_expr
m_expr                 ::=  u_expr | m_expr "*" u_expr | m_expr "@" m_expr |
                              m_expr "//" u_expr | m_expr "/" u_expr |
                              m_expr "%" u_expr
u_expr                 ::=  power | "-" u_expr | "+" u_expr | "~" u_expr
power                  ::=  (await_expr | primary) ["**" u_expr]
primary                ::=  atom | attributeref | subscription | slicing | call
atom                   ::=  identifier | literal | enclosure
literal                ::=  stringliteral | bytesliteral
                              | integer | floatnumber | imagnumber
integer                ::=  decinteger | bininteger | octinteger | hexinteger
decinteger             ::=  nonzerodigit (["_"] digit)* | "0"+ (["_"] "0")*
nonzerodigit           ::=  "1"..."9"

What makes it confusing is that for every element from conditional_expression down to power, the thing that makes it look like the "thing it is" is optional!

For instance, in power, the ** operator is actually not even required. So we think of 2**16 as a power, but 2 also qualifies as a power. Similarly for or_test, an or keyword is not actually required.

It works like that all the way up. For every line, 9 satisfies the simplest version of the syntactic element with none of the optional parts included.