""" The process of translating JS will go like that: # TOP = 'imports and scope set' 1. Remove all the comments 2. Replace number, string and regexp literals with markers 4. Remove global Functions and move their translation to the TOP. Also add register code there. 5. Replace inline functions with lvals 6. Remove List and Object literals and replace them with lvals 7. Find and remove var declarations, generate python register code that would go on TOP. Here we should be left with global code only where 1 line of js code = 1 line of python code. Routine translating this code should be called glob_translate: 1. Search for outer structures and translate them using glob and inside using exps_translate exps_translate routine: 1. Remove outer {} 2. Split lines at ; 3. Convert line by line using exp_translate 4. In case of error in 3 try to insert ; according to ECMA rules and repeat 3. exp_translate routine: It takes a single line of JS code and returns a SINGLE line of Python code. Note var is not present here because it was removed in previous stages. If case of parsing errors it must return a pos of error. 1. Convert all assignment operations to put operations, this may be hard :( 2. Convert all gets and calls to get and callprop. 3. Convert unary operators like typeof, new, !, delete. Delete can be handled by replacing last get method with delete. 4. Convert remaining operators that are not handled by python eg: === and , lval format PyJsLvalNR marker PyJs(TYPE_NAME)(NR) TODO 1. Number literal replacement 2. Array literal replacement 3. Object literal replacement 5. Function replacement 4. Literal replacement translators """ from utils import * OP_METHODS = {'*': '__mul__', '/': '__div__', '%': '__mod__', '+': '__add__', '-': '__sub__', '<<': '__lshift__', '>>': '__rshift__', '&': '__and__', '^': '__xor__', '|': '__or__'} def dbg(source): try: with open('C:\Users\Piotrek\Desktop\dbg.py','w') as f: f.write(source) except: pass def indent(lines, ind=4): return ind*' '+lines.replace('\n', '\n'+ind*' ').rstrip(' ') def inject_before_lval(source, lval, code): if source.count(lval)>1: dbg(source) print print lval raise RuntimeError('To many lvals (%s)' % lval) elif not source.count(lval): dbg(source) print print lval assert lval not in source raise RuntimeError('No lval found "%s"' % lval) end = source.index(lval) inj = source.rfind('\n', 0, end) ind = inj while source[ind+1]==' ': ind+=1 ind -= inj return source[:inj+1]+ indent(code, ind) + source[inj+1:] def bracket_split(source, brackets=('()','{}','[]'), strip=False): """DOES NOT RETURN EMPTY STRINGS (can only return empty bracket content if strip=True)""" starts = [e[0] for e in brackets] in_bracket = 0 n = 0 last = 0 while n len(source): return None if source[start:start+kl] != keyword: return None if kl+starttext_len: continue if validitate and not validitate(e, text[:n], text[n+s:]): continue if any(text[n+s:].startswith(e) for e in not_after): #Cant end with end before n+=1 break if e==text[n:n+s]: yield text[last:n] if not translate else translate(text[last:n]) yield e n+=s last = n break else: n+=1 yield text[last:n] if not translate else translate(text[last:n]) def split_at_single(text, sep, not_before=[], not_after=[]): """Works like text.split(sep) but separated fragments cant end with not_before or start with not_after""" n = 0 lt, s= len(text), len(sep) last = 0 while nlt: if sep==text[n:n+s]: if any(text[last:n].endswith(e) for e in not_before): pass elif any(text[n+s:].startswith(e) for e in not_after): pass else: yield text[last:n] last = n+s n += s-1 n+=1 yield text[last:]