|
I wrote a recursive descent solution for project 10, but I didn't feel fully confident that it recognised the Jack grammar correctly, so I chose to write my answer to project 11 using a Yacc-like tool called Yapp. Here are some tips for a Yacc-style solution to project 11.
To get ()s working properly:
expression: term
| expression op term
not
expression: term
| term op expression
There are only 3 scopes: a static scope for the class which holds only static variables, a class scope which holds only the field variables, and a current scope which holds the locals and arguments for the current function/method/constructor. I had originally written a stack of scopes, and then had to remove it once I realised that I didn't need it.
Methods have an implicit 0th argument which is a pointer to the object in question. Make sure that you pass it to the method and record that there is an extra argument in its scope.
If using a Yacc-like tool, most of the code can be done in shift operations, not just at the end of each rule in the reduce operations.
Each function/method/constructor needs to know the # of locals before the 'function' line is printed out. Wait until the subroutine body to print it.
'if' and 'while's can be nested. You need to create unique labels for these in each function (i.e. successive functions can restart at 0), but when you enter an 'if' or 'while', make sure to keep using that one's specific label; don't just increment each time you hit a new one. The 'else' is optional. The labels you print out depend on knowing if the 'else' is there or not.
|