module parser_nodes
import location
+import ordered_tree
# Root of the AST class-hierarchy
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
# Visit all nodes in order.
# Thus, call `v.enter_visit(e)` for each child `e`
fun visit_all(v: Visitor) is abstract
+
+ # Do a deep search and return an array of tokens that match a given text
+ fun collect_tokens_by_text(text: String): Array[Token]
+ do
+ var v = new CollectTokensByTextVisitor(text)
+ v.enter_visit(self)
+ return v.result
+ end
+
+ # Do a deep search and return an array of node that are annotated
+ # The attached node can be retrieved by two invocations of parent
+ fun collect_annotations_by_name(name: String): Array[AAnnotation]
+ do
+ var v = new CollectAnnotationsByNameVisitor(name)
+ v.enter_visit(self)
+ return v.result
+ end
+end
+
+private class CollectTokensByTextVisitor
+ super Visitor
+ var text: String
+ var result = new Array[Token]
+ redef fun visit(node)
+ do
+ node.visit_all(self)
+ if node isa Token and node.text == text then result.add(node)
+ end
+end
+
+private class CollectAnnotationsByNameVisitor
+ super Visitor
+ var name: String
+ var result = new Array[AAnnotation]
+ redef fun visit(node)
+ do
+ node.visit_all(self)
+ if node isa AAnnotation and node.n_atid.n_id.text == name then result.add(node)
+ 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
# All the annotations attached directly to the node
var n_annotations: nullable AAnnotations = null is writable
+ # Return all its annotations of a given name in the order of their declaration
+ # Retun an empty array if no such an annotation.
+ fun get_annotations(name: String): Array[AAnnotation]
+ do
+ var res = new Array[AAnnotation]
+ var nas = n_annotations
+ 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
+
redef fun replace_with(n: ANode)
do
super
# The extern block code
var n_extern_code_block: nullable AExternCodeBlock = null is writable
- # The list of super-classes
- var n_superclasses = new ANodes[ASuperclass](self)
-
# The `end` keyword
var n_kwend: TKwend is writable, noinit
+ fun n_superclasses: Array[ASuperPropdef] do
+ return [for d in n_propdefs do if d isa ASuperPropdef then d]
+ end
+
redef fun hot_location do return n_id.location
end
var n_type: nullable AType = null is writable
end
-# A super-class. eg `super X`
-class ASuperclass
- super Prod
-
- # The super keyword
- var n_kwsuper: TKwsuper is writable, noinit
-
- # The super-class (indicated as a type)
- var n_type: AType is writable, noinit
-end
-
# The definition of a property
abstract class APropdef
super ADefinition
super AMethPropdef
end
+class AAnnotPropdef
+ super APropdef
+ super AAnnotation
+end
+
+# A super-class. eg `super X`
+class ASuperPropdef
+ super APropdef
+
+ # The super keyword
+ var n_kwsuper: TKwsuper is writable, noinit
+
+ # The super-class (indicated as a type)
+ var n_type: AType is writable, noinit
+end
+
+
# Declaration of callbacks for extern methods
class AExternCalls
super Prod
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
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
# The closing parenthesis
var n_cpar: nullable TCpar = null is writable
+
+ # The name of the annotation
+ fun name: String
+ do
+ return n_atid.n_id.text
+ end
end
# An annotation name