PEP-0318, @decorator-style. In Guido's words:
"@ seems the syntax that everybody can hate equally"
Implementation by Mark Russell, from SF #979728.
diff --git a/Lib/compiler/ast.py b/Lib/compiler/ast.py
index 064df50..a81937f 100644
--- a/Lib/compiler/ast.py
+++ b/Lib/compiler/ast.py
@@ -48,31 +48,333 @@
 class EmptyNode(Node):
     pass
 
-class Slice(Node):
-    nodes["slice"] = "Slice"
-    def __init__(self, expr, flags, lower, upper):
+class Expression(Node):
+    # Expression is an artificial node class to support "eval"
+    nodes["expression"] = "Expression"
+    def __init__(self, node):
+        self.node = node
+
+    def getChildren(self):
+        return self.node,
+
+    def getChildNodes(self):
+        return self.node,
+
+    def __repr__(self):
+        return "Expression(%s)" % (repr(self.node))
+
+class Add(Node):
+    nodes["add"] = "Add"
+    def __init__(self, (left, right)):
+        self.left = left
+        self.right = right
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Add((%s, %s))" % (repr(self.left), repr(self.right))
+
+class And(Node):
+    nodes["and"] = "And"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "And(%s)" % (repr(self.nodes),)
+
+class AssAttr(Node):
+    nodes["assattr"] = "AssAttr"
+    def __init__(self, expr, attrname, flags):
         self.expr = expr
+        self.attrname = attrname
         self.flags = flags
-        self.lower = lower
-        self.upper = upper
+
+    def getChildren(self):
+        return self.expr, self.attrname, self.flags
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags))
+
+class AssList(Node):
+    nodes["asslist"] = "AssList"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "AssList(%s)" % (repr(self.nodes),)
+
+class AssName(Node):
+    nodes["assname"] = "AssName"
+    def __init__(self, name, flags):
+        self.name = name
+        self.flags = flags
+
+    def getChildren(self):
+        return self.name, self.flags
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "AssName(%s, %s)" % (repr(self.name), repr(self.flags))
+
+class AssTuple(Node):
+    nodes["asstuple"] = "AssTuple"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "AssTuple(%s)" % (repr(self.nodes),)
+
+class Assert(Node):
+    nodes["assert"] = "Assert"
+    def __init__(self, test, fail):
+        self.test = test
+        self.fail = fail
+
+    def getChildren(self):
+        children = []
+        children.append(self.test)
+        children.append(self.fail)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.test)
+        if self.fail is not None:            nodelist.append(self.fail)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Assert(%s, %s)" % (repr(self.test), repr(self.fail))
+
+class Assign(Node):
+    nodes["assign"] = "Assign"
+    def __init__(self, nodes, expr):
+        self.nodes = nodes
+        self.expr = expr
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        children.append(self.expr)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        nodelist.append(self.expr)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr))
+
+class AugAssign(Node):
+    nodes["augassign"] = "AugAssign"
+    def __init__(self, node, op, expr):
+        self.node = node
+        self.op = op
+        self.expr = expr
+
+    def getChildren(self):
+        return self.node, self.op, self.expr
+
+    def getChildNodes(self):
+        return self.node, self.expr
+
+    def __repr__(self):
+        return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr))
+
+class Backquote(Node):
+    nodes["backquote"] = "Backquote"
+    def __init__(self, expr):
+        self.expr = expr
+
+    def getChildren(self):
+        return self.expr,
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Backquote(%s)" % (repr(self.expr),)
+
+class Bitand(Node):
+    nodes["bitand"] = "Bitand"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Bitand(%s)" % (repr(self.nodes),)
+
+class Bitor(Node):
+    nodes["bitor"] = "Bitor"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Bitor(%s)" % (repr(self.nodes),)
+
+class Bitxor(Node):
+    nodes["bitxor"] = "Bitxor"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Bitxor(%s)" % (repr(self.nodes),)
+
+class Break(Node):
+    nodes["break"] = "Break"
+    def __init__(self, ):
+        pass
+
+    def getChildren(self):
+        return ()
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Break()"
+
+class CallFunc(Node):
+    nodes["callfunc"] = "CallFunc"
+    def __init__(self, node, args, star_args = None, dstar_args = None):
+        self.node = node
+        self.args = args
+        self.star_args = star_args
+        self.dstar_args = dstar_args
+
+    def getChildren(self):
+        children = []
+        children.append(self.node)
+        children.extend(flatten(self.args))
+        children.append(self.star_args)
+        children.append(self.dstar_args)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.node)
+        nodelist.extend(flatten_nodes(self.args))
+        if self.star_args is not None:            nodelist.append(self.star_args)
+        if self.dstar_args is not None:            nodelist.append(self.dstar_args)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args))
+
+class Class(Node):
+    nodes["class"] = "Class"
+    def __init__(self, name, bases, doc, code):
+        self.name = name
+        self.bases = bases
+        self.doc = doc
+        self.code = code
+
+    def getChildren(self):
+        children = []
+        children.append(self.name)
+        children.extend(flatten(self.bases))
+        children.append(self.doc)
+        children.append(self.code)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.bases))
+        nodelist.append(self.code)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Class(%s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code))
+
+class Compare(Node):
+    nodes["compare"] = "Compare"
+    def __init__(self, expr, ops):
+        self.expr = expr
+        self.ops = ops
 
     def getChildren(self):
         children = []
         children.append(self.expr)
-        children.append(self.flags)
-        children.append(self.lower)
-        children.append(self.upper)
+        children.extend(flatten(self.ops))
         return tuple(children)
 
     def getChildNodes(self):
         nodelist = []
         nodelist.append(self.expr)
-        if self.lower is not None:            nodelist.append(self.lower)
-        if self.upper is not None:            nodelist.append(self.upper)
+        nodelist.extend(flatten_nodes(self.ops))
         return tuple(nodelist)
 
     def __repr__(self):
-        return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper))
+        return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops))
 
 class Const(Node):
     nodes["const"] = "Const"
@@ -88,29 +390,133 @@
     def __repr__(self):
         return "Const(%s)" % (repr(self.value),)
 
-class Raise(Node):
-    nodes["raise"] = "Raise"
-    def __init__(self, expr1, expr2, expr3):
-        self.expr1 = expr1
-        self.expr2 = expr2
-        self.expr3 = expr3
+class Continue(Node):
+    nodes["continue"] = "Continue"
+    def __init__(self, ):
+        pass
+
+    def getChildren(self):
+        return ()
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Continue()"
+
+class Decorators(Node):
+    nodes["decorators"] = "Decorators"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        return tuple(flatten(self.nodes))
+
+    def getChildNodes(self):
+        return flatten_nodes(self.nodes)
+
+    def __repr__(self):
+        return "Decorators(%s)" % (repr(self.nodes),)
+
+class Dict(Node):
+    nodes["dict"] = "Dict"
+    def __init__(self, items):
+        self.items = items
 
     def getChildren(self):
         children = []
-        children.append(self.expr1)
-        children.append(self.expr2)
-        children.append(self.expr3)
+        children.extend(flatten(self.items))
         return tuple(children)
 
     def getChildNodes(self):
         nodelist = []
-        if self.expr1 is not None:            nodelist.append(self.expr1)
-        if self.expr2 is not None:            nodelist.append(self.expr2)
-        if self.expr3 is not None:            nodelist.append(self.expr3)
+        nodelist.extend(flatten_nodes(self.items))
         return tuple(nodelist)
 
     def __repr__(self):
