In a Recursive Descent compiler, the parsing and compiling functions are one and the same. That is why the parsing routines recommended in chapter 10 are named "CompileEtc".
Here's pseudocode for my CompileExpression():
void CompileExpression() {
/*
Compiles <expression> := <term> (<op> <term>)*
ENTRY: Tokenizer positioned on the start of the expression.
EXIT: Tokenizer positioned after the expression.
*/
// Parse and compile the first <term>.
CompileTerm()
while current token is an <op> {
// Save the operator for code generation.
operator = token.symbol
token.next()
// Parse and compile the next <term>.
CompileTerm()
// Generate code for <op>.
switch (operator) {
case '+':
vmWriter.WriteArithmetic(OP_ADD)
case '-':
vmWriter.WriteArithmetic(OP_SUB)
// more code writers...
}
}
This code results in simple left-to-right operator precedence. If you want to compile standard precedence, you need to redefine <expression> syntax to reflect the desired precedence and write appropriate CompileSum(), CompileProduct(), etc. functions. See
this post.
--Mark