forked from VimPlug/jedi
basic listcomprehension/lambda move
This commit is contained in:
@@ -297,7 +297,7 @@ class Parser(object):
|
|||||||
return scope
|
return scope
|
||||||
|
|
||||||
def _parse_statement(self, pre_used_token=None, added_breaks=None,
|
def _parse_statement(self, pre_used_token=None, added_breaks=None,
|
||||||
stmt_class=pr.Statement, list_comp=False):
|
stmt_class=pr.Statement):
|
||||||
"""
|
"""
|
||||||
Parses statements like:
|
Parses statements like:
|
||||||
|
|
||||||
@@ -355,79 +355,9 @@ class Parser(object):
|
|||||||
set_vars.append(n)
|
set_vars.append(n)
|
||||||
tok_list.append(n)
|
tok_list.append(n)
|
||||||
continue
|
continue
|
||||||
elif tok == 'lambda':
|
elif tok in ['lambda', 'for', 'in']:
|
||||||
params = []
|
pass # don't parse these keywords, parse later in stmt.
|
||||||
start_pos = self.start_pos
|
|
||||||
while tok != ':':
|
|
||||||
param, tok = self._parse_statement(
|
|
||||||
added_breaks=[':', ','], stmt_class=pr.Param)
|
|
||||||
if param is None:
|
|
||||||
break
|
|
||||||
params.append(param)
|
|
||||||
if tok != ':':
|
|
||||||
continue
|
|
||||||
|
|
||||||
lambd = pr.Lambda(self.module, params, start_pos)
|
|
||||||
ret, tok = self._parse_statement(added_breaks=[','])
|
|
||||||
if ret is not None:
|
|
||||||
ret.parent = lambd
|
|
||||||
lambd.returns.append(ret)
|
|
||||||
lambd.parent = self.scope
|
|
||||||
lambd.end_pos = self.end_pos
|
|
||||||
tok_list[-1] = lambd
|
|
||||||
continue
|
|
||||||
elif token_type == tokenize.NAME:
|
elif token_type == tokenize.NAME:
|
||||||
if tok == 'for':
|
|
||||||
# list comprehensions!
|
|
||||||
middle, tok = self._parse_statement(
|
|
||||||
added_breaks=['in'])
|
|
||||||
if tok != 'in' or middle is None:
|
|
||||||
if middle is None:
|
|
||||||
level -= 1
|
|
||||||
else:
|
|
||||||
middle.parent = self.scope
|
|
||||||
debug.warning('list comprehension formatting @%s' %
|
|
||||||
self.start_pos[0])
|
|
||||||
continue
|
|
||||||
|
|
||||||
b = [')', ']']
|
|
||||||
in_clause, tok = self._parse_statement(added_breaks=b,
|
|
||||||
list_comp=True)
|
|
||||||
if tok not in b or in_clause is None:
|
|
||||||
middle.parent = self.scope
|
|
||||||
if in_clause is None:
|
|
||||||
self._gen.push_last_back()
|
|
||||||
else:
|
|
||||||
in_clause.parent = self.scope
|
|
||||||
in_clause.parent = self.scope
|
|
||||||
debug.warning('list comprehension in_clause %s@%s'
|
|
||||||
% (repr(tok), self.start_pos[0]))
|
|
||||||
continue
|
|
||||||
other_level = 0
|
|
||||||
|
|
||||||
for i, tok in enumerate(reversed(tok_list)):
|
|
||||||
if not isinstance(tok, (pr.Name,
|
|
||||||
pr.ListComprehension)):
|
|
||||||
tok = tok[1]
|
|
||||||
if tok in closing_brackets:
|
|
||||||
other_level -= 1
|
|
||||||
elif tok in opening_brackets:
|
|
||||||
other_level += 1
|
|
||||||
if other_level > 0:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# could not detect brackets -> nested list comp
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
tok_list, toks = tok_list[:-i], tok_list[-i:-1]
|
|
||||||
st = pr.Statement(self.module, [], [],
|
|
||||||
toks, first_pos, self.end_pos)
|
|
||||||
|
|
||||||
tok = pr.ListComprehension(st, middle, in_clause,
|
|
||||||
self.scope)
|
|
||||||
tok_list.append(tok)
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
n, token_type, tok = self._parse_dot_name(self.current)
|
n, token_type, tok = self._parse_dot_name(self.current)
|
||||||
# removed last entry, because we add Name
|
# removed last entry, because we add Name
|
||||||
tok_list.pop()
|
tok_list.pop()
|
||||||
|
|||||||
@@ -499,8 +499,9 @@ class Flow(Scope):
|
|||||||
"""
|
"""
|
||||||
Get the names for the flow. This includes also a call to the super
|
Get the names for the flow. This includes also a call to the super
|
||||||
class.
|
class.
|
||||||
:param is_internal_call: defines an option for internal files to crawl\
|
|
||||||
through this class. Normally it will just call its superiors, to\
|
:param is_internal_call: defines an option for internal files to crawl
|
||||||
|
through this class. Normally it will just call its superiors, to
|
||||||
generate the output.
|
generate the output.
|
||||||
"""
|
"""
|
||||||
if is_internal_call:
|
if is_internal_call:
|
||||||
@@ -756,7 +757,8 @@ class Statement(Simple):
|
|||||||
return isinstance(tok, (str, unicode)) and tok.endswith('=') \
|
return isinstance(tok, (str, unicode)) and tok.endswith('=') \
|
||||||
and not tok in ['>=', '<=', '==', '!=']
|
and not tok in ['>=', '<=', '==', '!=']
|
||||||
|
|
||||||
def parse_array(token_iterator, array_type, start_pos, add_el=None):
|
def parse_array(token_iterator, array_type, start_pos, add_el=None,
|
||||||
|
added_breaks=()):
|
||||||
arr = Array(self._sub_module, start_pos, array_type, self)
|
arr = Array(self._sub_module, start_pos, array_type, self)
|
||||||
if add_el is not None:
|
if add_el is not None:
|
||||||
arr.add_statement(add_el)
|
arr.add_statement(add_el)
|
||||||
@@ -765,8 +767,9 @@ class Statement(Simple):
|
|||||||
break_tok = None
|
break_tok = None
|
||||||
is_array = None
|
is_array = None
|
||||||
while True:
|
while True:
|
||||||
stmt, break_tok = parse_array_el(token_iterator, maybe_dict,
|
stmt, break_tok = parse_stmt(token_iterator, maybe_dict,
|
||||||
break_on_assignment=bool(add_el))
|
break_on_assignment=bool(add_el),
|
||||||
|
added_breaks=added_breaks)
|
||||||
if stmt is None:
|
if stmt is None:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
@@ -774,7 +777,9 @@ class Statement(Simple):
|
|||||||
is_array = True
|
is_array = True
|
||||||
is_key = maybe_dict and break_tok == ':'
|
is_key = maybe_dict and break_tok == ':'
|
||||||
arr.add_statement(stmt, is_key)
|
arr.add_statement(stmt, is_key)
|
||||||
if break_tok in closing_brackets or is_assignment(break_tok):
|
if break_tok in closing_brackets \
|
||||||
|
or break_tok in added_breaks \
|
||||||
|
or is_assignment(break_tok):
|
||||||
break
|
break
|
||||||
if arr.type == Array.TUPLE and len(arr) == 1 and not is_array:
|
if arr.type == Array.TUPLE and len(arr) == 1 and not is_array:
|
||||||
arr.type = Array.NOARRAY
|
arr.type = Array.NOARRAY
|
||||||
@@ -791,12 +796,14 @@ class Statement(Simple):
|
|||||||
else 0)
|
else 0)
|
||||||
return arr, break_tok
|
return arr, break_tok
|
||||||
|
|
||||||
def parse_array_el(token_iterator, maybe_dict=False,
|
def parse_stmt(token_iterator, maybe_dict=False, added_breaks=(),
|
||||||
break_on_assignment=False):
|
break_on_assignment=False, stmt_class=Statement):
|
||||||
token_list = []
|
token_list = []
|
||||||
|
used_vars = []
|
||||||
level = 1
|
level = 1
|
||||||
tok = None
|
tok = None
|
||||||
first = True
|
first = True
|
||||||
|
end_pos = None
|
||||||
for i, tok_temp in token_iterator:
|
for i, tok_temp in token_iterator:
|
||||||
if isinstance(tok_temp, Base):
|
if isinstance(tok_temp, Base):
|
||||||
# the token is a Name, which has already been parsed
|
# the token is a Name, which has already been parsed
|
||||||
@@ -808,19 +815,33 @@ class Statement(Simple):
|
|||||||
if isinstance(tok, ListComprehension):
|
if isinstance(tok, ListComprehension):
|
||||||
# it's not possible to set it earlier
|
# it's not possible to set it earlier
|
||||||
tok.parent = self
|
tok.parent = self
|
||||||
|
if isinstance(tok, Name):
|
||||||
|
used_vars.append(tok)
|
||||||
else:
|
else:
|
||||||
token_type, tok, start_tok_pos = tok_temp
|
token_type, tok, start_tok_pos = tok_temp
|
||||||
|
last_end_pos = end_pos
|
||||||
end_pos = start_tok_pos[0], start_tok_pos[1] + len(tok)
|
end_pos = start_tok_pos[0], start_tok_pos[1] + len(tok)
|
||||||
if first:
|
if first:
|
||||||
first = False
|
first = False
|
||||||
start_pos = start_tok_pos
|
start_pos = start_tok_pos
|
||||||
|
|
||||||
|
if tok == 'lambda':
|
||||||
|
lambd = parse_lambda(token_iterator)
|
||||||
|
if lambd is not None:
|
||||||
|
token_list.append(lambd)
|
||||||
|
elif tok == 'for':
|
||||||
|
list_comp, tok = parse_list_comp(token_iterator,
|
||||||
|
token_list, start_pos, last_end_pos)
|
||||||
|
if list_comp is not None:
|
||||||
|
token_list = [list_comp]
|
||||||
|
|
||||||
if tok in closing_brackets:
|
if tok in closing_brackets:
|
||||||
level -= 1
|
level -= 1
|
||||||
elif tok in brackets.keys():
|
elif tok in brackets.keys():
|
||||||
level += 1
|
level += 1
|
||||||
|
|
||||||
if level == 0 and tok in closing_brackets \
|
if level == 0 and tok in closing_brackets \
|
||||||
|
or tok in added_breaks \
|
||||||
or level == 1 and (tok == ','
|
or level == 1 and (tok == ','
|
||||||
or maybe_dict and tok == ':'
|
or maybe_dict and tok == ':'
|
||||||
or is_assignment(tok) and break_on_assignment):
|
or is_assignment(tok) and break_on_assignment):
|
||||||
@@ -831,11 +852,101 @@ class Statement(Simple):
|
|||||||
if not token_list:
|
if not token_list:
|
||||||
return None, tok
|
return None, tok
|
||||||
|
|
||||||
statement = Statement(self._sub_module, [], [],
|
statement = Statement(self._sub_module, [], [], token_list,
|
||||||
token_list, start_pos, end_pos)
|
start_pos, end_pos, self.parent)
|
||||||
statement.parent = self.parent
|
statement.used_vars = used_vars
|
||||||
return statement, tok
|
return statement, tok
|
||||||
|
|
||||||
|
def parse_lambda(token_iterator):
|
||||||
|
params = []
|
||||||
|
start_pos = self.start_pos
|
||||||
|
tok = next(token_iterator)
|
||||||
|
while tok != ':':
|
||||||
|
param, tok = parse_stmt(token_iterator,
|
||||||
|
added_breaks=[':', ','], stmt_class=Param)
|
||||||
|
if param is None:
|
||||||
|
break
|
||||||
|
params.append(param)
|
||||||
|
if tok != ':':
|
||||||
|
return None, tok
|
||||||
|
|
||||||
|
lambd = Lambda(self.module, params, start_pos)
|
||||||
|
ret, tok = self._parse_statement(added_breaks=[','])
|
||||||
|
if ret is not None:
|
||||||
|
ret.parent = lambd
|
||||||
|
lambd.returns.append(ret)
|
||||||
|
lambd.parent = self.scope
|
||||||
|
lambd.end_pos = self.end_pos
|
||||||
|
return lambd
|
||||||
|
|
||||||
|
|
||||||
|
def parse_list_comp(token_iterator, token_list, start_pos, end_pos):
|
||||||
|
def parse_stmt_or_arr(token_iterator, added_breaks=()):
|
||||||
|
stmt, tok = parse_stmt(token_iterator, added_breaks=added_breaks)
|
||||||
|
if tok == ',':
|
||||||
|
arr, tok = parse_array(token_iterator, Array.TUPLE,
|
||||||
|
stmt.start_pos, stmt,
|
||||||
|
added_breaks=added_breaks)
|
||||||
|
used_vars = []
|
||||||
|
for stmt in arr:
|
||||||
|
used_vars += stmt.used_vars
|
||||||
|
start_pos = arr.start_pos[0], arr.start_pos[1] - 1
|
||||||
|
stmt = Statement(self._sub_module, [], used_vars, [],
|
||||||
|
start_pos, arr.end_pos)
|
||||||
|
arr.parent = stmt
|
||||||
|
stmt.token_list = stmt._commands = [arr]
|
||||||
|
else:
|
||||||
|
for v in stmt.used_vars:
|
||||||
|
v.parent = stmt
|
||||||
|
return stmt, tok
|
||||||
|
|
||||||
|
st = Statement(self._sub_module, [], [], token_list, start_pos,
|
||||||
|
end_pos)
|
||||||
|
|
||||||
|
middle, tok = parse_stmt_or_arr(token_iterator, added_breaks=['in'])
|
||||||
|
if tok != 'in' or middle is None:
|
||||||
|
#if middle is None:
|
||||||
|
# level -= 1
|
||||||
|
#else:
|
||||||
|
#middle.parent = self.scope
|
||||||
|
debug.warning('list comprehension formatting @%s' %
|
||||||
|
start_pos[0])
|
||||||
|
return None, tok
|
||||||
|
|
||||||
|
in_clause, tok = parse_stmt_or_arr(token_iterator)
|
||||||
|
"""
|
||||||
|
if tok not in b or in_clause is None:
|
||||||
|
#middle.parent = self.scope
|
||||||
|
if in_clause is None:
|
||||||
|
self._gen.push_last_back()
|
||||||
|
#else:
|
||||||
|
# in_clause.parent = self.scope
|
||||||
|
# in_clause.parent = self.scope
|
||||||
|
debug.warning('list comprehension in_clause %s@%s'
|
||||||
|
% (repr(tok), start_pos[0]))
|
||||||
|
return None, tok
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
other_level = 0
|
||||||
|
|
||||||
|
for i, tok in enumerate(reversed(token_list)):
|
||||||
|
if not isinstance(tok, (Name, ListComprehension)):
|
||||||
|
tok = tok[1]
|
||||||
|
if tok in closing_brackets:
|
||||||
|
other_level -= 1
|
||||||
|
elif tok in brackets.keys():
|
||||||
|
other_level += 1
|
||||||
|
if other_level > 0:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# could not detect brackets -> nested list comp
|
||||||
|
i = 0
|
||||||
|
"""
|
||||||
|
#token_list, toks = token_list[:-i], token_list[-i:-1]
|
||||||
|
|
||||||
|
|
||||||
|
return ListComprehension(st, middle, in_clause, self), tok
|
||||||
|
|
||||||
# initializations
|
# initializations
|
||||||
result = []
|
result = []
|
||||||
is_chain = False
|
is_chain = False
|
||||||
@@ -860,7 +971,7 @@ class Statement(Simple):
|
|||||||
is_chain = False
|
is_chain = False
|
||||||
start = i + 1
|
start = i + 1
|
||||||
continue
|
continue
|
||||||
elif tok == 'as': # just ignore as
|
elif tok == 'as': # just ignore as, because it sets values
|
||||||
next(token_iterator, None)
|
next(token_iterator, None)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -893,7 +1004,7 @@ class Statement(Simple):
|
|||||||
is_chain = True
|
is_chain = True
|
||||||
elif tok == ',': # implies a tuple
|
elif tok == ',': # implies a tuple
|
||||||
# rewrite `result`, because now the whole thing is a tuple
|
# rewrite `result`, because now the whole thing is a tuple
|
||||||
add_el, t = parse_array_el(enumerate(self.token_list[start:i]))
|
add_el, t = parse_stmt(enumerate(self.token_list[start:i]))
|
||||||
arr, break_tok = parse_array(token_iterator, Array.TUPLE,
|
arr, break_tok = parse_array(token_iterator, Array.TUPLE,
|
||||||
add_el.start_pos, add_el)
|
add_el.start_pos, add_el)
|
||||||
result = [arr]
|
result = [arr]
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class RecursionDecorator(object):
|
|||||||
def push_stmt(self, stmt):
|
def push_stmt(self, stmt):
|
||||||
self.current = RecursionNode(stmt, self.current)
|
self.current = RecursionNode(stmt, self.current)
|
||||||
check = self._check_recursion()
|
check = self._check_recursion()
|
||||||
if check:
|
if check:# TODO remove False!!!!
|
||||||
debug.warning('catched stmt recursion: %s against %s @%s'
|
debug.warning('catched stmt recursion: %s against %s @%s'
|
||||||
% (stmt, check.stmt, stmt.start_pos))
|
% (stmt, check.stmt, stmt.start_pos))
|
||||||
self.pop_stmt()
|
self.pop_stmt()
|
||||||
|
|||||||
Reference in New Issue
Block a user