My problem occurs at the check identifier because I don't know ahead of time whether it is a varName, subroutineName, or className, so if I check if it exists in the Symbol Table and it tells me no, then I can't tell if it's a varName that's undeclared or if it's a class/subName.
Since you are writing a one-pass compiler, there is no way to know what external class names will be available when the VM translator combines all the VM files generated by the Jack sources in the current directory.
Since all fields and variables must be defined in Jack before they are used, any undefined symbol you encounter at this point is either a class/subroutine name or an error that the compiler cannot detect
. The compiler must assume that the symbol is a class/subroutine name and generate VM code for the call.
If the symbol is not a valid external name, the VM translator will generate ASM code that references the bad name. The VM Emulator will catch this error, but the assembler will assign a RAM address to the bogus symbol, which will result in a program bug or crash.
To properly report this error your compiler would need to scan all the other Jack files in the current directory and include their classes and functions/methods in the symbol table, and it would need to know about the OS classes and functions/methods.