2 # -*- coding: ISO-8859-1 -*-
5 # Copyright (C) 2002-2004 Jörg Lehmann <joergl@users.sourceforge.net>
6 # Copyright (C) 2003-2004 Michael Schindler <m-schindler@users.sourceforge.net>
7 # Copyright (C) 2002-2004 André Wobst <wobsta@users.sourceforge.net>
9 # This file is part of PyX (http://pyx.sourceforge.net/).
11 # PyX is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2 of the License, or
14 # (at your option) any later version.
16 # PyX is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with PyX; if not, write to the Free Software
23 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 import string
, re
, math
, symbol
, token
27 import parser
as pythonparser
30 class ArgCountError(Exception): pass
31 class DerivativeError(Exception): pass
35 def __init__(self
, ArgCount
, *Args
):
36 self
.ArgCount
= ArgCount
41 def __repr__(self
, depth
= 0):
44 for i
in range(depth
):
45 indent
= indent
+ SingleIndent
46 result
= indent
+ self
.__class
__.__name
__ + "(\n"
47 for SubTree
in self
.Args
:
48 if isinstance(SubTree
, MathTree
):
49 result
= result
+ SubTree
.__repr
__(depth
+ 1)
51 result
= result
+ indent
+ SingleIndent
+ repr(SubTree
)
53 if SubTree
!= self
.Args
[-1]:
54 result
= result
+ ",\n"
59 def AddArg(self
, Arg
, Last
=0, NotLast
=0):
60 if len(self
.Args
) == self
.ArgCount
:
63 if NotLast
and len(self
.Args
) == self
.ArgCount
:
65 if Last
and len(self
.Args
) != self
.ArgCount
:
68 def DependOn(self
, arg
):
74 def Derivative(self
, arg
):
75 if not self
.DependOn(arg
):
76 return MathTreeValConst(0.0)
77 return self
.CalcDerivative(arg
)
82 newlist
= Arg
.VarList()
89 class MathTreeVal(MathTree
):
91 def __init__(self
, *args
):
92 MathTree
.__init
__(self
, 1, *args
)
95 return str(self
.Args
[0])
98 ConstPattern
= re
.compile(r
"-?\d*((\d\.?)|(\.?\d))\d*(E[+-]?\d+)?",
101 class MathTreeValConst(MathTreeVal
):
103 def InitByParser(self
, arg
):
104 Match
= arg
.MatchPattern(ConstPattern
)
106 self
.AddArg(string
.atof(Match
))
109 def CalcDerivative(self
, arg
):
110 raise DerivativeError("expression doesn't depend on \"%s\"" % arg
)
112 def Derivative(self
, arg
):
113 return MathTreeValConst(0.0)
115 def DependOn(self
, arg
):
121 def Calc(HIDDEN_self
, **args
):
122 return HIDDEN_self
.Args
[0]
125 VarPattern
= re
.compile(r
"[a-z_][a-z0-9_]*", re
.IGNORECASE
)
126 MathConst
= {"pi": math
.pi
, "e": math
.e
}
128 class MathTreeValVar(MathTreeVal
):
130 def InitByParser(self
, arg
):
131 Match
= arg
.MatchPattern(VarPattern
)
136 def CalcDerivative(self
, arg
):
137 if arg
!= self
.Args
[0]:
138 raise DerivativeError("expression doesn't depend on \"%s\"" % arg
)
139 return MathTreeValConst(1.0)
141 def DependOn(self
, arg
):
142 if arg
== self
.Args
[0]:
147 if self
.Args
[0] in MathConst
.keys():
149 return [self
.Args
[0]]
151 def Calc(HIDDEN_self
, **args
):
152 if HIDDEN_self
.Args
[0] in args
.keys():
153 return float(args
[HIDDEN_self
.Args
[0]])
154 return MathConst
[HIDDEN_self
.Args
[0]]
157 class MathTreeFunc(MathTree
):
159 def __init__(self
, name
, ArgCount
, *args
):
161 MathTree
.__init
__(self
, ArgCount
, *args
)
163 def InitByParser(self
, arg
):
164 return arg
.MatchStrParenthesis(self
.name
)
168 for SubTree
in self
.Args
:
169 args
= args
+ str(SubTree
)
170 if SubTree
!= self
.Args
[-1]:
172 return self
.name
+ "(" + args
+ ")"
175 class MathTreeFunc1(MathTreeFunc
):
177 def __init__(self
, name
, *args
):
178 MathTreeFunc
.__init
__(self
, name
, 1, *args
)
181 class MathTreeFunc1Neg(MathTreeFunc1
):
183 def __init__(self
, *args
):
184 MathTreeFunc1
.__init__(self
, "neg", *args
)
186 def CalcDerivative(self
, arg
):
187 return MathTreeFunc1Neg(self
.Args
[0].CalcDerivative(arg
))
189 def Calc(HIDDEN_self
, **args
):
190 return -HIDDEN_self
.Args
[0].Calc(**args
)
193 class MathTreeFunc1Abs(MathTreeFunc1
):
195 def __init__(self
, *args
):
196 MathTreeFunc1
.__init__(self
, "abs", *args
)
198 def CalcDerivative(self
, arg
):
199 return MathTreeOpMul(
200 MathTreeFunc1Sgn(self
.Args
[0]),
201 self
.Args
[0].CalcDerivative(arg
))
203 def Calc(HIDDEN_self
, **args
):
204 return abs(HIDDEN_self
.Args
[0].Calc(**args
))
207 class MathTreeFunc1Sgn(MathTreeFunc1
):
209 def __init__(self
, *args
):
210 MathTreeFunc1
.__init__(self
, "sgn", *args
)
212 def CalcDerivative(self
, arg
):
213 return MathTreeValConst(0.0)
215 def Calc(HIDDEN_self
, **args
):
216 if HIDDEN_self
.Args
[0].Calc(**args
) < 0:
221 class MathTreeFunc1Sqrt(MathTreeFunc1
):
223 def __init__(self
, *args
):
224 MathTreeFunc1
.__init__(self
, "sqrt", *args
)
226 def CalcDerivative(self
, arg
):
227 return MathTreeOpMul(
229 MathTreeValConst(0.5),
231 self
.Args
[0].CalcDerivative(arg
))
233 def Calc(HIDDEN_self
, **args
):
234 return math
.sqrt(HIDDEN_self
.Args
[0].Calc(**args
))
237 class MathTreeFunc1Exp(MathTreeFunc1
):
239 def __init__(self
, *args
):
240 MathTreeFunc1
.__init__(self
, "exp", *args
)
242 def CalcDerivative(self
, arg
):
243 return MathTreeOpMul(self
, self
.Args
[0].CalcDerivative(arg
))
245 def Calc(HIDDEN_self
, **args
):
246 return math
.exp(HIDDEN_self
.Args
[0].Calc(**args
))
249 class MathTreeFunc1Log(MathTreeFunc1
):
251 def __init__(self
, *args
):
252 MathTreeFunc1
.__init__(self
, "log", *args
)
254 def CalcDerivative(self
, arg
):
255 return MathTreeOpDiv(self
.Args
[0].CalcDerivative(arg
), self
.Args
[0])
257 def Calc(HIDDEN_self
, **args
):
258 return math
.log(HIDDEN_self
.Args
[0].Calc(**args
))
261 class MathTreeFunc1Sin(MathTreeFunc1
):
263 def __init__(self
, *args
):
264 MathTreeFunc1
.__init__(self
, "sin", *args
)
266 def CalcDerivative(self
, arg
):
267 return MathTreeOpMul(
268 MathTreeFunc1Cos(self
.Args
[0]),
269 self
.Args
[0].CalcDerivative(arg
))
271 def Calc(HIDDEN_self
, **args
):
272 return math
.sin(HIDDEN_self
.Args
[0].Calc(**args
))
275 class MathTreeFunc1Cos(MathTreeFunc1
):
277 def __init__(self
, *args
):
278 MathTreeFunc1
.__init__(self
, "cos", *args
)
280 def CalcDerivative(self
, arg
):
281 return MathTreeOpMul(
282 MathTreeFunc1Neg(MathTreeFunc1Sin(self
.Args
[0])),
283 self
.Args
[0].CalcDerivative(arg
))
285 def Calc(HIDDEN_self
, **args
):
286 return math
.cos(HIDDEN_self
.Args
[0].Calc(**args
))
289 class MathTreeFunc1Tan(MathTreeFunc1
):
291 def __init__(self
, *args
):
292 MathTreeFunc1
.__init__(self
, "tan", *args
)
294 def CalcDerivative(self
, arg
):
295 return MathTreeOpDiv(
296 self
.Args
[0].CalcDerivative(arg
),
298 MathTreeFunc1Cos(self
.Args
[0]),
299 MathTreeValConst(2.0)))
301 def Calc(HIDDEN_self
, **args
):
302 return math
.tan(HIDDEN_self
.Args
[0].Calc(**args
))
305 class MathTreeFunc1ASin(MathTreeFunc1
):
307 def __init__(self
, *args
):
308 MathTreeFunc1
.__init__(self
, "asin", *args
)
310 def CalcDerivative(self
, arg
):
311 return MathTreeOpDiv(
312 self
.Args
[0].CalcDerivative(arg
),
315 MathTreeValConst(1.0),
318 MathTreeValConst(2.0)))))
320 def Calc(HIDDEN_self
, **args
):
321 return math
.asin(HIDDEN_self
.Args
[0].Calc(**args
))
324 class MathTreeFunc1ACos(MathTreeFunc1
):
326 def __init__(self
, *args
):
327 MathTreeFunc1
.__init__(self
, "acos", *args
)
329 def CalcDerivate(self
, arg
):
330 return MathTreeOpDiv(
331 MathTreeFunc1Neg(self
.Args
[0].CalcDerivative(arg
)),
334 MathTreeValConst(1.0),
337 MathTreeValConst(2.0)))))
339 def Calc(HIDDEN_self
, **args
):
340 return math
.acos(HIDDEN_self
.Args
[0].Calc(**args
))
343 class MathTreeFunc1ATan(MathTreeFunc1
):
345 def __init__(self
, *args
):
346 MathTreeFunc1
.__init__(self
, "atan", *args
)
348 def CalcDerivate(self
, arg
):
349 return MathTreeOpDiv(
350 self
.Args
[0].CalcDerivative(arg
),
352 MathTreeValConst(1.0),
355 MathTreeValConst(2.0))))
357 def Calc(HIDDEN_self
, **args
):
358 return math
.atan(HIDDEN_self
.Args
[0].Calc(**args
))
361 class MathTreeFunc1SinD(MathTreeFunc1
):
363 def __init__(self
, *args
):
364 MathTreeFunc1
.__init__(self
, "sind", *args
)
366 def CalcDerivative(self
, arg
):
367 return MathTreeOpMul(
368 MathTreeFunc1CosD(self
.Args
[0]),
370 MathTreeValConst(math
.pi
/180.0),
371 self
.Args
[0].CalcDerivative(arg
)))
373 def Calc(HIDDEN_self
, **args
):
374 return math
.sin(math
.pi
/180.0*HIDDEN_self
.Args
[0].Calc(**args
))
377 class MathTreeFunc1CosD(MathTreeFunc1
):
379 def __init__(self
, *args
):
380 MathTreeFunc1
.__init__(self
, "cosd", *args
)
382 def CalcDerivative(self
, arg
):
383 return MathTreeOpMul(
384 MathTreeFunc1Neg(MathTreeFunc1Sin(self
.Args
[0])),
386 MathTreeValConst(math
.pi
/180.0),
387 self
.Args
[0].CalcDerivative(arg
)))
389 def Calc(HIDDEN_self
, **args
):
390 return math
.cos(math
.pi
/180.0*HIDDEN_self
.Args
[0].Calc(**args
))
393 class MathTreeFunc1TanD(MathTreeFunc1
):
395 def __init__(self
, *args
):
396 MathTreeFunc1
.__init__(self
, "tand", *args
)
398 def CalcDerivative(self
, arg
):
399 return MathTreeOpDiv(
401 MathTreeValConst(math
.pi
/180.0),
402 self
.Args
[0].CalcDerivative(arg
)),
404 MathTreeFunc1Cos(self
.Args
[0]),
405 MathTreeValConst(2.0)))
407 def Calc(HIDDEN_self
, **args
):
408 return math
.tan(math
.pi
/180.0*HIDDEN_self
.Args
[0].Calc(**args
))
411 class MathTreeFunc1ASinD(MathTreeFunc1
):
413 def __init__(self
, *args
):
414 MathTreeFunc1
.__init__(self
, "asind", *args
)
416 def CalcDerivative(self
, arg
):
417 return MathTreeOpDiv(
419 MathTreeValConst(180.0/math
.pi
),
420 self
.Args
[0].CalcDerivative(arg
)),
423 MathTreeValConst(1.0),
426 MathTreeValConst(2.0)))))
428 def Calc(HIDDEN_self
, **args
):
429 return 180.0/math
.pi
*math
.asin(HIDDEN_self
.Args
[0].Calc(**args
))
432 class MathTreeFunc1ACosD(MathTreeFunc1
):
434 def __init__(self
, *args
):
435 MathTreeFunc1
.__init__(self
, "acosd", *args
)
437 def CalcDerivate(self
, arg
):
438 return MathTreeOpDiv(
441 MathTreeValConst(180.0/math
.pi
),
442 self
.Args
[0].CalcDerivative(arg
))),
445 MathTreeValConst(1.0),
448 MathTreeValConst(2.0)))))
450 def Calc(HIDDEN_self
, **args
):
451 return 180.0/math
.pi
*math
.acos(HIDDEN_self
.Args
[0].Calc(**args
))
454 class MathTreeFunc1ATanD(MathTreeFunc1
):
456 def __init__(self
, *args
):
457 MathTreeFunc1
.__init__(self
, "atand", *args
)
459 def CalcDerivate(self
, arg
):
460 return MathTreeOpDiv(
462 MathTreeValConst(180.0/math
.pi
),
463 self
.Args
[0].CalcDerivative(arg
)),
465 MathTreeValConst(1.0),
468 MathTreeValConst(2.0))))
470 def Calc(HIDDEN_self
, **args
):
471 return 180.0/math
.pi
*math
.atan(HIDDEN_self
.Args
[0].Calc(**args
))
474 class MathTreeFunc2(MathTreeFunc
):
476 def __init__(self
, name
, *args
):
477 MathTreeFunc
.__init
__(self
, name
, 2, *args
)
480 class MathTreeFunc2Norm(MathTreeFunc2
):
482 def __init__(self
, *args
):
483 MathTreeFunc2
.__init__(self
, "norm", *args
)
485 def CalcDerivative(self
, arg
):
486 if self
.Args
[0].DependOn(arg
):
487 if self
.Args
[1].DependOn(arg
):
488 return MathTreeOpDiv(
492 self
.Args
[0].CalcDerivative(arg
)),
495 self
.Args
[1].CalcDerivative(arg
))),
498 return MathTreeOpDiv(
501 self
.Args
[0].CalcDerivative(arg
)),
504 if self
.Args
[1].DependOn(arg
):
505 return MathTreeOpDiv(
508 self
.Args
[1].CalcDerivative(arg
)),
511 def Calc(HIDDEN_self
, **args
):
512 return math
.sqrt(HIDDEN_self
.Args
[0].Calc(**args
) ** 2 +
513 HIDDEN_self
.Args
[1].Calc(**args
) ** 2)
516 class MathTreeFuncSplitAtValue(MathTreeFunc
):
518 def __init__(self
, *args
):
519 MathTreeFunc
.__init
__(self
, "splitatvalue", -1, *args
)
521 def CalcDerivative(self
, arg
):
522 return self
.Args
[0].CalcDerivative(arg
)
524 def Calc(HIDDEN_self
, **args
):
525 result
= HIDDEN_self
.Args
[0].Calc(**args
)
526 splits
= [split
.Calc(**args
) for split
in HIDDEN_self
.Args
[1:]]
528 while section
< len(splits
) and splits
[section
] < result
:
535 return (section
, result
)
538 FuncExternPattern
= re
.compile(r
"([a-z_][a-z0-9_]*)\s*\(", re
.IGNORECASE
)
540 class MathTreeFuncExtern(MathTreeFunc
):
542 def __init__(self
, *args
):
543 MathTreeFunc
.__init
__(self
, None, -1, *args
)
545 def InitByParser(self
, arg
):
546 Match
= arg
.MatchPattern(FuncExternPattern
)
548 self
.name
= Match
[:-1].strip()
551 def SetName(self
, arg
):
552 self
.name
= arg
.strip()
555 def Calc(HIDDEN_self
, **args
):
556 return args
[HIDDEN_self
.name
](*[arg
.Calc(**args
) for arg
in HIDDEN_self
.Args
])
559 class MathTreeOp(MathTree
):
561 def __init__(self
, level
, symbol
, *args
):
562 self
.ParenthesisBarrier
= 0
565 MathTree
.__init
__(self
, 2, *args
)
569 if isinstance(self
.Args
[0], MathTreeOp
) and\
570 self
.level
> self
.Args
[0].level
:
571 result
= result
+ "(" + str(self
.Args
[0]) + ")"
573 result
= result
+ str(self
.Args
[0])
574 result
= result
+ self
.symbol
575 if isinstance(self
.Args
[1], MathTreeOp
) and\
576 self
.level
>= self
.Args
[1].level
:
577 result
= result
+ "(" + str(self
.Args
[1]) + ")"
579 result
= result
+ str(self
.Args
[1])
582 def InitByParser(self
, arg
):
583 return arg
.MatchStr(self
.symbol
)
586 class MathTreeOpAdd(MathTreeOp
):
588 def __init__(self
, *args
):
589 MathTreeOp
.__init
__(self
, 1, "+", *args
)
591 def CalcDerivative(self
, arg
):
592 if self
.Args
[0].DependOn(arg
):
593 if self
.Args
[1].DependOn(arg
):
594 return MathTreeOpAdd(
595 self
.Args
[0].CalcDerivative(arg
),
596 self
.Args
[1].CalcDerivative(arg
))
598 return self
.Args
[0].CalcDerivative(arg
)
600 if self
.Args
[1].DependOn(arg
):
601 return self
.Args
[1].CalcDerivative(arg
)
603 def Calc(HIDDEN_self
, **args
):
604 return HIDDEN_self
.Args
[0].Calc(**args
) + HIDDEN_self
.Args
[1].Calc(**args
)
607 class MathTreeOpSub(MathTreeOp
):
609 def __init__(self
, *args
):
610 MathTreeOp
.__init
__(self
, 1, "-", *args
)
612 def CalcDerivative(self
, arg
):
613 if self
.Args
[0].DependOn(arg
):
614 if self
.Args
[1].DependOn(arg
):
615 return MathTreeOpSub(
616 self
.Args
[0].CalcDerivative(arg
),
617 self
.Args
[1].CalcDerivative(arg
))
619 return self
.Args
[0].CalcDerivative(arg
)
621 if self
.Args
[1].DependOn(arg
):
622 return MathTreeFunc1Neg(self
.Args
[1].CalcDerivative(arg
))
624 def Calc(HIDDEN_self
, **args
):
625 return HIDDEN_self
.Args
[0].Calc(**args
) - HIDDEN_self
.Args
[1].Calc(**args
)
628 class MathTreeOpMul(MathTreeOp
):
630 def __init__(self
, *args
):
631 MathTreeOp
.__init
__(self
, 2, "*", *args
)
633 def CalcDerivative(self
, arg
):
634 if self
.Args
[0].DependOn(arg
):
635 if self
.Args
[1].DependOn(arg
):
636 return MathTreeOpAdd(
639 self
.Args
[1].CalcDerivative(arg
)),
641 self
.Args
[0].CalcDerivative(arg
),
644 return MathTreeOpMul(
645 self
.Args
[0].CalcDerivative(arg
),
648 if self
.Args
[1].DependOn(arg
):
649 return MathTreeOpMul(
651 self
.Args
[1].CalcDerivative(arg
))
653 def Calc(HIDDEN_self
, **args
):
654 return HIDDEN_self
.Args
[0].Calc(**args
) * HIDDEN_self
.Args
[1].Calc(**args
)
657 class MathTreeOpDiv(MathTreeOp
):
659 def __init__(self
, *args
):
660 MathTreeOp
.__init
__(self
, 2, "/", *args
)
662 def CalcDerivative(self
, arg
):
663 if self
.Args
[0].DependOn(arg
):
664 if self
.Args
[1].DependOn(arg
):
665 return MathTreeOpMul(
668 self
.Args
[0].CalcDerivative(arg
),
672 self
.Args
[1].CalcDerivative(arg
))),
675 MathTreeValConst(-2.0)))
677 return MathTreeOpDiv(
678 self
.Args
[0].CalcDerivative(arg
),
681 if self
.Args
[1].DependOn(arg
):
682 return MathTreeOpMul(
684 MathTreeFunc1Neg(self
.Args
[0]),
687 MathTreeValConst(-2.0))),
688 self
.Args
[1].CalcDerivative(arg
))
690 def Calc(HIDDEN_self
, **args
):
691 return HIDDEN_self
.Args
[0].Calc(**args
) / HIDDEN_self
.Args
[1].Calc(**args
)
694 class MathTreeOpPow(MathTreeOp
):
696 def __init__(self
, *args
):
697 MathTreeOp
.__init
__(self
, 3, "^", *args
)
699 def InitByParser(self
, arg
):
700 pos
= arg
.MatchStr("^")
704 return arg
.MatchStr("**")
706 def CalcDerivative(self
, arg
):
707 if self
.Args
[0].DependOn(arg
):
708 if self
.Args
[1].DependOn(arg
):
709 return MathTreeOpMul(
715 MathTreeFunc1Log(self
.Args
[0]),
716 self
.Args
[1].CalcDerivative(arg
)),
720 self
.Args
[0].CalcDerivative(arg
),
723 return MathTreeOpMul(
730 MathTreeValConst(1.0))),
731 self
.Args
[0].CalcDerivative(arg
)))
733 if self
.Args
[1].DependOn(arg
):
734 return MathTreeOpMul(
739 MathTreeFunc1Log(self
.Args
[0])),
740 self
.Args
[1].CalcDerivative(arg
))
742 def Calc(HIDDEN_self
, **args
):
743 return HIDDEN_self
.Args
[0].Calc(**args
) ** HIDDEN_self
.Args
[1].Calc(**args
)
747 DefaultMathTreeFuncs
= [MathTreeFunc1Neg
, MathTreeFunc1Abs
, MathTreeFunc1Sgn
, MathTreeFunc1Sqrt
,
748 MathTreeFunc1Exp
, MathTreeFunc1Log
,
749 MathTreeFunc1Sin
, MathTreeFunc1Cos
, MathTreeFunc1Tan
,
750 MathTreeFunc1ASin
, MathTreeFunc1ACos
, MathTreeFunc1ATan
,
751 MathTreeFunc1SinD
, MathTreeFunc1CosD
, MathTreeFunc1TanD
,
752 MathTreeFunc1ASinD
, MathTreeFunc1ACosD
, MathTreeFunc1ATanD
,
754 MathTreeFuncSplitAtValue
]
758 def __init__(self
, MathTreeFuncs
=DefaultMathTreeFuncs
):
759 self
.MathTreeFuncs
= MathTreeFuncs
761 def parse(self
, expr
):
762 return self
.astseq2mtree(pythonparser
.expr(expr
.strip()).totuple())
764 def astseq2mtree(self
, astseq
, isfunc
=0):
765 # astseq has to be a sequence!
768 if token
.ISTERMINAL(astseq
[0]):
771 if astseq
[0] == symbol
.arith_expr
: # {{{
773 # 1. arith_expr "PLUS" term
774 if astseq
[-2][0] == token
.PLUS
:
775 tree
= MathTreeOpAdd(
776 self
.astseq2mtree(astseq
[:-2], isfunc
=isfunc
),
777 self
.astseq2mtree(astseq
[-1], isfunc
=isfunc
))
778 # 2. arith_expr "MINUS" term
779 elif astseq
[-2][0] == token
.MINUS
:
780 tree
= MathTreeOpSub(
781 self
.astseq2mtree(astseq
[:-2], isfunc
=isfunc
),
782 self
.astseq2mtree(astseq
[-1], isfunc
=isfunc
))
787 tree
= self
.astseq2mtree(astseq
[1], isfunc
=isfunc
)
790 if astseq
[0] == symbol
.term
: # {{{
792 # 1. term "STAR" factor
793 if astseq
[-2][0] == token
.STAR
:
794 tree
= MathTreeOpMul(
795 self
.astseq2mtree(astseq
[:-2], isfunc
=isfunc
),
796 self
.astseq2mtree(astseq
[-1], isfunc
=isfunc
))
797 # 2. term "SLASH" factor
798 elif astseq
[-2][0] == token
.SLASH
:
799 tree
= MathTreeOpDiv(
800 self
.astseq2mtree(astseq
[:-2], isfunc
=isfunc
),
801 self
.astseq2mtree(astseq
[-1], isfunc
=isfunc
))
806 tree
= self
.astseq2mtree(astseq
[1], isfunc
=isfunc
)
809 if astseq
[0] == symbol
.factor
: # {{{
812 if astseq
[1][0] == token
.PLUS
:
813 tree
= self
.astseq2mtree(astseq
[2], isfunc
=isfunc
)
815 elif astseq
[1][0] == token
.MINUS
:
816 tree
= MathTreeFunc1Neg(self
.astseq2mtree(astseq
[2], isfunc
=isfunc
))
818 raise Exception("unknown factor")
819 elif len(astseq
) == 2:
821 tree
= self
.astseq2mtree(astseq
[1], isfunc
=isfunc
)
823 raise Exception("wrong length of factor")
826 if astseq
[0] == symbol
.power
: # {{{
828 # 1. "DOUBLESTAR" factor
829 if astseq
[-2][0] == token
.DOUBLESTAR
:
830 tree
= MathTreeOpPow(
831 self
.astseq2mtree(astseq
[:-2], isfunc
=isfunc
),
832 self
.astseq2mtree(astseq
[-1], isfunc
=isfunc
))
836 # 2. atom + [trailer]
838 # we have a function call atom + "LPAR" + argumentlist + "RPAR"
839 if astseq
[2][0] == symbol
.trailer
and \
840 astseq
[2][1][0] == token
.LPAR
and \
841 astseq
[2][2][0] == symbol
.arglist
and \
842 astseq
[2][3][0] == token
.RPAR
:
843 tree
= self
.astseq2mtree(astseq
[1], isfunc
=1)
844 for subtree
in self
.astseq2mtree(astseq
[2][2], isfunc
=0):
846 elif astseq
[2][0] == symbol
.trailer
and \
847 astseq
[2][1][0] == token
.LPAR
and \
848 astseq
[2][2][0] == token
.RPAR
:
849 tree
= self
.astseq2mtree(astseq
[1], isfunc
=1)
851 raise Exception("wrong function call")
853 tree
= self
.astseq2mtree(astseq
[1], isfunc
=0)
857 if astseq
[0] == symbol
.atom
: # {{{
858 # only one nontrivial term:
860 if astseq
[1][0] == token
.NUMBER
:
862 # XXX: for evaluation of brackets we will need integers as well
863 tree
= MathTreeValConst(string
.atof(astseq
[1][1]))
864 elif astseq
[1][0] == token
.NAME
:
868 for funcclass
in self
.MathTreeFuncs
:
869 func
= funcclass() # ist das guenstig, da jedesmal eine Instanz zu erzeugen?
870 # doofe Frage, nein! <wobsta>
871 if func
.name
== astseq
[1][1]:
873 # an unknown function
874 tree
= MathTreeFuncExtern()
875 tree
.SetName(astseq
[1][1])
878 return MathTreeValVar(astseq
[1][1])
879 elif len(astseq
) == 4:
880 # parentheses or brackets for structuring an atom
881 if (astseq
[1][0] == token
.LPAR
and astseq
[3][0] == token
.RPAR
) or \
882 (astseq
[1][0] == token
.LSQB
and astseq
[3][0] == token
.RSQB
):
883 tree
= self
.astseq2mtree(astseq
[2], isfunc
=isfunc
)
885 raise Exception("symbol.atom with unknown number of arguments")
888 if astseq
[0] == symbol
.arglist
: # {{{
890 for arg
in astseq
[1:]:
891 if arg
[0] == token
.COMMA
:
893 elif arg
[0] == symbol
.argument
:
894 treelist
.append(self
.astseq2mtree(arg
, isfunc
=isfunc
))
895 return treelist
# }}}
897 if astseq
[0] == symbol
.testlist
: # {{{
899 for arg
in astseq
[1:]:
900 if arg
[0] == token
.COMMA
:
902 elif arg
[0] == symbol
.test
:
903 treelist
.append(self
.astseq2mtree(arg
, isfunc
=isfunc
))
904 if len(treelist
) == 1: return treelist
[0]
905 else: return treelist
# }}}
907 if astseq
[0] != symbol
.eval_input
and len(astseq
) > 2:
908 raise Exception("invalid expression structure (contains several parts)")
909 return self
.astseq2mtree(astseq
[1], isfunc
=isfunc
)