words
import words from "words";
@tape { words.gen_lookup("Kw", ["break", "case", "const", "let", "if"]); }
fn statement(name: []const u8) {
match (kw_of(name)) {
Kw.Let => { declaration(); }
Kw.Const => { declaration(); }
Kw.If => { if_statement(); }
Kw.None => { expression(); }
_ => { other(); }
}
}words turns a fixed list of words, such as a lexer’s keywords, CSS
property names or HTML tag names, into an enum and a function that finds a
word’s variant. The table is built at compile time, so a lookup is a hash
and a check of the word’s bytes, with no chain of comparisons and no
allocation. It is pure and freestanding: every profile can use it.
gen_lookup
@tape { words.gen_lookup("CssProp", ["color", "background-color", "z-index"]); }This emits, in your module:
pub enum CssProp : u16 { None; Color; BackgroundColor; ZIndex; }
pub fn css_prop_of(s: []const u8) -> CssProp; // CssProp.None: not in the list- The enum.
Nonecomes first (0), then one variant per word, in list order. - Variant names. The word’s letters and digits, each run capitalized:
break→Break,background-color→BackgroundColor,h1→H1. - The function. The enum’s name in snake case followed by
_of. Words compare byte for byte, socss_prop_of("Color")isNone.
A list holds up to 4096 words of 1 to 64 bytes. An empty word, a longer one, or a word listed twice is a compile error.
gen_lookup_named
Words that make no name of their own, such as operators, take their names from a second list:
@tape { words.gen_lookup_named("Op", ["==", "===", "!="], ["Eq", "StrictEq", "Ne"]); }
let op = op_of("==="); // Op.StrictEqSpeed
For 600 property names a lookup takes about 17 ns, about 33 times faster
than testing them one by one with bytes.eq. The list compiles in under a
tenth of a second.
Last modified: