--- esc.py- 2016-09-12 01:00:00.000000000 +0900 +++ esc.py 2016-09-13 00:00:00.000000000 +0900 @@ -67,12 +67,13 @@ def join_type(top, lst): i = next( ( i for (i, e) in enumerate(lst) if e[0] == 'type' ), None ) return lst if i is None else lst[:i] + join_type( lst[i], lst[i+1:] ) i = next( ( i for (i, e) in enumerate(lst) if e[0] == 'type' or e == [ 'op', '*' ] ), None ) + to_len2 = lambda e: [ e[0], e[1:] ] if i is None: - return [ top ] + lst + return [ to_len2(top) ] + lst if i > 0: - return [ top ] + lst[:i] + join_type( None, lst[i:] ) - top += lst[0][1] - return join_type( top, lst[1:] ) + return [ to_len2(top) ] + lst[:i] + join_type( None, lst[i:] ) + top += [ lst[0][1] ] + return join_type( to_len2(top), lst[1:] ) def tree_bra(lst, kdic, sta=None): d = dict( zip( kdic.get('br_s'), kdic.get('br_e') ) ) @@ -132,15 +133,13 @@ def ops_idx(ops, term, op): op = op[0] i = next( ( i for (i, (term_, bind, lst)) in enumerate(ops) if term_ == term and op in lst ), None ) if i is None: - print yaml.dump(tstk) - err_exit("not found term={} op='{}' in ops".format(term, op)) + err_not_found("term={} op='{}' in ops".format(term, op)) return i def tree_op1(lst, ops, k, v): r = tree_op( lst[1:], ops ) if len(r) == 0: - print yaml.dump(tstk) - err_exit("not found rignt term op='{}'".format(v)) + err_not_found("rignt term op='{}'".format(v)) (k2, v2) = r[0][:2] if k2 == 'op': i1 = ops_idx(ops, 1, v) @@ -162,8 +161,7 @@ def op2(ops, e, k1, v1, r0): def tree_op2(lst, ops, e, k1, v1): r = tree_op( lst[2:], ops ) if len(r) == 0: - print yaml.dump(tstk) - err_exit("not found right term op='{}'".format(v1)) + err_not_found("right term op='{}'".format(v1)) return [ op2( ops, e, k1, v1, r[0] ) ] + r[1:] def tree_op(lst, ops): @@ -215,7 +213,7 @@ def tree_kwd(lst, kdic): return [ [ k, v, r[0] ] ] + r[1:] if v == 'if' and len( lst[2:] ) > 0: if lst[1][:2] != [ 'br_s', '(' ]: - err_exit("not found '(' after 'if'") + err_not_found("'(' after 'if'") r = tree_kwd( lst[2:], kdic ) e = [ k, v, lst[1], r.pop(0) ] if top_is(r, 'etc', ';'): @@ -225,13 +223,30 @@ def tree_kwd(lst, kdic): return [ e ] + r if v in [ 'while', 'for' ] and len( lst[2:] ) > 0: if lst[1][:2] != [ 'br_s', '(' ]: - err_exit("not found '(' after '{}'".format(v)) + err_not_found("'(' after '{}'".format(v)) r = tree_kwd( lst[2:], kdic ) e = [ k, v, lst[1], r.pop(0) ] return [ e ] + r e = e[:2] + tree_kwd( e[2:], kdic ) return step(e, 1) +def tree_type(lst): + if len(lst) == 0: + return lst + e = lst[0] + step = lambda e, i: [ e ] + tree_type( lst[i:] ) + if e[0] == 'br_s': + e = [ e[0], e[1], tree_type( e[2] ) ] + return step(e, 1) + if e[0] == 'fdef': + e4 = tree_type( [ e[4] ] )[0] + e = [ e[0], e[1], e[2], e[3], e4 ] + return step(e, 1) + if e[0] == 'type' and len( lst[1:] ) > 0: + e = [ e[0], e[1], lst[1] ] + return step(e, 2) + return step(e, 1) + def es_split(s): s = s.replace('@', '@ ') @@ -325,6 +340,8 @@ def es_split(s): lst = tree_kwd(lst, kdic) + lst = tree_type(lst) + return lst def get_call_inf(info): @@ -346,17 +363,35 @@ def was_flags(info, f): flags.remove(f) return ret +def is_exist(name, info): + return name in get_env(info) + +def get_val(name, info): + if is_exist(name, info): + return get_env(info).get(name) + err_not_found(name) + +def set_val(name, val, info): + if is_exist(name, info): + get_env(info)[name] = val + return val + err_not_found(name) + +def new_val(name, val, info): + if not is_exist(name, info): + get_env(info)[name] = val + return val + err_exit("alredy exist '{}'".format(name)) + def do_set(e, val, info): (k, v) = e[:2] if k == 'name': - get_env(info)[v] = val + set_val(v, val, info) return val if k == 'arr': idx = e[2] i = int( do_expr(idx, info) ) arr = get_arr_with_chk(v, i, info) - if arr is None: - err_exit("not found arr '{}'".format(name)) arr[i] = val return val @@ -428,18 +463,15 @@ def do_op(v, args, info): warn_no_sup('do_op', 'term', term) def get_arr_with_chk(name, i, info): - arr = get_env(info).get(name) - if arr is not None and i >= len(arr): + arr = get_val(name, info) + if i >= len(arr): err_exit('over acc {}[{}]'.format(name, i)) return arr def do_arr(name, idx, info): i = int( do_expr(idx, info) ) arr = get_arr_with_chk(name, i, info) - if arr is not None: - return arr[i] - get_env(info)[name] = [ None ] * i # new - return None + return arr[i] def do_kwd(v, expr, info): if v == 'return': @@ -478,15 +510,34 @@ def do_kwd(v, expr, info): loop_add(info, -1) return None if v in [ 'break', 'continue' ]: - get_call_inf(info).get('flags').append(v) + get_flags(info).append(v) return None warn_no_sup('do_kwd', 'v', v) +def flat_comma(e): + if e[:2] != [ 'op', ',' ]: + return [ e ] + return flat_comma( e[2] ) + [ e[3] ] + def do_comma(e, info): - if e[:2] != ['op', ',']: - return [ do_expr(e, info) ] - return do_comma( e[2], info ) + [ do_expr( e[3], info ) ] + lst = flat_comma(e) + return [ do_expr(e, info) for e in lst ] + +def do_type(expr, info): + for e in flat_comma( expr[2] ): + val = None + if e[:2] == [ 'op', '=' ]: + val = do_expr( e[3], info ) + e = e[2] + if e[0] == 'arr': + idx = e[2] + n = int( do_expr(idx, info) ) + if val is None: + val = [ None ] * n + name = e[1] + new_val(name, val, info) + return None def do_expr(expr, info): if info.get('verb') >= 2: @@ -499,7 +550,7 @@ def do_expr(expr, info): if k == 'str': return expr[2] if k == 'name': - return get_env(info).get(v) + return get_val(v, info) if k == 'br_s': if v in [ '(', '[' ]: # '[' for do_arr() e = expr[2][0] @@ -516,8 +567,10 @@ def do_expr(expr, info): if len(args) > 0: args = do_comma( args[0], info ) return do_fcall(v, args, info) + if k == 'type': + return do_type(expr, info) - if k in [ 'type', 'fproto', 'etc' ]: # do nothing !!! + if k in [ 'fproto', 'etc' ]: # do nothing !!! return None warn_no_sup('do_expr', '[k, v]', [k, v]) @@ -525,7 +578,7 @@ def do_expr(expr, info): def do_blk(blk, info): (_, _, lst) = blk # [ 'br_s', '{', lst ] - call_inf = info.get('call_stk')[-1] + call_inf = get_call_inf(info) for expr in lst: do_expr(expr, info) if 'ret' in call_inf: @@ -550,11 +603,10 @@ def do_fcall(name, args, info): f = lambda (k, nm): k == 'fdef' and nm == name fdef = next( ( e for e in lst if f( e[:2] ) ), None ) if fdef is None: - v = get_env(info).get(name) - func = v if v else get_sys_func(name) + func = get_val(name, info) if is_exist(name, info) else get_sys_func(name) if func: return func(*args) - err_exit("not found fdef '{}'".format(name)) + err_not_found("fdef '{}'".format(name)) (args_info, ret_type, body) = fdef[2:] (_, _, args_lst) = args_info @@ -573,30 +625,45 @@ def warn_no_sup(f, t, v): def warn(msg): print('Warn {}'.format(msg)) +def err_not_found(name): + err_exit("not found {}".format(name)) + +ginfo = {} + +def show_yaml(v, title): + print('--- {} ---'.format(title)) + print( yaml.dump(v) ) + def err_exit(msg, rcode=1): + if tstk: + show_yaml(tstk, 'tree stack') + if ginfo: + if ginfo.get('verb') < 2: + ginfo['lst'] = '...' + show_yaml(ginfo, 'info') print('Err {}'.format(msg)) sys.exit(rcode) if __name__ == "__main__": rcode = 0 if len(sys.argv) <= 1: - print('usage: {} [-v -vv] file'.format(sys.argv[0])) + print('usage: {} [-v -vv -vvv] file'.format(sys.argv[0])) else: verb = 0 argv = sys.argv[:] - for (i, opt) in enumerate( [ '-v', '-vv' ] ): + for (i, opt) in enumerate( [ '-v', '-vv', '-vvv' ] ): if opt in argv: argv.remove(opt) verb = i + 1 with open(argv[1], 'r') as f: s = f.read() lst = es_split(s) - if verb >= 1: - print yaml.dump(lst) - + if verb >= 3: + show_yaml(lst, 'lst') argv = argv[1:] args = [ len(argv), argv ] info = { 'lst' : lst, 'call_stk' : [], 'verb' : verb } + ginfo = info rcode = do_fcall( 'main', args, info ) rcode = int(rcode) sys.exit(rcode)