Raku Books / Creating a Compiler in Raku / Arrays and Hashes

Off-topic: The joy of syntax

Before going on with more features for arrays and hashes, let us transform the grammar a bit. In the assignment method, the if-else check occupies more lines than the “useful” code. We can do two things to make the methods more compact.

First, let us repeat the trick with splitting a rule into two. Instead of one universal assignment rule, we can have two subrules:

rule assignment {
    | <array-item-assignment>
    | <scalar-assignment>
}

rule array-item-assignment {
    <variable-name> [ '[' <integer> ']' ] '=' <value>
}

rule scalar-assignment {
    <variable-name> '=' <value>
}

It made the grammar more verbose, but the action became more compact:

method array-item-assignment($/) {
    %!var{~$<variable-name>}[+$<integer>] = $<value>.made;
}

method scalar-assignment($/) {
    %!var{~$<variable-name>} = $<value>.made;
}

The second possible solution is to keep the original assignment rule and use the where clause in method’s signatures and dispatch the calls depending of the content of the match object.

multi method assignment($/ where $<integer>) {
    %!var{~$<variable-name>}[+$<integer>] = $<value>.made;
}

multi method assignment($/ where !$<integer>) {
    %!var{~$<variable-name>} = $<value>.made;
}

The negative condition in the signature of the second variant of the multi-method is optional, but I’d advise to keep it for clarity of the code.

There are two more actions that can be re-written in the same manner. The value action:

multi method value($/ where $<expression>) {
    $/.make($<expression>.made);
}

multi method value($/ where $<string>) {
    $/.make($<string>.made);
}

The second action with a big if-elsif-else condition is expr:

multi method expr($/ where $<number>) {
    $/.make($<number>.made);
}

multi method expr($/ where $<string>) {
    $/.make($<string>.made);
}

multi method expr($/ where $<variable-name> && $<integer>) {
    $/.make(%!var{$<variable-name>}.substr(+$<integer>, 1));
}

multi method expr($/ where $<variable-name> && !$<integer>) {
    $/.make(%!var{$<variable-name>});
}

multi method expr($/ where $<expr>) {
    $/.make(process($<expr>, $<op>));
}

multi method expr($/ where $<expression>) {
    $/.make($<expression>.made);
}

These methods look trivial now. Notice that some of the candidates check more than one key in the match object.

Course navigation

Assigning to an array item   |   Accessing array elements