In my grammar, variables start with the $, so
$a = 10
is valid. Of course, so is the following statement:
$c = $a + $b
My grammar treats variables with this (partial) definition;
start: (expr | stmt)* EOF ;
stmt
: lvalue=id EQUAL assignexpr=expr # AssignId
| declare EQUAL assignexpr=expr #DeclareAndAssign
| declare # DeclareVar
;
expr
: sign=(PLUS|MINUS) expr # signed_expr
| LPAREN expr RPAREN # paren_exp
| id # idval
| value #constval
| lvalue=expr op=(PLUS | MINUS | MULT |DIV) rvalue=expr # arith
;
Up until now, when I encounter a constant value in my listener, I simply issue an ICONST (assuming it's an integer) which pushes the value to the stack. When I get to a variable, I issue an ILOAD to grab the variable value and push it to the stack - which is fine as long as it's on the right side of a statement.
The problem I have is: when the variable is on the left side .. I need to not issue an ILOAD because the value is going to be overwritten and not popped from the stack at any point. So upon reaching this variable in code, I need a way of knowing how it's going to be used.
How can I know how to treat this variable $c? Do I need to change my grammar to more specifically treat this case? Do I need to walk the tree twice? How do people usually treat what must be a trivial, common case?
As you clarified in your comment, you're listening for id
s, which is used by both assignments and variable expressions. If you listen for idval
s instead, you'll only get variables that are used as expressions / rvalues.
You can handle variables as lvalues directly in the listener for AssignId
.