Merge: new `with` statement
[nit.git] / src / parser / parser_nodes.nit
index 93a26e2..95c83bc 100644 (file)
@@ -17,6 +17,7 @@
 module parser_nodes
 
 import location
+import ordered_tree
 
 # Root of the AST class-hierarchy
 abstract class ANode
@@ -33,6 +34,15 @@ abstract class ANode
                sys.stderr.write "{hot_location} {self.class_name}: {message}\n{hot_location.colored_line("0;32")}\n"
        end
 
+       # Write the subtree on stdout.
+       # See `ASTDump`
+       fun dump_tree
+       do
+               var d = new ASTDump
+               d.enter_visit(self)
+               d.write_to(sys.stdout)
+       end
+
        # Parent of the node in the AST
        var parent: nullable ANode = null
 
@@ -158,6 +168,33 @@ private class CollectAnnotationsByNameVisitor
        end
 end
 
+# A helper class to handle (print) Nit AST as an OrderedTree
+class ASTDump
+       super Visitor
+       super OrderedTree[ANode]
+
+       # Reference to the last parent in the Ordered Tree
+       # Is used to handle the initial node parent and workaround possible inconsistent `ANode::parent`
+       private var last_parent: nullable ANode = null
+
+       redef fun visit(n)
+       do
+               var p = last_parent
+               add(p, n)
+               last_parent = n
+               n.visit_all(self)
+               last_parent = p
+       end
+
+       redef fun display(n)
+       do
+               if n isa Token then
+                       return "{n.class_name} \"{n.text.escape_to_c}\" @{n.location}"
+               else
+                       return "{n.class_name} @{n.location}"
+               end
+       end
+end
 
 # A sequence of nodes
 # It is a specific class (instead of using a Array) to track the parent/child relation when nodes are added or removed
@@ -315,11 +352,17 @@ abstract class Prod
        do
                var res = new Array[AAnnotation]
                var nas = n_annotations
-               if nas == null then return res
-               for na in nas.n_items do
+               if nas != null then for na in nas.n_items do
                        if na.name != name then continue
                        res.add(na)
                end
+               if self isa AClassdef then for na in n_propdefs do
+                       if na isa AAnnotPropdef then
+                               if na.name != name then continue
+                               res.add na
+                       end
+               end
+
                return res
        end
 
@@ -618,6 +661,11 @@ class TKwlabel
        super TokenKeyword
 end
 
+# The keyword `with`
+class TKwwith
+       super TokenKeyword
+end
+
 # The special keyword `__DEBUG__`
 class TKwdebug
        super Token
@@ -1190,6 +1238,11 @@ class AMainMethPropdef
        super AMethPropdef
 end
 
+class AAnnotPropdef
+       super APropdef
+       super AAnnotation
+end
+
 # A super-class. eg `super X`
 class ASuperPropdef
        super APropdef
@@ -1550,7 +1603,7 @@ class ALabel
        var n_kwlabel: TKwlabel is writable, noinit
 
        # The name of the label, if any
-       var n_id: nullable TId is writable
+       var n_id: nullable TId is writable, noinit
 end
 
 # Expression and statements
@@ -1577,7 +1630,7 @@ class AVardeclExpr
        super AExpr
 
        # The `var` keyword
-       var n_kwvar: TKwvar is writable, noinit
+       var n_kwvar: nullable TKwvar = null is writable
 
        # The name of the local variable
        var n_id: TId is writable, noinit
@@ -1747,6 +1800,24 @@ class AForExpr
        var n_block: nullable AExpr = null is writable
 end
 
+# A `with` statement
+class AWithExpr
+       super AExpr
+       super ALabelable
+
+       # The `with` keyword
+       var n_kwwith: TKwwith is writable, noinit
+
+       # The expression used to get the value to control
+       var n_expr: AExpr is writable, noinit
+
+       # The `do` keyword
+       var n_kwdo: TKwdo is writable, noinit
+
+       # The body of the loop
+       var n_block: nullable AExpr = null is writable
+end
+
 # An `assert` statement
 class AAssertExpr
        super AExpr
@@ -2174,7 +2245,7 @@ class ASelfExpr
        super AExpr
 
        # The `self` keyword
-       var n_kwself: nullable TKwself is writable
+       var n_kwself: nullable TKwself = null is writable
 end
 
 # When there is no explicit receiver, `self` is implicit