3c80b0652619556ceb6961a8ddb413a0cbca4b06
1 """BulletML expression evaluator.
3 http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html
6 # BulletML assumes 1/2 = 0.5.
7 from __future__
import division
12 from bulletml
.errors
import Error
14 class ExprError(Error
):
15 """Raised when an invalid expression is evaluated/compiled."""
18 class NumberDef(object):
19 """BulletML numeric expression.
21 This translates BulletML numeric expressions into Python expressions.
33 GLOBALS
= dict(random
=random
.random
, __builtins__
={})
35 def __init__(self
, expr
):
38 except AttributeError:
41 repl
= lambda match
: "params[%d]" % (int(match
.group()[1:]) - 1)
42 expr
= re
.sub(r
"\$\d+", repl
, expr
.lower())
43 self
.__expr
= expr
.replace("$rand", "random()").replace("$rank", "rank")
46 self
.__value
= eval(self
.__expr
, dict(__builtins__
={}))
48 variables
= dict(rank
=1, params
=[0] * 99)
49 value
= eval(self
.__expr
, self
.GLOBALS
, variables
)
50 if not isinstance(value
, (int, float)):
55 self
.__expr
= compile(self
.__expr
, __file__
, "eval")
57 def __call__(self
, params
, rank
):
58 """Evaluate the expression and return its value."""
59 if self
.__value
is not None:
61 variables
= { 'rank': rank
, 'params': params
}
62 return eval(self
.__expr
, self
.GLOBALS
, variables
)
65 return "%s(%r)" % (type(self
).__name
__, self
.string
)
67 class INumberDef(NumberDef
):
68 """A NumberDef, but returns rounded integer results."""
69 def __call__(self
, params
, rank
):
70 return int(round(super(INumberDef
, self
).__call
__(params
, rank
)))