New render seems to be ok some debuging still have to be done
This commit is contained in:
parent
41aa8dfb11
commit
2132c2ba59
@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from .generic import Stack, flatten_list, expand_list
|
||||
from .generic import Stack, flatten_list, expand_list, isNumber, isOperator
|
||||
from .renders import txt, post2in_fix, tex
|
||||
from .str2tokens import str2tokens, isNumber, isOperator
|
||||
from .str2tokens import str2tokens
|
||||
|
||||
__all__ = ['Expression']
|
||||
|
||||
|
@ -60,6 +60,15 @@ class Fraction(object):
|
||||
def __repr__(self):
|
||||
return "< Fraction " + self.__str__() + ">"
|
||||
|
||||
def __txt__(self):
|
||||
return str(self)
|
||||
|
||||
def __tex__(self):
|
||||
if self._denom == 1:
|
||||
return str(self._num)
|
||||
else:
|
||||
return "\\frac{{ {a} }}{{ {b} }}".format(a = self._num, b = self._denom)
|
||||
|
||||
def __float__(self):
|
||||
return self._num / self._denom
|
||||
|
||||
|
@ -243,6 +243,37 @@ def convolution_dict(D1, D2, op = lambda x,y:x*y,\
|
||||
|
||||
return new_dict
|
||||
|
||||
def isOperator(exp):
|
||||
"""Check if the expression is an opération in "+-*/:^"
|
||||
|
||||
:param exp: an expression
|
||||
:returns: boolean
|
||||
|
||||
"""
|
||||
|
||||
#return (type(exp) == str and exp in "+-*/:^")
|
||||
try:
|
||||
exp.isOperator
|
||||
except AttributeError:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def isNumber(exp):
|
||||
"""Check if the expression can be a number
|
||||
|
||||
:param exp: an expression
|
||||
:returns: True if the expression can be a number and false otherwise
|
||||
|
||||
"""
|
||||
try:
|
||||
exp.isNumber
|
||||
except AttributeError:
|
||||
if type(exp) == int:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
from .fraction import Fraction
|
||||
from .generic import flatten_list
|
||||
from .generic import flatten_list, isNumber
|
||||
|
||||
class Operator(str):
|
||||
|
||||
@ -75,25 +75,23 @@ class Operator(str):
|
||||
>>> add = Operator("+", 2)
|
||||
>>> sub1 = Operator("-", 1)
|
||||
>>> div = Operator("/", 1)
|
||||
>>> mul.__txt__(1,2)
|
||||
>>> mul.__txt__('1','2')
|
||||
'1 * 2'
|
||||
>>> add.__txt__(1,2)
|
||||
>>> add.__txt__('1','2')
|
||||
'1 + 2'
|
||||
>>> f = save_mainOp('2 + 3',add)
|
||||
>>> mul.__txt__(f, 4)
|
||||
>>> mul.__txt__(f, '4')
|
||||
'( 2 + 3 ) * 4'
|
||||
>>> f = save_mainOp('-3',sub1)
|
||||
>>> sub1.__txt__(f)
|
||||
'- ( -3 )'
|
||||
>>> sub1.__txt__(-3)
|
||||
>>> sub1.__txt__('-3')
|
||||
'- ( -3 )'
|
||||
>>> f = save_mainOp('2 + 3',add)
|
||||
>>> sub1.__txt__(f)
|
||||
'- ( 2 + 3 )'
|
||||
"""
|
||||
|
||||
#vive le inline? ...
|
||||
replacement = {"op"+str(i+1): ' '.join([str(o) if type(o)==int else o for o in self.add_parenthesis(op)]) for (i,op) in enumerate(args)}
|
||||
replacement = {"op"+str(i+1): ' '.join(self.add_parenthesis(op)) for (i,op) in enumerate(args)}
|
||||
|
||||
ans = self._txt.format(**replacement)
|
||||
ans = save_mainOp(ans, self)
|
||||
@ -109,23 +107,23 @@ class Operator(str):
|
||||
>>> add = Operator("+", 2)
|
||||
>>> sub1 = Operator("-", 1)
|
||||
>>> div = Operator("/", 1)
|
||||
>>> mul.__tex__(1,2)
|
||||
>>> mul.__tex__('1','2')
|
||||
'1 \\\\times 2'
|
||||
>>> add.__tex__(1,2)
|
||||
>>> add.__tex__('1','2')
|
||||
'1 + 2'
|
||||
>>> f = save_mainOp('2 + 3',add)
|
||||
>>> mul.__tex__(f, 4)
|
||||
>>> mul.__tex__(f, '4')
|
||||
'( 2 + 3 ) \\\\times 4'
|
||||
>>> f = save_mainOp('-3',sub1)
|
||||
>>> sub1.__tex__(f)
|
||||
'- ( -3 )'
|
||||
>>> sub1.__tex__(-3)
|
||||
>>> sub1.__tex__('-3')
|
||||
'- ( -3 )'
|
||||
>>> f = save_mainOp('2 + 3',add)
|
||||
>>> sub1.__tex__(f)
|
||||
'- ( 2 + 3 )'
|
||||
"""
|
||||
replacement = {"op"+str(i+1): ' '.join([str(o) if type(o)==int else o for o in self.add_parenthesis(op)]) for (i,op) in enumerate(args)}
|
||||
replacement = {"op"+str(i+1): ' '.join(self.add_parenthesis(op)) for (i,op) in enumerate(args)}
|
||||
|
||||
ans = self._tex.format(**replacement)
|
||||
ans = save_mainOp(ans, self)
|
||||
@ -174,13 +172,15 @@ class Operator(str):
|
||||
if op.mainOp.priority < self.priority:
|
||||
op = flatten_list(["("] + [op] + [")"])
|
||||
except AttributeError:
|
||||
if type(op) == int and op < 0:
|
||||
try:
|
||||
if int(op) < 0:
|
||||
op = ['(', op, ')']
|
||||
except ValueError:
|
||||
pass
|
||||
return flatten_list([op])
|
||||
|
||||
|
||||
|
||||
|
||||
def save_mainOp(obj, mainOp):
|
||||
"""Create a temporary class build over built-in type to stock the main operation of a calculus
|
||||
|
||||
@ -198,21 +198,27 @@ def save_mainOp(obj, mainOp):
|
||||
return Fake(obj)
|
||||
|
||||
if __name__ == '__main__':
|
||||
#op = Operator("+", 2)
|
||||
#print(op.__txt__(1,2))
|
||||
#mul = Operator("*", 2)
|
||||
#add = Operator("+", 2)
|
||||
#sub1 = Operator("-", 1)
|
||||
#div = Operator("/", 1)
|
||||
#print(mul.__txt__(1,2))
|
||||
#print(add.__txt__(1,2))
|
||||
#f = save_mainOp('2 + 3',add)
|
||||
#print(mul.__txt__(f, 4))
|
||||
#f = save_mainOp('-3',sub1)
|
||||
#print(sub1.__txt__(f))
|
||||
#print(sub1.__txt__(-3))
|
||||
#f = save_mainOp('2 + 3',add)
|
||||
#print(sub1.__txt__(f))
|
||||
op = Operator("+", 2)
|
||||
print(op.__txt__('1','2'))
|
||||
mul = Operator("*", 2)
|
||||
add = Operator("+", 2)
|
||||
sub1 = Operator("-", 1)
|
||||
div = Operator("/", 1)
|
||||
print(mul.__txt__('1','2'))
|
||||
print(add.__txt__('1','2'))
|
||||
f = save_mainOp('2 + 3',add)
|
||||
print(mul.__txt__(f, '4'))
|
||||
f = save_mainOp('-3',sub1)
|
||||
print(sub1.__txt__(f))
|
||||
print(sub1.__txt__('-3'))
|
||||
f = save_mainOp('2 + 3',add)
|
||||
print(sub1.__txt__(f))
|
||||
|
||||
from .fraction import Fraction
|
||||
f = Fraction(1, 2)
|
||||
print(add.__txt__(f.__txt__(),'2'))
|
||||
print(add.__tex__(f.__tex__(),'2'))
|
||||
|
||||
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
@ -38,13 +38,36 @@ class Render(object):
|
||||
# Switch op1 and op2 to respect order
|
||||
operandeStack.push(self.render(token)(op2, op1))
|
||||
else:
|
||||
operandeStack.push(token)
|
||||
operandeStack.push(self.render(token)())
|
||||
|
||||
return operandeStack.pop()
|
||||
|
||||
txt = Render(lambda x:x.__txt__)
|
||||
tex = Render(lambda x:x.__tex__)
|
||||
p2i = Render(lambda x:x.__p2i__)
|
||||
def txt_render(token):
|
||||
def render(*args):
|
||||
try:
|
||||
return getattr(token, '__txt__')(*args)
|
||||
except AttributeError:
|
||||
return str(token)
|
||||
return render
|
||||
|
||||
txt = Render(txt_render)
|
||||
def tex_render(token):
|
||||
def render(*args):
|
||||
try:
|
||||
return getattr(token, '__tex__')(*args)
|
||||
except AttributeError:
|
||||
return str(token)
|
||||
return render
|
||||
tex = Render(tex_render)
|
||||
|
||||
def p2i_render(token):
|
||||
def render(*args):
|
||||
try:
|
||||
return getattr(token, '__p2i__')(*args)
|
||||
except AttributeError:
|
||||
return list(token)
|
||||
return render
|
||||
p2i = Render(p2i_render)
|
||||
|
||||
if __name__ == '__main__':
|
||||
from .operator import Operator
|
||||
|
@ -1,103 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from .render import Render
|
||||
from .fraction import Fraction
|
||||
from .generic import first_elem, last_elem
|
||||
|
||||
__all__ = ['post2in_fix', 'tex', 'txt']
|
||||
|
||||
# ------------------------
|
||||
# A infix to postfix list convertor
|
||||
|
||||
p2i_infix = {"+": "+", "-": "-", "*": "*", "/" : "/", ":": ":", "^":"^"}
|
||||
p2i_postfix = {}
|
||||
p2i_other = {"(": "(", ")": ")"}
|
||||
|
||||
post2in_fix = Render(p2i_infix, p2i_postfix, p2i_other, join = False)
|
||||
|
||||
# ------------------------
|
||||
# A console render
|
||||
|
||||
def txtMult(op1,op2):
|
||||
""" Tex render for *
|
||||
Cases where \\times won't be displayed
|
||||
* nbr letter
|
||||
* nbr (
|
||||
* )(
|
||||
"""
|
||||
first_nbr = type(op1) in [int, Fraction]
|
||||
seg_letter = type(op2) == str and op2.isalpha()
|
||||
first_par = (first_elem(op2) == "(")
|
||||
seg_par = (last_elem(op1) == ")")
|
||||
|
||||
if (first_nbr and (seg_letter or seg_par)) \
|
||||
or (first_par and seg_par):
|
||||
return [op1, op2]
|
||||
else:
|
||||
return [op1, "*", op2]
|
||||
|
||||
txt_infix = {"+": "+", "-": "-", "*": txtMult, "/" : "/", ":":":", "^":"^"}
|
||||
txt_postfix = {}
|
||||
txt_other = {"(": "(", ")": ")"}
|
||||
|
||||
txt = Render(txt_infix, txt_postfix, txt_other)
|
||||
|
||||
# ------------------------
|
||||
# A latex render
|
||||
|
||||
def texSlash(op1, op2):
|
||||
""" Tex render for / """
|
||||
if not Render.isNumerande(op1) and op1[0] == "(" and op1[-1] == ")":
|
||||
op1 = op1[1:-1]
|
||||
if not Render.isNumerande(op2) and op2[0] == "(" and op2[-1] == ")":
|
||||
op2 = op2[1:-1]
|
||||
return ["\\frac{" , op1 , "}{" , op2 , "}"]
|
||||
|
||||
def texFrac(frac):
|
||||
""" Tex render for Fractions"""
|
||||
return ["\\frac{" , str(frac._num) , "}{" , str(frac._denom) , "}"]
|
||||
|
||||
def texMult(op1,op2):
|
||||
""" Tex render for *
|
||||
Cases where \\times won't be displayed
|
||||
* nbr letter
|
||||
* nbr (
|
||||
* )(
|
||||
"""
|
||||
first_nbr = type(op1) in [int, Fraction]
|
||||
seg_letter = type(op2) == str and op2.isalpha()
|
||||
first_par = (first_elem(op2) == "(")
|
||||
seg_par = (last_elem(op1) == ")")
|
||||
|
||||
if (first_nbr and (seg_letter or seg_par)) \
|
||||
or (first_par and seg_par):
|
||||
return [op1, op2]
|
||||
else:
|
||||
return [op1, "\\times", op2]
|
||||
|
||||
tex_infix = {"+": " + ", "-": " - ", "*": texMult , ":": ":", "^":"^"}
|
||||
tex_postfix = {"/": texSlash}
|
||||
tex_other = {"(": "(", ")": ")"}
|
||||
tex_type_render = {str:str, int: str, Fraction: texFrac}
|
||||
|
||||
tex = Render(tex_infix, tex_postfix, tex_other, type_render = tex_type_render)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
#exp = [2, 5, '^', 1, '-', 3, 4, '*', ':']
|
||||
#print(txt(exp))
|
||||
#exp = [2, 5, '^', 1, '-', 3, 4, '*', '/', 3, 5, '/', ':']
|
||||
exp = [2, -3, "*"]
|
||||
print(tex(exp))
|
||||
#exp = [2, 5, '^', 1, '-', 3, 4, '*', '/', 3, '+']
|
||||
#print(post2in_fix(exp))
|
||||
|
||||
|
||||
|
||||
|
||||
# -----------------------------
|
||||
# Reglages pour 'vim'
|
||||
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
|
||||
# cursor: 16 del
|
@ -2,7 +2,7 @@
|
||||
# encoding: utf-8
|
||||
|
||||
from .operator import Operator
|
||||
from .generic import Stack
|
||||
from .generic import Stack, isOperator, isNumber
|
||||
|
||||
def str2tokens(exp):
|
||||
""" Parse the string into tokens then turn it into postfix form
|
||||
@ -147,36 +147,6 @@ def in2post_fix(infix_tokens):
|
||||
return postfix_tokens
|
||||
|
||||
|
||||
def isOperator(exp):
|
||||
"""Check if the expression is an opération in "+-*/:^"
|
||||
|
||||
:param exp: an expression
|
||||
:returns: boolean
|
||||
|
||||
"""
|
||||
|
||||
#return (type(exp) == str and exp in "+-*/:^")
|
||||
try:
|
||||
exp.isOperator
|
||||
except AttributeError:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def isNumber(exp):
|
||||
"""Check if the expression can be a number
|
||||
|
||||
:param exp: an expression
|
||||
:returns: True if the expression can be a number and false otherwise
|
||||
|
||||
"""
|
||||
try:
|
||||
exp.isNumber
|
||||
except AttributeError:
|
||||
if type(exp) == int:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
if __name__ == '__main__':
|
||||
#a, s, m, d, p = Operator("+"), Operator("-"), Operator("*"), Operator("/"), Operator("^")
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
import unittest
|
||||
|
||||
from pymath.renders import tex, txt
|
||||
from pymath.render import tex, txt,p2i
|
||||
from pymath.fraction import Fraction
|
||||
from pymath.operator import Operator
|
||||
|
||||
@ -43,8 +43,24 @@ class TestTexRender(unittest.TestCase):
|
||||
rend = tex(e)
|
||||
self.assertEqual(rend, wanted_render[i])
|
||||
|
||||
def test_mult_exp(self):
|
||||
pass
|
||||
def test_parentheses(self):
|
||||
mul = Operator("*", 2)
|
||||
add = Operator("+", 2)
|
||||
exps = [\
|
||||
[ 2, 3, add, 4, mul],\
|
||||
[ 2, 3, mul, 4, add],\
|
||||
[ 2, 3, 4, mul, add],\
|
||||
[ 2, 3, 4, add, add],\
|
||||
]
|
||||
wanted_render = [\
|
||||
'( 2 + 3 ) \\times 4',\
|
||||
'2 \\times 3 + 4',\
|
||||
'2 + 3 \\times 4',\
|
||||
'2 + 3 + 4',\
|
||||
]
|
||||
for (i,e) in enumerate(exps):
|
||||
rend = tex(e)
|
||||
self.assertEqual(rend, wanted_render[i])
|
||||
|
||||
def test_slash(self):
|
||||
pass
|
||||
@ -91,8 +107,24 @@ class TesttxtRender(unittest.TestCase):
|
||||
rend = txt(e)
|
||||
self.assertEqual(rend, wanted_render[i])
|
||||
|
||||
def test_mult_exp(self):
|
||||
pass
|
||||
def test_parentheses(self):
|
||||
mul = Operator("*", 2)
|
||||
add = Operator("+", 2)
|
||||
exps = [\
|
||||
[ 2, 3, add, 4, mul],\
|
||||
[ 2, 3, mul, 4, add],\
|
||||
[ 2, 3, 4, mul, add],\
|
||||
[ 2, 3, 4, add, add],\
|
||||
]
|
||||
wanted_render = [\
|
||||
'( 2 + 3 ) * 4',\
|
||||
'2 * 3 + 4',\
|
||||
'2 + 3 * 4',\
|
||||
'2 + 3 + 4',\
|
||||
]
|
||||
for (i,e) in enumerate(exps):
|
||||
rend = txt(e)
|
||||
self.assertEqual(rend, wanted_render[i])
|
||||
|
||||
def test_slash(self):
|
||||
pass
|
Loading…
Reference in New Issue
Block a user