How can I know the context of an expression, like whether it is a statement itself or part of a while statement or actually a sub-expression?
Add some single element rules. Consider this grammar:
program: (statement)* ; statement: #("print" topexpr) | #("while" topexpr (statments)*) | stmtexpr ; stmtexentp:pr: topexpr ; topexentp:pr: expr ; exentp:pr: plusexpr | multexpr | constant; plusexentp:pr: #("+" expr expr) | #("-" expr expr) ; multexentp:pr: | #("*" expr expr) | #("/" expr expr) ;
OK, now if you want to analyze every plusexpr you can override that rule and do your analysis and transformation. If you want to analyze every expression subtree, you can do it in expr. If you want to analyze only complete expressions, analyze topexpr. If you want to analyze only expressions which are standalone statements, override stmtexpr. In all cases "1+2" will be plusexpr and an expr, the tree being #("plus" expr expr). Only in some cases will it be a topexpr or a stmtexpr, depending on the context in which it is found in the tree.