1
0
forked from VimPlug/jedi

basic implementation of recursive array parser in statement

This commit is contained in:
David Halter
2013-02-07 14:06:14 +01:00
parent 5be5d08441
commit edb401eb48

View File

@@ -662,8 +662,9 @@ class Statement(Simple):
'_assignment_calls_calculated') '_assignment_calls_calculated')
def __init__(self, module, code, set_vars, used_funcs, used_vars, def __init__(self, module, code, set_vars, used_funcs, used_vars,
token_list, start_pos, end_pos): token_list, start_pos, end_pos, parent=None):
super(Statement, self).__init__(module, start_pos, end_pos) super(Statement, self).__init__(module, start_pos, end_pos)
# TODO remove code -> much cleaner
self.code = code self.code = code
self.used_funcs = used_funcs self.used_funcs = used_funcs
self.used_vars = used_vars self.used_vars = used_vars
@@ -671,6 +672,7 @@ class Statement(Simple):
for s in set_vars + used_funcs + used_vars: for s in set_vars + used_funcs + used_vars:
s.parent = self.use_as_parent s.parent = self.use_as_parent
self.set_vars = self._remove_executions_from_set_vars(set_vars) self.set_vars = self._remove_executions_from_set_vars(set_vars)
self.parent = parent
# cache # cache
self._assignment_calls = None self._assignment_calls = None
@@ -741,6 +743,49 @@ class Statement(Simple):
This is not really nice written, sorry for that. If you plan to replace This is not really nice written, sorry for that. If you plan to replace
it and make it nicer, that would be cool :-) it and make it nicer, that would be cool :-)
""" """
brackets = {'(': Array.TUPLE, '[': Array.LIST, '{': Array.SET}
closing_brackets = [')', '}', ']']
def parse_array(token_iterator, array_type, start_pos):
arr = Array(start_pos, array_type)
maybe_dict = array_type == Array.SET
while True:
statement, break_tok = parse_statement(token_iterator,
start_pos, maybe_dict)
if statement is not None:
is_key = maybe_dict and break_tok == ':'
arr.add_statement(statement, is_key)
return arr
def parse_statement(token_iterator, start_pos, maybe_dict=False):
token_list = []
level = 0
tok = None
for i, tok_temp in token_iterator:
try:
token_type, tok, start_tok_pos = tok_temp
except TypeError:
# the token is a Name, which has already been parsed
tok = tok_temp
end_pos = tok.end_pos
else:
if tok in closing_brackets:
level -= 1
elif tok in brackets.keys():
level += 1
if level == 0 and tok in closing_brackets + (',',):
break
token_list.append(tok_temp)
if not token_list:
return None, tok
statement = Statement(self.module, "XXX" + self.code, [], [], [],
token_list, start_pos, end_pos)
statement.parent = self.parent
return statement
if self._assignment_calls_calculated: if self._assignment_calls_calculated:
return self._assignment_calls return self._assignment_calls
self._assignment_details = [] self._assignment_details = []
@@ -749,8 +794,11 @@ class Statement(Simple):
is_chain = False is_chain = False
close_brackets = False close_brackets = False
tok_iter = enumerate(self.token_list) is_call = lambda: type(result) == Call
for i, tok_temp in tok_iter: is_call_or_close = lambda: is_call() or close_brackets
token_iterator = enumerate(self.token_list)
for i, tok_temp in token_iterator:
#print 'tok', tok_temp, result #print 'tok', tok_temp, result
if isinstance(tok_temp, ListComprehension): if isinstance(tok_temp, ListComprehension):
result.add_to_current_field(tok_temp) result.add_to_current_field(tok_temp)
@@ -782,14 +830,18 @@ class Statement(Simple):
is_chain = False is_chain = False
continue continue
elif tok == 'as': elif tok == 'as':
next(tok_iter, None) next(token_iterator, None)
continue continue
# here starts the statement creation madness! if level >= 0:
brackets = {'(': Array.TUPLE, '[': Array.LIST, '{': Array.SET} if tok in brackets.keys(): # brackets
is_call = lambda: type(result) == Call level += 1
is_call_or_close = lambda: is_call() or close_brackets elif tok in closing_brackets:
level -= 1
if level == 0:
pass
# here starts the statement creation madness!
is_literal = token_type in [tokenize.STRING, tokenize.NUMBER] is_literal = token_type in [tokenize.STRING, tokenize.NUMBER]
if isinstance(tok, Name) or is_literal: if isinstance(tok, Name) or is_literal:
_tok = tok _tok = tok
@@ -847,7 +899,7 @@ class Statement(Simple):
# important - it cannot be empty anymore # important - it cannot be empty anymore
if result.type == Array.NOARRAY: if result.type == Array.NOARRAY:
result.type = Array.TUPLE result.type = Array.TUPLE
elif tok in [')', '}', ']']: elif tok in closing_brackets:
while is_call_or_close(): while is_call_or_close():
result = result.parent result = result.parent
close_brackets = False close_brackets = False
@@ -1021,7 +1073,7 @@ class Array(Call):
below. below.
:type array_type: int :type array_type: int
""" """
NOARRAY = None NOARRAY = None # just brackets, like `1 * (3 + 2)`
TUPLE = 'tuple' TUPLE = 'tuple'
LIST = 'list' LIST = 'list'
DICT = 'dict' DICT = 'dict'
@@ -1056,7 +1108,15 @@ class Array(Call):
one array. one array.
""" """
self.arr_el_pos.append(start_pos) self.arr_el_pos.append(start_pos)
self.values.append([]) self.statements.append([])
def add_statement(self, statement, is_key=False):
"""Just add a new statement"""
statement.parent = self
if is_key:
self.keys.append(statement)
else:
self.values.append(statement)
def add_to_current_field(self, tok): def add_to_current_field(self, tok):
""" Adds a token to the latest field (in content). """ """ Adds a token to the latest field (in content). """