"""This module translates JS flow into PY flow. Translates: IF ELSE DO WHILE WHILE FOR 123 FOR iter CONTINUE, BREAK, RETURN, LABEL, THROW, TRY, SWITCH """ from utils import * from jsparser import * from nodevisitor import exp_translator import random TO_REGISTER = [] CONTINUE_LABEL = 'JS_CONTINUE_LABEL_%s' BREAK_LABEL = 'JS_BREAK_LABEL_%s' PREPARE = '''HOLDER = var.own.get(NAME)\nvar.force_own_put(NAME, PyExceptionToJs(PyJsTempException))\n''' RESTORE = '''if HOLDER is not None:\n var.own[NAME] = HOLDER\nelse:\n del var.own[NAME]\ndel HOLDER\n''' TRY_CATCH = '''%stry:\nBLOCKfinally:\n%s''' % (PREPARE, indent(RESTORE)) def get_continue_label(label): return CONTINUE_LABEL%label.encode('hex') def get_break_label(label): return BREAK_LABEL%label.encode('hex') def pass_until(source, start, tokens=(';',)): while start < len(source) and source[start] not in tokens: start+=1 return start+1 def do_bracket_exp(source, start, throw=True): bra, cand = pass_bracket(source, start, '()') if throw and not bra: raise SyntaxError('Missing bracket expression') bra = exp_translator(bra[1:-1]) if throw and not bra: raise SyntaxError('Empty bracket condition') return bra, cand if bra else start def do_if(source, start): start += 2 # pass this if bra, start = do_bracket_exp(source, start, throw=True) statement, start = do_statement(source, start) if statement is None: raise SyntaxError('Invalid if statement') translated = 'if %s:\n'%bra+indent(statement) elseif = except_keyword(source, start, 'else') is_elseif = False if elseif: start = elseif if except_keyword(source, start, 'if'): is_elseif = True elseif, start = do_statement(source, start) if elseif is None: raise SyntaxError('Invalid if statement)') if is_elseif: translated += 'el' + elseif else: translated += 'else:\n'+ indent(elseif) return translated, start def do_statement(source, start): """returns none if not found other functions that begin with 'do_' raise also this do_ type function passes white space""" start = pass_white(source, start) # start is the fist position after initial start that is not a white space or \n if not start < len(source): #if finished parsing return None return None, start if any(startswith_keyword(source[start:], e) for e in {'case', 'default'}): return None, start rest = source[start:] for key, meth in KEYWORD_METHODS.iteritems(): # check for statements that are uniquely defined by their keywords if rest.startswith(key): # has to startwith this keyword and the next letter after keyword must be either EOF or not in IDENTIFIER_PART if len(key)==len(rest) or rest[len(key)] not in IDENTIFIER_PART: return meth(source, start) if rest[0] == '{': #Block return do_block(source, start) # Now only label and expression left cand = parse_identifier(source, start, False) if cand is not None: # it can mean that its a label label, cand_start = cand cand_start = pass_white(source, cand_start) if source[cand_start]==':': return do_label(source, start) return do_expression(source, start) def do_while(source, start): start += 5 # pass while bra, start = do_bracket_exp(source, start, throw=True) statement, start = do_statement(source, start) if statement is None: raise SyntaxError('Missing statement to execute in while loop!') return 'while %s:\n'%bra + indent(statement), start def do_dowhile(source, start): start += 2 # pass do statement, start = do_statement(source, start) if statement is None: raise SyntaxError('Missing statement to execute in do while loop!') start = except_keyword(source, start, 'while') if not start: raise SyntaxError('Missing while keyword in do-while loop') bra, start = do_bracket_exp(source, start, throw=True) statement += 'if not %s:\n' % bra + indent('break\n') return 'while 1:\n' + indent(statement), start def do_block(source, start): bra, start = pass_bracket(source, start, '{}') #print source[start:], bra #return bra +'\n', start if bra is None: raise SyntaxError('Missing block ( {code} )') code = '' bra = bra[1:-1]+';' bra_pos = 0 while bra_pos=len(rev): raise if filter(lambda x: x not in SPACE, rev[lpos:rpos]): break end = start + len(rev) - rpos + 1 def do_var(source, start): #todo auto ; insertion start += 3 #pass var end = pass_until(source, start, tokens=(';',)) defs = argsplit(source[start:end-1]) # defs is the list of defined vars with optional initializer code = '' for de in defs: var, var_end = parse_identifier(de, 0, True) TO_REGISTER.append(var) var_end = pass_white(de, var_end) if var_end