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