Custom Grammars

our $SYMBOLS  = [
    # variable sigils and other high precedence operators
    [ '$'  => sig_item =>   0, 350 ],      # $foo
    [ '@'  => sig_list =>   0, 350 ],      # @foo
    [ '%'  => sig_hash =>   0, 350 ],      # %foo
    [ '.'  => op_dot   => 340,   0 ],      # foo.bar

    # ++/-- unary prefix/postfix self-modification operators
    [ '++' => num_inc  => 295, 295 ],      # foo++, ++foo
    [ '--' => num_dec  => 295, 295 ],      # foo--, --foo
    .
    .
    .
    [ for => cmd_for   => 100, 100 ],
    [ if  => cmd_if    => 100, 100 ],
];
Thus Spake Andy:

A grammar is, at the simplest level, a collection of operators. The code above is an extract from the default TT3 grammar. Each entry defines the operator token, an identifier mapping it to an element module (e.g. sig_item is mapped to Template::TT3::Element::Sigil::Item) and leftward/rightward precedence levels (leftward for postfix/infix operators binding to items on their left, rightward for prefix operators bind to items on their right - some operators are both). Note also that for, if and other command keywords are also operators. Everything is an operator. Everything is driven by operator precedence.

Creating your own language/dialect with a different set of operators is (almost) as simple as defining a symbol table using a package variable. It's essentially the same thing that we did when we wanted to define a new tagset. Just define some package variables and let the base class make sense of your declaration.

So to cut a long story short, if you don't think a template language should have an assignment operator then you can easily implement your own dialect that does away with it (along with any other that can cause side-effects). How useful that would be in practice remains to be seen... but it's now possible.