wolfhece 2.1.20__py3-none-any.whl → 2.1.21__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,855 @@
1
+ #! /usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Author: AxiaCore S.A.S. http://axiacore.com
4
+ #
5
+ # Based on js-expression-eval, by Matthew Crumley (email@matthewcrumley.com, http://silentmatt.com/)
6
+ # https://github.com/silentmatt/js-expression-eval
7
+ #
8
+ # Ported to Python and modified by Vera Mazhuga (ctrl-alt-delete@live.com, http://vero4ka.info/)
9
+ #
10
+ # You are free to use and modify this code in anyway you find useful. Please leave this comment in the code
11
+ # to acknowledge its original source. If you feel like it, I enjoy hearing about projects that use my code,
12
+ # but don't feel like you have to let me know or ask permission.
13
+
14
+ import math
15
+ import random
16
+ import re
17
+
18
+ TNUMBER = 0
19
+ TOP1 = 1
20
+ TOP2 = 2
21
+ TVAR = 3
22
+ TFUNCALL = 4
23
+
24
+
25
+ class Token():
26
+
27
+ def __init__(self, type_, index_, prio_, number_):
28
+ self.type_ = type_
29
+ self.index_ = index_ or 0
30
+ self.prio_ = prio_ or 0
31
+ self.number_ = number_ if number_ != None else 0
32
+
33
+ def toString(self):
34
+ if self.type_ == TNUMBER:
35
+ return self.number_
36
+ if self.type_ == TOP1 or self.type_ == TOP2 or self.type_ == TVAR:
37
+ return self.index_
38
+ elif self.type_ == TFUNCALL:
39
+ return 'CALL'
40
+ else:
41
+ return 'Invalid Token'
42
+
43
+
44
+ class Expression():
45
+
46
+ def __init__(self, tokens, ops1, ops2, functions):
47
+ self.tokens = tokens
48
+ self.ops1 = ops1
49
+ self.ops2 = ops2
50
+ self.functions = functions
51
+
52
+ def simplify(self, values):
53
+ values = values or {}
54
+ nstack = []
55
+ newexpression = []
56
+ L = len(self.tokens)
57
+ for i in range(0, L):
58
+ item = self.tokens[i]
59
+ type_ = item.type_
60
+ if type_ == TNUMBER:
61
+ nstack.append(item)
62
+ elif type_ == TVAR and item.index_ in values:
63
+ item = Token(TNUMBER, 0, 0, values[item.index_])
64
+ nstack.append(item)
65
+ elif type_ == TOP2 and len(nstack) > 1:
66
+ n2 = nstack.pop()
67
+ n1 = nstack.pop()
68
+ f = self.ops2[item.index_]
69
+ item = Token(TNUMBER, 0, 0, f(n1.number_, n2.number_))
70
+ nstack.append(item)
71
+ elif type_ == TOP1 and nstack:
72
+ n1 = nstack.pop()
73
+ f = self.ops1[item.index_]
74
+ item = Token(TNUMBER, 0, 0, f(n1.number_))
75
+ nstack.append(item)
76
+ else:
77
+ while len(nstack) > 0:
78
+ newexpression.append(nstack.pop(0))
79
+ newexpression.append(item)
80
+ while nstack:
81
+ newexpression.append(nstack.pop(0))
82
+
83
+ return Expression(newexpression, self.ops1, self.ops2, self.functions)
84
+
85
+ def substitute(self, variable, expr):
86
+ if not isinstance(expr, Expression):
87
+ expr = Parser().parse(str(expr))
88
+ newexpression = []
89
+ L = len(self.tokens)
90
+ for i in range(0, L):
91
+ item = self.tokens[i]
92
+ type_ = item.type_
93
+ if type_ == TVAR and item.index_ == variable:
94
+ for j in range(0, len(expr.tokens)):
95
+ expritem = expr.tokens[j]
96
+ replitem = Token(
97
+ expritem.type_,
98
+ expritem.index_,
99
+ expritem.prio_,
100
+ expritem.number_,
101
+ )
102
+ newexpression.append(replitem)
103
+ else:
104
+ newexpression.append(item)
105
+
106
+ ret = Expression(newexpression, self.ops1, self.ops2, self.functions)
107
+ return ret
108
+
109
+ def evaluate(self, values):
110
+ values = values or {}
111
+ nstack = []
112
+ L = len(self.tokens)
113
+ for item in self.tokens:
114
+ type_ = item.type_
115
+ if type_ == TNUMBER:
116
+ nstack.append(item.number_)
117
+ elif type_ == TOP2:
118
+ n2 = nstack.pop()
119
+ n1 = nstack.pop()
120
+ f = self.ops2[item.index_]
121
+ nstack.append(f(n1, n2))
122
+ elif type_ == TVAR:
123
+ if item.index_ in values:
124
+ nstack.append(values[item.index_])
125
+ elif item.index_ in self.functions:
126
+ nstack.append(self.functions[item.index_])
127
+ else:
128
+ raise Exception('undefined variable: ' + item.index_)
129
+ elif type_ == TOP1:
130
+ n1 = nstack.pop()
131
+ f = self.ops1[item.index_]
132
+ nstack.append(f(n1))
133
+ elif type_ == TFUNCALL:
134
+ n1 = nstack.pop()
135
+ f = nstack.pop()
136
+ if callable(f):
137
+ if type(n1) is list:
138
+ nstack.append(f(*n1))
139
+ else:
140
+ nstack.append(f(n1))
141
+ else:
142
+ raise Exception(f + ' is not a function')
143
+ else:
144
+ raise Exception('invalid Expression')
145
+ if len(nstack) > 1:
146
+ raise Exception('invalid Expression (parity)')
147
+ return nstack[0]
148
+
149
+ def toString(self, toJS=False):
150
+ nstack = []
151
+ L = len(self.tokens)
152
+ for i in range(0, L):
153
+ item = self.tokens[i]
154
+ type_ = item.type_
155
+ if type_ == TNUMBER:
156
+ if type(item.number_) == str:
157
+ nstack.append("'"+item.number_+"'")
158
+ else:
159
+ nstack.append( item.number_)
160
+ elif type_ == TOP2:
161
+ n2 = nstack.pop()
162
+ n1 = nstack.pop()
163
+ f = item.index_
164
+ if toJS and f == '^':
165
+ nstack.append('math.pow(' + n1 + ',' + n2 + ')')
166
+ else:
167
+ frm='({n1}{f}{n2})'
168
+ if f == ',':
169
+ frm = '{n1}{f}{n2}'
170
+
171
+ nstack.append(frm.format(
172
+ n1=n1,
173
+ n2=n2,
174
+ f=f,
175
+ ))
176
+
177
+
178
+ elif type_ == TVAR:
179
+ nstack.append(item.index_)
180
+ elif type_ == TOP1:
181
+ n1 = nstack.pop()
182
+ f = item.index_
183
+ if f == '-':
184
+ nstack.append('(' + f + str(n1) + ')')
185
+ else:
186
+ nstack.append(f + '(' + str(n1) + ')')
187
+ elif type_ == TFUNCALL:
188
+ n1 = nstack.pop()
189
+ f = nstack.pop()
190
+ nstack.append(f + '(' + n1 + ')')
191
+ else:
192
+ raise Exception('invalid Expression')
193
+ if len(nstack) > 1:
194
+ raise Exception('invalid Expression (parity)')
195
+ return nstack[0]
196
+
197
+ def __str__(self):
198
+ return self.toString()
199
+
200
+ def symbols(self):
201
+ vars = []
202
+ for i in range(0, len(self.tokens)):
203
+ item = self.tokens[i]
204
+ if item.type_ == TVAR and not item.index_ in vars:
205
+ vars.append(item.index_)
206
+ return vars
207
+
208
+ def variables(self):
209
+ return [
210
+ sym for sym in self.symbols()
211
+ if sym not in self.functions]
212
+
213
+
214
+ class Parser:
215
+
216
+ PRIMARY = 1
217
+ OPERATOR = 2
218
+ FUNCTION = 4
219
+ LPAREN = 8
220
+ RPAREN = 16
221
+ COMMA = 32
222
+ SIGN = 64
223
+ CALL = 128
224
+ NULLARY_CALL = 256
225
+
226
+ def add(self, a, b):
227
+ return a + b
228
+
229
+ def norm(self, a, b):
230
+ return math.sqrt(a * a + b * b)
231
+
232
+ def Froude(self, a, b, c):
233
+
234
+ return math.sqrt(a * a + b * b) / math.sqrt(9.81 * c)
235
+
236
+ def sto(self, a, b):
237
+ return dict(a = b)
238
+
239
+ def sub(self, a, b):
240
+ return a - b
241
+
242
+ def mul(self, a, b):
243
+ return a * b
244
+
245
+ def div(self, a, b):
246
+ return a / b
247
+
248
+ def pow(self, a, b):
249
+ return a ** b
250
+
251
+ def mod(self, a, b):
252
+ return a % b
253
+
254
+ def concat(self, a, b,*args):
255
+ result=u'{0}{1}'.format(a, b)
256
+ for arg in args:
257
+ result=u'{0}{1}'.format(result, arg)
258
+ return result
259
+
260
+ def equal (self, a, b ):
261
+ return a == b
262
+
263
+ def notEqual (self, a, b ):
264
+ return a != b
265
+
266
+ def greaterThan (self, a, b ):
267
+ return a > b
268
+
269
+ def lessThan (self, a, b ):
270
+ return a < b
271
+
272
+ def greaterThanEqual (self, a, b ):
273
+ return a >= b
274
+
275
+ def lessThanEqual (self, a, b ):
276
+ return a <= b
277
+
278
+ def andOperator (self, a, b ):
279
+ return ( a and b )
280
+
281
+ def orOperator (self, a, b ):
282
+ return ( a or b )
283
+
284
+ def xorOperator (self, a, b ):
285
+ return ( a ^ b )
286
+
287
+ def inOperator(self, a, b):
288
+ return a in b
289
+
290
+ def notOperator(self, a):
291
+ return not a
292
+
293
+ def neg(self, a):
294
+ return -a
295
+
296
+ def random(self, a):
297
+ return random.random() * (a or 1)
298
+
299
+ def fac(self, a): # a!
300
+ return math.factorial(a)
301
+
302
+ def pyt(self, a, b):
303
+ return math.sqrt(a * a + b * b)
304
+
305
+ def sind(self, a):
306
+ return math.sin(math.radians(a))
307
+
308
+ def cosd(self, a):
309
+ return math.cos(math.radians(a))
310
+
311
+ def tand(self, a):
312
+ return math.tan(math.radians(a))
313
+
314
+ def asind(self, a):
315
+ return math.degrees(math.asin(a))
316
+
317
+ def acosd(self, a):
318
+ return math.degrees(math.acos(a))
319
+
320
+ def atand(self, a):
321
+ return math.degrees(math.atan(a))
322
+
323
+ def roll(self, a, b):
324
+ rolls = []
325
+ roll = 0
326
+ final = 0
327
+ for c in range(1, a):
328
+ roll = random.randint(1, b)
329
+ rolls.append(roll)
330
+ return rolls
331
+
332
+ def ifFunction(self,a,b,c):
333
+ return b if a else c
334
+
335
+ def append(self, a, b):
336
+ if type(a) != list:
337
+ return [a, b]
338
+ a.append(b)
339
+ return a
340
+
341
+ def __init__(self, string_literal_quotes = ("'", "\"")):
342
+ self.string_literal_quotes = string_literal_quotes
343
+
344
+ self.success = False
345
+ self.errormsg = ''
346
+ self.expression = ''
347
+
348
+ self.pos = 0
349
+
350
+ self.tokennumber = 0
351
+ self.tokenprio = 0
352
+ self.tokenindex = 0
353
+ self.tmpprio = 0
354
+
355
+ self.ops1 = {
356
+ 'sin': math.sin,
357
+ 'cos': math.cos,
358
+ 'tan': math.tan,
359
+ 'asin': math.asin,
360
+ 'acos': math.acos,
361
+ 'atan': math.atan,
362
+
363
+ 'sind': self.sind,
364
+ 'cosd': self.cosd,
365
+ 'tand': self.tand,
366
+ 'asind': self.asind,
367
+ 'acosd': self.acosd,
368
+ 'atand': self.atand,
369
+
370
+ 'sqrt': math.sqrt,
371
+ 'abs': abs,
372
+ 'ceil': math.ceil,
373
+ 'floor': math.floor,
374
+ 'round': round,
375
+ '-': self.neg,
376
+ 'not': self.notOperator,
377
+ 'exp': math.exp,
378
+ }
379
+
380
+ self.ops2 = {
381
+ '+': self.add,
382
+ '-': self.sub,
383
+ '*': self.mul,
384
+ '/': self.div,
385
+ '%': self.mod,
386
+ '^': self.pow,
387
+ '**': self.pow,
388
+ ',': self.append,
389
+ '||': self.concat,
390
+ "==": self.equal,
391
+ "!=": self.notEqual,
392
+ ">": self.greaterThan,
393
+ "<": self.lessThan,
394
+ ">=": self.greaterThanEqual,
395
+ "<=": self.lessThanEqual,
396
+ "and": self.andOperator,
397
+ "or": self.orOperator,
398
+ "xor": self.xorOperator,
399
+ "in": self.inOperator,
400
+ "D": self.roll,
401
+ }
402
+
403
+ self.functions = {
404
+ 'random': self.random,
405
+ 'fac': self.fac,
406
+ 'log': math.log,
407
+ 'min': min,
408
+ 'max': max,
409
+ 'pyt': self.pyt,
410
+ 'pow': math.pow,
411
+ 'atan2': math.atan2,
412
+ 'concat':self.concat,
413
+ 'if': self.ifFunction,
414
+ 'norm': self.norm,
415
+ 'Froude': self.Froude,
416
+ 'sto': self.sto,
417
+ }
418
+
419
+ self.consts = {
420
+ 'E': math.e,
421
+ 'PI': math.pi,
422
+ 'pi': math.pi,
423
+ 'g':9.81
424
+ }
425
+
426
+ self.values = {
427
+ 'sin': math.sin,
428
+ 'cos': math.cos,
429
+ 'tan': math.tan,
430
+ 'asin': math.asin,
431
+ 'acos': math.acos,
432
+ 'atan': math.atan,
433
+ 'sqrt': math.sqrt,
434
+ 'log': math.log,
435
+ 'abs': abs,
436
+ 'ceil': math.ceil,
437
+ 'floor': math.floor,
438
+ 'round': round,
439
+ 'random': self.random,
440
+ 'fac': self.fac,
441
+ 'exp': math.exp,
442
+ 'min': min,
443
+ 'max': max,
444
+ 'pyt': self.pyt,
445
+ 'pow': math.pow,
446
+ 'atan2': math.atan2,
447
+ 'E': math.e,
448
+ 'PI': math.pi,
449
+ 'g': 9.81,
450
+ 'pi':math.pi
451
+ }
452
+
453
+ def parse(self, expr) -> Expression:
454
+ self.errormsg = ''
455
+ self.success = True
456
+ operstack = []
457
+ tokenstack = []
458
+ self.tmpprio = 0
459
+ expected = self.PRIMARY | self.LPAREN | self.FUNCTION | self.SIGN
460
+ noperators = 0
461
+ self.expression = expr
462
+ self.pos = 0
463
+
464
+ while self.pos < len(self.expression):
465
+ if self.isOperator():
466
+ if self.isSign() and expected & self.SIGN:
467
+ if self.isNegativeSign():
468
+ self.tokenprio = 5
469
+ self.tokenindex = '-'
470
+ noperators += 1
471
+ self.addfunc(tokenstack, operstack, TOP1)
472
+ expected = \
473
+ self.PRIMARY | self.LPAREN | self.FUNCTION | self.SIGN
474
+ elif self.isLogicalNot() and expected & self.SIGN:
475
+ self.tokenprio = 2
476
+ self.tokenindex = 'not'
477
+ noperators += 1
478
+ self.addfunc(tokenstack, operstack, TOP1)
479
+ expected = \
480
+ self.PRIMARY | self.LPAREN | self.FUNCTION | self.SIGN
481
+ elif self.isComment():
482
+ pass
483
+ else:
484
+ if expected and self.OPERATOR == 0:
485
+ self.error_parsing(self.pos, 'unexpected operator')
486
+ noperators += 2
487
+ self.addfunc(tokenstack, operstack, TOP2)
488
+ expected = \
489
+ self.PRIMARY | self.LPAREN | self.FUNCTION | self.SIGN
490
+ elif self.isNumber():
491
+ if expected and self.PRIMARY == 0:
492
+ self.error_parsing(self.pos, 'unexpected number')
493
+ token = Token(TNUMBER, 0, 0, self.tokennumber)
494
+ tokenstack.append(token)
495
+ expected = self.OPERATOR | self.RPAREN | self.COMMA
496
+ elif self.isString():
497
+ if (expected & self.PRIMARY) == 0:
498
+ self.error_parsing(self.pos, 'unexpected string')
499
+ token = Token(TNUMBER, 0, 0, self.tokennumber)
500
+ tokenstack.append(token)
501
+ expected = self.OPERATOR | self.RPAREN | self.COMMA
502
+ elif self.isLeftParenth():
503
+ if (expected & self.LPAREN) == 0:
504
+ self.error_parsing(self.pos, 'unexpected \"(\"')
505
+ if expected & self.CALL:
506
+ noperators += 2
507
+ self.tokenprio = -2
508
+ self.tokenindex = -1
509
+ self.addfunc(tokenstack, operstack, TFUNCALL)
510
+ expected = \
511
+ self.PRIMARY | self.LPAREN | self.FUNCTION | \
512
+ self.SIGN | self.NULLARY_CALL
513
+ elif self.isRightParenth():
514
+ if expected & self.NULLARY_CALL:
515
+ token = Token(TNUMBER, 0, 0, [])
516
+ tokenstack.append(token)
517
+ elif (expected & self.RPAREN) == 0:
518
+ self.error_parsing(self.pos, 'unexpected \")\"')
519
+ expected = \
520
+ self.OPERATOR | self.RPAREN | self.COMMA | \
521
+ self.LPAREN | self.CALL
522
+ elif self.isComma():
523
+ if (expected & self.COMMA) == 0:
524
+ self.error_parsing(self.pos, 'unexpected \",\"')
525
+ self.addfunc(tokenstack, operstack, TOP2)
526
+ noperators += 2
527
+ expected = \
528
+ self.PRIMARY | self.LPAREN | self.FUNCTION | self.SIGN
529
+ elif self.isConst():
530
+ if (expected & self.PRIMARY) == 0:
531
+ self.error_parsing(self.pos, 'unexpected constant')
532
+ consttoken = Token(TNUMBER, 0, 0, self.tokennumber)
533
+ tokenstack.append(consttoken)
534
+ expected = self.OPERATOR | self.RPAREN | self.COMMA
535
+ elif self.isOp2():
536
+ if (expected & self.FUNCTION) == 0:
537
+ self.error_parsing(self.pos, 'unexpected function')
538
+ self.addfunc(tokenstack, operstack, TOP2)
539
+ noperators += 2
540
+ expected = self.LPAREN
541
+ elif self.isOp1():
542
+ if (expected & self.FUNCTION) == 0:
543
+ self.error_parsing(self.pos, 'unexpected function')
544
+ self.addfunc(tokenstack, operstack, TOP1)
545
+ noperators += 1
546
+ expected = self.LPAREN
547
+ elif self.isVar():
548
+ if (expected & self.PRIMARY) == 0:
549
+ self.error_parsing(self.pos, 'unexpected variable')
550
+ vartoken = Token(TVAR, self.tokenindex, 0, 0)
551
+ tokenstack.append(vartoken)
552
+ expected = \
553
+ self.OPERATOR | self.RPAREN | \
554
+ self.COMMA | self.LPAREN | self.CALL
555
+ elif self.isWhite():
556
+ pass
557
+ else:
558
+ if self.errormsg == '':
559
+ self.error_parsing(self.pos, 'unknown character')
560
+ else:
561
+ self.error_parsing(self.pos, self.errormsg)
562
+ if self.tmpprio < 0 or self.tmpprio >= 10:
563
+ self.error_parsing(self.pos, 'unmatched \"()\"')
564
+ while len(operstack) > 0:
565
+ tmp = operstack.pop()
566
+ tokenstack.append(tmp)
567
+ if (noperators + 1) != len(tokenstack):
568
+ self.error_parsing(self.pos, 'parity')
569
+
570
+ return Expression(tokenstack, self.ops1, self.ops2, self.functions)
571
+
572
+ def evaluate(self, expr, variables):
573
+ return self.parse(expr).evaluate(variables)
574
+
575
+ def error_parsing(self, column, msg):
576
+ self.success = False
577
+ self.errormsg = 'parse error [column ' + str(column) + ']: ' + msg + ', expression: ' + self.expression
578
+ raise Exception(self.errormsg)
579
+
580
+ def addfunc(self, tokenstack, operstack, type_):
581
+ operator = Token(
582
+ type_,
583
+ self.tokenindex,
584
+ self.tokenprio + self.tmpprio,
585
+ 0,
586
+ )
587
+ while len(operstack) > 0:
588
+ if operator.prio_ <= operstack[len(operstack) - 1].prio_:
589
+ tokenstack.append(operstack.pop())
590
+ else:
591
+ break
592
+ operstack.append(operator)
593
+
594
+ def isNumber(self):
595
+ r = False
596
+
597
+ if self.expression[self.pos] == 'E':
598
+ return False
599
+
600
+ # number in scientific notation
601
+ pattern = r'([-+]?([0-9]*\.?[0-9]*)[eE][-+]?[0-9]+).*'
602
+ match = re.match(pattern, self.expression[self.pos: ])
603
+ if match:
604
+ self.pos += len(match.group(1))
605
+ self.tokennumber = float(match.group(1))
606
+ return True
607
+
608
+ hex_pattern = r'(0x[0-9a-fA-F]+)'
609
+ match = re.match(hex_pattern, self.expression[self.pos: ])
610
+ if match:
611
+ self.pos += len(match.group(1))
612
+ self.tokennumber = int(match.group(1), base=16)
613
+ return True
614
+
615
+ # number in decimal
616
+ str = ''
617
+ while self.pos < len(self.expression):
618
+ code = self.expression[self.pos]
619
+ if (code >= '0' and code <= '9') or code == '.':
620
+ if (len(str) == 0 and code == '.' ):
621
+ str = '0'
622
+ str += code
623
+ self.pos += 1
624
+ try:
625
+ self.tokennumber = int(str)
626
+ except ValueError:
627
+ self.tokennumber = float(str)
628
+ r = True
629
+ else:
630
+ break
631
+ return r
632
+
633
+ def unescape(self, v, pos):
634
+ buffer = []
635
+ escaping = False
636
+
637
+ for i in range(0, len(v)):
638
+ c = v[i]
639
+
640
+ if escaping:
641
+ if c == "'":
642
+ buffer.append("'")
643
+ break
644
+ elif c == '\\':
645
+ buffer.append('\\')
646
+ break
647
+ elif c == '/':
648
+ buffer.append('/')
649
+ break
650
+ elif c == 'b':
651
+ buffer.append('\b')
652
+ break
653
+ elif c == 'f':
654
+ buffer.append('\f')
655
+ break
656
+ elif c == 'n':
657
+ buffer.append('\n')
658
+ break
659
+ elif c == 'r':
660
+ buffer.append('\r')
661
+ break
662
+ elif c == 't':
663
+ buffer.append('\t')
664
+ break
665
+ elif c == 'u':
666
+ # interpret the following 4 characters
667
+ # as the hex of the unicode code point
668
+ codePoint = int(v[i + 1, i + 5], 16)
669
+ buffer.append(chr(codePoint))
670
+ i += 4
671
+ break
672
+ else:
673
+ raise self.error_parsing(
674
+ pos + i,
675
+ 'Illegal escape sequence: \'\\' + c + '\'',
676
+ )
677
+ escaping = False
678
+ else:
679
+ if c == '\\':
680
+ escaping = True
681
+ else:
682
+ buffer.append(c)
683
+
684
+ return ''.join(buffer)
685
+
686
+ def isString(self):
687
+ r = False
688
+ str = ''
689
+ startpos = self.pos
690
+ if self.pos < len(self.expression) and self.expression[self.pos] in self.string_literal_quotes:
691
+ quote_type = self.expression[self.pos]
692
+ self.pos += 1
693
+ while self.pos < len(self.expression):
694
+ code = self.expression[self.pos]
695
+ if code != quote_type or (str != '' and str[-1] == '\\'):
696
+ str += self.expression[self.pos]
697
+ self.pos += 1
698
+ else:
699
+ self.pos += 1
700
+ self.tokennumber = self.unescape(str, startpos)
701
+ r = True
702
+ break
703
+ return r
704
+
705
+ def isConst(self):
706
+ for i in self.consts:
707
+ L = len(i)
708
+ str = self.expression[self.pos:self.pos+L]
709
+ if i == str:
710
+ if len(self.expression) <= self.pos + L:
711
+ self.tokennumber = self.consts[i]
712
+ self.pos += L
713
+ return True
714
+ if not self.expression[self.pos + L].isalnum() and self.expression[self.pos + L] != "_":
715
+ self.tokennumber = self.consts[i]
716
+ self.pos += L
717
+ return True
718
+ return False
719
+
720
+ def isOperator(self):
721
+ ops = (
722
+ ('**', 8, '**'),
723
+ ('^', 8, '^'),
724
+ ('%', 6, '%'),
725
+ ('/', 6, '/'),
726
+ (u'\u2219', 5, '*'), # bullet operator
727
+ (u'\u2022', 5, '*'), # black small circle
728
+ ('*', 5, '*'),
729
+ ('+', 4, '+'),
730
+ ('-', 4, '-'),
731
+ ('||', 3, '||'),
732
+ ('==', 3, '=='),
733
+ ('!=', 3, '!='),
734
+ ('<=', 3, '<='),
735
+ ('>=', 3, '>='),
736
+ ('<', 3, '<'),
737
+ ('>', 3, '>'),
738
+ ('in ', 3, 'in'),
739
+ ('not ', 2, 'not'),
740
+ ('and ', 1, 'and'),
741
+ ('xor ', 0, 'xor'),
742
+ ('or ', 0, 'or'),
743
+ )
744
+ for token, priority, index in ops:
745
+ if self.expression.startswith(token, self.pos):
746
+ self.tokenprio = priority
747
+ self.tokenindex = index
748
+ self.pos += len(token)
749
+ return True
750
+ return False
751
+
752
+ def isSign(self):
753
+ code = self.expression[self.pos - 1]
754
+ return (code == '+') or (code == '-')
755
+
756
+ def isPositiveSign(self):
757
+ code = self.expression[self.pos - 1]
758
+ return code == '+'
759
+
760
+ def isNegativeSign(self):
761
+ code = self.expression[self.pos - 1]
762
+ return code == '-'
763
+
764
+ def isLogicalNot(self):
765
+ code = self.expression[self.pos - 4: self.pos]
766
+ return code == 'not '
767
+
768
+ def isLeftParenth(self):
769
+ code = self.expression[self.pos]
770
+ if code == '(':
771
+ self.pos += 1
772
+ self.tmpprio += 10
773
+ return True
774
+ return False
775
+
776
+ def isRightParenth(self):
777
+ code = self.expression[self.pos]
778
+ if code == ')':
779
+ self.pos += 1
780
+ self.tmpprio -= 10
781
+ return True
782
+ return False
783
+
784
+ def isComma(self):
785
+ code = self.expression[self.pos]
786
+ if code==',':
787
+ self.pos+=1
788
+ self.tokenprio=-1
789
+ self.tokenindex=","
790
+ return True
791
+ return False
792
+
793
+ def isWhite(self):
794
+ code = self.expression[self.pos]
795
+ if code.isspace():
796
+ self.pos += 1
797
+ return True
798
+ return False
799
+
800
+ def isOp1(self):
801
+ str = ''
802
+ for i in range(self.pos, len(self.expression)):
803
+ c = self.expression[i]
804
+ if c.upper() == c.lower():
805
+ if i == self.pos or (c != '_' and (c < '0' or c > '9')):
806
+ break
807
+ str += c
808
+ if len(str) > 0 and str in self.ops1:
809
+ self.tokenindex = str
810
+ self.tokenprio = 9
811
+ self.pos += len(str)
812
+ return True
813
+ return False
814
+
815
+ def isOp2(self):
816
+ str = ''
817
+ for i in range(self.pos, len(self.expression)):
818
+ c = self.expression[i]
819
+ if c.upper() == c.lower():
820
+ if i == self.pos or (c != '_' and (c < '0' or c > '9')):
821
+ break
822
+ str += c
823
+ if len(str) > 0 and (str in self.ops2):
824
+ self.tokenindex = str
825
+ self.tokenprio = 9
826
+ self.pos += len(str)
827
+ return True
828
+ return False
829
+
830
+ def isVar(self):
831
+ str = ''
832
+ inQuotes = False
833
+ for i in range(self.pos, len(self.expression)):
834
+ c = self.expression[i]
835
+ if c.lower() == c.upper():
836
+ if ((i == self.pos and c != '"') or (not (c in '_."') and (c < '0' or c > '9'))) and not inQuotes :
837
+ break
838
+ if c == '"':
839
+ inQuotes = not inQuotes
840
+ str += c
841
+ if str:
842
+ self.tokenindex = str
843
+ self.tokenprio = 6
844
+ self.pos += len(str)
845
+ return True
846
+ return False
847
+
848
+ def isComment(self):
849
+ code = self.expression[self.pos - 1]
850
+ if code == '/' and self.expression[self.pos] == '*':
851
+ self.pos = self.expression.index('*/', self.pos) + 2
852
+ if self.pos == 1:
853
+ self.pos = len(self.expression)
854
+ return True
855
+ return False