4 ms·
Because of msgs that are larger than I want to allocate. Explicit state machines forces one to think thru the problem. And it forces the solution to be one pass
by lanstin 2y ago
Because of msgs that are larger than I want to allocate. Explicit state machines forces one to think thru the problem. And it forces the solution to be one pass over the input data. I almost never am forced to use Java so unsure about that reference.
- IshKebab 2y agoPull parsers can deal with arbitrarily large messages too. And they also do one pass over the input data. Yeah if you're unfamiliar, SAX is like this (pseudocode): interface SAXCallbacks { void onBeginToken(string name); void onAttribute(string key, string val); void onText(string text); void onEndToken(string name); } void parse(Reader input, SAXCallbacks yourCallbackImplementations); Whereas pull parsers are like this: enum Token { Begin(string name), Attribute(string key, string val), Text(string text), End(string name), } class PullParser { void open(Reader input); Token next(); } They are much easier to use because you can trivially write a recursive descent parser: void parseThing(parser) { let token = parser.next(); if (token == Begin("foo")) { parseFoo(parser); } else if ... Whereas with SAX you're going to end up with some monstrous hand-coded state machine like class ThingParser { enum State { ParsingThing, ParsingFoo, ParsingFooExpectingAttributes, ParsingFooExpectingEndTag, ... So painful. Honestly it's so obviously the right way to do tokenisation and parsing that I have yet to see another language that even has names for them. They all just use pull parsers. Nobody else does callback-based parsing like SAX because it's obviously ridiculous.