ne pouvait pas tout à fait comprendre qu'il manipulait liste des listes ou un ensemble de listes ou liste des jeux etc ..
Il ne distingue pas les listes de jeux ou autre:
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [listmaker] ']' |
'{' [dictorsetmaker] '}' |
'`' testlist1 '`' |
NAME | NUMBER | STRING+)
La façon dont ils traitent la récursivité du type que vous décrivez est que listmaker
, dictorsetmaker
etc. peuvent finalement contenir atom
. Par exemple:
listmaker: test (list_for | (',' test)* [','])
test: or_test ['if' or_test 'else' test] | lambdef
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)*
expr: xor_expr ('|' xor_expr)*
xor_expr: and_expr ('^' and_expr)*
and_expr: shift_expr ('&' shift_expr)*
shift_expr: arith_expr (('<<'|'>>') arith_expr)*
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
power: atom trailer* ['**' factor]
Il y a beaucoup d'intermédiaires; c'est parce qu'ils doivent établir la priorité pour un groupe d'opérateurs mathématiques. Puis il list_for
, ce qui permet d'ajouter les trucs supplémentaires pour une compréhension de la liste.
Un exemple beaucoup plus simplifiée pourrait ressembler à:
atom: ('[' [list_or_set] ']' |
'{' [list_or_set] '}' |
NAME | NUMBER | STRING+)
list_or_set: atom (',' atom)* [',']
Ou si vous voulez que la distinction entre les listes et les ensembles à effectuer à ce niveau:
atom: list | set | NAME | NUMBER | STRING+
list: '[' atom (',' atom)* [','] ']'
set: '{' atom (',' atom)* [','] '}'
« Il ne fait pas la distinction » est faux; il y a, bien sûr, des productions séparées 'listmaker' et' dictorsetmaker', et l'analyseur peut compter sur cela pour construire l'AST au lieu de devoir revérifier les parenthèses pour comprendre ce qu'il a. –