'\nThis module defines the data structures used to represent a grammar.\n\nSpecifying grammars in pgen is possible with this grammar::\n\n    grammar: (NEWLINE | rule)* ENDMARKER\n    rule: NAME \':\' rhs NEWLINE\n    rhs: items (\'|\' items)*\n    items: item+\n    item: \'[\' rhs \']\' | atom [\'+\' | \'*\']\n    atom: \'(\' rhs \')\' | NAME | STRING\n\nThis grammar is self-referencing.\n\nThis parser generator (pgen2) was created by Guido Rossum and used for lib2to3.\nMost of the code has been refactored to make it more Pythonic. Since this was a\n"copy" of the CPython Parser parser "pgen", there was some work needed to make\nit more readable. It should also be slightly faster than the original pgen2,\nbecause we made some optimizations.\n'
_E='    %s -> %d'
_D='(final)'
_C='  State'
_B=False
_A=None
from ast import literal_eval
from typing import TypeVar,Generic,Mapping,Sequence,Set,Union
from parso.pgen2.grammar_parser import GrammarParser,NFAState
_TokenTypeT=TypeVar('_TokenTypeT')
class Grammar(Generic[_TokenTypeT]):
	'\n    Once initialized, this class supplies the grammar tables for the\n    parsing engine implemented by parse.py.  The parsing engine\n    accesses the instance variables directly.\n\n    The only important part in this parsers are dfas and transitions between\n    dfas.\n    '
	def __init__(A,start_nonterminal,rule_to_dfas,reserved_syntax_strings):A.nonterminal_to_dfas=rule_to_dfas;A.reserved_syntax_strings=reserved_syntax_strings;A.start_nonterminal=start_nonterminal
class DFAPlan:
	'\n    Plans are used for the parser to create stack nodes and do the proper\n    DFA state transitions.\n    '
	def __init__(A,next_dfa,dfa_pushes=[]):A.next_dfa=next_dfa;A.dfa_pushes=dfa_pushes
	def __repr__(A):return'%s(%s, %s)'%(A.__class__.__name__,A.next_dfa,A.dfa_pushes)
class DFAState(Generic[_TokenTypeT]):
	'\n    The DFAState object is the core class for pretty much anything. DFAState\n    are the vertices of an ordered graph while arcs and transitions are the\n    edges.\n\n    Arcs are the initial edges, where most DFAStates are not connected and\n    transitions are then calculated to connect the DFA state machines that have\n    different nonterminals.\n    '
	def __init__(A,from_rule,nfa_set,final):C=final;B=nfa_set;assert isinstance(B,set);assert isinstance(next(iter(B)),NFAState);assert isinstance(C,NFAState);A.from_rule=from_rule;A.nfa_set=B;A.arcs={};A.nonterminal_arcs={};A.transitions={};A.is_final=C in B
	def add_arc(B,next_,label):C=next_;A=label;assert isinstance(A,str);assert A not in B.arcs;assert isinstance(C,DFAState);B.arcs[A]=C
	def unifystate(A,old,new):
		for(B,C)in A.arcs.items():
			if C is old:A.arcs[B]=new
	def __eq__(B,other):
		A=other;assert isinstance(A,DFAState)
		if B.is_final!=A.is_final:return _B
		if len(B.arcs)!=len(A.arcs):return _B
		for(C,D)in B.arcs.items():
			if D is not A.arcs.get(C):return _B
		return True
	def __repr__(A):return'<%s: %s is_final=%s>'%(A.__class__.__name__,A.from_rule,A.is_final)
class ReservedString:
	'\n    Most grammars will have certain keywords and operators that are mentioned\n    in the grammar as strings (e.g. "if") and not token types (e.g. NUMBER).\n    This class basically is the former.\n    '
	def __init__(A,value):A.value=value
	def __repr__(A):return'%s(%s)'%(A.__class__.__name__,A.value)
def _simplify_dfas(dfas):
	'\n    This is not theoretically optimal, but works well enough.\n    Algorithm: repeatedly look for two states that have the same\n    set of arcs (same labels pointing to the same nodes) and\n    unify them, until things stop changing.\n\n    dfas is a list of DFAState instances\n    ';A=dfas;B=True
	while B:
		B=_B
		for(F,C)in enumerate(A):
			for D in range(F+1,len(A)):
				E=A[D]
				if C==E:
					del A[D]
					for G in A:G.unifystate(E,C)
					B=True;break
