>>2377
>I don't get it
I don't have stdio.h for this particular project, so what ended up happening is a lot of functions like this:
static int _discardwhitespace(STREAM *source)
{
int err; /* Error(s)? */
CHECKSTREAM(source, IO_MODE_IN);
err = 0;
do {
ITERATE_STREAM(source) {
if( source->next[0] > 32 )
goto END;
}
err = flushstream(source);
} while( !err );
END:
return err;
}
This is fine for simple things, but when it came to parsing string literals, I needed something that didn't involve
copy-pasting all that boilerplate all over the place; by abusing goto I was able to have all of the rules share the same boilerplate.
>I'm not sure thats a trampoline either
>https://en.wikipedia.org/wiki/Tail_call#Through_trampolining
>All functions are entered via the trampoline. When a function has to call another, instead of calling it directly it returns the address of the function to be called, the arguments to be used, and so on, to the trampoline. This ensures that the C stack does not grow and iteration can continue indefinitely.
Which is basically what I've done here.
For example, when the "scan" rule encounters a backslash in the string literal, it copies anything it's already read to the buffer, then:
mode = PLMODE_ESCAPE;
goto READ_AND_DISPATCH;
The "dispatch" rule reads some more data from the stream, then locates the "escape" rule and jumps to it.
That rule then handles [whatever escape sequence], and passes the continuation back to the "scan" rule.