Compiles dispatch rules to an Erlang module for quick matching.
The dispatch compiler takes a list of dispatch rules and creates an Erlang module that matches those rules.
The compiled Erlang module exports a single function: match/2
.
Dispatch rules are lists of tokens with some extra information:
{name, ["foo", "bar", id], controller_name, [controller,options]}
The path parts can be one of the following:
- a string
"foo"
. This is translated to a binary and must match literally - an atom
id
this binds the variable to the token and is returned - the atom
'*'
, this binds to any left tokens, which could be an empty list - regular expressions
{id, "^[0-9]+$"}
- regular expressions with re compile options
{id, "^[a-z]+$", [caseless]}
It is also possible to define functions to perform runtime checks on the tokens.
Functions can be defined as:
- A module, function pair:
{var, {foo, bar}}
, this will callfoo:bar(Token, Context)
- A module, function, args triple:
{var, {foo, bar, [some, args]}}
, this will callfoo:bar(Token, Context, some, args)
- A function with a single arg:
{var, fun(<<C,Rest/binary>>) -> C < $z end}
- A function with a two arguments:
{var, fun(<<C,Rest/binary>>, Context) -> C < $z end}
Functions must return one of the following
true
on a matchfalse
if not matched{ok, Term}
to bind the variable to the returnTerm
First compile the dispatch rules to an Erlang module:
Rules = [
{test, ["a", v], foo, []},
{wildcard, ["w", '*'], foo, []}
],
ok = dispatch_compiler:compile_load('mydispatch', Rules).
Now the compiled module can be used to match (the undefined will be passed as Context
to any functions in the dispatch rules):
1> mydispatch:match([<<"a">>, <<"b">>], undefined).
{ok, { {test, ["a", v], foo, []}, [{v,<<"b">>}]}}
The return value contains the matched dispatch rule and any bound variables. The first matching rule is returned.
Another example showing a matching wildcard:
2> mydispatch:match([<<"w">>, <<"b">>, <<"c">>], undefined).
{ok, { {wildcard, ["w", '*'], foo, []}, [{'*',[<<"b">>, <<"c">>]}]}}
If no dispatch rule could be matched, then fail
is returned:
3> mydispatch:match([<<"a">>, <<"b">>, <<"c">>], undefined).
fail
Run make test
to run the tests.