def _make_dfas(start,finish):
	'\n    Uses the powerset construction algorithm to create DFA states from sets of\n    NFA states.\n\n    Also does state reduction if some states are not needed.\n    ';E=finish;A=start;assert isinstance(A,NFAState);assert isinstance(E,NFAState)
	def F(nfa_state,base_nfa_set):
		B=base_nfa_set;A=nfa_state;assert isinstance(A,NFAState)
		if A in B:return
		B.add(A)
		for C in A.arcs:
			if C.nonterminal_or_string is _A:F(C.next,B)
	H=set();F(A,H);B=[DFAState(A.from_rule,H,E)]
	for I in B:
		J={}
		for K in I.nfa_set:
			for G in K.arcs:
				if G.nonterminal_or_string is not _A:C=J.setdefault(G.nonterminal_or_string,set());F(G.next,C)
		for(L,C)in J.items():
			for D in B:
				if D.nfa_set==C:break
			else:D=DFAState(A.from_rule,C,E);B.append(D)
			I.add_arc(D,L)
	return B
def _dump_nfa(start,finish):
	D=start;print('Dump of NFA for',D.from_rule);A=[D]
	for(H,E)in enumerate(A):
		print(_C,H,E is finish and _D or'')
		for F in E.arcs:
			G,B=F.nonterminal_or_string,F.next
			if B in A:C=A.index(B)
			else:C=len(A);A.append(B)
			if G is _A:print('    -> %d'%C)
			else:print(_E%(G,C))
def _dump_dfas(dfas):
	A=dfas;print('Dump of DFA for',A[0].from_rule)
	for(C,B)in enumerate(A):
		print(_C,C,B.is_final and _D or'')
		for(D,E)in B.arcs.items():print(_E%(D,A.index(E)))
def generate_grammar(bnf_grammar,token_namespace):
	"\n    ``bnf_text`` is a grammar in extended BNF (using * for repetition, + for\n    at-least-once repetition, [] for optional parts, | for alternatives and ()\n    for grouping).\n\n    It's not EBNF according to ISO/IEC 14977. It's a dialect Python uses in its\n    own parser.\n    ";A={};C=_A
	for(D,I)in GrammarParser(bnf_grammar).parse():
		B=_make_dfas(D,I);_simplify_dfas(B);A[D.from_rule]=B
		if C is _A:C=D.from_rule
	G={}
	for(K,B)in A.items():
		for E in B:
			for(F,H)in E.arcs.items():
				if F in A:E.nonterminal_arcs[F]=H
				else:J=_make_transition(token_namespace,G,F);E.transitions[J]=DFAPlan(H)
	_calculate_tree_traversal(A);return Grammar(C,A,G)
def _make_transition(token_namespace,reserved_syntax_strings,label):
	'\n    Creates a reserved string ("if", "for", "*", ...) or returns the token type\n    (NUMBER, STRING, ...) for a given grammar terminal.\n    ';C=reserved_syntax_strings;A=label
	if A[0].isalpha():return getattr(token_namespace,A)
	else:
		assert A[0]in('"',"'"),A;assert not A.startswith('"""')and not A.startswith("'''");B=literal_eval(A)
		try:return C[B]
		except KeyError:D=C[B]=ReservedString(B);return D
def _calculate_tree_traversal(nonterminal_to_dfas):
	"\n    By this point we know how dfas can move around within a stack node, but we\n    don't know how we can add a new stack node (nonterminal transitions).\n    ";C=nonterminal_to_dfas;D={};I=list(C.keys());I.sort()
	for A in I:
		if A not in D:_calculate_first_plans(C,D,A)
	for K in C.values():
		for E in K:
			F=E.transitions
			for(A,J)in E.nonterminal_arcs.items():
				for(B,G)in D[A].items():
					if B in F:H=F[B];L=sorted([H.dfa_pushes[0].from_rule if H.dfa_pushes else H.next_dfa.from_rule,G[0].from_rule if G else J.from_rule]);raise ValueError("Rule %s is ambiguous; given a %s token, we can't determine if we should evaluate %s or %s."%((E.from_rule,B)+tuple(L)))
					F[B]=DFAPlan(J,G)
def _calculate_first_plans(nonterminal_to_dfas,first_plans,nonterminal):
	'\n    Calculates the first plan in the first_plans dictionary for every given\n    nonterminal. This is going to be used to know when to create stack nodes.\n    ';F=nonterminal_to_dfas;A=nonterminal;B=first_plans;I=F[A];C={};B[A]=_A;G=I[0]
	for(J,D)in G.transitions.items():C[J]=[D.next_dfa]
	for(H,D)in G.nonterminal_arcs.items():
		try:E=B[H]
		except KeyError:E=_calculate_first_plans(F,B,H)
		else:
			if E is _A:raise ValueError('left recursion for rule %r'%A)
		for(K,L)in E.items():C[K]=[D]+L
	B[A]=C;return C