Origen-SDK / o2

MIT License
4 stars 0 forks source link

Simplified AST node definition #94

Closed ginty closed 4 years ago

ginty commented 4 years ago

I started writing a STIL parser and when creating the AST for it I quickly realized that the existing way to add new nodes was extremely tedious - the node had to be defined, then a call to its handler and then a default handler for it.

With this update the process of adding a new node is greatly simplified, only the node definition is now required. The processors don't require any significant additional code to support this, but they have to be changed slightly - instead of implementing handler methods for each node type they care about, they should only now define one method (on_node) and then create a match inside that to handle the nodes that they care about.

For example, an existing processor with a handler method like this:

fn on_comment(&mut self, level: u8, msg: &str, node: &Node) -> Return {
    let new_node = node.replace_attrs(Attrs::Comment(level, msg.to_uppercase()));
    Return::Replace(new_node)
}

would be changed to this:

fn on_node(&mut self, node: &Node) -> Return {
    match &node.attrs {
            Attrs::Comment(level, msg) => {
                let new_node = node.replace_attrs(Attrs::Comment(*level, msg.to_uppercase()));
                Return::Replace(new_node)
            }
            // Instructs the processor to walk through the children of all other node types
            _ => Return::ProcessChildren,
        }
    }
}

If the processor wished to handle additional node types then it would simply add additional branches to the match statement.