'\nThe ``Parser`` tries to convert the available Python code in an easy to read\nformat, something like an abstract syntax tree. The classes who represent this\ntree, are sitting in the :mod:`parso.tree` module.\n\nThe Python module ``tokenize`` is a very important part in the ``Parser``,\nbecause it splits the code into different words (tokens).  Sometimes it looks a\nbit messy. Sorry for that! You might ask now: "Why didn\'t you use the ``ast``\nmodule for this? Well, ``ast`` does a very good job understanding proper Python\ncode, but fails to work as soon as there\'s a single line of broken code.\n\nThere\'s one important optimization that needs to be known: Statements are not\nbeing parsed completely. ``Statement`` is just a representation of the tokens\nwithin the statement. This lowers memory usage and cpu time and reduces the\ncomplexity of the ``Parser`` (there\'s another parser sitting inside\n``Statement``, which produces ``Array`` and ``Call``).\n'
from typing import Dict,Type
from parso import tree
from parso.pgen2.generator import ReservedString
class ParserSyntaxError(Exception):
	'\n    Contains error information about the parser tree.\n\n    May be raised as an exception.\n    '
	def __init__(A,message,error_leaf):A.message=message;A.error_leaf=error_leaf
class InternalParseError(Exception):
	"\n    Exception to signal the parser is stuck and error recovery didn't help.\n    Basically this shouldn't happen. It's a sign that something is really\n    wrong.\n    "
	def __init__(A,msg,type_,value,start_pos):B=start_pos;C=value;Exception.__init__(A,'%s: type=%r, value=%r, start_pos=%r'%(msg,type_.name,C,B));A.msg=msg;A.type=type;A.value=C;A.start_pos=B
class Stack(list):
	def _allowed_transition_names_and_token_types(C):
		def A():
			for B in reversed(C):
				for A in B.dfa.transitions:
					if isinstance(A,ReservedString):yield A.value
					else:yield A
				if not B.dfa.is_final:break
		return list(A())
class StackNode:
	def __init__(A,dfa):A.dfa=dfa;A.nodes=[]
	@property
	def nonterminal(self):return self.dfa.from_rule
	def __repr__(A):return'%s(%s, %s)'%(A.__class__.__name__,A.dfa,A.nodes)
def _token_to_transition(grammar,type_,value):
	A=type_
	if A.value.contains_syntax:
		try:return grammar.reserved_syntax_strings[value]
		except KeyError:pass
	return A
class BaseParser:
	'Parser engine.\n\n    A Parser instance contains state pertaining to the current token\n    sequence, and should not be used concurrently by different threads\n    to parse separate token sequences.\n\n    See python/tokenize.py for how to get input tokens by a string.\n\n    When a syntax error occurs, error_recovery() is called.\n    ';node_map:Dict[str,Type[tree.BaseNode]]={};default_node=tree.Node;leaf_map:Dict[str,Type[tree.Leaf]]={};default_leaf=tree.Leaf
	def __init__(A,pgen_grammar,start_nonterminal='file_input',error_recovery=False):A._pgen_grammar=pgen_grammar;A._start_nonterminal=start_nonterminal;A._error_recovery=error_recovery
	def parse(A,tokens):
		D=A._pgen_grammar.nonterminal_to_dfas[A._start_nonterminal][0];A.stack=Stack([StackNode(D)])
		for B in tokens:A._add_token(B)
		while True:
			C=A.stack[-1]
			if not C.dfa.is_final:raise InternalParseError('incomplete input',B.type,B.string,B.start_pos)
			if len(A.stack)>1:A._pop()
			else:return A.convert_node(C.nonterminal,C.nodes)
	def error_recovery(A,token):
		if A._error_recovery:raise NotImplementedError('Error Recovery is not implemented')
		else:B,C,D,E=token;F=tree.ErrorLeaf(B,C,D,E);raise ParserSyntaxError('SyntaxError: invalid syntax',F)
	def convert_node(A,nonterminal,children):
		B=children;C=nonterminal
		try:D=A.node_map[C](B)
		except KeyError:D=A.default_node(C,B)
		return D
	def convert_leaf(A,type_,value,prefix,start_pos):
		B=start_pos;C=prefix;D=value
		try:return A.leaf_map[type_](D,B,C)
		except KeyError:return A.default_leaf(D,B,C)
	def _add_token(A,token):
		'\n        This is the only core function for parsing. Here happens basically\n        everything. Everything is well prepared by the parser generator and we\n        only apply the necessary steps here.\n        ';E=token;H=A._pgen_grammar;B=A.stack;C,D,F,I=E;J=_token_to_transition(H,C,D)
		while True:
			try:G=B[-1].dfa.transitions[J];break
			except KeyError:
				if B[-1].dfa.is_final:A._pop()
				else:A.error_recovery(E);return
			except IndexError:raise InternalParseError('too much input',C,D,F)
		B[-1].dfa=G.next_dfa
		for K in G.dfa_pushes:B.append(StackNode(K))
		L=A.convert_leaf(C,D,I,F);B[-1].nodes.append(L)
	def _pop(B):
		A=B.stack.pop()
		if len(A.nodes)==1:C=A.nodes[0]
		else:C=B.convert_node(A.dfa.from_rule,A.nodes)
		B.stack[-1].nodes.append(C)