# TO-DO: GET RID OF GLOBAL STATE
Yep. You seem to already understand this one. Having a reset betrays a place in your design that would be well-suited to an object that can be thrown away and re-constructed, which is usually a more useful model than existing state that can be reset.
# parse_resp is the main function ...
Your speed-up claim:
avoid loading the whole file at once, instead parsing a file line by line, which seems to be 2x as fast according to testing
seems highly unlikely, and I would like to see proof of this. A compiled-and-tuned built-in JSON parser that operates on an in-memory buffer is nearly certain to outperform a non-compiled, non-built-in, line-by-...
If you have a regular pattern that describes what you want to do with a string, using a regular expression (regex) is usually a good idea. In addition to using re.split, as shown in another answer by @python_user, you can also use re.findall, which has the advantage that you don't have to manually deal with the opening and closing delimiters:
A Regex based solution
>>> re.split(r"\[([A-Z])\]", my_string_one)[1:-1:2]
['A', 'B', 'C']
>>> re.split(r"\[([A-Z])\]", my_string_two)[1:-1:2]
['A', 'B', 'C', 'D', 'E']
You can use re.split with the expression \[([A-Z])\ having a capture ...
Thank you for the code alternative.
I like many of the changes you did: The non-quadratic tokenizer, of course, as well as the use of a stack of the minimum size needed, and the is_number check.
I am less fond of the allocation of a temporary array to the possible maximum number of tokens, though, even if the data in the unused elements is not allocated. As ...
Things to improve in the current solution:
It is always better to use an integer, parameter for the desired kinds of types. You can still set integer, parameter :: wp = kind(1.d0) to achieve the same result as currently, but you can change it in one place, if you want to.
Some reused functionality should be encapsulated into functions. (For example the ...