mirror of
https://github.com/davidhalter/jedi.git
synced 2026-05-19 23:09:43 +08:00
basic precedence algorithm - not tested yet
This commit is contained in:
+80
-70
@@ -12,37 +12,41 @@ class PythonGrammar(object):
|
|||||||
Some kind of mirror of http://docs.python.org/3/reference/grammar.html.
|
Some kind of mirror of http://docs.python.org/3/reference/grammar.html.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class AtStart(tuple):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class MultiPart(str):
|
class MultiPart(str):
|
||||||
def __new__(cls, first, second):
|
def __new__(cls, first, second):
|
||||||
self = str.__new__(cls, first)
|
self = str.__new__(cls, first)
|
||||||
self.second = second
|
self.second = second
|
||||||
|
|
||||||
factor = AtStart(('+', '-', '~'))
|
def __str__(self):
|
||||||
power = '**',
|
return self.__str__() + ' ' + self.second
|
||||||
term = '*', '/', '%', '//'
|
|
||||||
arith_expr = '+', '-'
|
|
||||||
|
|
||||||
shift_expr = '<<', '>>'
|
FACTOR = '+', '-', '~'
|
||||||
and_expr = '&',
|
POWER = '**',
|
||||||
xor_expr = '^',
|
TERM = '*', '/', '%', '//'
|
||||||
expr = '|',
|
ARITH_EXPR = '+', '-'
|
||||||
|
|
||||||
comparison = ('<', '>', '==', '>=', '<=', '!=', 'in',
|
SHIFT_EXPR = '<<', '>>'
|
||||||
MultiPart('not', 'in'), 'is', MultiPart('is', 'not'))
|
AND_EXPR = '&',
|
||||||
|
XOR_EXPR = '^',
|
||||||
|
EXPR = '|',
|
||||||
|
|
||||||
not_test = AtStart(('not',))
|
COMPARISON = ('<', '>', '==', '>=', '<=', '!=', 'in',
|
||||||
and_test = 'and',
|
MultiPart('not', 'in'), MultiPart('is', 'not')), 'is'
|
||||||
or_test = 'or',
|
|
||||||
|
|
||||||
#test = or_test ['if' or_test 'else' test] | lambdef
|
NOT_TEST = 'not',
|
||||||
|
AND_TEST = 'and',
|
||||||
|
OR_TEST = 'or',
|
||||||
|
|
||||||
#sliceop = ':' [test]
|
#TEST = or_test ['if' or_test 'else' test] | lambdef
|
||||||
#subscript = test | [test] ':' [test] [sliceop]
|
|
||||||
order = (factor, power, term, arith_expr, shift_expr, and_expr, xor_expr,
|
#SLICEOP = ':' [test]
|
||||||
expr, comparison, not_test, and_test, or_test)
|
#SUBSCRIPT = test | [test] ':' [test] [sliceop]
|
||||||
|
ORDER = (POWER, TERM, ARITH_EXPR, SHIFT_EXPR, AND_EXPR, XOR_EXPR,
|
||||||
|
EXPR, COMPARISON, AND_TEST, OR_TEST)
|
||||||
|
|
||||||
|
FACTOR_PRIORITY = 0 # highest priority
|
||||||
|
LOWEST_PRIORITY = len(ORDER)
|
||||||
|
NOT_TEST_PRIORITY = LOWEST_PRIORITY - 2 # priority only lower for `and`/`or`
|
||||||
|
|
||||||
|
|
||||||
class Precedence(object):
|
class Precedence(object):
|
||||||
@@ -51,58 +55,64 @@ class Precedence(object):
|
|||||||
self.operator = operator
|
self.operator = operator
|
||||||
self.right = right
|
self.right = right
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '(%s %s %s)' % (self.left, self.operator, self.right)
|
||||||
|
|
||||||
|
|
||||||
def create_precedence(expression_list):
|
def create_precedence(expression_list):
|
||||||
def get_op(current, expression_list):
|
iterator = PushBackIterator(expression_list)
|
||||||
for element in expression_list:
|
return _check_operator(iterator)
|
||||||
return
|
|
||||||
if not isinstance(obj, str):
|
|
||||||
debug.warning('normal element in place of operator: %s', element)
|
def _syntax_error(element, msg='SyntaxError in precedence'):
|
||||||
|
debug.warning('%s: %s, %s' % (msg, element, element.start_pos))
|
||||||
|
|
||||||
|
|
||||||
|
def _get_number(iterator, priority=PythonGrammar.LOWEST_PRIORITY):
|
||||||
|
el = next(iterator)
|
||||||
|
if isinstance(el, pr.Operator):
|
||||||
|
if el in PythonGrammar.FACTOR:
|
||||||
|
right = _get_number(iterator, PythonGrammar.FACTOR_PRIORITY)
|
||||||
|
elif el in PythonGrammar.NOT_TEST and priority <= PythonGrammar.FACTOR_PRIORITY:
|
||||||
|
right = _get_number(iterator, PythonGrammar.NOT_TEST_PRIORITY)
|
||||||
|
else:
|
||||||
|
_syntax_error(el)
|
||||||
|
return _get_number(iterator, priority)
|
||||||
|
return Precedence(None, el, right)
|
||||||
|
else:
|
||||||
|
return el
|
||||||
|
|
||||||
|
|
||||||
|
def _check_operator(iterator, priority=PythonGrammar.LOWEST_PRIORITY):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
left = _get_number(iterator, priority)
|
||||||
|
for el in iterator:
|
||||||
|
if not isinstance(el, pr.Operator):
|
||||||
|
_syntax_error(el)
|
||||||
|
continue
|
||||||
|
|
||||||
|
operator = None
|
||||||
|
for check_prio, check in enumerate(PythonGrammar.ORDER):
|
||||||
|
if check_prio >= priority:
|
||||||
|
break # respect priorities.
|
||||||
|
|
||||||
|
try:
|
||||||
|
match = check.index(el)
|
||||||
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
def is_operator(obj):
|
if isinstance(match, PythonGrammar.MultiPart):
|
||||||
if isinstance(obj, pr.Call):
|
next_tok = next(iterator)
|
||||||
element = str(obj.name)
|
if next_tok != match.second:
|
||||||
for term in PythonGrammar.order:
|
iterator.push_back(next_tok)
|
||||||
pass
|
continue
|
||||||
return element
|
|
||||||
|
|
||||||
def tokenize():
|
operator = check
|
||||||
pass
|
break
|
||||||
|
|
||||||
new
|
if operator is None:
|
||||||
current = None
|
_syntax_error(el)
|
||||||
exp_iterator = PushBackIterator(expression_list)
|
continue
|
||||||
for element in expression_list:
|
left = Precedence(left, operator, _check_operator(iterator, check_prio))
|
||||||
op_name = element
|
return left
|
||||||
if isinstance(element, pr.Call):
|
|
||||||
op_name = str(element.name)
|
|
||||||
current = s
|
|
||||||
if isinstance(element, pr.Call):
|
|
||||||
x = str(element.name)
|
|
||||||
new = _process_element(element, expression_list)
|
|
||||||
if current is None:
|
|
||||||
current = new
|
|
||||||
else:
|
|
||||||
current = _process_element(element, expression_list)
|
|
||||||
return current
|
|
||||||
|
|
||||||
|
|
||||||
def _process_element(element, expression_list, previous=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 _process_element(expression_list, previous=previous)
|
|
||||||
|
|
||||||
for term in PythonGrammar.order:
|
|
||||||
if element in term:
|
|
||||||
right = _process_element(expression_list)
|
|
||||||
if right is None:
|
|
||||||
return previous
|
|
||||||
else:
|
|
||||||
return Precedence(previous, element, right)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user