Beispiel #1
0
def do_switch(source, start):
    start += 6  # pass switch
    code = 'while 1:\n' + indent('SWITCHED = False\nCONDITION = (%s)\n')
    # parse value of check
    val, start = pass_bracket(source, start, '()')
    if val is None:
        raise SyntaxError('Missing () after switch statement')
    if not val.strip():
        raise SyntaxError('Missing content inside () after switch statement')
    code = code % exp_translator(val)
    bra, start = pass_bracket(source, start, '{}')
    if bra is None:
        raise SyntaxError('Missing block {} after switch statement')
    bra_pos = 0
    bra = bra[1:-1] + ';'
    while True:
        case = except_keyword(bra, bra_pos, 'case')
        default = except_keyword(bra, bra_pos, 'default')
        assert not (case and default)
        if case or default:  # this ?: expression makes things much harder....
            case_code = None
            if case:
                case_code = 'if SWITCHED or PyJsStrictEq(CONDITION, %s):\n'
                # we are looking for a first : with count 1. ? gives -1 and : gives +1.
                count = 0
                for pos, e in enumerate(bra[case:], case):
                    if e == '?':
                        count -= 1
                    elif e == ':':
                        count += 1
                        if count == 1:
                            break
                else:
                    raise SyntaxError(
                        'Missing : token after case in switch statement')
                case_condition = exp_translator(
                    bra[case:pos])  # switch {case CONDITION: statements}
                case_code = case_code % case_condition
                case = pos + 1
            if default:
                case = except_token(bra, default, ':')
                case_code = 'if True:\n'
            # now parse case statements (things after ':' )
            cand, case = do_statement(bra, case)
            while cand:
                case_code += indent(cand)
                cand, case = do_statement(bra, case)
            case_code += indent('SWITCHED = True\n')
            code += indent(case_code)
            bra_pos = case
        else:
            break
    # prevent infinite loop :)
    code += indent('break\n')
    return code, start
Beispiel #2
0
def do_return(source, start):
    start += 6 # pass return
    end = source.find(';', start)+1
    if end==-1:
        end = len(source)
    trans = exp_translator(source[start:end].rstrip(';'))
    return 'return %s\n' % (trans if trans else "var.get('undefined')"), end
Beispiel #3
0
def do_expression(source, start):
    start = pass_white(source, start)
    end = pass_until(source, start, tokens=(';',))
    if end==start+1: #empty statement
        return 'pass\n', end
    # AUTOMATIC SEMICOLON INSERTION FOLLOWS
    # Without ASI this function would end with: return exp_translator(source[start:end].rstrip(';'))+'\n', end
    # ASI makes things a bit more complicated:
    # we will try to parse as much as possible, inserting ; in place of last new line in case of error
    rev = False
    rpos = 0
    while True:
        try:
            code = source[start:end].rstrip(';')
            cand = exp_translator(code)+'\n', end
            just_to_test = compile(cand[0], '', 'exec')
            return cand
        except Exception as e:
            if not rev:
                rev = source[start:end][::-1]
        lpos = rpos
        while True:
            rpos = pass_until(rev, rpos, LINE_TERMINATOR)
            if rpos>=len(rev):
                raise
            if filter(lambda x: x not in SPACE, rev[lpos:rpos]):
               break
        end = start + len(rev) - rpos + 1
Beispiel #4
0
def do_return(source, start):
    start += 6  # pass return
    end = source.find(';', start) + 1
    if end == -1:
        end = len(source)
    trans = exp_translator(source[start:end].rstrip(';'))
    return 'return %s\n' % (trans if trans else "var.get('undefined')"), end
Beispiel #5
0
def do_expression(source, start):
    start = pass_white(source, start)
    end = pass_until(source, start, tokens=(';', ))
    if end == start + 1:  #empty statement
        return 'pass\n', end
    # AUTOMATIC SEMICOLON INSERTION FOLLOWS
    # Without ASI this function would end with: return exp_translator(source[start:end].rstrip(';'))+'\n', end
    # ASI makes things a bit more complicated:
    # we will try to parse as much as possible, inserting ; in place of last new line in case of error
    rev = False
    rpos = 0
    while True:
        try:
            code = source[start:end].rstrip(';')
            cand = exp_translator(code) + '\n', end
            just_to_test = compile(cand[0], '', 'exec')
            return cand
        except Exception as e:
            if not rev:
                rev = source[start:end][::-1]
        lpos = rpos
        while True:
            rpos = pass_until(rev, rpos, LINE_TERMINATOR)
            if rpos >= len(rev):
                raise
            if filter(lambda x: x not in SPACE, rev[lpos:rpos]):
                break
        end = start + len(rev) - rpos + 1
