- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Description
There are some crates which do something like this (e.g. string_cache_codegen):
macro_rules! foo {
    ("a") => (A);
    ("b") => (B);
    ("c") => (C);
    // ... etc. (maybe hundreds more)
}(@nnethercote came across this when profiling html5ever's compilation)
Also, prefixing patterns with @foo to create "internal rules" is common.
But the current implementation (AFAICT) has to check each of the patterns in turn.
Instead, we could build something like a decision tree ahead of time, from the constant (i.e. $-less) prefix of all arms, using maps for operators/idents/literals, to make the pattern-matching of the prefix amortize to being linear in the number of input tokens.
We could keep it simple by limiting the constant prefix to leaf tokens (no (...), [...] or {...}).
For the example above, we'd pre-compute something like this:
DecisionTree::Match {
    op: {},
    ident: {},
    literal: {
        "a": DecisionTree::Done([0]),
        "b": DecisionTree::Done([1]),
        "c": DecisionTree::Done([2]),
        // ...
    },
}Whereas for something using @foo rules it could be:
DecisionTree::Match {
    op: {
        '@': DecisionTree::Match {
            op: {},
            ident: {
                "foo": DecisionTree::Done([0, 1]),
                "bar": DecisionTree::Done([2, 3, 4]),
                "baz": DecisionTree::Done([5]),
            },
            literal: {},
        }
    },
    ident: {},
    literal: {},
}(where DecisionTree::Done indicates the arms to continue with)
cc @rust-lang/compiler (this might need a design meeting?)