first succeeding precedence tests

This commit is contained in:
Dave Halter
2014-01-31 11:12:28 +01:00
parent 62a74a6d2f
commit cd1660dc53
4 changed files with 105 additions and 42 deletions

View File

@@ -82,6 +82,7 @@ from jedi.evaluate.cache import memoize_default
from jedi.evaluate import stdlib
from jedi.evaluate import finder
from jedi.evaluate import compiled
from jedi.evaluate import precedence
class Evaluator(object):
@@ -138,25 +139,11 @@ class Evaluator(object):
It is used to evaluate a two dimensional object, that has calls, arrays and
operators in it.
"""
def evaluate_list_comprehension(lc, parent=None):
input = lc.input
nested_lc = lc.input.token_list[0]
if isinstance(nested_lc, pr.ListComprehension):
# is nested LC
input = nested_lc.stmt
module = input.get_parent_until()
# create a for loop, which does the same as list comprehensions
loop = pr.ForFlow(module, [input], lc.stmt.start_pos, lc.middle, True)
loop.parent = parent or lc.get_parent_until(pr.IsScope)
if isinstance(nested_lc, pr.ListComprehension):
loop = evaluate_list_comprehension(nested_lc, loop)
return loop
debug.dbg('eval_expression_list: %s', expression_list)
result = []
calls_iterator = iter(expression_list)
if len(expression_list) > 1:
print expression_list
for call in calls_iterator:
if pr.Array.is_type(call, pr.Array.NOARRAY):
r = list(itertools.chain.from_iterable(self.eval_statement(s)
@@ -166,7 +153,7 @@ class Evaluator(object):
result += self.follow_path(call_path, r, call.parent,
position=call.start_pos)
elif isinstance(call, pr.ListComprehension):
loop = evaluate_list_comprehension(call)
loop = _evaluate_list_comprehension(call)
# Caveat: parents are being changed, but this doesn't matter,
# because nothing else uses it.
call.stmt.parent = loop
@@ -374,3 +361,20 @@ def filter_private_variable(scope, call_scope, var_name):
if s != scope.base.base:
return True
return False
def _evaluate_list_comprehension(lc, parent=None):
input = lc.input
nested_lc = lc.input.token_list[0]
if isinstance(nested_lc, pr.ListComprehension):
# is nested LC
input = nested_lc.stmt
module = input.get_parent_until()
# create a for loop, which does the same as list comprehensions
loop = pr.ForFlow(module, [input], lc.stmt.start_pos, lc.middle, True)
loop.parent = parent or lc.get_parent_until(pr.IsScope)
if isinstance(nested_lc, pr.ListComprehension):
loop = _evaluate_list_comprehension(nested_lc, loop)
return loop

View File

@@ -0,0 +1,71 @@
"""
Handles operator precedence.
"""
from jedi.parser import representation as pr
class PythonGrammar(object):
"""
Some kind of mirror of http://docs.python.org/3/reference/grammar.html.
"""
class AtStart(tuple):
pass
class MultiPart(str):
def __new__(cls, first, second):
self = str.__new__(cls, first)
self.second = second
factor = AtStart(('+', '-', '~'))
power = '**',
term = '*', '/', '%', '//'
arith_expr = '+', '-'
shift_expr = '<<', '>>'
and_expr = '&',
xor_expr = '^',
expr = '|',
comparison = ('<', '>', '==', '>=', '<=', '!=', 'in',
MultiPart('not', 'in'), 'is', MultiPart('is', 'not'))
not_test = AtStart(('not',))
and_test = 'and',
or_test = 'or',
#test = or_test ['if' or_test 'else' test] | lambdef
#sliceop = ':' [test]
#subscript = test | [test] ':' [test] [sliceop]
order = (factor, power, term, arith_expr, shift_expr, and_expr, xor_expr,
expr, comparison, not_test, and_test, or_test)
class Precedence(object):
def __init__(self, left, operator, right=None):
self.left = left
self.operator = operator
self.right = right
def create_precedence(expression_list, previous=None):
element = next(expression_list, None)
if element is None:
return previous
if isinstance(element, pr.Call):
element = str(element.name)
elif not isinstance(element, str):
if previous is None:
previous = element
return create_precedence(expression_list, previous=previous)
for term in PythonGrammar.order:
if element in term:
right = create_precedence(expression_list)
if right is None:
return previous
else:
return Precedence(previous, element, right)

View File

@@ -1,25 +0,0 @@
"""
Test Jedi's operation understanding. Jedi should understand simple additions,
multiplications, etc.
"""
x = [1, '', 'a', 1.0]
#? int() str() float()
x[12]
#? str()
x[1 + 1]
index = 0 + 1
#? str()
x[index]
def calculate(number):
return number + constant
constant = 1
#? float()
x[calculate(2)]

View File

@@ -0,0 +1,13 @@
from jedi.evaluate import precedence
def test_simple():
p = precedence.create_precedence(iter([1, '+', 2]))
assert p.left == 1
assert p.operator == '+'
assert p.right == 2
def test_invalid():
"""Should just return a simple operation"""
assert precedence.create_precedence(iter([1, '+'])) == 1