Blog

Token and Trie Approaches to Parsing

Regular expression lists dominate user agent parsing, but they are not the only approach. Token-based and tree-based parsers make different trade-offs worth understanding.

Tokenising first separates two problems

A token parser splits the string into products, versions and comment fields according to the format's grammar, then interprets the resulting structure.

This separates structural parsing, which the specification defines, from interpretation, which requires knowledge. Regular expression lists conflate the two in every pattern.

The separation makes failures easier to diagnose. A malformed string fails structurally; an unknown browser fails at interpretation, and the two look different.

Prefix trees exploit shared beginnings

Most strings from a browser family share a long common prefix. A tree keyed on that prefix narrows candidates in a few steps rather than testing patterns sequentially.

Lookup cost becomes proportional to string length rather than to dataset size, which matters when the dataset holds many thousands of rules.

The structure is built once from the rule set, so the cost of construction is paid at load rather than per request.

Speed differences show up at volume

On a single request the difference is negligible. Parsing every line of a large log or every request at an edge makes it significant.

Ordered lists degrade as they grow, because unmatched strings run the full list before failing. Unusual clients are therefore the most expensive to parse.

That is the wrong direction for a system under load, where unusual traffic often arrives in volume.

Flexibility is what the alternatives give up

Regular expressions can match anywhere in a string and capture arbitrary fragments. Prefix structures need the discriminating content near the beginning.

User agent strings frequently place the identifying token last, after inherited compatibility tokens. That works against a naive prefix approach.

Practical implementations therefore combine methods: a fast structural pass, a tree or table lookup where it applies, and patterns for the residue.

Choosing by workload

For a site parsing a request occasionally, a maintained pattern library is the right answer and performance is irrelevant.

For log analysis at scale, a hybrid or tokenising parser saves real resources, and the added implementation cost is amortised across the volume.

The classification data is the harder problem in every design. Structure determines how fast the answer is found, not whether the answer is correct.