+ def p_switch_smt(self, p):
+ """switch_stmt : SWITCH LPAR atom RPAR COLON NEWLINE INDENT switches DEDENT
+ """
+ switchon = p[3]
+ print("switch stmt")
+ print(astor.dump_tree(p[1]))
+
+ cases = []
+ current_cases = [] # for deferral
+ for (case, suite) in p[8]:
+ print("for", case, suite)
+ if suite is None:
+ for c in case:
+ current_cases.append(ast.Num(c))
+ continue
+ if case == 'default': # last
+ break
+ for c in case:
+ current_cases.append(ast.Num(c))
+ print("cases", current_cases)
+ compare = ast.Compare(switchon, [ast.In()],
+ [ast.List(current_cases, ast.Load())])
+ current_cases = []
+ cases.append((compare, suite))
+
+ print("ended", case, current_cases)
+ if case == 'default':
+ if current_cases:
+ compare = ast.Compare(switchon, [ast.In()],
+ [ast.List(current_cases, ast.Load())])
+ cases.append((compare, suite))
+ cases.append((None, suite))
+
+ cases.reverse()
+ res = []
+ for compare, suite in cases:
+ print("after rev", compare, suite)
+ if compare is None:
+ assert len(res) == 0, "last case should be default"
+ res = suite
+ else:
+ if not isinstance(res, list):
+ res = [res]
+ res = ast.If(compare, suite, res)
+ p[0] = res
+
+ def p_switches(self, p):
+ """switches : switch_list switch_default
+ | switch_default
+ """
+ if len(p) == 3:
+ p[0] = p[1] + [p[2]]
+ else:
+ p[0] = [p[1]]
+
+ def p_switch_list(self, p):
+ """switch_list : switch_case switch_list
+ | switch_case
+ """
+ if len(p) == 3:
+ p[0] = [p[1]] + p[2]
+ else:
+ p[0] = [p[1]]
+
+ def p_switch_case(self, p):
+ """switch_case : CASE LPAR atomlist RPAR COLON suite
+ """
+ # XXX bad hack
+ if isinstance(p[6][0], ast.Name) and p[6][0].id == 'fallthrough':
+ p[6] = None
+ p[0] = (p[3], p[6])
+
+ def p_switch_default(self, p):
+ """switch_default : DEFAULT COLON suite
+ """
+ p[0] = ('default', p[3])
+
+ def p_atomlist(self, p):
+ """atomlist : atom COMMA atomlist
+ | atom
+ """
+ assert isinstance(p[1], ast.Constant), "case must be numbers"
+ if len(p) == 4:
+ p[0] = [p[1].value] + p[3]
+ else:
+ p[0] = [p[1].value]
+