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 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
)
526 self
.name
= Match
[:-1].strip()
529 def SetName(self
, arg
):
530 self
.name
= arg
.strip()
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
543 MathTree
.__init
__(self
, 2, *args
)
547 if isinstance(self
.Args
[0], MathTreeOp
) and\
548 self
.level
> self
.Args
[0].level
:
549 result
= result
+ "(" + str(self
.Args
[0]) + ")"
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]) + ")"
557 result
= result
+ str(self
.Args
[1])
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
))
576 return self
.Args
[0].CalcDerivative(arg
)
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
))
597 return self
.Args
[0].CalcDerivative(arg
)
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(
617 self
.Args
[1].CalcDerivative(arg
)),
619 self
.Args
[0].CalcDerivative(arg
),
622 return MathTreeOpMul(
623 self
.Args
[0].CalcDerivative(arg
),
626 if self
.Args
[1].DependOn(arg
):
627 return MathTreeOpMul(
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(
646 self
.Args
[0].CalcDerivative(arg
),
650 self
.Args
[1].CalcDerivative(arg
))),
653 MathTreeValConst(-2.0)))
655 return MathTreeOpDiv(
656 self
.Args
[0].CalcDerivative(arg
),
659 if self
.Args
[1].DependOn(arg
):
660 return MathTreeOpMul(
662 MathTreeFunc1Neg(self
.Args
[0]),
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("^")
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(
693 MathTreeFunc1Log(self
.Args
[0]),
694 self
.Args
[1].CalcDerivative(arg
)),
698 self
.Args
[0].CalcDerivative(arg
),
701 return MathTreeOpMul(
708 MathTreeValConst(1.0))),
709 self
.Args
[0].CalcDerivative(arg
)))
711 if self
.Args
[1].DependOn(arg
):
712 return MathTreeOpMul(
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
,
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!
745 if token
.ISTERMINAL(astseq
[0]):
748 if astseq
[0] == symbol
.arith_expr
: # {{{
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
))
764 tree
= self
.astseq2mtree(astseq
[1], isfunc
=isfunc
)
767 if astseq
[0] == symbol
.term
: # {{{
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
))
783 tree
= self
.astseq2mtree(astseq
[1], isfunc
=isfunc
)
786 if astseq
[0] == symbol
.factor
: # {{{
789 if astseq
[1][0] == token
.PLUS
:
790 tree
= self
.astseq2mtree(astseq
[2], isfunc
=isfunc
)
792 elif astseq
[1][0] == token
.MINUS
:
793 tree
= MathTreeFunc1Neg(self
.astseq2mtree(astseq
[2], isfunc
=isfunc
))
795 raise Exception("unknown factor")
796 elif len(astseq
) == 2:
798 tree
= self
.astseq2mtree(astseq
[1], isfunc
=isfunc
)
800 raise Exception("wrong length of factor")
803 if astseq
[0] == symbol
.power
: # {{{
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
))
813 # 2. atom + [trailer]
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):
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)
828 raise Exception("wrong function call")
830 tree
= self
.astseq2mtree(astseq
[1], isfunc
=0)
834 if astseq
[0] == symbol
.atom
: # {{{
835 # only one nontrivial term:
837 if astseq
[1][0] == token
.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
:
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]:
850 # an unknown function
851 tree
= MathTreeFuncExtern()
852 tree
.SetName(astseq
[1][1])
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
)
862 raise Exception("symbol.atom with unknown number of arguments")
865 if astseq
[0] == symbol
.arglist
: # {{{
867 for arg
in astseq
[1:]:
868 if arg
[0] == token
.COMMA
:
870 elif arg
[0] == symbol
.argument
:
871 treelist
.append(self
.astseq2mtree(arg
, isfunc
=isfunc
))
872 return treelist
# }}}
874 if astseq
[0] == symbol
.testlist
: # {{{
876 for arg
in astseq
[1:]:
877 if arg
[0] == token
.COMMA
:
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
)