Why so many patches were required to get ELSE working and why I was not expecting it. I've looked at the internals of other versions of Microsoft BASIC before, so why the surprise? It has to do with the size of the Microcolor BASIC ROM.
The other version of Microsoft BASIC I worked with used a 256 byte jump table and did not require the range check. Any tokens that would be a syntax error simply have the address of the syntax error routine at their location in the table. This is faster because no range check is required before making the table call, but it does require around 60 more bytes than the code using the range check on the token.
Valid keyword tokens are all negative numbers. That means there are up to 128 tokens without using multiple bytes to represent keywords. A jump table filled with the address of every possible function those tokens might represent would require 2 bytes per address, times 128 tokens, for a total of 256 bytes. In 8K, 256 bytes is a lot, and reducing the size of the jump table is an easy way to save space.
Simply group all the valid tokens together starting with the lowest token value, and any token greater than the highest one in the group is a syntax error.
The other version of Microsoft BASIC I worked with used a 256 byte jump table and did not require the range check. Any tokens that would be a syntax error simply have the address of the syntax error routine at their location in the table. This is faster because no range check is required before making the table call, but it does require around 60 more bytes than the code using the range check on the token.
Microsoft made a trade off, they sacrificing a few clock cycles in exchange for a few bytes. Sadly, it creates another problem. In addition to a few clock cycles, it also makes it difficult to add additional commands while maintaining the original tokens. There were two possible solutions to the problem once I encountered it. Either patch the functions performing a range check so they perform an additional check for the ELSE token, or switch to larger table. Given the time and ROM space I had, I chose the first approach. Now that I have time, I may see if I can switch to the table. A full 256 byte table isn't mandatory, but it means the interpreter will crash if an unknown token is encountered.