all:
    `ctx.opts = None`
    (
    args_def
    `ctx.opts = args_def.res`
    )?
    rule_seq
    `ctx.rule_defs = rule_seq.res`
    '$'

args_def:
    args_sign
    args_group
    ```
pairs = []
item = args_group
while 'arg_item' in item:
    pairs.append(item.arg_item.res)
    item = item.arg_item
args = dict(pairs)
ctx.res = args
    ```

args_sign:
    r'@'

args_group:
    brkt_beg (brkt_end | arg_item)

brkt_beg:
    r'[(]'

brkt_end:
    r'[)]'

arg_item:
    arg_expr
    ```
ctx.res = arg_expr.res
ctx.par.arg_item = ctx
    ```
    (brkt_end | arg_sep (brkt_end | arg_item))

arg_expr:
    arg_key
    arg_kvsep
    arg_val
    `ctx.res = (arg_key.res, arg_val.res)`

arg_key:
    r'[a-zA-Z_][a-zA-Z0-9_]*'
    `ctx.res = arg_key.rem.group()`

arg_kvsep:
    r'[=]'

arg_val:
    lit_val
    `ctx.res = lit_val.res`

lit_val:
    lit_str `ctx.res = lit_str.res`
    | lit_num `ctx.res = lit_num.res`
    | lit_bool `ctx.res = lit_bool.res`
    | lit_none `ctx.res = lit_none.res`

lit_str:
    'r?(\'\'\'|"""|\'|")((?:[^\\\\]|\\\\.)*?)(\\1)'
    `ctx.res = eval(lit_str.rem.group())`

lit_num:
    r"""
([-+])?         # Sign
(?=\d|[.]\d)    # Next is an integer part or a fraction part
(\d*)           # Integer part
([.]\d*)?       # Fraction part
(e[-+]?\d+)?    # Exponent part
""" @(flags='re.VERBOSE | re.IGNORECASE')
    `ctx.res = eval(lit_num.rem.group())`

lit_bool:
    r'(True|False)(?![a-zA-Z0-9_])'
    `ctx.res = True if (lit_bool.rem.group() == 'True') else False`

lit_none:
    r'None(?![a-zA-Z0-9_])'
    `ctx.res = None`

arg_sep:
    r'[,]'

rule_seq:
    `ctx.res = []`
    (rule_def
    `ctx.res.append(rule_def.res)`
    )+

rule_def:
    rule_name
    rule_colon
    `args = None`
    (args_def
    `args = args_def.res`
    )?
    rexpr_or
    `ctx.res = RuleDef(name=rule_name.res, expr=rexpr_or.res, args=args)`

rule_name:
    r'[a-zA-Z_][a-zA-Z0-9_]*'
    `ctx.res = rule_name.rem.group()`

rule_colon:
    r'[:]'

rexpr_or:
    rexpr_seq
    `items = [rexpr_seq.res]`
    (rexpr_op
    rexpr_seq
    `items.append(rexpr_seq.res)`
    )*
    `ctx.res = ExprOr(items) if len(items) > 1 else items[0]`

rexpr_op:
    r'[|]'

rexpr_seq:
    `items = []`
    (
        (code `items.append(code.res)`)*
        rexpr_occ `items.append(rexpr_occ.res)`
        (code `items.append(code.res)`)*
    ) +
    `ctx.res = ExprSeq(items) if len(items) > 1 else items[0]`

code:
    r'(`+)((?:.|\n)*?)\1'
    `ctx.res = Code(code.rem.group(2))`

rexpr_occ:
    rexpr_btm
    `occ_type = None`
    ( rexpr_occ01 `occ_type = '01'`
    | rexpr_occ0m `occ_type = '0m'`
    | rexpr_occ1m `occ_type = '1m'`
    )?
    ```
if occ_type is None:
    ctx.res = rexpr_btm.res
elif occ_type == '01':
    ctx.res = ExprOcc01(rexpr_btm.res)
elif occ_type == '0m':
    ctx.res = ExprOcc0m(rexpr_btm.res)
elif occ_type == '1m':
    ctx.res = ExprOcc1m(rexpr_btm.res)
else:
    assert 0
    ```

rexpr_occ01:
    r'[?]'

rexpr_occ0m:
    r'[*]'

rexpr_occ1m:
    r'[+]'

rexpr_btm:
    pattern
    `args = None`
    (args_def
    `args = args_def.res`
    )?
    `ctx.res = Pattern(pattern.res, args=args)`
    | rule_ref `ctx.res = rule_ref.res`
    | rexpr_group `ctx.res = rexpr_group.res`

pattern:
    'r?(\'\'\'|"""|\'|")((?:[^\\\\]|\\\\.)*?)(\\1)'
    `ctx.res = pattern.rem.group()`

rule_ref:
    r'([a-zA-Z_][a-zA-Z0-9_]*)(?![a-zA-Z0-9_])[\s]*(?![:])'
    ```
name = rule_ref.rem.group(1)
ctx.res = RuleRef(name)
    ```

rexpr_group:
    brkt_beg
    rexpr_or
    brkt_end
    `ctx.res = rexpr_or.res`
