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 re
|
||||||
import js2py
|
|
||||||
import base64
|
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)
|
def to_ecma5_function(f:str) -> str:
|
||||||
if not arrow:
|
pass
|
||||||
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 atob(s):
|
def atob(s):
|
||||||
return base64.standard_b64decode(str(s)).decode('utf-8')
|
return base64.standard_b64decode(str(s)).decode('utf-8')
|
||||||
|
|
||||||
def arrow_conv(f):
|
def exec(f:str) -> Any:
|
||||||
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):
|
|
||||||
ctx = js2py.EvalJs({'atob': atob})
|
ctx = js2py.EvalJs({'atob': atob})
|
||||||
ctx.execute(to_ecma5_function(f))
|
ctx.execute(to_ecma5_function(f))
|
||||||
return ctx
|
return ctx
|
||||||
|
|
|
@ -59,5 +59,6 @@ for f in tests:
|
||||||
# 2iXh5W5uEYq5fWJIazQ6
|
# 2iXh5W5uEYq5fWJIazQ6
|
||||||
# CuUcmZ27Fb8bVBNw12Vj
|
# CuUcmZ27Fb8bVBNw12Vj
|
||||||
# YPPe8Ph7vzYaZ9PF9oQP
|
# YPPe8Ph7vzYaZ9PF9oQP
|
||||||
|
# ...
|
||||||
# (Note: The last four
|
# (Note: The last four
|
||||||
# tokens are different)
|
# tokens are different)
|
||||||
|
|
Reference in a new issue