--- esb.py- 2016-09-12 00:00:00.000000000 +0900 +++ esb.py 2016-09-12 01:00:00.000000000 +0900 @@ -285,7 +285,7 @@ def es_split(s): 'br_e' : [ ')', ']', '}' ], 'op' : ops_flat, 'type' : [ 'int', 'char', 'void' ], - 'kwd' : [ 'return', 'if', 'else', 'while', 'for' ], + 'kwd' : [ 'return', 'if', 'else', 'while', 'for', 'break', 'continue' ], 'spc' : [ ' ', '\t', '\n' ], 'etc' : [ ';' ], } @@ -333,6 +333,19 @@ def get_call_inf(info): def get_env(info): return get_call_inf(info).get('env') +def get_flags(info): + return get_call_inf(info).get('flags') + +def loop_add(info, add): + get_call_inf(info)['loop'] += add + +def was_flags(info, f): + flags = get_flags(info) + ret = f in flags + if ret: + flags.remove(f) + return ret + def do_set(e, val, info): (k, v) = e[:2] if k == 'name': @@ -440,18 +453,32 @@ def do_kwd(v, expr, info): do_expr( expr[4], info ) return None if v == 'while': + loop_add(info, 1) while do_expr( expr[2], info ): do_expr( expr[3], info ) + if was_flags(info, 'break'): + break + was_flags(info, 'continue') + loop_add(info, -1) return None if v == 'for': args = expr[2][2] is_omit = lambda lst, i: len(lst) <= i or lst[i] == [ 'etc', ';' ] f = lambda lst, i: lst[:i] + [ [ 'num', '1' ] ] + lst[i:] if is_omit(lst, i) else lst args = reduce( f, [ 0, 2, 4 ], args )[::2] + + loop_add(info, 1) do_expr( args[0], info ) while do_expr( args[1], info ): do_expr( expr[3], info ) + if was_flags(info, 'break'): + break + was_flags(info, 'continue') do_expr( args[2], info ) + loop_add(info, -1) + return None + if v in [ 'break', 'continue' ]: + get_call_inf(info).get('flags').append(v) return None warn_no_sup('do_kwd', 'v', v) @@ -503,6 +530,9 @@ def do_blk(blk, info): do_expr(expr, info) if 'ret' in call_inf: return + flags = get_flags(info) + if 'break' in flags or 'continue' in flags: + return def get_sys_func(name): try: @@ -532,7 +562,7 @@ def do_fcall(name, args, info): env = dict( zip(names, args) ) call_stk = info.get('call_stk') - call_stk.append( { 'name' : name, 'env' : env } ) + call_stk.append( { 'name' : name, 'env' : env, 'flags' : [], 'loop' : 0 } ) do_blk(body, info) call_inf = call_stk.pop() return call_inf.get('ret', None)