Raku Books / Creating a Compiler in Raku / Building AST

Value nodes

Consider a bit bigger program:

my c = 2 + 3;

Here, we are expecting that the compiler will generate the code to add two numbers. We are not considering any optimisations at this point, so we have to generate the AST nodes for every arithmetical operation. Comparing with the last AST tree, we can see that the value attribute of the AST::ScalarDeclaration node should not be a number but some other kind of the node that represents addition. To keep the design simple, it is wise to introduce AST nodes whose only work is to keep values, either integers, or floating point, or strings.

class AST::NumberValue is ASTNode {
    has $.value;
}

If there is no value (as in a minimal variable declaration without initialiser), we can assign either 0 or an empty string, but the better solution is to define the null value and its wrapper AST node:

class AST::Null is ASTNode {
}

The AST::ScalarDeclaration node must now point to an AST node, so let us restrict the type of its value attribute:

class AST::ScalarDeclaration is ASTNode {
    has Str $.variable-name;    
    has ASTNode $.value;
}

We are adding two more AST nodes to the tree, as shown in the diagram below.

diagram

The value node must be generated by the number action of the grammar:

method number($/) {
    $/.make(AST::NumberValue.new(value => +$/));
}

This node is taken as is in the scalar-declaration method, but if there is no value, then an AST::Null node is created:

method scalar-declaration($/) {
    $/.make(AST::ScalarDeclaration.new(
        variable-name => ~$<variable-name>,
        value => $<value> ?? 
                 $<value>.made !!
                 AST::Null.new(),
    ));
}

Extend the program with another variable declaration:

my c = b;

This time, we’ve got a variable instead of a value. But as soon as the type of the $.value attribute in AST::ScalarDeclaration is ASTNode, we can make a new class, AST::Variable, and save an instance of it. The AST::Variable object has a string attribute $.variable-name.

class AST::Variable is ASTNode {
    has Str $.variable-name;
}

Integrating the new node type is easy, as most of our action methods have descriptive signatures:

multi method expr($/ where $<variable-name> && !$<index>) {
    $/.make(AST::Variable.new(
        variable-name => ~$<variable-name>));
}

Here is the resulting AST tree:

diagram

This tree corresponds to the following program:

my a;
my b = 2;
my c = b;

Course navigation

The AST blocks   |   Declaring strings