diff --git a/evaluate.py b/evaluate.py index 94a5bbbf..d147c8eb 100644 --- a/evaluate.py +++ b/evaluate.py @@ -2,14 +2,26 @@ import parsing def get_names_for_scope(scope): """ Get all completions possible for the current scope. """ - comp = [] + compl = [] start_scope = scope while scope: # class variables/functions are only availabe if not isinstance(scope, parsing.Class) or scope == start_scope: - comp += scope.get_set_vars() + compl += scope.get_set_vars() scope = scope.parent - return comp + return compl + + +# default: name in scope +# point: chaining +# execution: -> eval returns default & ? +def follow_statement(scope, stmt): + arr = stmt.get_assignment_calls() + return call + + +def follow_array(scope, array): + return def follow_path(scope, path): @@ -18,17 +30,17 @@ def follow_path(scope, path): recursive! :returns: list(Scope) """ - comp = get_names_for_scope(scope) - print path, comp + compl = get_names_for_scope(scope) + print path, compl path = list(path) name = path.pop(0) scopes = [] # make the full comparison, because the names have to match exactly - comp = [c for c in comp if [name] == list(c.names)] + compl = [c for c in compl if [name] == list(c.names)] # TODO differentiate between the different comp input (some are overridden) - for c in comp: + for c in compl: p_class = c.parent.__class__ if p_class == parsing.Class or p_class == parsing.Scope: scopes.append(c.parent) diff --git a/functions.py b/functions.py index a623928f..87f62072 100644 --- a/functions.py +++ b/functions.py @@ -171,7 +171,7 @@ def complete(source, row, column, file_callback=None): :type row: int :param col: The column to complete in. :type col: int - :return: list + :return: list of completion objects :rtype: list """ row = 84 @@ -198,15 +198,23 @@ def complete(source, row, column, file_callback=None): result = [] if path: - name = path.pop() if path: + # just parse one statement + r = parsing.PyFuzzyParser(".".join(path)) + print 'p', r.top.get_code(), r.top.statements[0] + evaluate.follow_statement(scope, r.top.statements[0]) + exit() + scopes = evaluate.follow_path(scope, tuple(path)) - dbg('possible scopes', scopes) - compl = [] - for s in scopes: - compl += s.get_defined_names() + dbg('possible scopes', scopes) + compl = [] + for s in scopes: + compl += s.get_defined_names() + + else: + compl = evaluate.get_names_for_scope(scope) dbg('possible-compl', compl) diff --git a/parsing.py b/parsing.py index 9531683d..989f693e 100644 --- a/parsing.py +++ b/parsing.py @@ -39,10 +39,6 @@ import cStringIO import re -class TokenNotFoundError(Exception): - pass - - class ParserError(Exception): pass @@ -502,19 +498,18 @@ class Statement(Simple): most of the statements won't need this data anyway. This is something 'like' a lazy execution. """ - result = None - has_assignment = False + result = Array(Array.EMPTY) level = 0 is_chain = False for tok_temp in self.token_list: - print 'tok', tok_temp + #print 'tok', tok_temp try: token_type, tok, indent = tok_temp - if '=' in tok and not tok in ['>=', '<=', '==', '!=']: + if level == 0 and \ + '=' in tok and not tok in ['>=', '<=', '==', '!=']: # This means, there is an assignment here. # TODO there may be multiple assignments: a = b = 1 - has_assignment = True # initialize the first item result = Array(Array.EMPTY) @@ -523,52 +518,50 @@ class Statement(Simple): # the token is a Name, which has already been parsed tok = tok_temp - if has_assignment: - brackets = {'(': Array.EMPTY, '[': Array.LIST, '{': Array.SET} - is_call = isinstance(result, Call) - if isinstance(tok, Name): - call = Call(tok, result) - if is_chain: - result = result.set_next_chain_call(call) - is_chain = False - else: - result.add_to_current_field(call) - result = call - print 'asdf', result, result.parent - elif tok in brackets.keys(): - level += 1 - result = Array(brackets[tok], result) - if is_call: - result = result.parent.add_execution(result) - else: - result.parent.add_to_current_field(result) - elif tok == ':': - if is_call: - result = result.parent - result.add_dictionary_key() - elif tok == '.': - is_chain = True - elif tok == ',': - if is_call: - result = result.parent - result.add_field() - # important - it cannot be empty anymore - if result.arr_type == Array.EMPTY: - result.arr_type = Array.TUPLE - elif tok in [')', '}', ']']: - level -= 1 - print 'asdf2', result, result.parent - result = result.parent + brackets = {'(': Array.EMPTY, '[': Array.LIST, '{': Array.SET} + is_call = isinstance(result, Call) + if isinstance(tok, Name): + call = Call(tok, result) + if is_chain: + result = result.set_next_chain_call(call) + is_chain = False else: - # TODO catch numbers and strings -> token_type and make - # calls out of them - if is_call: - result = result.parent - result.add_to_current_field(tok) + result.add_to_current_field(call) + result = call + elif tok in brackets.keys(): + level += 1 + result = Array(brackets[tok], result) + if is_call: + result = result.parent.add_execution(result) + else: + result.parent.add_to_current_field(result) + elif tok == ':': + if is_call: + result = result.parent + result.add_dictionary_key() + elif tok == '.': + is_chain = True + elif tok == ',': + if is_call: + result = result.parent + result.add_field() + # important - it cannot be empty anymore + if result.arr_type == Array.EMPTY: + result.arr_type = Array.TUPLE + elif tok in [')', '}', ']']: + level -= 1 + result = result.parent + else: + # TODO catch numbers and strings -> token_type and make + # calls out of them + if is_call: + result = result.parent + result.add_to_current_field(tok) - if not has_assignment: - raise TokenNotFoundError("You are requesting the result of an " - "assignment, where the token cannot be found") + if isinstance(result, Call): + # if the last added object was a name, the result will not be the + # top tree. + result = result.parent if level != 0: raise ParserError("Brackets don't match: %s. This is not normal " "behaviour. Please submit a bug" % level) @@ -635,6 +628,18 @@ class Array(object): else: return self.values + def __repr__(self): + if self.arr_type == self.EMPTY: + temp = 'empty' + elif self.arr_type == self.TUPLE: + temp = 'tuple' + elif self.arr_type == self.DICT: + temp = 'dict' + elif self.arr_type == self.SET: + temp = 'set' + return "<%s: %s of %s>" % \ + (self.__class__.__name__, temp, self.parent) + class Call(object): """ The statement object of functions, to """ @@ -660,6 +665,10 @@ class Call(object): self.executions.append(call) return call + def __repr__(self): + return "<%s: %s of %s>" % \ + (self.__class__.__name__, self.name, self.parent) + class Name(Simple): """ @@ -706,7 +715,7 @@ class PyFuzzyParser(object): """ def __init__(self, code, user_line=None): self.user_line = user_line - self.code = code + self.code = code + '\n' # end with \n, because the parser needs it # initialize global Scope self.top = Scope(0, 0) diff --git a/test.py b/test.py index 9d6d5b82..68be53d5 100644 --- a/test.py +++ b/test.py @@ -136,5 +136,5 @@ class c1(): -c1.c2.\ +c1().c2.\ c