You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
5.1 KiB

5 months ago
"""A module providing information about the necessity of brackets"""
# Default precedence values for some basic types
PRECEDENCE = {
"Lambda": 1,
"Xor": 10,
"Or": 20,
"And": 30,
"Relational": 35,
"Add": 40,
"Mul": 50,
"Pow": 60,
"Func": 70,
"Not": 100,
"Atom": 1000,
"BitwiseOr": 36,
"BitwiseXor": 37,
"BitwiseAnd": 38
}
# A dictionary assigning precedence values to certain classes. These values are
# treated like they were inherited, so not every single class has to be named
# here.
# Do not use this with printers other than StrPrinter
PRECEDENCE_VALUES = {
"Equivalent": PRECEDENCE["Xor"],
"Xor": PRECEDENCE["Xor"],
"Implies": PRECEDENCE["Xor"],
"Or": PRECEDENCE["Or"],
"And": PRECEDENCE["And"],
"Add": PRECEDENCE["Add"],
"Pow": PRECEDENCE["Pow"],
"Relational": PRECEDENCE["Relational"],
"Sub": PRECEDENCE["Add"],
"Not": PRECEDENCE["Not"],
"Function" : PRECEDENCE["Func"],
"NegativeInfinity": PRECEDENCE["Add"],
"MatAdd": PRECEDENCE["Add"],
"MatPow": PRECEDENCE["Pow"],
"MatrixSolve": PRECEDENCE["Mul"],
"Mod": PRECEDENCE["Mul"],
"TensAdd": PRECEDENCE["Add"],
# As soon as `TensMul` is a subclass of `Mul`, remove this:
"TensMul": PRECEDENCE["Mul"],
"HadamardProduct": PRECEDENCE["Mul"],
"HadamardPower": PRECEDENCE["Pow"],
"KroneckerProduct": PRECEDENCE["Mul"],
"Equality": PRECEDENCE["Mul"],
"Unequality": PRECEDENCE["Mul"],
}
# Sometimes it's not enough to assign a fixed precedence value to a
# class. Then a function can be inserted in this dictionary that takes
# an instance of this class as argument and returns the appropriate
# precedence value.
# Precedence functions
def precedence_Mul(item):
if item.could_extract_minus_sign():
return PRECEDENCE["Add"]
return PRECEDENCE["Mul"]
def precedence_Rational(item):
if item.p < 0:
return PRECEDENCE["Add"]
return PRECEDENCE["Mul"]
def precedence_Integer(item):
if item.p < 0:
return PRECEDENCE["Add"]
return PRECEDENCE["Atom"]
def precedence_Float(item):
if item < 0:
return PRECEDENCE["Add"]
return PRECEDENCE["Atom"]
def precedence_PolyElement(item):
if item.is_generator:
return PRECEDENCE["Atom"]
elif item.is_ground:
return precedence(item.coeff(1))
elif item.is_term:
return PRECEDENCE["Mul"]
else:
return PRECEDENCE["Add"]
def precedence_FracElement(item):
if item.denom == 1:
return precedence_PolyElement(item.numer)
else:
return PRECEDENCE["Mul"]
def precedence_UnevaluatedExpr(item):
return precedence(item.args[0]) - 0.5
PRECEDENCE_FUNCTIONS = {
"Integer": precedence_Integer,
"Mul": precedence_Mul,
"Rational": precedence_Rational,
"Float": precedence_Float,
"PolyElement": precedence_PolyElement,
"FracElement": precedence_FracElement,
"UnevaluatedExpr": precedence_UnevaluatedExpr,
}
def precedence(item):
"""Returns the precedence of a given object.
This is the precedence for StrPrinter.
"""
if hasattr(item, "precedence"):
return item.precedence
try:
mro = item.__class__.__mro__
except AttributeError:
return PRECEDENCE["Atom"]
for i in mro:
n = i.__name__
if n in PRECEDENCE_FUNCTIONS:
return PRECEDENCE_FUNCTIONS[n](item)
elif n in PRECEDENCE_VALUES:
return PRECEDENCE_VALUES[n]
return PRECEDENCE["Atom"]
PRECEDENCE_TRADITIONAL = PRECEDENCE.copy()
PRECEDENCE_TRADITIONAL['Integral'] = PRECEDENCE["Mul"]
PRECEDENCE_TRADITIONAL['Sum'] = PRECEDENCE["Mul"]
PRECEDENCE_TRADITIONAL['Product'] = PRECEDENCE["Mul"]
PRECEDENCE_TRADITIONAL['Limit'] = PRECEDENCE["Mul"]
PRECEDENCE_TRADITIONAL['Derivative'] = PRECEDENCE["Mul"]
PRECEDENCE_TRADITIONAL['TensorProduct'] = PRECEDENCE["Mul"]
PRECEDENCE_TRADITIONAL['Transpose'] = PRECEDENCE["Pow"]
PRECEDENCE_TRADITIONAL['Adjoint'] = PRECEDENCE["Pow"]
PRECEDENCE_TRADITIONAL['Dot'] = PRECEDENCE["Mul"] - 1
PRECEDENCE_TRADITIONAL['Cross'] = PRECEDENCE["Mul"] - 1
PRECEDENCE_TRADITIONAL['Gradient'] = PRECEDENCE["Mul"] - 1
PRECEDENCE_TRADITIONAL['Divergence'] = PRECEDENCE["Mul"] - 1
PRECEDENCE_TRADITIONAL['Curl'] = PRECEDENCE["Mul"] - 1
PRECEDENCE_TRADITIONAL['Laplacian'] = PRECEDENCE["Mul"] - 1
PRECEDENCE_TRADITIONAL['Union'] = PRECEDENCE['Xor']
PRECEDENCE_TRADITIONAL['Intersection'] = PRECEDENCE['Xor']
PRECEDENCE_TRADITIONAL['Complement'] = PRECEDENCE['Xor']
PRECEDENCE_TRADITIONAL['SymmetricDifference'] = PRECEDENCE['Xor']
PRECEDENCE_TRADITIONAL['ProductSet'] = PRECEDENCE['Xor']
def precedence_traditional(item):
"""Returns the precedence of a given object according to the
traditional rules of mathematics.
This is the precedence for the LaTeX and pretty printer.
"""
# Integral, Sum, Product, Limit have the precedence of Mul in LaTeX,
# the precedence of Atom for other printers:
from sympy.core.expr import UnevaluatedExpr
if isinstance(item, UnevaluatedExpr):
return precedence_traditional(item.args[0])
n = item.__class__.__name__
if n in PRECEDENCE_TRADITIONAL:
return PRECEDENCE_TRADITIONAL[n]
return precedence(item)