This is essentiallt the syntax of Python given in pysyntax.txt with
some syntactic categories renanamed plus a few minor modifications.
It also contains fragments of Ascii style flowgraphs.

Copyright (c) Martin Richards 29 Jan 2025


Category                    Replacement

aassignment_expression      NAME ':=' ~ E0
starred_expression          '*' E0

primary                     E30
await_primary               E29
power                       E28
factor                      E27
term                        E26
sum                         E25
shift_expr                  E24
bitwise_and                 E23
bitwise_xor                 E22
bitwise_or                  E21
comparison                  E20
inversion                   E19
conjuction                  E18
disjunction                 E17

expression                  E0



********************* The Rules *****************************

statements: statement+

statement: compound_stmt | simple_stmts

statement_newline:
  | compound_stment NEWLINE
  | simple_stmts
  | NEWLINE
  | ENDMARKER

simple_stmts:
  | simple_stmt !';' NEWLINE
  | ';'.simple_stmt+ [';'] NEWLINE

simple_stmt:
  | assignment
  | NAME [type_params] '=' E0
  | star_expressions
  | 'return' [star_expressions]
  | 'import' dotted_as_names
  | import_from
  | 'raise' [E0 ['from' E0 ])
  | 'pass'
  | del_stmt:
  | 'del' del_targets &(';' | NEWLINE}
  | yield_expr
  | 'assert' E0 [',' E0]
  | 'break'
  | 'continue'
  | 'global' ','.NAME+
  | 'nonlocal' ','.NAME+


