Ecma6 Parsing
This commit is contained in:
parent
c0f60cfe5c
commit
08743f69bd
2 changed files with 49 additions and 33 deletions
|
@ -1,45 +1,60 @@
|
|||
import re
|
||||
import js2py
|
||||
import base64
|
||||
import js2py
|
||||
from typing import Optional, Union, List, Any
|
||||
|
||||
brkregex = re.compile(r'\((?!\)|[\'\"])(.+?)(?<!\(|[\'\"])\)')
|
||||
# regexr.com/6el10
|
||||
arrowexp = re.compile(r'(\(?(\w+(?:,\s*\w+)*)\)?|\(\))\s*=>\s*(({\s*.+\s*})|(.+;|.+$))')
|
||||
|
||||
def parse_brackets(f, arrow):
|
||||
# Thanks to https://stackoverflow.com/a/1651562/17901968
|
||||
def brackets(s:str, search:Optional[str]=None) -> List[Union[int]]:
|
||||
result = []
|
||||
content = [s]
|
||||
repeated = False
|
||||
for expr in content:
|
||||
if expr.find('(') == -1: continue
|
||||
count = -1
|
||||
indexes = []
|
||||
cont = False
|
||||
for i, ch in enumerate(expr):
|
||||
if ch == '(':
|
||||
indexes.append(i)
|
||||
if count == -1:
|
||||
count = 1
|
||||
else:
|
||||
count += 1
|
||||
if ch == ')':
|
||||
if len(indexes) > 1:
|
||||
indexes.pop()
|
||||
else:
|
||||
indexes.append(i)
|
||||
if expr.find('(', i) != -1:
|
||||
cont = True
|
||||
count -= 1
|
||||
if count == 0: break
|
||||
if count != 0:
|
||||
raise ValueError('Unmatched parenthesis')
|
||||
else:
|
||||
inner = expr[indexes[0]+1:indexes[1]]
|
||||
if repeated:
|
||||
content.pop()
|
||||
repeated = False
|
||||
content.append(inner)
|
||||
if search == None \
|
||||
or search in inner:
|
||||
result.append(indexes)
|
||||
if cont:
|
||||
content.append(content[len(content)-2])
|
||||
repeated = True
|
||||
return result
|
||||
|
||||
match = brkregex.finditer(f)
|
||||
if not arrow:
|
||||
return match[0].group(1)
|
||||
|
||||
for r in match:
|
||||
func = r.group(1)
|
||||
if '=>' in func:
|
||||
return func
|
||||
|
||||
def to_ecma5_function(f):
|
||||
fnstart = f.find('{')+1
|
||||
fnend = f.rfind('}')
|
||||
f = arrow_conv(f[fnstart:fnend])
|
||||
return f
|
||||
def to_ecma5_function(f:str) -> str:
|
||||
pass
|
||||
|
||||
def atob(s):
|
||||
return base64.standard_b64decode(str(s)).decode('utf-8')
|
||||
|
||||
def arrow_conv(f):
|
||||
if '=>' in f:
|
||||
inner = parse_brackets(f)
|
||||
while brkregex.match(inner) != None:
|
||||
inner = parse_brackets(inner)
|
||||
|
||||
func = re.sub(
|
||||
r'(\w+)\s*=>\s*(.+)',
|
||||
r'function(\1){return \2}', inner
|
||||
)
|
||||
start = f.find(inner)
|
||||
end = start + len(inner)
|
||||
f = f[:start] + func + f[end:]
|
||||
return f
|
||||
|
||||
def exec(f):
|
||||
def exec(f:str) -> Any:
|
||||
ctx = js2py.EvalJs({'atob': atob})
|
||||
ctx.execute(to_ecma5_function(f))
|
||||
return ctx
|
||||
|
|
|
@ -59,5 +59,6 @@ for f in tests:
|
|||
# 2iXh5W5uEYq5fWJIazQ6
|
||||
# CuUcmZ27Fb8bVBNw12Vj
|
||||
# YPPe8Ph7vzYaZ9PF9oQP
|
||||
# ...
|
||||
# (Note: The last four
|
||||
# tokens are different)
|
||||
|
|
Reference in a new issue