Beispiel #6
0
def do_switch(source, start):
    start += 6 # pass switch
    code = 'while 1:\n' + indent('SWITCHED = False\nCONDITION = (%s)\n')
    # parse value of check
    val, start = pass_bracket(source, start, '()')
    if val is None:
        raise SyntaxError('Missing () after switch statement')
    if not val.strip():
        raise SyntaxError('Missing content inside () after switch statement')
    code = code % exp_translator(val)
    bra, start = pass_bracket(source, start, '{}')
    if bra is None:
        raise SyntaxError('Missing block {} after switch statement')
    bra_pos = 0
    bra = bra[1:-1] + ';'
    while True:
        case = except_keyword(bra, bra_pos, 'case')
        default = except_keyword(bra, bra_pos, 'default')
        assert not (case and default)
        if case or default:  # this ?: expression makes things much harder....
            case_code = None
            if case:
                case_code = 'if SWITCHED or PyJsStrictEq(CONDITION, %s):\n'
                # we are looking for a first : with count 1. ? gives -1 and : gives +1.
                count = 0
                for pos, e in enumerate(bra[case:], case):
                    if e=='?':
                        count -= 1
                    elif e==':':
                        count += 1
                        if count==1:
                            break
                else:
                    raise SyntaxError('Missing : token after case in switch statement')
                case_condition = exp_translator(bra[case:pos])  # switch {case CONDITION: statements}
Beispiel #7
0
def translate_object(obj, lval, obj_count=1, arr_count=1):
    obj = obj[1:-1]  # remove {} from both ends
    obj, obj_rep, obj_count = remove_objects(obj, obj_count)
    obj, arr_rep, arr_count = remove_arrays(obj, arr_count)
    # functions can be defined inside objects. exp translator cant translate them.
    # we have to remove them and translate with func translator
    # its better explained in translate_array function
    obj, hoisted, inline = functions.remove_functions(obj, all_inline=True)
    assert not hoisted
    gsetters_after = ''
    keys = argsplit(obj)
    res = []
    for i, e in enumerate(keys, 1):
        e = e.strip()
        if e.startswith('set '):
            gsetters_after += translate_setter(lval, e)
        elif e.startswith('get '):
            gsetters_after += translate_getter(lval, e)
        elif ':' not in e:
            if i < len(keys
                       ):  # can happen legally only in the last element {3:2,}
                raise SyntaxError('Unexpected "," in Object literal')
            break
        else:  #Not getter, setter or elision
            spl = argsplit(e, ':')
            if len(spl) < 2:
                raise SyntaxError('Invalid Object literal: ' + e)
            try:
                key, value = spl
            except:  #len(spl)> 2
                print 'Unusual case ' + repr(e)
                key = spl[0]
                value = ':'.join(spl[1:])
            key = key.strip()
            if is_internal(key):
                key = '%s.to_string().value' % key
            else:
                key = repr(key)

            value = exp_translator(value)
            if not value:
                raise SyntaxError('Missing value in Object literal')
            res.append('%s:%s' % (key, value))
    res = '%s = Js({%s})\n' % (lval, ','.join(res)) + gsetters_after
    # translate all the nested objects (including removed earlier functions)
    for nested_name, nested_info in inline.iteritems():  # functions
        nested_block, nested_args = nested_info
        new_def = FUNC_TRANSLATOR(nested_name, nested_block, nested_args)
        res = new_def + res
    for lval, obj in obj_rep.iteritems():  #objects
        new_def, obj_count, arr_count = translate_object(
            obj, lval, obj_count, arr_count)
        # add object definition BEFORE array definition
        res = new_def + res
    for lval, obj in arr_rep.iteritems():  # arrays
        new_def, obj_count, arr_count = translate_array(
            obj, lval, obj_count, arr_count)
        # add object definition BEFORE array definition
        res = new_def + res
    return res, obj_count, arr_count
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
def do_throw(source, start):
    start += 5 # pass throw
    end = source.find(';', start)+1
    if not end:
        end = len(source)
    trans = exp_translator(source[start:end].rstrip(';'))
    if not trans:
        raise SyntaxError('Invalid throw statement: nothing to throw')
    res = 'PyJsTempException = JsToPyException(%s)\nraise PyJsTempException\n' % trans
    return res, end
Beispiel #11
0
def do_throw(source, start):
    start += 5  # pass throw
    end = source.find(';', start) + 1
    if not end:
        end = len(source)
    trans = exp_translator(source[start:end].rstrip(';'))
    if not trans:
        raise SyntaxError('Invalid throw statement: nothing to throw')
    res = 'PyJsTempException = JsToPyException(%s)\nraise PyJsTempException\n' % trans
    return res, end
Beispiel #12
0
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<len(de): # we have something more to parse... It has to start with =
            if de[var_end] != '=':
                raise SyntaxError('Unexpected initializer in var statement. Expected "=", got "%s"'%de[var_end])
            code += exp_translator(de) + '\n'
    if not code.strip():
        code = 'pass\n'
    return code, end
Beispiel #13
0
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<len(de): # we have something more to parse... It has to start with =
            if de[var_end] != '=':
                raise SyntaxError('Unexpected initializer in var statement. Expected "=", got "%s"'%de[var_end])
            code += exp_translator(de) + '\n'
    if not code.strip():
        code = 'pass\n'
    return code, end