-        return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3))
+        return "Dict(%s)" % (repr(self.items),)
+
+class Discard(Node):
+    nodes["discard"] = "Discard"
+    def __init__(self, expr):
+        self.expr = expr
+
+    def getChildren(self):
+        return self.expr,
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Discard(%s)" % (repr(self.expr),)
+
+class Div(Node):
+    nodes["div"] = "Div"
+    def __init__(self, (left, right)):
+        self.left = left
+        self.right = right
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Div((%s, %s))" % (repr(self.left), repr(self.right))
+
+class Ellipsis(Node):
+    nodes["ellipsis"] = "Ellipsis"
+    def __init__(self, ):
+        pass
+
+    def getChildren(self):
+        return ()
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Ellipsis()"
+
+class Exec(Node):
+    nodes["exec"] = "Exec"
+    def __init__(self, expr, locals, globals):
+        self.expr = expr
+        self.locals = locals
+        self.globals = globals
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.append(self.locals)
+        children.append(self.globals)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        if self.locals is not None:            nodelist.append(self.locals)
+        if self.globals is not None:            nodelist.append(self.globals)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals))
+
+class FloorDiv(Node):
+    nodes["floordiv"] = "FloorDiv"
+    def __init__(self, (left, right)):
+        self.left = left
+        self.right = right
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right))
 
 class For(Node):
     nodes["for"] = "For"
@@ -139,86 +545,6 @@
     def __repr__(self):
         return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_))
 
-class AssTuple(Node):
-    nodes["asstuple"] = "AssTuple"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "AssTuple(%s)" % (repr(self.nodes),)
-
-class Mul(Node):
-    nodes["mul"] = "Mul"
-    def __init__(self, (left, right)):
-        self.left = left
-        self.right = right
-
-    def getChildren(self):
-        return self.left, self.right
-
-    def getChildNodes(self):
-        return self.left, self.right
-
-    def __repr__(self):
-        return "Mul((%s, %s))" % (repr(self.left), repr(self.right))
-
-class Invert(Node):
-    nodes["invert"] = "Invert"
-    def __init__(self, expr):
-        self.expr = expr
-
-    def getChildren(self):
-        return self.expr,
-
-    def getChildNodes(self):
-        return self.expr,
-
-    def __repr__(self):
-        return "Invert(%s)" % (repr(self.expr),)
-
-class RightShift(Node):
-    nodes["rightshift"] = "RightShift"
-    def __init__(self, (left, right)):
-        self.left = left
-        self.right = right
-
-    def getChildren(self):
-        return self.left, self.right
-
-    def getChildNodes(self):
-        return self.left, self.right
-
-    def __repr__(self):
-        return "RightShift((%s, %s))" % (repr(self.left), repr(self.right))
-
-class AssList(Node):
-    nodes["asslist"] = "AssList"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "AssList(%s)" % (repr(self.nodes),)
-
 class From(Node):
     nodes["from"] = "From"
     def __init__(self, modname, names):
@@ -234,6 +560,126 @@
     def __repr__(self):
         return "From(%s, %s)" % (repr(self.modname), repr(self.names))
 
+class Function(Node):
+    nodes["function"] = "Function"
+    def __init__(self, decorators, name, argnames, defaults, flags, doc, code):
+        self.decorators = decorators
+        self.name = name
+        self.argnames = argnames
+        self.defaults = defaults
+        self.flags = flags
+        self.doc = doc
+        self.code = code
+        self.varargs = self.kwargs = None
+        if flags & CO_VARARGS:
+            self.varargs = 1
+        if flags & CO_VARKEYWORDS:
+            self.kwargs = 1
+
+
+
+    def getChildren(self):
+        children = []
+        if self.decorators:
+            children.append(flatten(self.decorators.nodes))
+        children.append(self.name)
+        children.append(self.argnames)
+        children.extend(flatten(self.defaults))
+        children.append(self.flags)
+        children.append(self.doc)
+        children.append(self.code)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        if self.decorators:
+            nodelist.extend(flatten_nodes(self.decorators.nodes))
+        nodelist.extend(flatten_nodes(self.defaults))
+        nodelist.append(self.code)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Function(%s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code))
+
+class GenExpr(Node):
+    nodes["genexpr"] = "GenExpr"
+    def __init__(self, code):
+        self.code = code
+        self.argnames = ['[outmost-iterable]']
+        self.varargs = self.kwargs = None
+    
+
+
+    def getChildren(self):
+        return self.code,
+
+    def getChildNodes(self):
+        return self.code,
+
+    def __repr__(self):
+        return "GenExpr(%s)" % (repr(self.code),)
+
+class GenExprFor(Node):
+    nodes["genexprfor"] = "GenExprFor"
+    def __init__(self, assign, iter, ifs):
+        self.assign = assign
+        self.iter = iter
+        self.ifs = ifs
+        self.is_outmost = False
+
+
+    def getChildren(self):
+        children = []
+        children.append(self.assign)
+        children.append(self.iter)
+        children.extend(flatten(self.ifs))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.assign)
+        nodelist.append(self.iter)
+        nodelist.extend(flatten_nodes(self.ifs))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs))
+
+class GenExprIf(Node):
+    nodes["genexprif"] = "GenExprIf"
+    def __init__(self, test):
+        self.test = test
+
+    def getChildren(self):
+        return self.test,
+
+    def getChildNodes(self):
+        return self.test,
+
+    def __repr__(self):
+        return "GenExprIf(%s)" % (repr(self.test),)
+
+class GenExprInner(Node):
+    nodes["genexprinner"] = "GenExprInner"
+    def __init__(self, expr, quals):
+        self.expr = expr
+        self.quals = quals
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.extend(flatten(self.quals))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        nodelist.extend(flatten_nodes(self.quals))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals))
+
 class Getattr(Node):
     nodes["getattr"] = "Getattr"
     def __init__(self, expr, attrname):
@@ -249,23 +695,222 @@
     def __repr__(self):
         return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname))
 
-class Dict(Node):
-    nodes["dict"] = "Dict"
-    def __init__(self, items):
-        self.items = items
+class Global(Node):
+    nodes["global"] = "Global"
+    def __init__(self, names):
+        self.names = names
+
+    def getChildren(self):
+        return self.names,
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Global(%s)" % (repr(self.names),)
+
+class If(Node):
+    nodes["if"] = "If"
+    def __init__(self, tests, else_):
+        self.tests = tests
+        self.else_ = else_
 
     def getChildren(self):
         children = []
-        children.extend(flatten(self.items))
+        children.extend(flatten(self.tests))
+        children.append(self.else_)
         return tuple(children)
 
     def getChildNodes(self):
         nodelist = []
-        nodelist.extend(flatten_nodes(self.items))
+        nodelist.extend(flatten_nodes(self.tests))
+        if self.else_ is not None:            nodelist.append(self.else_)
         return tuple(nodelist)
 
     def __repr__(self):
-        return "Dict(%s)" % (repr(self.items),)
+        return "If(%s, %s)" % (repr(self.tests), repr(self.else_))
+
+class Import(Node):
+    nodes["import"] = "Import"
+    def __init__(self, names):
+        self.names = names
+
+    def getChildren(self):
+        return self.names,
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Import(%s)" % (repr(self.names),)
+
+class Invert(Node):
+    nodes["invert"] = "Invert"
+    def __init__(self, expr):
+        self.expr = expr
+
+    def getChildren(self):
+        return self.expr,
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Invert(%s)" % (repr(self.expr),)
+
+class Keyword(Node):
+    nodes["keyword"] = "Keyword"
+    def __init__(self, name, expr):
+        self.name = name
+        self.expr = expr
+
+    def getChildren(self):
+        return self.name, self.expr
+
+    def getChildNodes(self):
+        return self.expr,
+
+    def __repr__(self):
+        return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
+
+class Lambda(Node):
+    nodes["lambda"] = "Lambda"
+    def __init__(self, argnames, defaults, flags, code):
+        self.argnames = argnames
+        self.defaults = defaults
+        self.flags = flags
+        self.code = code
+        self.varargs = self.kwargs = None
+        if flags & CO_VARARGS:
+            self.varargs = 1
+        if flags & CO_VARKEYWORDS:
+            self.kwargs = 1
+    
+
+
+    def getChildren(self):
+        children = []
+        children.append(self.argnames)
+        children.extend(flatten(self.defaults))
+        children.append(self.flags)
+        children.append(self.code)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.defaults))
+        nodelist.append(self.code)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code))
+
+class LeftShift(Node):
+    nodes["leftshift"] = "LeftShift"
+    def __init__(self, (left, right)):
+        self.left = left
+        self.right = right
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right))
+
+class List(Node):
+    nodes["list"] = "List"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "List(%s)" % (repr(self.nodes),)
+
+class ListComp(Node):
+    nodes["listcomp"] = "ListComp"
+    def __init__(self, expr, quals):
+        self.expr = expr
+        self.quals = quals
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.extend(flatten(self.quals))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        nodelist.extend(flatten_nodes(self.quals))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals))
+
+class ListCompFor(Node):
+    nodes["listcompfor"] = "ListCompFor"
+    def __init__(self, assign, list, ifs):
+        self.assign = assign
+        self.list = list
+        self.ifs = ifs
+
+    def getChildren(self):
+        children = []
+        children.append(self.assign)
+        children.append(self.list)
+        children.extend(flatten(self.ifs))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.assign)
+        nodelist.append(self.list)
+        nodelist.extend(flatten_nodes(self.ifs))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs))
+
+class ListCompIf(Node):
+    nodes["listcompif"] = "ListCompIf"
+    def __init__(self, test):
+        self.test = test
+
+    def getChildren(self):
+        return self.test,
+
+    def getChildNodes(self):
+        return self.test,
+
+    def __repr__(self):
+        return "ListCompIf(%s)" % (repr(self.test),)
+
+class Mod(Node):
+    nodes["mod"] = "Mod"
+    def __init__(self, (left, right)):
+        self.left = left
+        self.right = right
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Mod((%s, %s))" % (repr(self.left), repr(self.right))
 
 class Module(Node):
     nodes["module"] = "Module"
