NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

expressiontree.py (13079B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\evegraphics\controllers\expressiontree.py
      2 from __future__ import print_function
      3 import re
      4 
      5 class ExpressionNode(object):
      6 
      7     def __init__(self, inputs = 0):
      8         self._inputs = []
      9         if inputs > 0:
     10             self._inputs = [None] * inputs
     11         self.startPosition = -1
     12 
     13     def Store(self):
     14         pass
     15 
     16     def BuildExpression(self):
     17         pass
     18 
     19     def GetTitle(self):
     20         pass
     21 
     22     def GetInputs(self):
     23         return self._inputs
     24 
     25     def GetPrecedence(self):
     26         return 100
     27 
     28     def SetInput(self, index, inputValue):
     29         self._inputs[index] = inputValue
     30 
     31     def SetInputs(self, inputs):
     32         for i, x in enumerate(inputs):
     33             self._inputs[i] = x
     34 
     35     def GetTextTemplate(self):
     36         return ('', '')
     37 
     38     def Dump(self, indent = 0):
     39         print('%s%s' % (' ' * indent, self.GetTitle()))
     40         for each in self._inputs:
     41             each.Dump(indent + 2)
     42 
     43 
     44 class Variable(ExpressionNode):
     45 
     46     def __init__(self, name):
     47         super(Variable, self).__init__()
     48         self.name = name
     49 
     50     def Store(self):
     51         return ['Variable', self.name]
     52 
     53     def GetTitle(self):
     54         return self.name
     55 
     56     def BuildExpression(self):
     57         return self.name
     58 
     59     def GetTextTemplate(self):
     60         return (self.name, '')
     61 
     62 
     63 class NumericConstant(ExpressionNode):
     64 
     65     def __init__(self, number):
     66         super(NumericConstant, self).__init__()
     67         self.number = number
     68 
     69     def Store(self):
     70         return ['NumericConstant', self.number]
     71 
     72     def GetTitle(self):
     73         return str(self.number)
     74 
     75     def BuildExpression(self):
     76         return str(self.number)
     77 
     78     def GetTextTemplate(self):
     79         return (str(self.number), '')
     80 
     81 
     82 class UnaryOperator(ExpressionNode):
     83 
     84     def __init__(self, operator, precedence = 10):
     85         super(UnaryOperator, self).__init__(1)
     86         self.operator = operator
     87         self.precedence = precedence
     88 
     89     def Store(self):
     90         return ['UnaryOperator', self.operator]
     91 
     92     def GetTitle(self):
     93         return self.operator
     94 
     95     def BuildExpression(self):
     96         e = self.GetInputs()[0].BuildExpression()
     97         if self.GetInputs()[0].GetPrecedence() < self.GetPrecedence():
     98             e = '(%s)' % e
     99         return '%s%s' % (self.operator, e)
    100 
    101     def GetPrecedence(self):
    102         return self.precedence
    103 
    104     def GetTextTemplate(self):
    105         return (self.operator, '')
    106 
    107 
    108 def GetOperatorPrecedence(operator):
    109     for i, each in enumerate(OP_PRIORITIES):
    110         if operator in each:
    111             return i
    112 
    113     return 0
    114 
    115 
    116 class Operator(ExpressionNode):
    117 
    118     def __init__(self, operator):
    119         super(Operator, self).__init__(2)
    120         self.operator = operator
    121 
    122     def Store(self):
    123         return ['Operator', self.operator]
    124 
    125     def GetTitle(self):
    126         return self.operator
    127 
    128     def BuildExpression(self):
    129         e0 = self.GetInputs()[0].BuildExpression()
    130         if self.GetInputs()[0].GetPrecedence() < self.GetPrecedence():
    131             e0 = '(%s)' % e0
    132         e1 = self.GetInputs()[1].BuildExpression()
    133         if self.GetInputs()[1].GetPrecedence() < self.GetPrecedence():
    134             e1 = '(%s)' % e1
    135         return '%s %s %s' % (e0, self.operator, e1)
    136 
    137     def GetPrecedence(self):
    138         return GetOperatorPrecedence(self.operator)
    139 
    140     def GetTextTemplate(self):
    141         return (self.operator, '')
    142 
    143 
    144 class FunctionCall(ExpressionNode):
    145 
    146     def __init__(self, name, paramsCount):
    147         super(FunctionCall, self).__init__(paramsCount)
    148         self.name = name
    149 
    150     def Store(self):
    151         return ['FunctionCall', self.name, len(self._inputs)]
    152 
    153     def GetTitle(self):
    154         return self.name
    155 
    156     def BuildExpression(self):
    157         args = [ x.BuildExpression() for x in self.GetInputs() ]
    158         return '%s(%s)' % (self.name, ', '.join(args))
    159 
    160     def GetTextTemplate(self):
    161         return ('%s(' % self.name, ')')
    162 
    163 
    164 class StringFunctionCall(ExpressionNode):
    165 
    166     def __init__(self, name, param):
    167         super(StringFunctionCall, self).__init__(0)
    168         self.name = name
    169         self.param = param
    170         self.paramStartPosition = -1
    171 
    172     def Store(self):
    173         return ['StringFunctionCall', self.name, self.param]
    174 
    175     def GetTitle(self):
    176         return '%s\n%s' % (self.name, self.param[1:-1])
    177 
    178     def BuildExpression(self):
    179         return '%s(%s)' % (self.name, self.param)
    180 
    181     def GetTextTemplate(self):
    182         return ('%s("' % self.name, '")')
    183 
    184 
    185 class ResultExpression(ExpressionNode):
    186 
    187     def __init__(self):
    188         super(ResultExpression, self).__init__(1)
    189 
    190     def Store(self):
    191         return ['ResultExpression']
    192 
    193     def GetTitle(self):
    194         return 'Result'
    195 
    196     def BuildExpression(self):
    197         return self.GetInputs()[0].BuildExpression()
    198 
    199 
    200 class Token(object):
    201 
    202     def __init__(self, token, string, startPosition):
    203         self.token = token
    204         self.string = string
    205         self.startPosition = startPosition
    206 
    207     def __eq__(self, other):
    208         return isinstance(other, Token) and self.token == other.token and self.string == other.string
    209 
    210     def __ne__(self, other):
    211         return not isinstance(other, Token) or self.token != other.token or self.string != other.string
    212 
    213 
    214 class Stream(object):
    215 
    216     def __init__(self, string):
    217         self._string = string
    218         self._position = 0
    219         self._length = len(string)
    220 
    221     def Eof(self):
    222         return self._position >= self._length
    223 
    224     def Peek(self, length):
    225         return self._string[self._position:self._position + length]
    226 
    227     def Consume(self, length):
    228         result = self.Peek(length)
    229         self._position += len(result)
    230         return result
    231 
    232     def GetPosition(self):
    233         return self._position
    234 
    235     def PeekAll(self):
    236         return self._string[self._position:]
    237 
    238 
    239 _TOKENS = re.compile('\\A\\s*((&&|\\|\\||>=|<=|!=|==|[+\\-*/^%><=!()])|([a-zA-Z_][a-zA-Z_0-9]*)|(\\"[^\\"]*\\")|(-?(([0-9]*\\.[0-9]*)|[0-9]+)([eE][+\\-]?[0-9]+)?))')
    240 
    241 def _GetToken(stream):
    242     pos = stream.GetPosition()
    243     if stream.Eof():
    244         return Token('', '', pos)
    245     elif stream.Peek(2) in ('&&', '||', '<=', '>=', '!=', '=='):
    246         return Token('OP', stream.Consume(2), pos)
    247     elif stream.Peek(1) in ('+', '-', '*', '/', '^', '%', '>', '<', '=', '!', '(', ')', ','):
    248         return Token('OP', stream.Consume(1), pos)
    249     m = _TOKENS.match(stream.PeekAll())
    250     if not m:
    251         raise ValueError(repr(stream.PeekAll()))
    252     stream.Consume(len(m.group(0)))
    253     if m.group(2):
    254         return Token('OP', m.group(2), pos)
    255     elif m.group(3):
    256         return Token('ID', m.group(3), pos)
    257     elif m.group(4):
    258         return Token('STR', m.group(4), pos)
    259     else:
    260         return Token('NUM', m.group(5), pos)
    261 
    262 
    263 OP_PRIORITIES = [('=',),
    264  (),
    265  ('||',),
    266  ('&&',),
    267  ('<=', '>=', '!=', '==', '>', '<'),
    268  ('+', '-'),
    269  ('*', '/', '%'),
    270  ('^',)]
    271 _OPEN_PAREN = Token('OP', '(', 0)
    272 _CLOSE_PAREN = Token('OP', ')', 0)
    273 _COMA = Token('OP', ',', 0)
    274 
    275 def _Term(token, stream):
    276     if token.token == 'ID':
    277         name = token.string
    278         start = token.startPosition
    279         token = _GetToken(stream)
    280         if token == _OPEN_PAREN:
    281             r = None
    282             args = []
    283             while True:
    284                 token = _GetToken(stream)
    285                 if token.token == 'STR':
    286                     r = StringFunctionCall(name, token.string)
    287                     r.startPosition = start
    288                     r.paramStartPosition = token.startPosition
    289                     token = _GetToken(stream)
    290                     if token != _CLOSE_PAREN:
    291                         raise ValueError()
    292                     break
    293                 elif token == _CLOSE_PAREN:
    294                     break
    295                 arg, token = _Expr(token, stream, 0)
    296                 args.append(arg)
    297                 if token == _CLOSE_PAREN:
    298                     break
    299                 elif token != _COMA:
    300                     raise ValueError()
    301 
    302             if not r:
    303                 r = FunctionCall(name, len(args))
    304                 r.startPosition = start
    305             r.SetInputs(args)
    306             token = _GetToken(stream)
    307         else:
    308             r = Variable(name)
    309             r.startPosition = start
    310         return (r, token)
    311     if token.token == 'NUM':
    312         e = NumericConstant(float(token.string))
    313         e.startPosition = token.startPosition
    314         return (e, _GetToken(stream))
    315     if token.string in ('+', '-'):
    316         e = UnaryOperator(token.string, 10)
    317         e.startPosition = token.startPosition
    318         r, token = _Term(_GetToken(stream), stream)
    319         e.SetInput(0, r)
    320         return (e, token)
    321     if token == _OPEN_PAREN:
    322         result, token = _Expr(_GetToken(stream), stream, 0)
    323         if token != _CLOSE_PAREN:
    324             raise ValueError()
    325         return (result, _GetToken(stream))
    326     raise ValueError()
    327 
    328 
    329 def _Expr(token, stream, priority):
    330     left, token = _Term(token, stream) if priority + 1 >= len(OP_PRIORITIES) else _Expr(token, stream, priority + 1)
    331     while token.string in OP_PRIORITIES[priority]:
    332         op = Operator(token.string)
    333         op.startPosition = token.startPosition
    334         op.SetInput(0, left)
    335         token = _GetToken(stream)
    336         right, token = _Term(token, stream) if priority + 1 >= len(OP_PRIORITIES) else _Expr(token, stream, priority + 1)
    337         op.SetInput(1, right)
    338         left = op
    339 
    340     return (left, token)
    341 
    342 
    343 def Parse(input):
    344     stream = Stream(input)
    345     r, t = _Expr(_GetToken(stream), stream, 0)
    346     if t.token != '':
    347         raise ValueError(t.string)
    348     return r
    349 
    350 
    351 class NodeGroup(object):
    352 
    353     def __init__(self, title, children):
    354         self.title = title
    355         self.children = list(children)
    356         self.description = ''
    357 
    358 
    359 class NodeDescription(object):
    360 
    361     def __init__(self, title, factory, description = ''):
    362         self.title = title
    363         self.factory = factory
    364         self.description = description
    365 
    366 
    367 NODE_DESCRIPTIONS = (NodeGroup('Operators', (NodeDescription('-x', lambda : UnaryOperator('-', 10)),
    368   NodeDescription('x ^ y', lambda : Operator('^')),
    369   NodeDescription('x * y', lambda : Operator('*')),
    370   NodeDescription('x / y', lambda : Operator('/')),
    371   NodeDescription('x + y', lambda : Operator('+')),
    372   NodeDescription('x - y', lambda : Operator('-')),
    373   NodeDescription('x == y', lambda : Operator('==')),
    374   NodeDescription('x != y', lambda : Operator('!=')),
    375   NodeDescription('x > y', lambda : Operator('>')),
    376   NodeDescription('x < y', lambda : Operator('<')),
    377   NodeDescription('x >= y', lambda : Operator('>=')),
    378   NodeDescription('x <= y', lambda : Operator('<=')),
    379   NodeDescription('x % y', lambda : Operator('%')),
    380   NodeDescription('AND', lambda : Operator('&&')),
    381   NodeDescription('OR', lambda : Operator('||')))), NodeGroup('Math', (NodeDescription('abs', lambda : FunctionCall('abs', 1), 'abs(x) - absolute value (drop the sign)'),
    382   NodeDescription('sqrt', lambda : FunctionCall('sqrt', 1), 'sqrt(x) - square root of x'),
    383   NodeDescription('sign', lambda : FunctionCall('sign', 1), 'sign(x) - sign (-1, 0 or 1) of the argument'),
    384   NodeDescription('log2', lambda : FunctionCall('log2', 1), 'log2(x) - base 2 logarithm'),
    385   NodeDescription('log10', lambda : FunctionCall('log10', 1), 'log10(x) - base 10 logarithm'),
    386   NodeDescription('log', lambda : FunctionCall('log', 1), 'log(x) - natural logarithm'),
    387   NodeDescription('ln', lambda : FunctionCall('ln', 1), 'ln(x) - natural logarithm'),
    388   NodeDescription('exp', lambda : FunctionCall('exp', 1), 'exp(x) - natural exponent'),
    389   NodeDescription('rint', lambda : FunctionCall('rint', 1), 'rint(x) - round value to an integer'),
    390   NodeDescription('sin', lambda : FunctionCall('sin', 1), 'sin(x) - sine'),
    391   NodeDescription('cos', lambda : FunctionCall('cos', 1), 'cos(x) - cosine'),
    392   NodeDescription('tan', lambda : FunctionCall('tan', 1), 'tan(x) - tangent'),
    393   NodeDescription('asin', lambda : FunctionCall('asin', 1), 'asin(x) - arcsine'),
    394   NodeDescription('acos', lambda : FunctionCall('acos', 1), 'acos(x) - arccosine'),
    395   NodeDescription('atan', lambda : FunctionCall('atan', 1), 'atan(x) - argtangent'),
    396   NodeDescription('sinh', lambda : FunctionCall('sinh', 1), 'sinh(x) - hyperbolic sine'),
    397   NodeDescription('cosh', lambda : FunctionCall('cosh', 1), 'cosh(x) - hyperbolic cosine'),
    398   NodeDescription('tanh', lambda : FunctionCall('tanh', 1), 'tanh(x) - hyperbolic tangent'),
    399   NodeDescription('asinh', lambda : FunctionCall('asinh', 1), 'asinh(x) - hyperbolic arcsine'),
    400   NodeDescription('acosh', lambda : FunctionCall('acosh', 1), 'acosh(x) - hyperbolic arccosine'),
    401   NodeDescription('atanh', lambda : FunctionCall('atanh', 1), 'atanh(x) - hyperbolic arctangent'),
    402   NodeDescription('min', lambda : FunctionCall('min', 0), 'min(arg1...) - minimum of all arguments (one or more)'),
    403   NodeDescription('max', lambda : FunctionCall('max', 0), 'max(arg1...) - maximum of all arguments (one or more)'),
    404   NodeDescription('sum', lambda : FunctionCall('sum', 0), 'sum(arg1...) - sum of all arguments (one or more)'),
    405   NodeDescription('avg', lambda : FunctionCall('avg', 0), 'avg(arg1...) - average of all arguments (one or more)'))))