Missing/misspelled variable name recommendations

This is the equivalent of PR #1776 but for variables instead of keywords. 

I've moved some of the reusable recommendation code from `namespace.py` to `utils/match.py` in a new `FuzzyMatcher` class. Trying to balance code duplication and complexity in this refactoring was tricky, so criticism/ideas are welcome.

There are a lot of special cases for variable naming, including accessing variable indexes, accessing extended variables, and accessing nested variables. I have only partially handled these special cases - recommendations for misspellings of the base variable name will generally work, but anything more complex will not work, and the recommendations will not include the index or extended variable syntax. 

I reworded some of the missing variable error messages, just to make them subjectively sound better. For example, `Non-existing variable '%s'` is now `Variable '%s' not found`. This breaks many tests throughout `atest`, but in this PR I have not fixed those tests yet. I'll fix them if this rewording/rephrasing is approved. 

For example recommendations, please see the new test cases I've added.
Is this needed? Can there actually be cases where same normalized name matches multiple original names?

For some reason I don't really like variable names starting with an underscore. Starting with an underscore typically means somehow private method/attribute, but here `_name` is apparently used to avoid shadowing earlier `name`. I would say that typically it's better to name at least one of the variables otherwise in cases like this. For example, `_name` could be just `var` or `variables`.