@@ -282,23 +927,37 @@
     def __repr__(self):
         return "Module(%s, %s)" % (repr(self.doc), repr(self.node))
 
-class Expression(Node):
-    # Expression is an artificial node class to support "eval"
-    nodes["expression"] = "Expression"
-    def __init__(self, node):
-        self.node = node
+class Mul(Node):
+    nodes["mul"] = "Mul"
+    def __init__(self, (left, right)):
+        self.left = left
+        self.right = right
 
     def getChildren(self):
-        return self.node,
+        return self.left, self.right
 
     def getChildNodes(self):
-        return self.node,
+        return self.left, self.right
 
     def __repr__(self):
-        return "Expression(%s)" % (repr(self.node))
+        return "Mul((%s, %s))" % (repr(self.left), repr(self.right))
 
-class UnaryAdd(Node):
-    nodes["unaryadd"] = "UnaryAdd"
+class Name(Node):
+    nodes["name"] = "Name"
+    def __init__(self, name):
+        self.name = name
+
+    def getChildren(self):
+        return self.name,
+
+    def getChildNodes(self):
+        return ()
+
+    def __repr__(self):
+        return "Name(%s)" % (repr(self.name),)
+
+class Not(Node):
+    nodes["not"] = "Not"
     def __init__(self, expr):
         self.expr = expr
 
@@ -309,10 +968,28 @@
         return self.expr,
 
     def __repr__(self):
-        return "UnaryAdd(%s)" % (repr(self.expr),)
+        return "Not(%s)" % (repr(self.expr),)
 
-class Ellipsis(Node):
-    nodes["ellipsis"] = "Ellipsis"
+class Or(Node):
+    nodes["or"] = "Or"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Or(%s)" % (repr(self.nodes),)
+
+class Pass(Node):
+    nodes["pass"] = "Pass"
     def __init__(self, ):
         pass
 
@@ -323,7 +1000,22 @@
         return ()
 
     def __repr__(self):
-        return "Ellipsis()"
+        return "Pass()"
+
+class Power(Node):
+    nodes["power"] = "Power"
+    def __init__(self, (left, right)):
+        self.left = left
+        self.right = right
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Power((%s, %s))" % (repr(self.left), repr(self.right))
 
 class Print(Node):
     nodes["print"] = "Print"
@@ -346,19 +1038,156 @@
     def __repr__(self):
         return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest))
 
-class Import(Node):
-    nodes["import"] = "Import"
-    def __init__(self, names):
-        self.names = names
+class Printnl(Node):
+    nodes["printnl"] = "Printnl"
+    def __init__(self, nodes, dest):
+        self.nodes = nodes
+        self.dest = dest
 
     def getChildren(self):
-        return self.names,
+        children = []
+        children.extend(flatten(self.nodes))
+        children.append(self.dest)
+        return tuple(children)
 
     def getChildNodes(self):
-        return ()
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        if self.dest is not None:            nodelist.append(self.dest)
+        return tuple(nodelist)
 
     def __repr__(self):
-        return "Import(%s)" % (repr(self.names),)
+        return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest))
+
+class Raise(Node):
+    nodes["raise"] = "Raise"
+    def __init__(self, expr1, expr2, expr3):
+        self.expr1 = expr1
+        self.expr2 = expr2
+        self.expr3 = expr3
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr1)
+        children.append(self.expr2)
+        children.append(self.expr3)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        if self.expr1 is not None:            nodelist.append(self.expr1)
+        if self.expr2 is not None:            nodelist.append(self.expr2)
+        if self.expr3 is not None:            nodelist.append(self.expr3)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3))
+
+class Return(Node):
+    nodes["return"] = "Return"
+    def __init__(self, value):
+        self.value = value
+
+    def getChildren(self):
+        return self.value,
+
+    def getChildNodes(self):
+        return self.value,
+
+    def __repr__(self):
+        return "Return(%s)" % (repr(self.value),)
+
+class RightShift(Node):
+    nodes["rightshift"] = "RightShift"
+    def __init__(self, (left, right)):
+        self.left = left
+        self.right = right
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "RightShift((%s, %s))" % (repr(self.left), repr(self.right))
+
+class Slice(Node):
+    nodes["slice"] = "Slice"
+    def __init__(self, expr, flags, lower, upper):
+        self.expr = expr
+        self.flags = flags
+        self.lower = lower
+        self.upper = upper
+
+    def getChildren(self):
+        children = []
+        children.append(self.expr)
+        children.append(self.flags)
+        children.append(self.lower)
+        children.append(self.upper)
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.append(self.expr)
+        if self.lower is not None:            nodelist.append(self.lower)
+        if self.upper is not None:            nodelist.append(self.upper)
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper))
+
+class Sliceobj(Node):
+    nodes["sliceobj"] = "Sliceobj"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Sliceobj(%s)" % (repr(self.nodes),)
+
+class Stmt(Node):
+    nodes["stmt"] = "Stmt"
+    def __init__(self, nodes):
+        self.nodes = nodes
+
+    def getChildren(self):
+        children = []
+        children.extend(flatten(self.nodes))
+        return tuple(children)
+
+    def getChildNodes(self):
+        nodelist = []
+        nodelist.extend(flatten_nodes(self.nodes))
+        return tuple(nodelist)
+
+    def __repr__(self):
+        return "Stmt(%s)" % (repr(self.nodes),)
+
+class Sub(Node):
+    nodes["sub"] = "Sub"
+    def __init__(self, (left, right)):
+        self.left = left
+        self.right = right
+
+    def getChildren(self):
+        return self.left, self.right
+
+    def getChildNodes(self):
+        return self.left, self.right
+
+    def __repr__(self):
+        return "Sub((%s, %s))" % (repr(self.left), repr(self.right))
 
 class Subscript(Node):
     nodes["subscript"] = "Subscript"
@@ -407,231 +1236,6 @@
     def __repr__(self):
         return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_))
 
