Create a Scanner or Tokenizer class, which takes the input data (the text to be parsed) and holds the position of the current token or similar state. It can also provide some shared helper functions. Then provide a reference (or a shared pointer) to the Scanner object to all your individual xyzParser
objects, so they can all access the same scanner. The "scanner" will be only responsible for accessing the data by basic tokenize functions, the individual parsers will be responsible for the actual parsing logic.
This will work most easily as long as your scanner does not need to know which individual parsers exists. If the scanner actually needs to know this, you might consider to resolve the cyclic dependency by introducing abstract "interface" base classes, or by implementing some kind of call back or event mechanism, where the scanner can notify any kind of observers.
It's extremely popular, dominates on mobile devices, is in active development, and supported on all kinds of GPUs. Why?
Well... what's your alternative?
Ignoring Vulkan, if you want to write a cross-platform application for mobile devices, and you want to use hardware 3D, what exactly are you going to use except OpenGL ES?
Nobody has ever claimed (at least recently) that OpenGL is a sensible, well-designed API. But it works; it gets the job done, and there's no more broadly available, cross-platform alternative.
And now for some fact checking:
There is only one "slot" for errors so effectively if you don't check after every function, you will never get to the bottom of it properly, since errors will get lost if there is more than one before checking.
That's false. Errors in OpenGL are queued. Each call to glGetError
returns the error least recently added to the queue. OpenGL errors are not lost in OpenGL.
The problem with not checking for errors reasonably frequently is that, if you don't, then it'll be hard to know which function was responsible for which error.
such as border=0 in glTexImage2D
That exists because textures pre-GL 3.1 could have border texels. But since no consumer-grade hardware supported border texels, they removed it from core OpenGL in 3.1. But you can't just remove a parameter from a function; that would break ABIs all over the place. So they took the path of least resistance: keep the parameter, but required that it be zero.
ES retained it to preserve API compatibility with desktop OpenGL.
In general, pretty much every annoyance of the OpenGL API ultimately comes down to some level of "because backwards compatibility".
Absolutely no checking for any kinds of errors at compile time
OpenGL is a C API. There's not much room in C for compile-time verification of stuff.
Best Answer
While I always favor compact, self-contained functions over huge, sprawling if/else trees, it is true that real-world programs are seldom as nice and neat (untangled) as we would wish. Application state (global or not) is generally unavoidable.
I believe that it is also true that there are diminishing returns to splitting things up into smaller and smaller functions. For a logical extreme, take a look at the book Clean Code by Robert C. Martin. Not everyone will agree with me, but I find many of his examples to actually be slightly less comprehensible after his refactoring. (Maybe I don't write enough Java to appreciate them?)
Having said that, I do personally believe that the function is the most powerful abstraction available to us. Sure, functions can be used incorrectly. There is absolutely nothing stopping you from writing terrible, tangled code with a bunch of tiny functions, even without those evil weapons, the global variables. But on a whole, functions are a force of goodness and light.
When practically possible, heed the standard wisdom of the crowd in creating "clean" functions:
Just these two rules will avoid 90% of the most common design headaches. It also allows you to easily write tests for your functions!
Beyond that, just try your hardest to make only "clean" functions when you can. Depending on the application, this can actually be a very difficult exercise at first. But one does get better at it. As with most things, it's a real craft and it takes experience (programming experience in general and experience with that project, in particular) to get it just right.
Untangled code doesn't just happen. It's hard work and an art...and totally worth it.