rename context->currentpoint to reflect what has become now
[PyX/mjg.git] / pyx / mathtree.py
blob7453b751b8000731dee4ef0b3c92f8ff914c8282
1 #!/usr/bin/env python
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
33 class MathTree:
35 def __init__(self, ArgCount, *Args):
36 self.ArgCount = ArgCount
37 self.Args = []
38 for arg in Args:
39 self.AddArg(arg)
41 def __repr__(self, depth = 0):
42 indent = ""
43 SingleIndent = " "
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)
50 else:
51 result = result + indent + SingleIndent + repr(SubTree)
53 if SubTree != self.Args[-1]:
54 result = result + ",\n"
55 else:
56 result = result + ")"
57 return result
59 def AddArg(self, Arg, Last=0, NotLast=0):
60 if len(self.Args) == self.ArgCount:
61 raise ArgCountError
62 self.Args.append(Arg)
63 if NotLast and len(self.Args) == self.ArgCount:
64 raise ArgCountError
65 if Last and len(self.Args) != self.ArgCount:
66 raise ArgCountError
68 def DependOn(self, arg):
69 for Arg in self.Args:
70 if Arg.DependOn(arg):
71 return 1
72 return 0
74 def Derivative(self, arg):
75 if not self.DependOn(arg):
76 return MathTreeValConst(0.0)
77 return self.CalcDerivative(arg)
79 def VarList(self):
80 list = [ ]
81 for Arg in self.Args:
82 newlist = Arg.VarList()
83 for x in newlist:
84 if x not in list:
85 list.append(x)
86 return list
89 class MathTreeVal(MathTree):
91 def __init__(self, *args):
92 MathTree.__init__(self, 1, *args)
94 def __str__(self):
95 return str(self.Args[0])
98 ConstPattern = re.compile(r"-?\d*((\d\.?)|(\.?\d))\d*(E[+-]?\d+)?",
99 re.IGNORECASE)
101 class MathTreeValConst(MathTreeVal):
103 def InitByParser(self, arg):
104 Match = arg.MatchPattern(ConstPattern)
105 if Match:
106 self.AddArg(string.atof(Match))
107 return 1
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):
116 return 0
118 def VarList(self):
119 return [ ]
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)
132 if Match:
133 self.AddArg(Match)
134 return 1
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]:
143 return 1
144 return 0
146 def VarList(self):
147 if self.Args[0] in MathConst.keys():
148 return []
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):
160 self.name = name
161 MathTree.__init__(self, ArgCount, *args)
163 def InitByParser(self, arg):
164 return arg.MatchStrParenthesis(self.name)
166 def __str__(self):
167 args = ""
168 for SubTree in self.Args:
169 args = args + str(SubTree)
170 if SubTree != self.Args[-1]:
171 args = args + ","
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:
217 return -1.0
218 return 1.0
221 class MathTreeFunc1Sqrt(MathTreeFunc1):
223 def __init__(self, *args):
224 MathTreeFunc1.__init__(self, "sqrt", *args)
226 def CalcDerivative(self, arg):
227 return MathTreeOpMul(
228 MathTreeOpDiv(
229 MathTreeValConst(0.5),
230 self),
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),
297 MathTreeOpPow(
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),
313 MathTreeFunc1Sqrt(
314 MathTreeOpSub(
315 MathTreeValConst(1.0),
316 MathTreeOpPow(
317 self.Args[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)),
332 MathTreeFunc1Sqrt(
333 MathTreeOpSub(
334 MathTreeValConst(1.0),
335 MathTreeOpPow(
336 self.Args[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),
351 MathTreeOpAdd(
352 MathTreeValConst(1.0),
353 MathTreeOpPow(
354 self.Args[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]),
369 MathTreeOpMul(
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])),
385 MathTreeOpMul(
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(
400 MathTreeOpMul(
401 MathTreeValConst(math.pi/180.0),
402 self.Args[0].CalcDerivative(arg)),
403 MathTreeOpPow(
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(
418 MathTreeOpMul(
419 MathTreeValConst(180.0/math.pi),
420 self.Args[0].CalcDerivative(arg)),
421 MathTreeFunc1Sqrt(
422 MathTreeOpSub(
423 MathTreeValConst(1.0),
424 MathTreeOpPow(
425 self.Args[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(
439 MathTreeFunc1Neg(
440 MathTreeOpMul(
441 MathTreeValConst(180.0/math.pi),
442 self.Args[0].CalcDerivative(arg))),
443 MathTreeFunc1Sqrt(
444 MathTreeOpSub(
445 MathTreeValConst(1.0),
446 MathTreeOpPow(
447 self.Args[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(
461 MathTreeOpMul(
462 MathTreeValConst(180.0/math.pi),
463 self.Args[0].CalcDerivative(arg)),
464 MathTreeOpAdd(
465 MathTreeValConst(1.0),
466 MathTreeOpPow(
467 self.Args[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(
489 MathTreeOpAdd(
490 MathTreeOpMul(
491 self.Args[0],
492 self.Args[0].CalcDerivative(arg)),
493 MathTreeOpMul(
494 self.Args[1],
495 self.Args[1].CalcDerivative(arg))),
496 self)
497 else:
498 return MathTreeOpDiv(
499 MathTreeOpMul(
500 self.Args[0],
501 self.Args[0].CalcDerivative(arg)),
502 self)
503 else:
504 if self.Args[1].DependOn(arg):
505 return MathTreeOpDiv(
506 MathTreeOpMul(
507 self.Args[1],
508 self.Args[1].CalcDerivative(arg)),
509 self)
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 FuncExternPattern = re.compile(r"([a-z_][a-z0-9_]*)\s*\(", re.IGNORECASE)
518 class MathTreeFuncExtern(MathTreeFunc):
520 def __init__(self, *args):
521 MathTreeFunc.__init__(self, None, -1, *args)
523 def InitByParser(self, arg):
524 Match = arg.MatchPattern(FuncExternPattern)
525 if Match:
526 self.name = Match[:-1].strip()
527 return self.name
529 def SetName(self, arg):
530 self.name = arg.strip()
531 return self
533 def Calc(HIDDEN_self, **args):
534 return args[HIDDEN_self.name](*[arg.Calc(**args) for arg in HIDDEN_self.Args])
537 class MathTreeOp(MathTree):
539 def __init__(self, level, symbol, *args):
540 self.ParenthesisBarrier = 0
541 self.level = level
542 self.symbol = symbol
543 MathTree.__init__(self, 2, *args)
545 def __str__(self):
546 result = ""
547 if isinstance(self.Args[0], MathTreeOp) and\
548 self.level > self.Args[0].level:
549 result = result + "(" + str(self.Args[0]) + ")"
550 else:
551 result = result + str(self.Args[0])
552 result = result + self.symbol
553 if isinstance(self.Args[1], MathTreeOp) and\
554 self.level >= self.Args[1].level:
555 result = result + "(" + str(self.Args[1]) + ")"
556 else:
557 result = result + str(self.Args[1])
558 return result
560 def InitByParser(self, arg):
561 return arg.MatchStr(self.symbol)
564 class MathTreeOpAdd(MathTreeOp):
566 def __init__(self, *args):
567 MathTreeOp.__init__(self, 1, "+", *args)
569 def CalcDerivative(self, arg):
570 if self.Args[0].DependOn(arg):
571 if self.Args[1].DependOn(arg):
572 return MathTreeOpAdd(
573 self.Args[0].CalcDerivative(arg),
574 self.Args[1].CalcDerivative(arg))
575 else:
576 return self.Args[0].CalcDerivative(arg)
577 else:
578 if self.Args[1].DependOn(arg):
579 return self.Args[1].CalcDerivative(arg)
581 def Calc(HIDDEN_self, **args):
582 return HIDDEN_self.Args[0].Calc(**args) + HIDDEN_self.Args[1].Calc(**args)
585 class MathTreeOpSub(MathTreeOp):
587 def __init__(self, *args):
588 MathTreeOp.__init__(self, 1, "-", *args)
590 def CalcDerivative(self, arg):
591 if self.Args[0].DependOn(arg):
592 if self.Args[1].DependOn(arg):
593 return MathTreeOpSub(
594 self.Args[0].CalcDerivative(arg),
595 self.Args[1].CalcDerivative(arg))
596 else:
597 return self.Args[0].CalcDerivative(arg)
598 else:
599 if self.Args[1].DependOn(arg):
600 return MathTreeFunc1Neg(self.Args[1].CalcDerivative(arg))
602 def Calc(HIDDEN_self, **args):
603 return HIDDEN_self.Args[0].Calc(**args) - HIDDEN_self.Args[1].Calc(**args)
606 class MathTreeOpMul(MathTreeOp):
608 def __init__(self, *args):
609 MathTreeOp.__init__(self, 2, "*", *args)
611 def CalcDerivative(self, arg):
612 if self.Args[0].DependOn(arg):
613 if self.Args[1].DependOn(arg):
614 return MathTreeOpAdd(
615 MathTreeOpMul(
616 self.Args[0],
617 self.Args[1].CalcDerivative(arg)),
618 MathTreeOpMul(
619 self.Args[0].CalcDerivative(arg),
620 self.Args[1]))
621 else:
622 return MathTreeOpMul(
623 self.Args[0].CalcDerivative(arg),
624 self.Args[1])
625 else:
626 if self.Args[1].DependOn(arg):
627 return MathTreeOpMul(
628 self.Args[0],
629 self.Args[1].CalcDerivative(arg))
631 def Calc(HIDDEN_self, **args):
632 return HIDDEN_self.Args[0].Calc(**args) * HIDDEN_self.Args[1].Calc(**args)
635 class MathTreeOpDiv(MathTreeOp):
637 def __init__(self, *args):
638 MathTreeOp.__init__(self, 2, "/", *args)
640 def CalcDerivative(self, arg):
641 if self.Args[0].DependOn(arg):
642 if self.Args[1].DependOn(arg):
643 return MathTreeOpMul(
644 MathTreeOpSub(
645 MathTreeOpMul(
646 self.Args[0].CalcDerivative(arg),
647 self.Args[1]),
648 MathTreeOpMul(
649 self.Args[0],
650 self.Args[1].CalcDerivative(arg))),
651 MathTreeOpPow(
652 self.Args[1],
653 MathTreeValConst(-2.0)))
654 else:
655 return MathTreeOpDiv(
656 self.Args[0].CalcDerivative(arg),
657 self.Args[1])
658 else:
659 if self.Args[1].DependOn(arg):
660 return MathTreeOpMul(
661 MathTreeOpMul(
662 MathTreeFunc1Neg(self.Args[0]),
663 MathTreeOpPow(
664 self.Args[1],
665 MathTreeValConst(-2.0))),
666 self.Args[1].CalcDerivative(arg))
668 def Calc(HIDDEN_self, **args):
669 return HIDDEN_self.Args[0].Calc(**args) / HIDDEN_self.Args[1].Calc(**args)
672 class MathTreeOpPow(MathTreeOp):
674 def __init__(self, *args):
675 MathTreeOp.__init__(self, 3, "^", *args)
677 def InitByParser(self, arg):
678 pos = arg.MatchStr("^")
679 if pos:
680 return 1
681 else:
682 return arg.MatchStr("**")
684 def CalcDerivative(self, arg):
685 if self.Args[0].DependOn(arg):
686 if self.Args[1].DependOn(arg):
687 return MathTreeOpMul(
688 MathTreeOpPow(
689 self.Args[0],
690 self.Args[1]),
691 MathTreeOpAdd(
692 MathTreeOpMul(
693 MathTreeFunc1Log(self.Args[0]),
694 self.Args[1].CalcDerivative(arg)),
695 MathTreeOpMul(
696 self.Args[1],
697 MathTreeOpDiv(
698 self.Args[0].CalcDerivative(arg),
699 self.Args[0]))))
700 else:
701 return MathTreeOpMul(
702 self.Args[1],
703 MathTreeOpMul(
704 MathTreeOpPow(
705 self.Args[0],
706 MathTreeOpSub(
707 self.Args[1],
708 MathTreeValConst(1.0))),
709 self.Args[0].CalcDerivative(arg)))
710 else:
711 if self.Args[1].DependOn(arg):
712 return MathTreeOpMul(
713 MathTreeOpMul(
714 MathTreeOpPow(
715 self.Args[0],
716 self.Args[1]),
717 MathTreeFunc1Log(self.Args[0])),
718 self.Args[1].CalcDerivative(arg))
720 def Calc(HIDDEN_self, **args):
721 return HIDDEN_self.Args[0].Calc(**args) ** HIDDEN_self.Args[1].Calc(**args)
725 DefaultMathTreeFuncs = [MathTreeFunc1Neg, MathTreeFunc1Abs, MathTreeFunc1Sgn, MathTreeFunc1Sqrt,
726 MathTreeFunc1Exp, MathTreeFunc1Log,
727 MathTreeFunc1Sin, MathTreeFunc1Cos, MathTreeFunc1Tan,
728 MathTreeFunc1ASin, MathTreeFunc1ACos, MathTreeFunc1ATan,
729 MathTreeFunc1SinD, MathTreeFunc1CosD, MathTreeFunc1TanD,
730 MathTreeFunc1ASinD, MathTreeFunc1ACosD, MathTreeFunc1ATanD,
731 MathTreeFunc2Norm]
733 class parser:
735 def __init__(self, MathTreeFuncs=DefaultMathTreeFuncs):
736 self.MathTreeFuncs = MathTreeFuncs
738 def parse(self, expr):
739 return self.astseq2mtree(pythonparser.expr(expr.strip()).totuple())
741 def astseq2mtree(self, astseq, isfunc=0):
742 # astseq has to be a sequence!
743 tree = None
745 if token.ISTERMINAL(astseq[0]):
746 raise Exception("")
748 if astseq[0] == symbol.arith_expr: # {{{
749 try:
750 # 1. arith_expr "PLUS" term
751 if astseq[-2][0] == token.PLUS:
752 tree = MathTreeOpAdd(
753 self.astseq2mtree(astseq[:-2], isfunc=isfunc),
754 self.astseq2mtree(astseq[-1], isfunc=isfunc))
755 # 2. arith_expr "MINUS" term
756 elif astseq[-2][0] == token.MINUS:
757 tree = MathTreeOpSub(
758 self.astseq2mtree(astseq[:-2], isfunc=isfunc),
759 self.astseq2mtree(astseq[-1], isfunc=isfunc))
760 else:
761 raise Exception("")
762 except:
763 # 3. term
764 tree = self.astseq2mtree(astseq[1], isfunc=isfunc)
765 return tree # }}}
767 if astseq[0] == symbol.term: # {{{
768 try:
769 # 1. term "STAR" factor
770 if astseq[-2][0] == token.STAR:
771 tree = MathTreeOpMul(
772 self.astseq2mtree(astseq[:-2], isfunc=isfunc),
773 self.astseq2mtree(astseq[-1], isfunc=isfunc))
774 # 2. term "SLASH" factor
775 elif astseq[-2][0] == token.SLASH:
776 tree = MathTreeOpDiv(
777 self.astseq2mtree(astseq[:-2], isfunc=isfunc),
778 self.astseq2mtree(astseq[-1], isfunc=isfunc))
779 else:
780 raise Exception("")
781 except:
782 # 3. factor
783 tree = self.astseq2mtree(astseq[1], isfunc=isfunc)
784 return tree # }}}
786 if astseq[0] == symbol.factor: # {{{
787 if len(astseq) == 3:
788 # 1. "PLUS" factor
789 if astseq[1][0] == token.PLUS:
790 tree = self.astseq2mtree(astseq[2], isfunc=isfunc)
791 # 2. "MINUS" factor
792 elif astseq[1][0] == token.MINUS:
793 tree = MathTreeFunc1Neg(self.astseq2mtree(astseq[2], isfunc=isfunc))
794 else:
795 raise Exception("unknown factor")
796 elif len(astseq) == 2:
797 # 3. power
798 tree = self.astseq2mtree(astseq[1], isfunc=isfunc)
799 else:
800 raise Exception("wrong length of factor")
801 return tree # }}}
803 if astseq[0] == symbol.power: # {{{
804 try:
805 # 1. "DOUBLESTAR" factor
806 if astseq[-2][0] == token.DOUBLESTAR:
807 tree = MathTreeOpPow(
808 self.astseq2mtree(astseq[:-2], isfunc=isfunc),
809 self.astseq2mtree(astseq[-1], isfunc=isfunc))
810 else:
811 raise Exception("")
812 except:
813 # 2. atom + [trailer]
814 if len(astseq) == 3:
815 # we have a function call atom + "LPAR" + argumentlist + "RPAR"
816 if astseq[2][0] == symbol.trailer and \
817 astseq[2][1][0] == token.LPAR and \
818 astseq[2][2][0] == symbol.arglist and \
819 astseq[2][3][0] == token.RPAR:
820 tree = self.astseq2mtree(astseq[1], isfunc=1)
821 for subtree in self.astseq2mtree(astseq[2][2], isfunc=0):
822 tree.AddArg(subtree)
823 elif astseq[2][0] == symbol.trailer and \
824 astseq[2][1][0] == token.LPAR and \
825 astseq[2][2][0] == token.RPAR:
826 tree = self.astseq2mtree(astseq[1], isfunc=1)
827 else:
828 raise Exception("wrong function call")
829 else:
830 tree = self.astseq2mtree(astseq[1], isfunc=0)
832 return tree # }}}
834 if astseq[0] == symbol.atom: # {{{
835 # only one nontrivial term:
836 if len(astseq) == 2:
837 if astseq[1][0] == token.NUMBER:
838 # 1. a number
839 # XXX: for evaluation of brackets we will need integers as well
840 tree = MathTreeValConst(string.atof(astseq[1][1]))
841 elif astseq[1][0] == token.NAME:
842 # 2. a function
843 if isfunc:
844 # a known function
845 for funcclass in self.MathTreeFuncs:
846 func = funcclass() # ist das guenstig, da jedesmal eine Instanz zu erzeugen?
847 # doofe Frage, nein! <wobsta>
848 if func.name == astseq[1][1]:
849 return func
850 # an unknown function
851 tree = MathTreeFuncExtern()
852 tree.SetName(astseq[1][1])
853 else:
854 # 3. a variable
855 return MathTreeValVar(astseq[1][1])
856 elif len(astseq) == 4:
857 # parentheses or brackets for structuring an atom
858 if (astseq[1][0] == token.LPAR and astseq[3][0] == token.RPAR) or \
859 (astseq[1][0] == token.LSQB and astseq[3][0] == token.RSQB):
860 tree = self.astseq2mtree(astseq[2], isfunc=isfunc)
861 else:
862 raise Exception("symbol.atom with unknown number of arguments")
863 return tree # }}}
865 if astseq[0] == symbol.arglist: # {{{
866 treelist = []
867 for arg in astseq[1:]:
868 if arg[0] == token.COMMA:
869 continue
870 elif arg[0] == symbol.argument:
871 treelist.append(self.astseq2mtree(arg, isfunc=isfunc))
872 return treelist # }}}
874 if astseq[0] == symbol.testlist: # {{{
875 treelist = []
876 for arg in astseq[1:]:
877 if arg[0] == token.COMMA:
878 continue
879 elif arg[0] == symbol.test:
880 treelist.append(self.astseq2mtree(arg, isfunc=isfunc))
881 if len(treelist) == 1: return treelist[0]
882 else: return treelist # }}}
884 if astseq[0] != symbol.eval_input and len(astseq) > 2:
885 raise Exception("invalid expression structure (contains several parts)")
886 return self.astseq2mtree(astseq[1], isfunc=isfunc)