-class Or(Node):
-    nodes["or"] = "Or"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Or(%s)" % (repr(self.nodes),)
-
-class Name(Node):
-    nodes["name"] = "Name"
-    def __init__(self, name):
-        self.name = name
-
-    def getChildren(self):
-        return self.name,
-
-    def getChildNodes(self):
-        return ()
-
-    def __repr__(self):
-        return "Name(%s)" % (repr(self.name),)
-
-class Function(Node):
-    nodes["function"] = "Function"
-    def __init__(self, name, argnames, defaults, flags, doc, code):
-        self.name = name
-        self.argnames = argnames
-        self.defaults = defaults
-        self.flags = flags
-        self.doc = doc
-        self.code = code
-        self.varargs = self.kwargs = None
-        if flags & CO_VARARGS:
-            self.varargs = 1
-        if flags & CO_VARKEYWORDS:
-            self.kwargs = 1
-
-
-
-    def getChildren(self):
-        children = []
-        children.append(self.name)
-        children.append(self.argnames)
-        children.extend(flatten(self.defaults))
-        children.append(self.flags)
-        children.append(self.doc)
-        children.append(self.code)
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.defaults))
-        nodelist.append(self.code)
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Function(%s, %s, %s, %s, %s, %s)" % (repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code))
-
-class Assert(Node):
-    nodes["assert"] = "Assert"
-    def __init__(self, test, fail):
-        self.test = test
-        self.fail = fail
-
-    def getChildren(self):
-        children = []
-        children.append(self.test)
-        children.append(self.fail)
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.append(self.test)
-        if self.fail is not None:            nodelist.append(self.fail)
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Assert(%s, %s)" % (repr(self.test), repr(self.fail))
-
-class Return(Node):
-    nodes["return"] = "Return"
-    def __init__(self, value):
-        self.value = value
-
-    def getChildren(self):
-        return self.value,
-
-    def getChildNodes(self):
-        return self.value,
-
-    def __repr__(self):
-        return "Return(%s)" % (repr(self.value),)
-
-class Power(Node):
-    nodes["power"] = "Power"
-    def __init__(self, (left, right)):
-        self.left = left
-        self.right = right
-
-    def getChildren(self):
-        return self.left, self.right
-
-    def getChildNodes(self):
-        return self.left, self.right
-
-    def __repr__(self):
-        return "Power((%s, %s))" % (repr(self.left), repr(self.right))
-
-class Exec(Node):
-    nodes["exec"] = "Exec"
-    def __init__(self, expr, locals, globals):
-        self.expr = expr
-        self.locals = locals
-        self.globals = globals
-
-    def getChildren(self):
-        children = []
-        children.append(self.expr)
-        children.append(self.locals)
-        children.append(self.globals)
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.append(self.expr)
-        if self.locals is not None:            nodelist.append(self.locals)
-        if self.globals is not None:            nodelist.append(self.globals)
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals))
-
-class Stmt(Node):
-    nodes["stmt"] = "Stmt"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Stmt(%s)" % (repr(self.nodes),)
-
-class Sliceobj(Node):
-    nodes["sliceobj"] = "Sliceobj"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Sliceobj(%s)" % (repr(self.nodes),)
-
-class Break(Node):
-    nodes["break"] = "Break"
-    def __init__(self, ):
-        pass
-
-    def getChildren(self):
-        return ()
-
-    def getChildNodes(self):
-        return ()
-
-    def __repr__(self):
-        return "Break()"
-
-class Bitand(Node):
-    nodes["bitand"] = "Bitand"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Bitand(%s)" % (repr(self.nodes),)
-
-class FloorDiv(Node):
-    nodes["floordiv"] = "FloorDiv"
-    def __init__(self, (left, right)):
-        self.left = left
-        self.right = right
-
-    def getChildren(self):
-        return self.left, self.right
-
-    def getChildNodes(self):
-        return self.left, self.right
-
-    def __repr__(self):
-        return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right))
-
 class TryFinally(Node):
     nodes["tryfinally"] = "TryFinally"
     def __init__(self, body, final):
@@ -647,81 +1251,6 @@
     def __repr__(self):
         return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final))
 
-class Not(Node):
-    nodes["not"] = "Not"
-    def __init__(self, expr):
-        self.expr = expr
-
-    def getChildren(self):
-        return self.expr,
-
-    def getChildNodes(self):
-        return self.expr,
-
-    def __repr__(self):
-        return "Not(%s)" % (repr(self.expr),)
-
-class Class(Node):
-    nodes["class"] = "Class"
-    def __init__(self, name, bases, doc, code):
-        self.name = name
-        self.bases = bases
-        self.doc = doc
-        self.code = code
-
-    def getChildren(self):
-        children = []
-        children.append(self.name)
-        children.extend(flatten(self.bases))
-        children.append(self.doc)
-        children.append(self.code)
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.bases))
-        nodelist.append(self.code)
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Class(%s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code))
-
-class Mod(Node):
-    nodes["mod"] = "Mod"
-    def __init__(self, (left, right)):
-        self.left = left
-        self.right = right
-
-    def getChildren(self):
-        return self.left, self.right
-
-    def getChildNodes(self):
-        return self.left, self.right
-
-    def __repr__(self):
-        return "Mod((%s, %s))" % (repr(self.left), repr(self.right))
-
-class Printnl(Node):
-    nodes["printnl"] = "Printnl"
-    def __init__(self, nodes, dest):
-        self.nodes = nodes
-        self.dest = dest
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        children.append(self.dest)
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        if self.dest is not None:            nodelist.append(self.dest)
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest))
-
 class Tuple(Node):
     nodes["tuple"] = "Tuple"
     def __init__(self, nodes):
@@ -740,114 +1269,33 @@
     def __repr__(self):
         return "Tuple(%s)" % (repr(self.nodes),)
 
-class AssAttr(Node):
-    nodes["assattr"] = "AssAttr"
-    def __init__(self, expr, attrname, flags):
+class UnaryAdd(Node):
+    nodes["unaryadd"] = "UnaryAdd"
+    def __init__(self, expr):
         self.expr = expr
-        self.attrname = attrname
-        self.flags = flags
 
     def getChildren(self):
-        return self.expr, self.attrname, self.flags
+        return self.expr,
 
     def getChildNodes(self):
         return self.expr,
 
     def __repr__(self):
-        return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags))
+        return "UnaryAdd(%s)" % (repr(self.expr),)
 
-class Keyword(Node):
-    nodes["keyword"] = "Keyword"
-    def __init__(self, name, expr):
-        self.name = name
+class UnarySub(Node):
+    nodes["unarysub"] = "UnarySub"
+    def __init__(self, expr):
         self.expr = expr
 
     def getChildren(self):
-        return self.name, self.expr
+        return self.expr,
 
     def getChildNodes(self):
         return self.expr,
 
     def __repr__(self):
-        return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
-
-class AugAssign(Node):
-    nodes["augassign"] = "AugAssign"
-    def __init__(self, node, op, expr):
-        self.node = node
-        self.op = op
-        self.expr = expr
-
-    def getChildren(self):
-        return self.node, self.op, self.expr
-
-    def getChildNodes(self):
-        return self.node, self.expr
-
-    def __repr__(self):
-        return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr))
-
-class List(Node):
-    nodes["list"] = "List"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "List(%s)" % (repr(self.nodes),)
-
-class Yield(Node):
-    nodes["yield"] = "Yield"
-    def __init__(self, value):
-        self.value = value
-
-    def getChildren(self):
-        return self.value,
-
-    def getChildNodes(self):
-        return self.value,
-
-    def __repr__(self):
-        return "Yield(%s)" % (repr(self.value),)
-
-class LeftShift(Node):
-    nodes["leftshift"] = "LeftShift"
-    def __init__(self, (left, right)):
-        self.left = left
-        self.right = right
-
-    def getChildren(self):
-        return self.left, self.right
-
-    def getChildNodes(self):
-        return self.left, self.right
-
-    def __repr__(self):
-        return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right))
-
-class AssName(Node):
-    nodes["assname"] = "AssName"
-    def __init__(self, name, flags):
-        self.name = name
-        self.flags = flags
-
-    def getChildren(self):
-        return self.name, self.flags
-
-    def getChildNodes(self):
-        return ()
-
-    def __repr__(self):
-        return "AssName(%s, %s)" % (repr(self.name), repr(self.flags))
+        return "UnarySub(%s)" % (repr(self.expr),)
 
 class While(Node):
     nodes["while"] = "While"
@@ -873,444 +1321,19 @@
     def __repr__(self):
         return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_))
 
-class Continue(Node):
-    nodes["continue"] = "Continue"
-    def __init__(self, ):
-        pass
+class Yield(Node):
+    nodes["yield"] = "Yield"
+    def __init__(self, value):
+        self.value = value
 
     def getChildren(self):
-        return ()
+        return self.value,
 
     def getChildNodes(self):
-        return ()
+        return self.value,
 
     def __repr__(self):
