$ // This file is part of NIT ( http://www.nitlanguage.org ). $ // $ // Copyright 2008 Jean Privat $ // Based on algorithms developped for ( http://www.sablecc.org/ ). $ // $ // Licensed under the Apache License, Version 2.0 (the "License"); $ // you may not use this file except in compliance with the License. $ // You may obtain a copy of the License at $ // $ // http://www.apache.org/licenses/LICENSE-2.0 $ // $ // Unless required by applicable law or agreed to in writing, software $ // distributed under the License is distributed on an "AS IS" BASIS, $ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. $ // See the License for the specific language governing permissions and $ // limitations under the License. $ template make_abs_nodes() # Root of the AST hierarchy abstract class PNode readable var _location: nullable Location end # Ancestor of all tokens abstract class Token special PNode end # Ancestor of all productions abstract class Prod special PNode fun location=(loc: nullable Location) do _location = loc end $ end template $ template make_nodes() redef class PNode # Parent of the node in the AST readable writable var _parent: nullable PNode # Remove a child from the AST fun remove_child(child: PNode) do replace_child(child, null) end # Replace a child with an other node in the AST fun replace_child(old_child: PNode, new_child: nullable PNode) is abstract # Replace itself with an other node in the AST fun replace_with(node: PNode) do if (_parent != null) then _parent.replace_child(self, node) end end # Visit all nodes in order. # Thus, call "v.visit(e)" for each node e fun visit_all(v: Visitor) is abstract # Visit all nodes in reverse order. # Thus, call "v.visit(e)" for each node e starting from the last child fun visit_all_reverse(v: Visitor) is abstract # Debug method: output a message prefixed with the location. fun printl(str: String) do if location == null then print("???: {str}\n") else print("{location}: {str}\n") end end end redef class Token redef fun visit_all(v: Visitor) do end redef fun visit_all_reverse(v: Visitor) do end redef fun replace_child(old_child: PNode, new_child: nullable PNode) do end end redef class Prod # The first token of the production node readable writable var _first_token: nullable Token # The last token of the production node readable writable var _last_token: nullable Token redef fun replace_with(n: PNode) do super assert n isa Prod n.first_token = first_token n.last_token = last_token n.location = location end end # Abstract standard visitor class Visitor # What the visitor do when a node is visited # Concrete visitors should redefine this method. protected fun visit(e: nullable PNode) is abstract # Ask the visitor to visit a given node. # Usually automatically called by visit_all* methods. # This methos should not be redefined fun enter_visit(e: nullable PNode) do var old = _current_node _current_node = e visit(e) _current_node = old end # The current visited node readable var _current_node: nullable PNode = null end $ end template