78 lines
1.9 KiB
TypeScript
78 lines
1.9 KiB
TypeScript
import yaml from "yaml";
|
|
import { DATA_DIR, RUST_OUT_DIR } from "./_common";
|
|
import { readFileSync, writeFileSync } from "fs";
|
|
import { join } from "path";
|
|
import { EOL } from "os";
|
|
import { parsePattern, TrieBuilder } from "./trie";
|
|
|
|
const dfa: { [node: string]: { [transition: string]: string } } = yaml.parse(
|
|
readFileSync(join(DATA_DIR, "dfa.yaml"), "utf8")
|
|
);
|
|
// These states must always exist; see lex/mod.rs for more details.
|
|
dfa["TextEntity"] = {};
|
|
dfa["AttrValueEntity"] = {};
|
|
dfa["Unknown"] = {};
|
|
dfa["EOF"] = {};
|
|
|
|
const nodes = Object.keys(dfa).sort();
|
|
|
|
const rsTransition = (val: string) => {
|
|
const [_, flag, next] = /^([_<+?]?)(.*)$/.exec(val)!;
|
|
const consumeMode = {
|
|
_: "AccumulateLowerCase",
|
|
"": "Accumulate",
|
|
"<": "Current",
|
|
"+": "Next",
|
|
"?": "Reconsume",
|
|
}[flag];
|
|
return `Transition {
|
|
to: State::${next},
|
|
consume: ConsumeMode::${consumeMode},
|
|
}`;
|
|
};
|
|
|
|
const output = `
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub enum State {
|
|
${nodes.map((n, i) => `${n} = ${i}`).join(`,${EOL} `)}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub enum ConsumeMode {
|
|
Current,
|
|
Next,
|
|
Reconsume,
|
|
Accumulate,
|
|
AccumulateLowerCase,
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct Transition {
|
|
// Make pub to allow destructuring.
|
|
pub to: State,
|
|
pub consume: ConsumeMode,
|
|
}
|
|
|
|
${nodes
|
|
.map((n) => {
|
|
const trieBuilder = new TrieBuilder(n.toUpperCase(), "Transition");
|
|
for (const [pat, val] of Object.entries(dfa[n])) {
|
|
if (pat == "") {
|
|
continue;
|
|
}
|
|
trieBuilder.addPattern(parsePattern(pat), rsTransition(val));
|
|
}
|
|
if (dfa[n][""] !== undefined) {
|
|
trieBuilder.fillRemaining(rsTransition(dfa[n][""]));
|
|
}
|
|
return trieBuilder.generate();
|
|
})
|
|
.join(EOL + EOL)}
|
|
|
|
pub static TRANSITIONS: [&'static crate::pattern::TrieNode<Transition>; ${
|
|
nodes.length
|
|
}] = [${nodes.map((n) => n.toUpperCase()).join(", ")}];
|
|
`;
|
|
|
|
writeFileSync(join(RUST_OUT_DIR, "dfa.rs"), output);
|