-        return "Continue()"
-
-class Backquote(Node):
-    nodes["backquote"] = "Backquote"
-    def __init__(self, expr):
-        self.expr = expr
-
-    def getChildren(self):
-        return self.expr,
-
-    def getChildNodes(self):
-        return self.expr,
-
-    def __repr__(self):
-        return "Backquote(%s)" % (repr(self.expr),)
-
-class Discard(Node):
-    nodes["discard"] = "Discard"
-    def __init__(self, expr):
-        self.expr = expr
-
-    def getChildren(self):
-        return self.expr,
-
-    def getChildNodes(self):
-        return self.expr,
-
-    def __repr__(self):
-        return "Discard(%s)" % (repr(self.expr),)
-
-class Div(Node):
-    nodes["div"] = "Div"
-    def __init__(self, (left, right)):
-        self.left = left
-        self.right = right
-
-    def getChildren(self):
-        return self.left, self.right
-
-    def getChildNodes(self):
-        return self.left, self.right
-
-    def __repr__(self):
-        return "Div((%s, %s))" % (repr(self.left), repr(self.right))
-
-class Assign(Node):
-    nodes["assign"] = "Assign"
-    def __init__(self, nodes, expr):
-        self.nodes = nodes
-        self.expr = expr
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        children.append(self.expr)
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        nodelist.append(self.expr)
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr))
-
-class Lambda(Node):
-    nodes["lambda"] = "Lambda"
-    def __init__(self, argnames, defaults, flags, code):
-        self.argnames = argnames
-        self.defaults = defaults
-        self.flags = flags
-        self.code = code
-        self.varargs = self.kwargs = None
-        if flags & CO_VARARGS:
-            self.varargs = 1
-        if flags & CO_VARKEYWORDS:
-            self.kwargs = 1
-
-
-    def getChildren(self):
-        children = []
-        children.append(self.argnames)
-        children.extend(flatten(self.defaults))
-        children.append(self.flags)
-        children.append(self.code)
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.defaults))
-        nodelist.append(self.code)
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code))
-
-class And(Node):
-    nodes["and"] = "And"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "And(%s)" % (repr(self.nodes),)
-
-class Compare(Node):
-    nodes["compare"] = "Compare"
-    def __init__(self, expr, ops):
-        self.expr = expr
-        self.ops = ops
-
-    def getChildren(self):
-        children = []
-        children.append(self.expr)
-        children.extend(flatten(self.ops))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.append(self.expr)
-        nodelist.extend(flatten_nodes(self.ops))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops))
-
-class Bitor(Node):
-    nodes["bitor"] = "Bitor"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Bitor(%s)" % (repr(self.nodes),)
-
-class Bitxor(Node):
-    nodes["bitxor"] = "Bitxor"
-    def __init__(self, nodes):
-        self.nodes = nodes
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.nodes))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.nodes))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "Bitxor(%s)" % (repr(self.nodes),)
-
-class CallFunc(Node):
-    nodes["callfunc"] = "CallFunc"
-    def __init__(self, node, args, star_args = None, dstar_args = None):
-        self.node = node
-        self.args = args
-        self.star_args = star_args
-        self.dstar_args = dstar_args
-
-    def getChildren(self):
-        children = []
-        children.append(self.node)
-        children.extend(flatten(self.args))
-        children.append(self.star_args)
-        children.append(self.dstar_args)
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.append(self.node)
-        nodelist.extend(flatten_nodes(self.args))
-        if self.star_args is not None:            nodelist.append(self.star_args)
-        if self.dstar_args is not None:            nodelist.append(self.dstar_args)
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args))
-
-class Global(Node):
-    nodes["global"] = "Global"
-    def __init__(self, names):
-        self.names = names
-
-    def getChildren(self):
-        return self.names,
-
-    def getChildNodes(self):
-        return ()
-
-    def __repr__(self):
-        return "Global(%s)" % (repr(self.names),)
-
-class Add(Node):
-    nodes["add"] = "Add"
-    def __init__(self, (left, right)):
-        self.left = left
-        self.right = right
-
-    def getChildren(self):
-        return self.left, self.right
-
-    def getChildNodes(self):
-        return self.left, self.right
-
-    def __repr__(self):
-        return "Add((%s, %s))" % (repr(self.left), repr(self.right))
-
-class ListCompIf(Node):
-    nodes["listcompif"] = "ListCompIf"
-    def __init__(self, test):
-        self.test = test
-
-    def getChildren(self):
-        return self.test,
-
-    def getChildNodes(self):
-        return self.test,
-
-    def __repr__(self):
-        return "ListCompIf(%s)" % (repr(self.test),)
-
-class Sub(Node):
-    nodes["sub"] = "Sub"
-    def __init__(self, (left, right)):
-        self.left = left
-        self.right = right
-
-    def getChildren(self):
-        return self.left, self.right
-
-    def getChildNodes(self):
-        return self.left, self.right
-
-    def __repr__(self):
-        return "Sub((%s, %s))" % (repr(self.left), repr(self.right))
-
-class Pass(Node):
-    nodes["pass"] = "Pass"
-    def __init__(self, ):
-        pass
-
-    def getChildren(self):
-        return ()
-
-    def getChildNodes(self):
-        return ()
-
-    def __repr__(self):
-        return "Pass()"
-
-class UnarySub(Node):
-    nodes["unarysub"] = "UnarySub"
-    def __init__(self, expr):
-        self.expr = expr
-
-    def getChildren(self):
-        return self.expr,
-
-    def getChildNodes(self):
-        return self.expr,
-
-    def __repr__(self):
-        return "UnarySub(%s)" % (repr(self.expr),)
-
-class If(Node):
-    nodes["if"] = "If"
-    def __init__(self, tests, else_):
-        self.tests = tests
-        self.else_ = else_
-
-    def getChildren(self):
-        children = []
-        children.extend(flatten(self.tests))
-        children.append(self.else_)
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.extend(flatten_nodes(self.tests))
-        if self.else_ is not None:            nodelist.append(self.else_)
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "If(%s, %s)" % (repr(self.tests), repr(self.else_))
-
-class ListComp(Node):
-    nodes["listcomp"] = "ListComp"
-    def __init__(self, expr, quals):
-        self.expr = expr
-        self.quals = quals
-
-    def getChildren(self):
-        children = []
-        children.append(self.expr)
-        children.extend(flatten(self.quals))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.append(self.expr)
-        nodelist.extend(flatten_nodes(self.quals))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals))
-
-class ListCompFor(Node):
-    nodes["listcompfor"] = "ListCompFor"
-    def __init__(self, assign, list, ifs):
-        self.assign = assign
-        self.list = list
-        self.ifs = ifs
-
-    def getChildren(self):
-        children = []
-        children.append(self.assign)
-        children.append(self.list)
-        children.extend(flatten(self.ifs))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.append(self.assign)
-        nodelist.append(self.list)
-        nodelist.extend(flatten_nodes(self.ifs))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs))
-
-class GenExpr(Node):
-    nodes["genexpr"] = "GenExpr"
-    def __init__(self, code):
-        self.code = code
-        self.argnames = ['[outmost-iterable]']
-        self.varargs = self.kwargs = None
-
-    def getChildren(self):
-        return self.code,
-
-    def getChildNodes(self):
-        return self.code,
-
-    def __repr__(self):
-        return "GenExpr(%s)" % (repr(self.code),)
-
-class GenExprInner(Node):
-    nodes["genexprinner"] = "GenExprInner"
-    def __init__(self, expr, quals):
-        self.expr = expr
-        self.quals = quals
-
-    def getChildren(self):
-        children = []
-        children.append(self.expr)
-        children.extend(flatten(self.quals))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.append(self.expr)
-        nodelist.extend(flatten_nodes(self.quals))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals))
-
-class GenExprFor(Node):
-    nodes["genexprfor"] = "GenExprFor"
-    def __init__(self, assign, iter, ifs):
-        self.assign = assign
-        self.iter = iter
-        self.ifs = ifs
-        self.is_outmost = False
-
-    def getChildren(self):
-        children = []
-        children.append(self.assign)
-        children.append(self.iter)
-        children.extend(flatten(self.ifs))
-        return tuple(children)
-
-    def getChildNodes(self):
-        nodelist = []
-        nodelist.append(self.assign)
-        nodelist.append(self.iter)
-        nodelist.extend(flatten_nodes(self.ifs))
-        return tuple(nodelist)
-
-    def __repr__(self):
-        return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs))
-
-class GenExprIf(Node):
-    nodes["genexprif"] = "GenExprIf"
-    def __init__(self, test):
-        self.test = test
-
-    def getChildren(self):
-        return self.test,
-
-    def getChildNodes(self):
-        return self.test,
-
-    def __repr__(self):
-        return "GenExprIf(%s)" % (repr(self.test),)
+        return "Yield(%s)" % (repr(self.value),)
 
 klasses = globals()
 for k in nodes.keys():
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index 4d5f728..e859ac5 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -366,6 +366,13 @@
         self._visitFuncOrLambda(node, isLambda=1)
 
     def _visitFuncOrLambda(self, node, isLambda=0):
