@@ 12,7 12,7 @@ fn print_regex_tikz(re: regex::regex) void = {
let line_size = 7;
for (let inst .. re.insts) {
- fmt::printf("\\node[state")!;
+ fmt::printf(`\node[state`)!;
if (idx == 0) {
fmt::printf(",initial")!;
};
@@ 21,7 21,11 @@ fn print_regex_tikz(re: regex::regex) void = {
};
fmt::printf(",align=center,label=above:{{{}}}] (n{}) [rectangle", idx, idx)!;
if (node_x > line_size) {
- fmt::printf(",below=of n{}", line_size * node_y)!;
+ let upper = idx: int - line_size - 2;
+ if (upper < 0) {
+ upper = 0;
+ };
+ fmt::printf(",below=of n{}", upper)!;
node_x = -1;
node_y += 1;
} else {
@@ 32,40 36,62 @@ fn print_regex_tikz(re: regex::regex) void = {
fmt::print("] {")!;
match (inst) {
case let inst: regex::inst_lit =>
- fmt::printf("inst_lit\\\\\\textit{{\\textquotesingle{{{}}}\\textquotesingle}}", inst: rune)!;
+ let s = strings::multireplace(
+ strings::fromrunes([inst: rune]),
+ (`#`, `\#`));
+ fmt::printf(`lit\\\textit{{\textquotesingle{{{}}}\textquotesingle}}`, s)!;
case let inst: regex::inst_charset =>
let pos_str = "";
if (!inst.is_positive) {
pos_str = "not ";
};
- fmt::printf("inst_charset\\\\\\textit{{{}$\\chi^{}$}}", pos_str, inst.idx)!;
+ fmt::printf(`charset\\\textit{{{}$\chi^{}$}}`, pos_str, inst.idx)!;
case let inst: regex::inst_any =>
- fmt::print("inst_any")!;
+ fmt::print("any")!;
case let inst: regex::inst_split =>
- fmt::printf("inst_split\\\\\\textit{{{}}}", inst: size)!;
+ fmt::printf(`split\\\textit{{$\rightarrow${}}}`, inst: size)!;
case let inst: regex::inst_jump =>
- fmt::printf("inst_jump\\\\\\textit{{{}}}", inst: size)!;
+ fmt::printf(`jump\\\textit{{$\rightarrow${}}}`, inst: size)!;
case let inst: regex::inst_skip =>
- fmt::print("inst_skip")!;
+ fmt::print("skip")!;
case let inst: regex::inst_match =>
- fmt::printf("inst_match\\\\\\textit{{{}}}", inst: bool)!;
+ let anchored = "anchored";
+ if (!inst) {
+ anchored = "unanchored";
+ };
+ fmt::printf(`match\\\textit{{{}}}`, anchored)!;
case let inst: regex::inst_groupstart =>
- fmt::print("inst_groupstart")!;
+ fmt::print("groupstart")!;
case let inst: regex::inst_groupend =>
- fmt::print("inst_groupend")!;
+ fmt::print("groupend")!;
case let inst: regex::inst_repeat =>
- fmt::printf("inst_repeat\\\\\\textit{{{}, {}, {}, {}}}",
- inst.id, inst.origin, inst.min, inst.max)!;
+ const min = inst.min;
+ const max = inst.max;
+ let times = if (min is size && max is size) {
+ yield if (min: size == max: size) {
+ yield fmt::asprintf("{}", min);
+ } else {
+ yield fmt::asprintf("{}–{}", min, max);
+ };
+ } else if (min is void && max is void) {
+ yield "?";
+ } else if (min is void) {
+ yield fmt::asprintf("–{}", max);
+ } else if (max is void) {
+ yield fmt::asprintf("{}–", min);
+ };
+ fmt::printf(`repeat\\\textit{{$\rightarrow${}, {} times}}`,
+ inst.origin, times)!;
};
fmt::println("};")!;
if (idx > 0) {
if (node_x == -1) {
- fmt::printfln("\\draw[->] (n{}) to node[auto] {{}} +(1.5cm,0);",
+ fmt::printfln(`\draw[->] (n{}) to node[auto] {{}} +(1.5cm,0);`,
idx - 1)!;
- fmt::printfln("\\draw[<-] (n{}) to node[swap] {{}} +(-1.5cm,0);",
+ fmt::printfln(`\draw[<-] (n{}) to node[swap] {{}} +(-1.5cm,0);`,
idx)!;
} else {
- fmt::printfln("\\path[->] (n{}) edge node {{}} (n{});",
+ fmt::printfln(`\path[->] (n{}) edge node {{}} (n{});`,
idx - 1, idx)!;
};
};
@@ 74,48 100,55 @@ fn print_regex_tikz(re: regex::regex) void = {
};
};
-fn print_regex_tex(expr: str) void = {
+fn print_regex_tex(title: str, expr: str) void = {
const re = regex::compile(expr)!;
+ const expr_clean = strings::multireplace(expr, (`\`, "\\\\"));
- fmt::println("\\begin{figure}")!;
- fmt::println("\\begin{center}")!;
- fmt::printfln("{{\\Large\\texttt{{{}}}}}\\\\", expr)!;
- fmt::println("\\vspace{0.5cm}")!;
- fmt::println("\\begin{tikzpicture}[node distance=0.8cm,auto]")!;
+ fmt::println(`\begin{figure}`)!;
+ fmt::println(`\begin{center}`)!;
+ fmt::printfln(`{{\Large {}}}\\`, title)!;
+ fmt::println(`\vspace{0.5cm}`)!;
+ fmt::printfln(`{{\Large\nolinkurl{{{}}}}}\\`, expr_clean)!;
+ fmt::println(`\vspace{0.5cm}`)!;
+ fmt::println(`\begin{tikzpicture}[node distance=0.8cm,auto]`)!;
print_regex_tikz(re);
- fmt::println("\\end{tikzpicture}")!;
- fmt::println("\\end{center}")!;
- fmt::println("\\vspace{0.5cm}\n")!;
+ fmt::println(`\end{tikzpicture}`)!;
+ fmt::println(`\end{center}`)!;
+ fmt::println(`\vspace{0.5cm}`)!;
+ fmt::println(``)!;
if (len(re.charsets) > 0) {
- fmt::println("Charsets:\n")!;
- fmt::println("\\begin{itemize}")!;
+ fmt::println(`Charsets:`)!;
+ fmt::println(``)!;
+ fmt::println(`\begin{itemize}`)!;
};
let idx_charset = 0z;
for (let charset .. re.charsets) {
- fmt::printfln("\\item $\\chi^{}$:", idx_charset)!;
- fmt::println("\\begin{itemize}")!;
+ fmt::printfln(`\item $\chi^{}$:`, idx_charset)!;
+ fmt::println(`\begin{itemize}`)!;
for (let item .. charset) {
match (item) {
case let item: regex::charset_lit_item =>
- fmt::printfln("\\item \\textquotesingle{{{}}}\\textquotesingle", item: rune)!;
+ fmt::printfln(`\item \textquotesingle{{\nolinkurl{{{}}}}}\textquotesingle`,
+ item: rune)!;
case let item: regex::charset_range_item =>
- fmt::println("\\item ({}, {})", item.0, item.1)!;
+ fmt::printfln(`\item U+{} to U+{}`, item.0, item.1)!;
case let item: regex::charset_class_item =>
const class_name = strings::sub(item.0, 0, len(item.0) - 1);
- fmt::println("\\item {}", class_name)!;
+ fmt::printfln(`\item {}`, class_name)!;
};
};
- fmt::println("\\end{itemize}")!;
+ fmt::println(`\end{itemize}`)!;
idx_charset += 1;
};
if (len(re.charsets) > 0) {
- fmt::println("\\end{itemize}")!;
+ fmt::println(`\end{itemize}`)!;
};
- fmt::println("\\end{figure}")!;
- fmt::println("\\pagebreak")!;
+ fmt::println(`\end{figure}`)!;
};
export fn main() void = {
- print_regex_tex(os::args[len(os::args) - 1]);
+ const title = os::args[len(os::args) - 2];
+ const expr = os::args[len(os::args) - 1];
+ print_regex_tex(title, expr);
};