1
0
forked from VimPlug/jedi

slice precedences should be working as well.

This commit is contained in:
Dave Halter
2014-03-09 01:05:46 +01:00
parent 29cfdfeab1
commit 48dd8f9cb0
2 changed files with 26 additions and 9 deletions

View File

@@ -40,14 +40,14 @@ class PythonGrammar(object):
#TEST = or_test ['if' or_test 'else' test] | lambdef #TEST = or_test ['if' or_test 'else' test] | lambdef
#SLICEOP = ':' [test] SLICE = ':',
#SUBSCRIPT = test | [test] ':' [test] [sliceop]
ORDER = (POWER, TERM, ARITH_EXPR, SHIFT_EXPR, AND_EXPR, XOR_EXPR, ORDER = (POWER, TERM, ARITH_EXPR, SHIFT_EXPR, AND_EXPR, XOR_EXPR,
EXPR, COMPARISON, AND_TEST, OR_TEST) EXPR, COMPARISON, AND_TEST, OR_TEST, SLICE)
FACTOR_PRIORITY = 0 # highest priority FACTOR_PRIORITY = 0 # highest priority
LOWEST_PRIORITY = len(ORDER) LOWEST_PRIORITY = len(ORDER)
NOT_TEST_PRIORITY = LOWEST_PRIORITY - 2 # priority only lower for `and`/`or` NOT_TEST_PRIORITY = LOWEST_PRIORITY - 3 # priority only lower for `and`/`or`
SLICE_PRIORITY = LOWEST_PRIORITY - 1 # priority only lower for `and`/`or`
class Precedence(object): class Precedence(object):
@@ -89,6 +89,10 @@ def _get_number(iterator, priority=PythonGrammar.LOWEST_PRIORITY):
elif el in PythonGrammar.NOT_TEST \ elif el in PythonGrammar.NOT_TEST \
and priority >= PythonGrammar.NOT_TEST_PRIORITY: and priority >= PythonGrammar.NOT_TEST_PRIORITY:
right = _get_number(iterator, PythonGrammar.NOT_TEST_PRIORITY) right = _get_number(iterator, PythonGrammar.NOT_TEST_PRIORITY)
elif el in PythonGrammar.SLICE \
and priority >= PythonGrammar.SLICE_PRIORITY:
iterator.push_back(el)
return None
else: else:
_syntax_error(el) _syntax_error(el)
return _get_number(iterator, priority) return _get_number(iterator, priority)
@@ -98,12 +102,9 @@ def _get_number(iterator, priority=PythonGrammar.LOWEST_PRIORITY):
def _check_operator(iterator, priority=PythonGrammar.LOWEST_PRIORITY): def _check_operator(iterator, priority=PythonGrammar.LOWEST_PRIORITY):
"""
"""
try: try:
left = _get_number(iterator, priority) left = _get_number(iterator, priority)
except StopIteration: except StopIteration:
_syntax_error(iterator.current, 'SyntaxError operand missing')
return None return None
for el in iterator: for el in iterator:
@@ -143,6 +144,8 @@ def _check_operator(iterator, priority=PythonGrammar.LOWEST_PRIORITY):
if operator == '**': if operator == '**':
check_prio += 1 # to the power of is right-associative check_prio += 1 # to the power of is right-associative
right = _check_operator(iterator, check_prio) right = _check_operator(iterator, check_prio)
if right is not None: if right is None and not operator in PythonGrammar.SLICE:
_syntax_error(iterator.current, 'SyntaxError operand missing')
else:
left = Precedence(left, str(operator), right) left = Precedence(left, str(operator), right)
return left return left

View File

@@ -2,9 +2,12 @@ from jedi.parser import Parser
from jedi.evaluate import precedence from jedi.evaluate import precedence
def parse_tree(statement_string): def parse_tree(statement_string, is_slice=False):
p = Parser(statement_string, no_docstr=True) p = Parser(statement_string, no_docstr=True)
stmt = p.module.statements[0] stmt = p.module.statements[0]
if is_slice:
# get the part of the execution that is the slice
stmt = stmt.expression_list()[0].execution[0]
iterable = iter(stmt.expression_list()) iterable = iter(stmt.expression_list())
pr = precedence.create_precedence(iterable) pr = precedence.create_precedence(iterable)
if isinstance(pr, precedence.Precedence): if isinstance(pr, precedence.Precedence):
@@ -51,3 +54,14 @@ def test_multi_part():
def test_power(): def test_power():
assert parse_tree('2 ** 3 ** 4') == (2, '**', (3, '**', 4)) assert parse_tree('2 ** 3 ** 4') == (2, '**', (3, '**', 4))
def test_slice():
"""
Should be parsed as normal operators. This is not proper Python syntax,
but the warning shouldn't be given in the precedence generation.
"""
assert parse_tree('[0][2+1:3]', is_slice=True) == ((2, '+', 1), ':', 3)
assert parse_tree('[0][:]', is_slice=True) == (None, ':', None)
assert parse_tree('[0][1:]', is_slice=True) == (1, ':', None)
assert parse_tree('[0][:2]', is_slice=True) == (None, ':', 2)