assignment:
  | NAME ':' E0 ['=' annotation_rhs']
  | ('(' single_target ')'
     | single_subscript_attribute_target) ':' E0 ['=' annotated_rhs]
  | (star_targets '=' )+ (yield_expression | star_expressions) !'=' [TYPE_COMMENT]
  | single_target augassign ~ (yield_expr | star_expressions)

annotated_rhs:
  | yield_expr
  | star_expressions

augassign:
  | '+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^='
  | '<<=' | '>>=' | '**=' | '//='








import_from:
  | 'from' ('.' | '...')* dotted_name 'import' import_from_targets
  | 'from' ('.' | '...')* 'import' import_from_targets

import_from_targets:
  | '(' import_from_as_names [','] ')'
  | import_from_as_names !','
  | '*'

import_from_as_names
  | ','.import_from_as_name+

import_from_as_name:
  | NAME ['as' NAME]

dotted_as_names:
  | ','.import_as_name+

dotted_as_name:
  | dotted_as_name ',' NAME
  | NAME

block:
  | NEWLINE INDENT statements DEDENT
  | simple_stmts

decorators:
  | ('@' named_expression NEWLINE)+

class_def:
  | decorators class_def_raw
  | class_def_raw

class_def_raw:
  | 'class' NAME [type_param] ['(' [arguments] ')'] ':' block

function_def:
  | decorators function_def_raw
  | function_def_raw

function_def_raw:
  | 'def' NAME [type_params] '(' [params] ')' ['->' E0] ':' [func_type_comment] block
  | 'async' 'def' NAME [type_params] '(' [params] ')' ['->' E0] ':' [func_type_comment] block

params:
  | parameters

parameters:
  | slash_no_default param_no_default* param_with_default* [star_etc]
  | slash_with_default param_with_default* [star_etc]
  | slash_no_default+ param_with_default* [star_etc]
  | param_with_default+ [star_etc]
  | star_etc

slash_no_default:
  | param_no_default+ '/' ','
  | param_no_default+ '/' &')'

slah_with_default:
  | param_no_default+ param_with_default+ '/' ','
  | param_no_default+ param_with_default+ '/' &')'

star_etc:
  | '*' param_no_default param_with_default* [kwds]
  | '*' param_no_default_star_annotation param_maybe_default* [kwds]
  | '*' ',' param_maybe_default* [kwds]
  | kwds

kwds:
  | '**' param_nodefault

param_nodefault:
  | param ',' TYPE_COMMENT?
  | param TYPE_COMMENR? &')'

param_no_default_star_annotation:
  | param_star_annotation ',' TYPE_COMMENT?
  | param_star_annotation TYPE_COMMENT? &')'

param_with_default:
  | param default ',' TYPE_COMMENT?
  | param default TYPE_COMMENR? &')'

param_maybe_default:
  | param default? ',' TYPE_COMMENT?
  | param default? TYPE_COMMENR? &')'

param:
  | NAME annotation?

param_star_annotation:
  | NAME star_annotation

annotation:
  | ':' E0

star_annotation:
  | ':' star_expression

default:
  | '=' E0
  | invalid_default

if_stmt:
  | 'if' named_expression ':' block
     ('elif' named_expression ':' block)*
     ['else' ':' block]


while_stmt:
  | 'while' named_expression ':' block [else_block]

for_stmt:
  | [async] 'for' star_targets 'in' ~ star_expressions ':' [TYPE_COMMENT] block [else_block]

with_stmt:
  | 'with' '(' ','.with_item+ ','? ')' ':' [TYPE_COMMENT] block
  | 'with' ','.with_item+ ':' [TYPE_COMMENT] block
  | 'async' 'with' '(' ','.with_item+ ','? ')' ':' block 
  | 'async' 'with' ','.with_item+ ':' [TYPE_COMMENT] block 

with_item:
  | E0 'as' star_star_target &(',' | ')' | ':')
  | E0

try_stmt:
  | 'try' ':' block finally_block
  | 'try' ':' block except_block+ [else_block] [finally_block]
  | 'try' ':' block except_star_block+ [else_block] [finally_block]

except_block:
  | 'except' [E0 ['as' NAME]] ':' block

except_star_block:
  | 'except' '*' E0 ['as' NAME] ':' block

finally_block:
  | 'finally' ':' block

 try_stmt--[try]--[:]--(block)---------------------------------[finally]--[:]--(block)-->
                                |                            |
      --------------------------                             |
     |                                                       |
     |            ----------------[except]-------------------|
     |           |                                           |         | 
      --[except]---------(E0)---[as]--[NAME]---[:]--(block)--|
                 |            |              |               |
                 |             --------------                |
		 |                                           |
                 |----------------[except]-------------------|
                 |                                           |
                  --[*]--(E0)---[as]--[NAME}---[:]--(block)--
                              |              |
                               --------------
      

match_stmt:
  | "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT

subject_expr:
  | star_named_expression ',' start_name_expressions?
  | named_expression

case_block:
  | "case" patterns guard? : block

guard:
  | 'if' named_expression

patterns:
  | open_sequence_pattern
  | pattern

pattern:
  | as_pattern
  | or_pattern

as_pattern:
  | or_pattern 'as' pattern_capture_target

or_pattern:
  | '|'.closed_pattern+

closed_pattern:
  | literal_pattern
  | capture_pattern
  | whildcard_pattern
  | value_pattern
  | group_pattern
  | sequence_pattern
  | mapping_pattern
  | class_pattern

literal_pattern:
  | signed_number !('+' | '-')
  | complex_number
  | strings
  | 'None'
  | 'True'
  | 'False'

literal_expr:
  | signed_number !('+' | '-')
  | complex_number
  | strings
  | 'None'
  | 'True'
  | 'False'

complex_number:
  | signed_real_number '+' NUMBER
  | signed_real_number '-' NUMBER

signed_number:
  | ['-'] NUMBER

real_number:
  | NUMBER

capture_pattern:
  | pattern_capture_target

pattern_capture_target:
  | !'_' NAME !(',' | '(' | '=')

whildcard_pattern:
  | '_'

value_pattern:
  | attr !('.' | ' (' | '=')

attr:
  | (attr | NAME) '.' NAME

name_or_attr:
  | attr
  | NAME

group_pattern:
  | '(' pattern ')'

sequence_pattern:
  | '[' maybe_sequence_pattern? ']'
  | '[' open_sequence_pattern? ']'

open_sequence_pattern:
  | maybe_star_pattern ',' maybe_sequence_pattern?

maybe_sequence_pattern:
  | ','.maybe_star_pattern+ ','?

maybe_star_pattern:
  | star_pattern
  | pattern

star_pattern:
  | '*' pattern_capture_target
  | '*' wildcard_pattern

mapping_pattern:
  | '{' '}'
  | '{' double_star_pattern ','? '}'
  | '{' items_pattern ',; double_star_pattern ','? '}'
  | '{' items_pattern ','? '}'

items_pattern:
  | ','.key_value_pattern+

key_value_pattern:
  | (literal_expr | attr) ':' pattern