+        if not isLambda and node.decorators:
+            for decorator in reversed(node.decorators.nodes):
+                self.visit(decorator)
+            ndecorators = len(node.decorators.nodes)
+        else:
+            ndecorators = 0
+            
         gen = self.FunctionGen(node, self.scopes, isLambda,
                                self.class_name, self.get_module())
         walk(node.code, gen)
@@ -382,6 +389,9 @@
         else:
             self.emit('LOAD_CONST', gen)
             self.emit('MAKE_FUNCTION', len(node.defaults))
+            
+        for i in range(ndecorators):
+            self.emit('CALL_FUNCTION', 1)
 
     def visitClass(self, node):
         gen = self.ClassGen(node, self.scopes,
diff --git a/Lib/compiler/symbols.py b/Lib/compiler/symbols.py
index e1581a4..9d4605a 100644
--- a/Lib/compiler/symbols.py
+++ b/Lib/compiler/symbols.py
@@ -224,6 +224,8 @@
     visitExpression = visitModule
 
     def visitFunction(self, node, parent):
+        if node.decorators:
+            self.visit(node.decorators, parent)
         parent.add_def(node.name)
         for n in node.defaults:
             self.visit(n, parent)
diff --git a/Lib/compiler/transformer.py b/Lib/compiler/transformer.py
index aa5a28b..229657b 100644
--- a/Lib/compiler/transformer.py
+++ b/Lib/compiler/transformer.py
@@ -185,29 +185,81 @@
         ### is this sufficient?
         return Expression(self.com_node(nodelist[0]))
 
+    def decorator_name(self, nodelist):
+        listlen = len(nodelist)
+        assert listlen >= 1 and listlen % 2 == 1
+
+        item = self.atom_name(nodelist)
+        i = 1
+        while i < listlen:
+            assert nodelist[i][0] == token.DOT
+            assert nodelist[i + 1][0] == token.NAME
+            item = Getattr(item, nodelist[i + 1][1])
+            i += 2
+
+        return item
+        
+    def decorator(self, nodelist):
+        # '@' dotted_name [ '(' [arglist] ')' ]
+        assert len(nodelist) in (2, 4, 5)
+        assert nodelist[0][0] == token.AT
+
+        assert nodelist[1][0] == symbol.dotted_name
+        funcname = self.decorator_name(nodelist[1][1:])
+
+        if len(nodelist) > 2:
+            assert nodelist[2][0] == token.LPAR
+            expr = self.com_call_function(funcname, nodelist[3])
+        else:
+            expr = funcname
+            
+        return expr
+    
+    def decorators(self, nodelist):
+        # decorators: decorator ([NEWLINE] decorator)* NEWLINE
+        listlen = len(nodelist)
+        i = 0
+        items = []
+        while i < listlen:
+            assert nodelist[i][0] == symbol.decorator
+            items.append(self.decorator(nodelist[i][1:]))
+            i += 1
+
+            if i < listlen and nodelist[i][0] == token.NEWLINE:
+                i += 1
+        return Decorators(items)
+    
     def funcdef(self, nodelist):
-        # funcdef: 'def' NAME parameters ':' suite
+        #                    -6   -5    -4         -3  -2    -1
+        # funcdef: [decorators] 'def' NAME parameters ':' suite
         # parameters: '(' [varargslist] ')'
 
-        lineno = nodelist[1][2]
-        name = nodelist[1][1]
-        args = nodelist[2][2]
+        if len(nodelist) == 6:
+            assert nodelist[0][0] == symbol.decorators
+            decorators = self.decorators(nodelist[0][1:])
+        else:
+            assert len(nodelist) == 5
+            decorators = None
+            
+        lineno = nodelist[-4][2]
+        name = nodelist[-4][1]
+        args = nodelist[-3][2]
 
         if args[0] == symbol.varargslist:
             names, defaults, flags = self.com_arglist(args[1:])
         else:
             names = defaults = ()
             flags = 0
-        doc = self.get_docstring(nodelist[4])
+        doc = self.get_docstring(nodelist[-1])
 
         # code for function
-        code = self.com_node(nodelist[4])
+        code = self.com_node(nodelist[-1])
 
         if doc is not None:
             assert isinstance(code, Stmt)
             assert isinstance(code.nodes[0], Discard)
             del code.nodes[0]
-        n = Function(name, names, defaults, flags, doc, code)
+        n = Function(decorators, name, names, defaults, flags, doc, code)
         n.lineno = lineno
         return n
 
diff --git a/Lib/pyclbr.py b/Lib/pyclbr.py
index 9e6bcb0..0812e22 100644
--- a/Lib/pyclbr.py
+++ b/Lib/pyclbr.py
@@ -222,7 +222,7 @@
                         else:
                             super.append(token)
                     inherit = names
-                cur_class = Class(module, class_name, inherit, file, lineno)
+                cur_class = Class(fullmodule, class_name, inherit, file, lineno)
                 if not stack:
                     dict[class_name] = cur_class
                 stack.append((cur_class, thisindent))
diff --git a/Lib/symbol.py b/Lib/symbol.py
index c839e4a..cb57208 100755
--- a/Lib/symbol.py
+++ b/Lib/symbol.py
@@ -13,75 +13,77 @@
 single_input = 256
 file_input = 257
 eval_input = 258
-funcdef = 259
-parameters = 260
-varargslist = 261
-fpdef = 262
-fplist = 263
-stmt = 264
-simple_stmt = 265
-small_stmt = 266
-expr_stmt = 267
-augassign = 268
-print_stmt = 269
-del_stmt = 270
-pass_stmt = 271
-flow_stmt = 272
-break_stmt = 273
-continue_stmt = 274
-return_stmt = 275
-yield_stmt = 276
-raise_stmt = 277
-import_stmt = 278
-import_as_name = 279
-dotted_as_name = 280
-dotted_name = 281
-global_stmt = 282
-exec_stmt = 283
-assert_stmt = 284
-compound_stmt = 285
-if_stmt = 286
-while_stmt = 287
-for_stmt = 288
-try_stmt = 289
-except_clause = 290
-suite = 291
-test = 292
-and_test = 293
-not_test = 294
-comparison = 295
-comp_op = 296
-expr = 297
-xor_expr = 298
-and_expr = 299
-shift_expr = 300
-arith_expr = 301
-term = 302
-factor = 303
-power = 304
-atom = 305
-listmaker = 306
-testlist_gexp = 307
-lambdef = 308
-trailer = 309
-subscriptlist = 310
-subscript = 311
-sliceop = 312
-exprlist = 313
-testlist = 314
-testlist_safe = 315
-dictmaker = 316
-classdef = 317
-arglist = 318
-argument = 319
-list_iter = 320
-list_for = 321
-list_if = 322
-gen_iter = 323
-gen_for = 324
-gen_if = 325
-testlist1 = 326
-encoding_decl = 327
+decorator = 259
+decorators = 260
+funcdef = 261
+parameters = 262
+varargslist = 263
+fpdef = 264
+fplist = 265
+stmt = 266
+simple_stmt = 267
+small_stmt = 268
+expr_stmt = 269
+augassign = 270
+print_stmt = 271
+del_stmt = 272
+pass_stmt = 273
+flow_stmt = 274
+break_stmt = 275
+continue_stmt = 276
+return_stmt = 277
+yield_stmt = 278
+raise_stmt = 279
+import_stmt = 280
+import_as_name = 281
+dotted_as_name = 282
+dotted_name = 283
+global_stmt = 284
+exec_stmt = 285
+assert_stmt = 286
+compound_stmt = 287
+if_stmt = 288
+while_stmt = 289
+for_stmt = 290
+try_stmt = 291
+except_clause = 292
+suite = 293
+test = 294
+and_test = 295
+not_test = 296
+comparison = 297
+comp_op = 298
+expr = 299
+xor_expr = 300
+and_expr = 301
+shift_expr = 302
+arith_expr = 303
+term = 304
+factor = 305
+power = 306
+atom = 307
+listmaker = 308
+testlist_gexp = 309
+lambdef = 310
+trailer = 311
+subscriptlist = 312
+subscript = 313
+sliceop = 314
+exprlist = 315
+testlist = 316
+testlist_safe = 317
+dictmaker = 318
+classdef = 319
+arglist = 320
+argument = 321
+list_iter = 322
+list_for = 323
+list_if = 324
+gen_iter = 325
+gen_for = 326
+gen_if = 327
+testlist1 = 328
+encoding_decl = 329
 #--end constants--
 
 sym_name = {}
diff --git a/Lib/test/output/test_tokenize b/Lib/test/output/test_tokenize
index ea55181..b78a223 100644
--- a/Lib/test/output/test_tokenize
+++ b/Lib/test/output/test_tokenize
@@ -645,4 +645,15 @@
 174,29-174,30:	OP	')'
 174,30-174,31:	NEWLINE	'\n'
 175,0-175,1:	NL	'\n'
-176,0-176,0:	ENDMARKER	''
+176,0-176,1:	OP	'@'
+176,1-176,13:	NAME	'staticmethod'
+176,13-176,14:	NEWLINE	'\n'
+177,0-177,3:	NAME	'def'
+177,4-177,7:	NAME	'foo'
+177,7-177,8:	OP	'('
+177,8-177,9:	OP	')'
+177,9-177,10:	OP	':'
+177,11-177,15:	NAME	'pass'
+177,15-177,16:	NEWLINE	'\n'
+178,0-178,1:	NL	'\n'
+179,0-179,0:	ENDMARKER	''
diff --git a/Lib/test/pyclbr_input.py b/Lib/test/pyclbr_input.py
new file mode 100644
index 0000000..b410fcc
--- /dev/null
+++ b/Lib/test/pyclbr_input.py
@@ -0,0 +1,33 @@
+"""Test cases for test_pyclbr.py"""
+
+def f(): pass
+
+class Other(object):
+    @classmethod
+    def foo(c): pass
+
+    def om(self): pass
+
+class B (object):
+    def bm(self): pass
+    
+class C (B):
+    foo = Other().foo
+    om = Other.om
+    
+    d = 10
+
+    # XXX: This causes test_pyclbr.py to fail, but only because the
+    #      introspection-based is_method() code in the test can't
+    #      distinguish between this and a geniune method function like m().
+    #      The pyclbr.py module gets this right as it parses the text.
+    #
+    #f = f
+    
+    def m(self): pass
+    
+    @staticmethod
+    def sm(self): pass
+
+    @classmethod
+    def cm(self): pass
diff --git a/Lib/test/test_decorators.py b/Lib/test/test_decorators.py
new file mode 100644
index 0000000..98d5d3e
--- /dev/null
+++ b/Lib/test/test_decorators.py
@@ -0,0 +1,194 @@
+import unittest
+from test import test_support
+
+def funcattrs(**kwds):
+    def decorate(func):
+        func.__dict__.update(kwds)
+        return func
+    return decorate
+
+class MiscDecorators (object):
+    @staticmethod
+    def author(name):
+        def decorate(func):
+            func.__dict__['author'] = name
+            return func
+        return decorate
+
+# -----------------------------------------------
+
+class DbcheckError (Exception):
+    def __init__(self, exprstr, func, args, kwds):
+        # A real version of this would set attributes here
+        Exception.__init__(self, "dbcheck %r failed (func=%s args=%s kwds=%s)" %
+                           (exprstr, func, args, kwds))
+    
+    
+def dbcheck(exprstr, globals=None, locals=None):
+    "Decorator to implement debugging assertions"
+    def decorate(func):
+        expr = compile(exprstr, "dbcheck-%s" % func.func_name, "eval")
+        def check(*args, **kwds):
+            if not eval(expr, globals, locals):
+                raise DbcheckError(exprstr, func, args, kwds)
+            return func(*args, **kwds)
+        return check
+    return decorate
+
+# -----------------------------------------------
+
+def countcalls(counts):
+    "Decorator to count calls to a function"
+    def decorate(func):
+        name = func.func_name
+        counts[name] = 0
+        def call(*args, **kwds):
+            counts[name] += 1
+            return func(*args, **kwds)
+        # XXX: Would like to say: call.func_name = func.func_name here
+        #      to make nested decorators work in any order, but func_name
+        #      is a readonly attribute
+        return call
+    return decorate
+
+# -----------------------------------------------
+
+def memoize(func):
+    saved = {}
+    def call(*args):
+        try:
+            return saved[args]
+        except KeyError:
+            res = func(*args)
+            saved[args] = res
+            return res
+        except TypeError:
+            # Unhashable argument
+            return func(*args)
+    return call
+            
+# -----------------------------------------------
+
+class TestDecorators(unittest.TestCase):
+
+    def test_single(self):
+        class C(object):
+            @staticmethod
+            def foo(): return 42
+        self.assertEqual(C.foo(), 42)
+        self.assertEqual(C().foo(), 42)
+
+    def test_dotted(self):
+        decorators = MiscDecorators()
+        @decorators.author('Cleese')
+        def foo(): return 42
+        self.assertEqual(foo(), 42)
+        self.assertEqual(foo.author, 'Cleese')
+
+    def test_argforms(self):
+        # A few tests of argument passing, as we use restricted form
+        # of expressions for decorators.
+        
+        def noteargs(*args, **kwds):
+            def decorate(func):
+                setattr(func, 'dbval', (args, kwds))
+                return func
+            return decorate
+
+        args = ( 'Now', 'is', 'the', 'time' )
+        kwds = dict(one=1, two=2)
+        @noteargs(*args, **kwds)
+        def f1(): return 42
+        self.assertEqual(f1(), 42)
+        self.assertEqual(f1.dbval, (args, kwds))
+
+        @noteargs('terry', 'gilliam', eric='idle', john='cleese')
+        def f2(): return 84
+        self.assertEqual(f2(), 84)
+        self.assertEqual(f2.dbval, (('terry', 'gilliam'),
+                                     dict(eric='idle', john='cleese')))
+
+        @noteargs(1, 2,)
+        def f3(): pass
+        self.assertEqual(f3.dbval, ((1, 2), {}))
+
+    def test_dbcheck(self):
+        @dbcheck('args[1] is not None')
+        def f(a, b):
+            return a + b
+        self.assertEqual(f(1, 2), 3)
+        self.assertRaises(DbcheckError, f, 1, None)
+
+    def test_memoize(self):
+        # XXX: This doesn't work unless memoize is the last decorator -
+        #      see the comment in countcalls.
+        counts = {}
+        @countcalls(counts) @memoize 
+        def double(x):
+            return x * 2
+
+        self.assertEqual(counts, dict(double=0))
+
+        # Only the first call with a given argument bumps the call count:
+        #
+        self.assertEqual(double(2), 4)
+        self.assertEqual(counts['double'], 1)
+        self.assertEqual(double(2), 4)
+        self.assertEqual(counts['double'], 1)
+        self.assertEqual(double(3), 6)
+        self.assertEqual(counts['double'], 2)
+
+        # Unhashable arguments do not get memoized:
+        #
+        self.assertEqual(double([10]), [10, 10])
+        self.assertEqual(counts['double'], 3)
+        self.assertEqual(double([10]), [10, 10])
+        self.assertEqual(counts['double'], 4)
+
+    def test_errors(self):
+        # Test syntax restrictions - these are all compile-time errors:
+        #
+        for expr in [ "1+2", "x[3]", "(1, 2)" ]:
+            # Sanity check: is expr is a valid expression by itself?
+            compile(expr, "testexpr", "exec")
+            
+            codestr = "@%s\ndef f(): pass" % expr
+            self.assertRaises(SyntaxError, compile, codestr, "test", "exec")
+
+        # Test runtime errors
+
+        def unimp(func):
+            raise NotImplementedError
+        context = dict(nullval=None, unimp=unimp)
+        
+        for expr, exc in [ ("undef", NameError),
+                           ("nullval", TypeError),
+                           ("nullval.attr", AttributeError),
+                           ("unimp", NotImplementedError)]:
+            codestr = "@%s\ndef f(): pass\nassert f() is None" % expr
+            code = compile(codestr, "test", "exec")
+            self.assertRaises(exc, eval, code, context)
+
+    def test_double(self):
+        class C(object):
+            @funcattrs(abc=1, xyz="haha")
+            @funcattrs(booh=42)
+            def foo(self): return 42
+        self.assertEqual(C().foo(), 42)
+        self.assertEqual(C.foo.abc, 1)
+        self.assertEqual(C.foo.xyz, "haha")
+        self.assertEqual(C.foo.booh, 42)
+
+    def test_order(self):
+        class C(object):
+            @funcattrs(abc=1) @staticmethod
+            def foo(): return 42
+        # This wouldn't work if staticmethod was called first
+        self.assertEqual(C.foo(), 42)
+        self.assertEqual(C().foo(), 42)
+
+def test_main():
+    test_support.run_unittest(TestDecorators)
+
+if __name__=="__main__":
+    test_main()
diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py
index 9652f6b..978ce57 100644
--- a/Lib/test/test_parser.py
+++ b/Lib/test/test_parser.py
@@ -15,8 +15,8 @@
         t = st1.totuple()
         try:
             st2 = parser.sequence2st(t)
-        except parser.ParserError:
-            self.fail("could not roundtrip %r" % s)
+        except parser.ParserError, why:
+            self.fail("could not roundtrip %r: %s" % (s, why))
 
         self.assertEquals(t, st2.totuple(),
                           "could not re-generate syntax tree")
@@ -119,6 +119,14 @@
         self.check_suite("def f(a, b, foo=bar, *args, **kw): pass")
         self.check_suite("def f(a, b, foo=bar, **kw): pass")
 
+        self.check_suite("@staticmethod\n"
+                         "def f(): pass")
+        self.check_suite("@staticmethod\n"
+                         "@funcattrs(x, y)\n"
+                         "def f(): pass")
+        self.check_suite("@funcattrs()\n"
+                         "def f(): pass")
+
     def test_import_from_statement(self):
         self.check_suite("from sys.path import *")
         self.check_suite("from sys.path import dirname")
diff --git a/Lib/test/test_pyclbr.py b/Lib/test/test_pyclbr.py
index 48e8bf7..eddd593 100644
--- a/Lib/test/test_pyclbr.py
+++ b/Lib/test/test_pyclbr.py
@@ -8,6 +8,9 @@
 import pyclbr
 from unittest import TestCase
 
+StaticMethodType = type(staticmethod(lambda: None))
+ClassMethodType = type(classmethod(lambda c: None))
+
 # This next line triggers an error on old versions of pyclbr.
 
 from commands import getstatus
@@ -43,11 +46,10 @@
             print >>sys.stderr, "***",key
         self.failUnless(obj.has_key(key))
 
-    def assertEquals(self, a, b, ignore=None):
+    def assertEqualsOrIgnored(self, a, b, ignore):
         ''' succeed iff a == b or a in ignore or b in ignore '''
-        if (ignore == None) or (a in ignore) or (b in ignore): return
-
-        unittest.TestCase.assertEquals(self, a, b)
+        if a not in ignore and b not in ignore:
+            self.assertEquals(a, b)
 
     def checkModule(self, moduleName, module=None, ignore=()):
         ''' succeed iff pyclbr.readmodule_ex(modulename) corresponds
@@ -62,11 +64,22 @@
 
         dict = pyclbr.readmodule_ex(moduleName)
 
-        def ismethod(obj, name):
-            if not  isinstance(obj, MethodType):
-                return False
-            if obj.im_self is not None:
-                return False
+        def ismethod(oclass, obj, name):
+            classdict = oclass.__dict__
+            if isinstance(obj, FunctionType):
+                if not isinstance(classdict[name], StaticMethodType):
+                    return False
+            else:
+                if not  isinstance(obj, MethodType):
+                    return False
+                if obj.im_self is not None:
+                    if (not isinstance(classdict[name], ClassMethodType) or
+                        obj.im_self is not oclass):
+                        return False
+                else:
+                    if not isinstance(classdict[name], FunctionType):
+                        return False
+
             objname = obj.__name__
             if objname.startswith("__") and not objname.endswith("__"):
                 objname = "_%s%s" % (obj.im_class.__name__, objname)
@@ -81,7 +94,7 @@
             if isinstance(value, pyclbr.Function):
                 self.assertEquals(type(py_item), FunctionType)
             else:
-                self.assertEquals(type(py_item), ClassType)
+                self.failUnless(isinstance(py_item, (ClassType, type)))
                 real_bases = [base.__name__ for base in py_item.__bases__]
                 pyclbr_bases = [ getattr(base, 'name', base)
                                  for base in value.super ]
@@ -94,7 +107,7 @@
 
                 actualMethods = []
                 for m in py_item.__dict__.keys():
-                    if ismethod(getattr(py_item, m), m):
+                    if ismethod(py_item, getattr(py_item, m), m):
                         actualMethods.append(m)
                 foundMethods = []
                 for m in value.methods.keys():
@@ -107,7 +120,8 @@
                     self.assertListEq(foundMethods, actualMethods, ignore)
                     self.assertEquals(py_item.__module__, value.module)
 
-                    self.assertEquals(py_item.__name__, value.name, ignore)
+                    self.assertEqualsOrIgnored(py_item.__name__, value.name,
+                                               ignore)
                     # can't check file or lineno
                 except:
                     print >>sys.stderr, "class=%s" % py_item
@@ -132,6 +146,12 @@
         self.checkModule('rfc822')
         self.checkModule('difflib')
 
+    def test_decorators(self):
+        # XXX: See comment in pyclbr_input.py for a test that would fail
+        #      if it were not commented out.
+        #
+        self.checkModule('test.pyclbr_input')
+        
     def test_others(self):
         cm = self.checkModule
 
diff --git a/Lib/test/tokenize_tests.txt b/Lib/test/tokenize_tests.txt
index e990a36..4ef3bf1 100644
--- a/Lib/test/tokenize_tests.txt
+++ b/Lib/test/tokenize_tests.txt
@@ -173,3 +173,6 @@
 import sys, time
 x = sys.modules['time'].time()
 
+@staticmethod
+def foo(): pass
+
diff --git a/Lib/token.py b/Lib/token.py
index f75412c..c4db6c5 100755
--- a/Lib/token.py
+++ b/Lib/token.py
@@ -60,9 +60,10 @@
 DOUBLESTAREQUAL = 47
 DOUBLESLASH = 48
 DOUBLESLASHEQUAL = 49
-OP = 50
-ERRORTOKEN = 51
-N_TOKENS = 52
+AT = 50
+OP = 51
+ERRORTOKEN = 52
+N_TOKENS = 53
 NT_OFFSET = 256
 #--end constants--
 
diff --git a/Lib/tokenize.py b/Lib/tokenize.py
index 7e6fa12..9087e84 100644
--- a/Lib/tokenize.py
+++ b/Lib/tokenize.py
@@ -83,7 +83,7 @@
                  r"~")
 
 Bracket = '[][(){}]'
-Special = group(r'\r?\n', r'[:;.,`]')
+Special = group(r'\r?\n', r'[:;.,`@]')
 Funny = group(Operator, Bracket, Special)
 
 PlainToken = group(Number, Funny, String, Name)