Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 26 additions & 17 deletions sympy/parsing/sympy_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@ def _token_splittable(token):
return False


def _token_callable(token, local_dict, global_dict, nextToken=None):
"""
Predicate for whether a token name represents a callable function.
"""
func = local_dict.get(token[1])
if not func:
func = global_dict.get(token[1])
is_Function = getattr(func, 'is_Function', False)
if (is_Function or
(callable(func) and not hasattr(func, 'is_Function')) or
isinstance(nextToken, AppliedFunction)):
return True
return False


def _add_factorial_tokens(name, result):
if result == [] or result[-1][1] == '(':
raise TokenError()
Expand Down Expand Up @@ -230,32 +245,27 @@ def _implicit_application(tokens, local_dict, global_dict):
if (tok[0] == NAME and
nextTok[0] != OP and
nextTok[0] != ENDMARKER):
func = global_dict.get(tok[1])
is_Function = getattr(func, 'is_Function', False)
if (is_Function or
(callable(func) and not hasattr(func, 'is_Function')) or
isinstance(nextTok, AppliedFunction)):
if _token_callable(tok, local_dict, global_dict, nextTok):
result.append((OP, '('))
appendParen += 1
# name followed by exponent - function exponentiation
elif (tok[0] == NAME and nextTok[0] == OP and nextTok[1] == '**'):
func = global_dict.get(tok[1])
is_Function = getattr(func, 'is_Function', False)
if (is_Function or
(callable(func) and not hasattr(func, 'is_Function'))):
if _token_callable(tok, local_dict, global_dict):
exponentSkip = True
elif exponentSkip:
# if the last token added was an applied function (i.e. the
# power of the function exponent) OR a multiplication (as
# implicit multiplication would have added an extraneous
# multiplication)
if (isinstance(tok, AppliedFunction)
or tok[0] == OP and tok[1] == '*'):
or (tok[0] == OP and tok[1] == '*')):
# don't add anything if the next token is a multiplication
# or if there's already a parenthesis
if not (nextTok[0] == OP and nextTok[1] in ('*', '(')):
result.append((OP, '('))
appendParen += 1
# or if there's already a parenthesis (if parenthesis, still
# stop skipping tokens)
if not (nextTok[0] == OP and nextTok[1] == '*'):
if not(nextTok[0] == OP and nextTok[1] == '('):
result.append((OP, '('))
appendParen += 1
exponentSkip = False
elif appendParen:
if nextTok[0] == OP and nextTok[1] in ('^', '**', '*'):
Expand All @@ -271,7 +281,6 @@ def _implicit_application(tokens, local_dict, global_dict):

if appendParen:
result.extend([(OP, ')')] * appendParen)

return result


Expand All @@ -290,10 +299,10 @@ def function_exponentiation(tokens, local_dict, global_dict):
exponent = []
consuming_exponent = False
level = 0

for tok, nextTok in zip(tokens, tokens[1:]):
if tok[0] == NAME and nextTok[0] == OP and nextTok[1] == '**':
consuming_exponent = True
if _token_callable(tok, local_dict, global_dict):
consuming_exponent = True
elif consuming_exponent:
exponent.append(tok)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ def test_implicit_application():
def test_function_exponentiation():
cases = {
'sin**2(x)': 'sin(x)**2',
'exp^y(z)': 'exp(z)^y'
'exp^y(z)': 'exp(z)^y',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add trailing commas in long line-based lists like this one so that you don't end up with fake changes like this in the diff.

'sin**2(E^(x))': 'sin(E^(x))**2'
}
transformations = standard_transformations + (convert_xor,)
transformations2 = transformations + (function_exponentiation,)
Expand Down Expand Up @@ -145,7 +146,10 @@ def test_all_implicit_steps():
'sin^2 x**2': 'sin(x**2)**2', # function raised to a power
'sin**3(x)': 'sin(x)**3',
'(factorial)': 'factorial',
'tan 3x': 'tan(3*x)'
'tan 3x': 'tan(3*x)',
'sin^2(3*E^(x))': 'sin(3*E**(x))**2',
'sin**2(E^(3x))': 'sin(E**(3*x))**2',
'sin^2 (3x*E^(x))': 'sin(3*x*E^x)**2'
}
transformations = standard_transformations + (convert_xor,)
transformations2 = transformations + (implicit_multiplication_application,)
Expand Down