<program> |    ::=    | <statement> |
<statement> |    ::=    | <identifier> = < expression> |
   |    | print <expression> | |
   |    | {{<statement>}*(;) } | |
   |    | if <expression> < statement> <statement> | |
   |    | while <expression> do <statement> | |
   |    | var {<identifier> = <expression> }*(,) ; <statement> | |
   |    | proc <identifier> ( { <identifier> }*(,) ) <statement> | |
   |    | call <identifier> ( { <expression> }*(,) ) | |
<expr> |    ::=    | <number> |
   |    | <symbol> | |
   |    | <boolean> | |
   |    | ( lambda ( {<symbol>}* ) <expr> ) | |
   |    | ( <expression> { <expression>}* ) | |
   |    | ( if <expr> <expr> <expr> ) | |
   |    | ( cond { ( <expr> <expr> ) }* ( else <expr> ) ) | |
   |    | ( let ( { ( <id> <expr> ) }* ) <expr> ) | |
   |    | ( let* ( { ( <id> <expr> ) }* ) <expr> ) | |
   |    | ( letrec ( { ( <id> ( lambda ( { <id> }* ) <expr> ) }* ) <expr> ) | |
   |    | ( set! <identifier> <expression> ) |
With primitive operators add, sub, mul, div, mod, cons, car, cdr, list, empty-list, empty?, equal, lesser, greater, and, or, xor.
You may modify your existing unparse function to work with the new abstract syntax and parse function, but the introduction of syntax outside of the normal Scheme format will make this more difficult. I encourage you to write an unparse function for your own debugging purposes, but this new function will probably need to rely more on the Scheme display primitive wherever it is impractical to return a list structure for concrete syntax.
Add an execute function for executing programs in the new language. Your existing evaluate function will still be useful for all of the expressions in the grammar.
Notes: