90 lines
1.9 KiB
Python
90 lines
1.9 KiB
Python
#!/usr/bin/env python
|
|
'''
|
|
WARNING USE OF `eval()`
|
|
'''
|
|
|
|
from dataclasses import dataclass, KW_ONLY
|
|
from typing import ClassVar, Iterable
|
|
from ._typing_ import *
|
|
from ._regex_ import regSpaceOnly
|
|
|
|
_varMap = {
|
|
'(': '(',
|
|
')': ')',
|
|
'or': 'or',
|
|
'and': 'and',
|
|
'not': 'not',
|
|
'!': 'not',
|
|
'~': 'not',
|
|
'&': 'and',
|
|
'&&': 'and',
|
|
'|': 'or',
|
|
'||': 'or',
|
|
N: N,
|
|
'none': N,
|
|
'null': N,
|
|
'n': N,
|
|
't': T,
|
|
'true': T,
|
|
'f': F,
|
|
'false': F,
|
|
}
|
|
|
|
MicroLangStatement = NewType('MicroLang', Iterable)
|
|
|
|
@dataclass(slots=T, kw_only=T, frozen=T)
|
|
class MicroLang():
|
|
# TODO string parse
|
|
stmnts: MicroLangStatement = field(kw_only=F, repr=T)
|
|
env: dict = field(default_factory=dict, repr=T)
|
|
|
|
@staticmethod
|
|
def strToToken(ss):
|
|
return re.split(r'([a-zA-Z0-9\_]+|.)', ss)
|
|
|
|
@staticmethod
|
|
def isToken(t) -> bool:
|
|
return t.lower() in _varMap
|
|
|
|
def _eval(_, *args, **kargs):
|
|
|
|
if isinstance(_.stmnts, str):
|
|
stmnts = MicroLang.strToToken(_.stmnts)
|
|
else:
|
|
stmnts = [x for x in _.stmnts]
|
|
|
|
for i, state in enumerate(stmnts):
|
|
if state in _.env:
|
|
state = _.env[state]
|
|
|
|
if callable(state):
|
|
state = state(*args, **kargs)
|
|
|
|
if isinstance(state, str):
|
|
state = state.strip()
|
|
stateLow = state.lower()
|
|
if (s := _varMap.get(stateLow, U)) is not U:
|
|
state = s
|
|
|
|
stmnts[i] = state
|
|
|
|
stmnts = [x for x in stmnts if not regSpaceOnly.any(x)]
|
|
|
|
return stmnts
|
|
|
|
def eval(_, *args, **kargs):
|
|
reduced = _._eval(*args, **kargs)
|
|
if not reduced:
|
|
return
|
|
toEval = ' '.join([str(x) for x in reduced])
|
|
try:
|
|
return bool(eval(toEval))
|
|
except SyntaxError as e:
|
|
e.add_note(str(reduced))
|
|
raise e
|
|
|
|
e = eval
|
|
|
|
def __bool__(_):
|
|
return _.eval()
|