double_star_pattern:
  | '**' pattern_capture_target

class_pattern:
  | name_or_attr '(' ')'
  | name_or_attr '(' positional_patterns ','? ')'
  | name_or_attr '(' keyword_patterns ','? ')'
  | name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'

positional_patterns:
  | ','.pattern+

keyword_patterns:
  | ','.keyword_pattern+

keyword_pattern:
  | NAME '=' pattern


type_params:
  | invalid-type_params
  | '[' type_params_seq ']'

type_param-seq:
  | ','.type_para+ [',']

type_param:
  | NAME [type_param_bound] [type_param_default]
  | '*' NAME [type_param_starred_default]
  | '**' NAME [type param_default]

type_param_bound:
  | ':' E0

type_param_default:
  | '=' E0

type_param_starred_default:
  | '=' star_expression

bexpo:

expressions:
  | E0 (',' E0)* [',']

E0:
  | E17 'if' E17 'else' E0
  | E17
  | lambdef

yield_expr:
  | 'yield' 'from' E0
  | 'yield' [star_expression]

star_expressions:
  | star_expression (',' start_expression )* [',']

star_expression:
  | '*' E21
  | E0

star_named_expressions:
  | ','.star_named_expression+ [',']

star_named_expression:
  | '*' E21
  | named_expression

named_expression:
  | NAME ':=' ~ E0
  | E0 !':='

E17:
  | E18 ('or' E18)+
  | E18

E18:
  | E19 ('and' E19)+
  | E19

E19:
  | 'not' E19
  | E20

E20:
  | E21 '=='       E21
  | E21 '!='       E21
  | E21 '<='       E21
  | E21 '<'        E21
  | E21 '>='       E21
  | E21 '>'        E21
  | E21 'not' 'in' E21
  | E21 'in'       E21
  | E21 'is' 'not' E21
  | E21 'is'       E21
  | E21

E21:
  | E21 '|' E22
  | E22

E22:
  | E22 '^' E23
  | E23

E23:
  | E23 '&' E24
  | E24

E24:
  | E24 '<<' E25
  | E24 '>>' E25
  | E25

E25:
  | E25 '+' E26
  | E25 '-' E26
  | E26

E26:
  | E26 '*'  E27
  | E26 '/'  E27
  | E26 '//' E27
  | E26 '%'  E27
  | E26 '@'  E27
  | E27

E27:
  | '+' E27
  | '-' E27
  | '~' E27
  | E28

E28:
  | E29 '**' E27
  | E29

E29:
  | 'await' E30
  | E30

E30:
  | E30 '.' NAME
  | E30 '(' [arguments] ')'
  | E30 '[' slices ']'
  | atom

slices:
  | slice !','
  | ','.(slices | '*' E0)+ [',']

slice:
  | [E0] ':' [E0] [':' [E0] ]
  | named_expression

atom:
  | NAME
  | 'True'
  | 'False'
  | 'None'
  | strings
  | NUMBER
  | (tuple | group | genexp)
  | (list | listcomp)
  | (dict | set | dictcomp | setcomp)
  | '...'

group:
  | '(' (yield_expr | named_expression) ')'

lambdef:
| 'lambda' [lambda_params] ':' E0

lambda_params:
  | lambda_parameters

lambda_parameters:
  | lambda_slash_no_default lambda_param_no default* lambda_param_with_default* [lambda_star_etc]
  | lambda_slash_with_default lambda_param_with_default* [lambda_star_etc]
  | lambda_param_no_default* lambda_param_with_default* [lambda_star_etc]
  | lambda_param_with_default* [lambda_star_etc]
  | lambda_star_etc  

lambda_slash_no_default:
  | lambda_param_no_default+ '/' ','
  | lambda_param_no_default+ '/' &':

lambda_slash_with_default:
  | lambda_param_no_default* lambda_param_with_default+ '/' ','
  | lambda_param_no_default* lambda_param_with_default+ '/' &':

lambda_star_etc:
  | '*' lambda_param_no_default lambda_param_maybe_default* [lambda_kwds]
  | '*' ',' lambda_param_maybe_default+ [lambda_kwds]
  | lambda_kwds

lambda_kwds:
  | '**' lambda_param_no_default

lambda_param_no_default:
  | lambda_param ','
  | lambda_param &':'

