#!/usr/bin/env python3.8
# @generated by pegen from metagrammar.gram

import ast
import sys
import tokenize

from typing import Any, Optional

from pegen.parser import memoize, memoize_left_rec, logger, Parser
from ast import literal_eval

from pegen.grammar import (
    Alt,
    Cut,
    Forced,
    Gather,
    Group,
    Item,
    Lookahead,
    LookaheadOrCut,
    MetaTuple,
    MetaList,
    NameLeaf,
    NamedItem,
    NamedItemList,
    NegativeLookahead,
    Opt,
    Plain,
    PositiveLookahead,
    Repeat0,
    Repeat1,
    Rhs,
    Rule,
    RuleList,
    RuleName,
    Grammar,
    StringLeaf,
)

# Keywords and soft keywords are listed at the end of the parser definition.
class GeneratedParser(Parser):

    @memoize
    def start(self) -> Optional[Grammar]:
        # start: grammar $
        mark = self._mark()
        if (
            (grammar := self.grammar())
            and
            (_endmarker := self.expect('ENDMARKER'))
        ):
            return grammar
        self._reset(mark)
        return None

    @memoize
    def grammar(self) -> Optional[Grammar]:
        # grammar: metas rules | rules
        mark = self._mark()
        if (
            (metas := self.metas())
            and
            (rules := self.rules())
        ):
            return Grammar ( rules , metas )
        self._reset(mark)
        if (
            (rules := self.rules())
        ):
            return Grammar ( rules , [] )
        self._reset(mark)
        return None

    @memoize
    def metas(self) -> Optional[MetaList]:
        # metas: meta metas | meta
        mark = self._mark()
        if (
            (meta := self.meta())
            and
            (metas := self.metas())
        ):
            return [meta] + metas
        self._reset(mark)
        if (
            (meta := self.meta())
        ):
            return [meta]
        self._reset(mark)
        return None

    @memoize
    def meta(self) -> Optional[MetaTuple]:
        # meta: "@" NAME NEWLINE | "@" NAME NAME NEWLINE | "@" NAME STRING NEWLINE
        mark = self._mark()
        if (
            (literal := self.expect("@"))
            and
            (name := self.name())
            and
            (_newline := self.expect('NEWLINE'))
        ):
            return ( name . string , None )
        self._reset(mark)
        if (
            (literal := self.expect("@"))
            and
            (a := self.name())
            and
            (b := self.name())
            and
            (_newline := self.expect('NEWLINE'))
        ):
            return ( a . string , b . string )
        self._reset(mark)
        if (
            (literal := self.expect("@"))
            and
            (name := self.name())
            and
            (string := self.string())
            and
            (_newline := self.expect('NEWLINE'))
        ):
            return ( name . string , literal_eval ( string . string ) )
        self._reset(mark)
        return None

    @memoize
    def rules(self) -> Optional[RuleList]:
        # rules: rule rules | rule
        mark = self._mark()
        if (
            (rule := self.rule())
            and
            (rules := self.rules())
        ):
            return [rule] + rules
        self._reset(mark)
        if (
            (rule := self.rule())
        ):
            return [rule]
        self._reset(mark)
        return None

    @memoize
    def rule(self) -> Optional[Rule]:
        # rule: rulename memoflag? ":" alts NEWLINE INDENT more_alts DEDENT | rulename memoflag? ":" NEWLINE INDENT more_alts DEDENT | rulename memoflag? ":" alts NEWLINE
        mark = self._mark()
        if (
            (rulename := self.rulename())
            and
            (opt := self.memoflag(),)
            and
            (literal := self.expect(":"))
            and
            (alts := self.alts())
            and
            (_newline := self.expect('NEWLINE'))
            and
            (_indent := self.expect('INDENT'))
            and
            (more_alts := self.more_alts())
            and
            (_dedent := self.expect('DEDENT'))
        ):
            return Rule ( rulename [0] , rulename [1] , Rhs ( alts . alts + more_alts . alts ) , memo = opt )
        self._reset(mark)
        if (
            (rulename := self.rulename())
            and
            (opt := self.memoflag(),)
            and
            (literal := self.expect(":"))
            and
            (_newline := self.expect('NEWLINE'))
            and
            (_indent := self.expect('INDENT'))
            and
            (more_alts := self.more_alts())
            and
            (_dedent := self.expect('DEDENT'))
        ):
            return Rule ( rulename [0] , rulename [1] , more_alts , memo = opt )
        self._reset(mark)
        if (
            (rulename := self.rulename())
            and
            (opt := self.memoflag(),)
            and
            (literal := self.expect(":"))
            and
            (alts := self.alts())
            and
            (_newline := self.expect('NEWLINE'))
        ):
            return Rule ( rulename [0] , rulename [1] , alts , memo = opt )
        self._reset(mark)
        return None

    @memoize
    def rulename(self) -> Optional[RuleName]:
        # rulename: NAME annotation | NAME
        mark = self._mark()
        if (
            (name := self.name())
            and
            (annotation := self.annotation())
        ):
            return ( name . string , annotation )
        self._reset(mark)
        if (
            (name := self.name())
        ):
            return ( name . string , None )
        self._reset(mark)
        return None

    @memoize
    def memoflag(self) -> Optional[str]:
        # memoflag: '(' "memo" ')'
        mark = self._mark()
        if (
            (literal := self.expect('('))
            and
            (literal_1 := self.expect("memo"))
            and
            (literal_2 := self.expect(')'))
        ):
            return "memo"
        self._reset(mark)
        return None

    @memoize
    def alts(self) -> Optional[Rhs]:
        # alts: alt "|" alts | alt
        mark = self._mark()
        if (
            (alt := self.alt())
            and
            (literal := self.expect("|"))
            and
            (alts := self.alts())
        ):
            return Rhs ( [alt] + alts . alts )
        self._reset(mark)
        if (
            (alt := self.alt())
        ):
            return Rhs ( [alt] )
        self._reset(mark)
        return None

    @memoize
    def more_alts(self) -> Optional[Rhs]:
        # more_alts: "|" alts NEWLINE more_alts | "|" alts NEWLINE
        mark = self._mark()
        if (
            (literal := self.expect("|"))
            and
            (alts := self.alts())
            and
            (_newline := self.expect('NEWLINE'))
            and
            (more_alts := self.more_alts())
        ):
            return Rhs ( alts . alts + more_alts . alts )
        self._reset(mark)
        if (
            (literal := self.expect("|"))
            and
            (alts := self.alts())
            and
            (_newline := self.expect('NEWLINE'))
        ):
            return Rhs ( alts . alts )
        self._reset(mark)
        return None

    @memoize
    def alt(self) -> Optional[Alt]:
        # alt: items '$' action | items '$' | items action | items
        mark = self._mark()
        if (
            (items := self.items())
            and
            (literal := self.expect('$'))
            and
            (action := self.action())
        ):
            return Alt ( items + [NamedItem ( None , NameLeaf ( 'ENDMARKER' ) )] , action = action )
        self._reset(mark)
        if (
            (items := self.items())
            and
            (literal := self.expect('$'))
        ):
            return Alt ( items + [NamedItem ( None , NameLeaf ( 'ENDMARKER' ) )] , action = None )
        self._reset(mark)
        if (
            (items := self.items())
            and
            (action := self.action())
        ):
            return Alt ( items , action = action )
        self._reset(mark)
        if (
            (items := self.items())
        ):
            return Alt ( items , action = None )
        self._reset(mark)
        return None

    @memoize
    def items(self) -> Optional[NamedItemList]:
        # items: named_item items | named_item
        mark = self._mark()
        if (
            (named_item := self.named_item())
            and
            (items := self.items())
        ):
            return [named_item] + items
        self._reset(mark)
        if (
            (named_item := self.named_item())
        ):
            return [named_item]
        self._reset(mark)
        return None

    @memoize
    def named_item(self) -> Optional[NamedItem]:
        # named_item: NAME annotation '=' ~ item | NAME '=' ~ item | item | forced_atom | lookahead
        mark = self._mark()
        cut = False
        if (
            (name := self.name())
            and
            (annotation := self.annotation())
            and
            (literal := self.expect('='))
            and
            (cut := True)
            and
            (item := self.item())
        ):
            return NamedItem ( name . string , item , annotation )
        self._reset(mark)
        if cut: return None
        cut = False
        if (
            (name := self.name())
            and
            (literal := self.expect('='))
            and
            (cut := True)
            and
            (item := self.item())
        ):
            return NamedItem ( name . string , item )
        self._reset(mark)
        if cut: return None
        if (
            (item := self.item())
        ):
            return NamedItem ( None , item )
        self._reset(mark)
        if (
            (forced := self.forced_atom())
        ):
            return NamedItem ( None , forced )
        self._reset(mark)
        if (
            (it := self.lookahead())
        ):
            return NamedItem ( None , it )
        self._reset(mark)
        return None

    @memoize
    def forced_atom(self) -> Optional[Forced]:
        # forced_atom: '&' '&' ~ atom
        mark = self._mark()
        cut = False
        if (
            (literal := self.expect('&'))
            and
            (literal_1 := self.expect('&'))
            and
            (cut := True)
            and
            (atom := self.atom())
        ):
            return Forced ( atom )
        self._reset(mark)
        if cut: return None
        return None

    @memoize
    def lookahead(self) -> Optional[LookaheadOrCut]:
        # lookahead: '&' ~ atom | '!' ~ atom | '~'
        mark = self._mark()
        cut = False
        if (
            (literal := self.expect('&'))
            and
            (cut := True)
            and
            (atom := self.atom())
        ):
            return PositiveLookahead ( atom )
        self._reset(mark)
        if cut: return None
        cut = False
        if (
            (literal := self.expect('!'))
            and
            (cut := True)
            and
            (atom := self.atom())
        ):
            return NegativeLookahead ( atom )
        self._reset(mark)
        if cut: return None
        if (
            (literal := self.expect('~'))
        ):
            return Cut ( )
        self._reset(mark)
        return None

    @memoize
    def item(self) -> Optional[Item]:
        # item: '[' ~ alts ']' | atom '?' | atom '*' | atom '+' | atom '.' atom '+' | atom
        mark = self._mark()
        cut = False
        if (
            (literal := self.expect('['))
            and
            (cut := True)
            and
            (alts := self.alts())
            and
            (literal_1 := self.expect(']'))
        ):
            return Opt ( alts )
        self._reset(mark)
        if cut: return None
        if (
            (atom := self.atom())
            and
            (literal := self.expect('?'))
        ):
            return Opt ( atom )
        self._reset(mark)
        if (
            (atom := self.atom())
            and
            (literal := self.expect('*'))
        ):
            return Repeat0 ( atom )
        self._reset(mark)
        if (
            (atom := self.atom())
            and
            (literal := self.expect('+'))
        ):
            return Repeat1 ( atom )
        self._reset(mark)
        if (
            (sep := self.atom())
            and
            (literal := self.expect('.'))
            and
            (node := self.atom())
            and
            (literal_1 := self.expect('+'))
        ):
            return Gather ( sep , node )
        self._reset(mark)
        if (
            (atom := self.atom())
        ):
            return atom
        self._reset(mark)
        return None

    @memoize
    def atom(self) -> Optional[Plain]:
        # atom: '(' ~ alts ')' | NAME | STRING
        mark = self._mark()
        cut = False
        if (
            (literal := self.expect('('))
            and
            (cut := True)
            and
            (alts := self.alts())
            and
            (literal_1 := self.expect(')'))
        ):
            return Group ( alts )
        self._reset(mark)
        if cut: return None
        if (
            (name := self.name())
        ):
            return NameLeaf ( name . string )
        self._reset(mark)
        if (
            (string := self.string())
        ):
            return StringLeaf ( string . string )
        self._reset(mark)
        return None

    @memoize
    def action(self) -> Optional[str]:
        # action: "{" ~ target_atoms "}"
        mark = self._mark()
        cut = False
        if (
            (literal := self.expect("{"))
            and
            (cut := True)
            and
            (target_atoms := self.target_atoms())
            and
            (literal_1 := self.expect("}"))
        ):
            return target_atoms
        self._reset(mark)
        if cut: return None
        return None

    @memoize
    def annotation(self) -> Optional[str]:
        # annotation: "[" ~ target_atoms "]"
        mark = self._mark()
        cut = False
        if (
            (literal := self.expect("["))
            and
            (cut := True)
            and
            (target_atoms := self.target_atoms())
            and
            (literal_1 := self.expect("]"))
        ):
            return target_atoms
        self._reset(mark)
        if cut: return None
        return None

    @memoize
    def target_atoms(self) -> Optional[str]:
        # target_atoms: target_atom target_atoms | target_atom
        mark = self._mark()
        if (
            (target_atom := self.target_atom())
            and
            (target_atoms := self.target_atoms())
        ):
            return target_atom + " " + target_atoms
        self._reset(mark)
        if (
            (target_atom := self.target_atom())
        ):
            return target_atom
        self._reset(mark)
        return None

    @memoize
    def target_atom(self) -> Optional[str]:
        # target_atom: "{" ~ target_atoms? "}" | "[" ~ target_atoms? "]" | NAME "*" | NAME | NUMBER | STRING | "?" | ":" | !"}" !"]" OP
        mark = self._mark()
        cut = False
        if (
            (literal := self.expect("{"))
            and
            (cut := True)
            and
            (atoms := self.target_atoms(),)
            and
            (literal_1 := self.expect("}"))
        ):
            return "{" + ( atoms or "" ) + "}"
        self._reset(mark)
        if cut: return None
        cut = False
        if (
            (literal := self.expect("["))
            and
            (cut := True)
            and
            (atoms := self.target_atoms(),)
            and
            (literal_1 := self.expect("]"))
        ):
            return "[" + ( atoms or "" ) + "]"
        self._reset(mark)
        if cut: return None
        if (
            (name := self.name())
            and
            (literal := self.expect("*"))
        ):
            return name . string + "*"
        self._reset(mark)
        if (
            (name := self.name())
        ):
            return name . string
        self._reset(mark)
        if (
            (number := self.number())
        ):
            return number . string
        self._reset(mark)
        if (
            (string := self.string())
        ):
            return string . string
        self._reset(mark)
        if (
            (literal := self.expect("?"))
        ):
            return "?"
        self._reset(mark)
        if (
            (literal := self.expect(":"))
        ):
            return ":"
        self._reset(mark)
        if (
            self.negative_lookahead(self.expect, "}")
            and
            self.negative_lookahead(self.expect, "]")
            and
            (op := self.op())
        ):
            return op . string
        self._reset(mark)
        return None

    KEYWORDS = ()
    SOFT_KEYWORDS = ('memo',)


if __name__ == '__main__':
    from pegen.parser import simple_parser_main
    simple_parser_main(GeneratedParser)
