這是一個相當很長,但仍然不完整的方法,不以任何方式涉及sympy。這是足以覆蓋其被翻譯爲\frac{- b - \sqrt{b^{2} - 4 \; a \; c}}{2 \; a}
,並呈現爲
它基本上創建AST並指導其生產的乳膠數學的對應於AST節點(-b-sqrt(b**2-4*a*c))/(2*a)
的例子。那裏有什麼應該給予足夠的想法如何在它缺乏的地方擴展它。
import ast
class LatexVisitor(ast.NodeVisitor):
def prec(self, n):
return getattr(self, 'prec_'+n.__class__.__name__, getattr(self, 'generic_prec'))(n)
def visit_Call(self, n):
func = self.visit(n.func)
args = ', '.join(map(self.visit, n.args))
if func == 'sqrt':
return '\sqrt{%s}' % args
else:
return r'\operatorname{%s}\left(%s\right)' % (func, args)
def prec_Call(self, n):
return 1000
def visit_Name(self, n):
return n.id
def prec_Name(self, n):
return 1000
def visit_UnaryOp(self, n):
if self.prec(n.op) > self.prec(n.operand):
return r'%s \left(%s\right)' % (self.visit(n.op), self.visit(n.operand))
else:
return r'%s %s' % (self.visit(n.op), self.visit(n.operand))
def prec_UnaryOp(self, n):
return self.prec(n.op)
def visit_BinOp(self, n):
if self.prec(n.op) > self.prec(n.left):
left = r'\left(%s\right)' % self.visit(n.left)
else:
left = self.visit(n.left)
if self.prec(n.op) > self.prec(n.right):
right = r'\left(%s\right)' % self.visit(n.right)
else:
right = self.visit(n.right)
if isinstance(n.op, ast.Div):
return r'\frac{%s}{%s}' % (self.visit(n.left), self.visit(n.right))
elif isinstance(n.op, ast.FloorDiv):
return r'\left\lfloor\frac{%s}{%s}\right\rfloor' % (self.visit(n.left), self.visit(n.right))
elif isinstance(n.op, ast.Pow):
return r'%s^{%s}' % (left, self.visit(n.right))
else:
return r'%s %s %s' % (left, self.visit(n.op), right)
def prec_BinOp(self, n):
return self.prec(n.op)
def visit_Sub(self, n):
return '-'
def prec_Sub(self, n):
return 300
def visit_Add(self, n):
return '+'
def prec_Add(self, n):
return 300
def visit_Mult(self, n):
return '\\;'
def prec_Mult(self, n):
return 400
def visit_Mod(self, n):
return '\\bmod'
def prec_Mod(self, n):
return 500
def prec_Pow(self, n):
return 700
def prec_Div(self, n):
return 400
def prec_FloorDiv(self, n):
return 400
def visit_LShift(self, n):
return '\\operatorname{shiftLeft}'
def visit_RShift(self, n):
return '\\operatorname{shiftRight}'
def visit_BitOr(self, n):
return '\\operatorname{or}'
def visit_BitXor(self, n):
return '\\operatorname{xor}'
def visit_BitAnd(self, n):
return '\\operatorname{and}'
def visit_Invert(self, n):
return '\\operatorname{invert}'
def prec_Invert(self, n):
return 800
def visit_Not(self, n):
return '\\neg'
def prec_Not(self, n):
return 800
def visit_UAdd(self, n):
return '+'
def prec_UAdd(self, n):
return 800
def visit_USub(self, n):
return '-'
def prec_USub(self, n):
return 800
def visit_Num(self, n):
return str(n.n)
def prec_Num(self, n):
return 1000
def generic_visit(self, n):
if isinstance(n, ast.AST):
return r'' % (n.__class__.__name__, ', '.join(map(self.visit, [getattr(n, f) for f in n._fields])))
else:
return str(n)
def generic_prec(self, n):
return 0
def py2tex(expr):
pt = ast.parse(expr)
return LatexVisitor().visit(pt.body[0].value)
一個重要的區別是你解析這些表達式不是爲了評估它們,而是要用它們做文檔佈局。這是說你知道用大括號替換'x + y'周圍的人,但肯定還有其他地方需要保留人。我認爲你將不得不徹底考慮你想要分析的內容以及完成後應該看起來的樣子。然後,您可以開始考慮如何通過給出合適的解析器來實現這種轉換。這也將幫助您制定解析器需要做的事情。 – PaulMcG 2010-10-05 21:11:09