Let's think about a set of rules for working with integer constants and expressions. We can reduce an INT_LITERAL
node to intConstant
:
intConstant = INT_LITERAL(void): 1
And we can then use that rule to build up a pattern that can accept an intConstant
rewrite of its corresponding child; but suppose we are adding x + 100000
and we can't use a addi
instruction? We need to be able to use the INT_LITERAL
node as an intExpression
. One way to do that would be to define another pattern match rule:
intExpression = INT_LITERAL(void): 2
But this duplication is going to become a maintenance problem very quickly, especially since it'll need to be done for every arithmetic operation that has similar variants.
JBurg provides a facility to continue transforming an already-reduced value, a nonterminal-to-nonterminal transformation. There are two varieties of these transformational rules.
The simple form of a transformational rule allows one nonterminal state to alias another:
generalExpression = intExpression;
This form of transformational rule is also called a chain rule in the literature. As the example suggests, it's useful to group various other forms of rules.
The second form of transformational rule is more powerful. It defines a generalized conversion from one nonterminal state to another:
intExpression = intConstant: 1 // reducer code to implement conversion, e.g., issue li instruction
Wiki: FirstCodeGenerator
Wiki: JBurg Reference
Wiki: JBurg2 Reference
Wiki: JBurg2 Syntax