lambda_param_with_default:
  | lambda_param default ','
  | lambda_param default &':'

lambd_param_maybe_default:
  | lambda_param default? ','
  | lambda_param default? &':'

lambda_param:
  | NAME
  
  
fstring_middle:
  | fstring_replacement_field
  | FSTRING_MIDDLE

fstring_replacement_field:
  | '(' annotated_rhs '=' [fstring_conversion] [fstring_full_format_spec] '}'

fstring_conversion:
  | ':' NAME

fstring_full_format_spec:
  | ':' fstring_format_spec:

fstring_format_spec:
  | FSTRING_MIDDLE
  | fstring_replacement_field

fstring:
  | FSTRING_START fstring_middle* FSTRING_END

string:
  | STRING

strings:
  | (fstring | string)+

list:
  | '[' [star_named_expression] ']'



tuple:
  | '(' [star_named_expression ',' [star_named_expressions] ] ')'

set:
  | '{' star_named_expressions '}'

dict:
  | '{' [double_starred_kvpairs] '}'

double_starred-kvpair:
  | '**' E21
  | kvpair

kvpair:
  | E0 ':' E0

for_if_clauses:
  | for_if_clause+

for_if_clause:
  | ['async'] 'for' star_targets 'in' ~ E17 ('if' E17)*

listcomp:
  | '[' named_expression for_if_clauses ']'

setcomp:
  | '{' named_expression for_if_clauses '}'

genexp:
  | '(' ( NAME ':=' ~ E0 | E0 !':=') for_if_clauses ')'

dictcomp:
  | '{' kvpair for_if_clauses '}'

arguments:
  | args [','] &')'

args:
  | ','.('*' E0 | ( NAME ':=' ~ E0 | E0 !':=') !'=')+ [',' kwargs]
  | kwargs

kwargs:
  | ','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+
  | ','.kwarg_or_starred+
  | ','.kwarg_or_double_starred+

starred_expression:
  | '*' E0

kwarg_or_starred:
  | NAME '=' E0
  | '*' E0

kwarg_or_double_starred:
  | NAME '=' E0
  | '**' E0

                -----------------[,]----------------
	       |                                    |
kwargs -[n:=0]-----[NAME}--[=  n=0 n:=1]------(E0)--------->
               |                           |
	       |-----------[*  n<1 n:=1]---|
               |                           |
	        -----------[**     n:=2]---


star_targets:
  | star_target !','
  | star_target (',' star_target)* [',']

star_targets_list_seq:
  | ','.star_target+ [',']

star_targets_tuple_seq:
  | star_target (',' star_target )+ [','] [',']
  | star_target ','

star_target:
  | '*' (!'*' star_target)
  | target_with_star_atom

target_with_star_atom:
  | t_primary ',' NAME !t_lookahead
  | t_primary '[' slices ']' !t_lookahead
  | star_atom

star_atom:
  | NAME
  | '(' target_with_star_atom ')'
  | '[' [star_targets_tuple_seq] ']'
  | '{' [star_targets_list_seq] '}'

single_target:
  | single_subscript_attribute_target
  | NAME
  | '(' single_target ')'

single_subscript_attribute_target:
  | t_primary ',' NAME !t_lookahead
  | t_primary '[' slices ']' !t_lookahead

t_primary:
  | t_primary ',' NAME &t_lookahead
  | t_primary '[' slices ']' &!t_lookahead
  | t_primary genexp &!t_lookahead
  | t_primary '(' [arguments] ')' &!t_lookahead
  | atom &!t_lookahead

t_lookahead:
  | '('
  | '['
  | '{'

del_targets:
  | ','.deltarget+ [',']

del_target:
  | t_primary ',' NAME !t_lookahead
  | t_primary '[' slices ']' !t_lookahead
  | del_atom

del_atom:
  | NAME
  | '(' del_target ')'
  | '(' [del_targets] ')'
  | '[' [del_targets] ']'

type_expression:
  | ','.E0+ ',' '*' E0 ',' '**' E0
  | ','.E0+ ',' '*' E0
  | ','.E0+ ',' '**' E0
  | '*' E0 ',' '**' E0
  | '*' E0
  | '**' E0
  | ','.E0+

func_type_comment:
  | NEWLINE TYPE_COMMENT &(NEWLINE INDENT)
  | TYPE_COMMENT
  