Beispiel #14
0
def do_for(source, start):
    start += 3  # pass for
    entered = start
    bra, start = pass_bracket(source, start, '()')
    inside, start = do_statement(source, start)
    if inside is None:
        raise SyntaxError('Missing statement after for')
    bra = bra[1:-1]
    if ';' in bra:
        init = argsplit(bra, ';')
        if len(init) != 3:
            raise SyntaxError('Invalid for statement')
        args = []
        for i, item in enumerate(init):
            end = pass_white(item, 0)
            if end == len(item):
                args.append('' if i != 1 else '1')
                continue
            if not i and except_keyword(item, end, 'var') is not None:
                # var statement
                args.append(do_var(item, end)[0])
                continue
            args.append(do_expression(item, end)[0])
        return '#for JS loop\n%swhile %s:\n%s%s\n' % (
            args[0], args[1].strip(), indent(inside), indent(args[2])), start
    # iteration
    end = pass_white(bra, 0)
    register = False
    if bra[end:].startswith('var '):
        end += 3
        end = pass_white(bra, end)
        register = True
    name, end = parse_identifier(bra, end)
    if register:
        TO_REGISTER.append(name)
    end = pass_white(bra, end)
    if bra[end:end + 2] != 'in' or bra[end + 2] in IDENTIFIER_PART:
        #print source[entered-10:entered+50]
        raise SyntaxError('Invalid "for x in y" statement')
    end += 2  # pass in
    exp = exp_translator(bra[end:])
    res = 'for temp in %s:\n' % exp
    res += indent('var.put(%s, temp)\n' % name.__repr__()) + indent(inside)
    return res, start
Beispiel #15
0
def do_for(source, start):
    start += 3  # pass for
    entered = start
    bra, start = pass_bracket(source, start, '()')
    inside, start = do_statement(source, start)
    if inside is None:
        raise SyntaxError('Missing statement after for')
    bra = bra[1:-1]
    if ';' in bra:
        init = argsplit(bra, ';')
        if len(init) != 3:
            raise SyntaxError('Invalid for statement')
        args = []
        for i, item in enumerate(init):
            end = pass_white(item, 0)
            if end == len(item):
                args.append('' if i != 1 else '1')
                continue
            if not i and except_keyword(item, end, 'var') is not None:
                # var statement
                args.append(do_var(item, end)[0])
                continue
            args.append(do_expression(item, end)[0])
        return '#for JS loop\n%swhile %s:\n%s%s\n' % (
            args[0], args[1].strip(), indent(inside), indent(args[2])), start
    # iteration
    end = pass_white(bra, 0)
    register = False
    if bra[end:].startswith('var '):
        end += 3
        end = pass_white(bra, end)
        register = True
    name, end = parse_identifier(bra, end)
    if register:
        TO_REGISTER.append(name)
    end = pass_white(bra, end)
    if bra[end:end + 2] != 'in' or bra[end + 2] in IDENTIFIER_PART:
        #print source[entered-10:entered+50]
        raise SyntaxError('Invalid "for x in y" statement')
    end += 2  # pass in
    exp = exp_translator(bra[end:])
    res = 'for temp in %s:\n' % exp
    res += indent('var.put(%s, temp)\n' % name.__repr__()) + indent(inside)
    return res, start
Beispiel #16
0
def translate_array(array, lval, obj_count=1, arr_count=1):
    """array has to be any js array for example [1,2,3]
       lval has to be name of this array.
       Returns python code that adds lval to the PY scope it should be put before lval"""
    array = array[1:-1]
    array, obj_rep, obj_count = remove_objects(array, obj_count)
    array, arr_rep, arr_count = remove_arrays(array, arr_count)
    #functions can be also defined in arrays, this caused many problems since in Python
    # functions cant be defined inside literal
    # remove functions (they dont contain arrays or objects so can be translated easily)
    # hoisted functions are treated like inline
    array, hoisted, inline = functions.remove_functions(array, all_inline=True)
    assert not hoisted
    arr = []
    # separate elements in array
    for e in argsplit(array, ','):
        # translate expressions in array PyJsLvalInline will not be translated!
        e = exp_translator(e.replace('\n', ''))
        arr.append(e if e else 'None')
    arr = '%s = Js([%s])\n' % (lval, ','.join(arr))
    #But we can have more code to add to define arrays/objects/functions defined inside this array
    # translate nested objects:
    # functions:
    for nested_name, nested_info in inline.iteritems():
        nested_block, nested_args = nested_info
        new_def = FUNC_TRANSLATOR(nested_name, nested_block, nested_args)
        arr = new_def + arr
    for lval, obj in obj_rep.iteritems():
        new_def, obj_count, arr_count = translate_object(
            obj, lval, obj_count, arr_count)
        # add object definition BEFORE array definition
        arr = new_def + arr
    for lval, obj in arr_rep.iteritems():
        new_def, obj_count, arr_count = translate_array(
            obj, lval, obj_count, arr_count)
        # add object definition BEFORE array definition
        arr = new_def + arr
    return arr, obj_count, arr_count