1 // This module is unused. It was written as an experiment to get a ballpark
2 // idea of what state machines look like when translated to Rust code, and
3 // in particular, an idea of how much code it generates. The implementation
4 // below isn't optimal with respect to size, but the result wasn't exactly
5 // small. At some point, we should pursue building this out beyond
6 // experimentation, and in particular, probably provide a command line tool
7 // and/or a macro. It's a fair bit of work, so I abandoned it for the initial
8 // release. ---AG
9
10 use std::collections::HashMap;
11 use std::io::Write;
12
13 use dense::DFA;
14 use state_id::StateID;
15
16 macro_rules! wstr {
17 ($($tt:tt)*) => { write!($($tt)*).unwrap() }
18 }
19
20 macro_rules! wstrln {
21 ($($tt:tt)*) => { writeln!($($tt)*).unwrap() }
22 }
23
is_match_forward<S: StateID>(dfa: &DFA<S>) -> String24 pub fn is_match_forward<S: StateID>(dfa: &DFA<S>) -> String {
25 let names = state_variant_names(dfa);
26
27 let mut buf = vec![];
28 wstrln!(buf, "pub fn is_match(input: &[u8]) -> bool {{");
29 if dfa.is_match_state(dfa.start()) {
30 wstrln!(buf, " return true;");
31 wstrln!(buf, "}}");
32 return String::from_utf8(buf).unwrap();
33 }
34
35 wstrln!(buf, "{}", state_enum_def(dfa, &names));
36
37 wstrln!(buf, " let mut state = {};", names[&dfa.start()]);
38 wstrln!(buf, " for &b in input.iter() {{");
39 wstrln!(buf, " state = match state {{");
40 for (id, s) in dfa.iter() {
41 if dfa.is_match_state(id) {
42 continue;
43 }
44
45 wstrln!(buf, " {} => {{", &names[&id]);
46 wstrln!(buf, " match b {{");
47 for (start, end, next_id) in s.sparse_transitions() {
48 if dfa.is_match_state(next_id) {
49 wstrln!(buf, " {:?}...{:?} => return true,", start, end);
50 } else {
51 if start == end {
52 wstrln!(buf, " {:?} => {},", start, &names[&next_id]);
53 } else {
54 wstrln!(buf, " {:?}...{:?} => {},", start, end, &names[&next_id]);
55 }
56 }
57 }
58 wstrln!(buf, " _ => S::S0,");
59 wstrln!(buf, " }}");
60 wstrln!(buf, " }}");
61 }
62 wstrln!(buf, " }};");
63 wstrln!(buf, " }}");
64
65 wstrln!(buf, " false");
66 wstrln!(buf, "}}");
67 String::from_utf8(buf).unwrap()
68 }
69
state_enum_def<S: StateID>( dfa: &DFA<S>, variant_names: &HashMap<S, String>, ) -> String70 fn state_enum_def<S: StateID>(
71 dfa: &DFA<S>,
72 variant_names: &HashMap<S, String>,
73 ) -> String {
74 let mut buf = vec![];
75 wstrln!(buf, " #[derive(Clone, Copy)]");
76 wstr!(buf, " enum S {{");
77
78 let mut i = 0;
79 for (id, _) in dfa.iter() {
80 if dfa.is_match_state(id) {
81 continue;
82 }
83 if i % 10 == 0 {
84 wstr!(buf, "\n ");
85 }
86 let name = format!("S{}", id.to_usize());
87 wstr!(buf, " {},", name);
88 i += 1;
89 }
90 wstr!(buf, "\n");
91 wstrln!(buf, " }}");
92 String::from_utf8(buf).unwrap()
93 }
94
state_variant_names<S: StateID>(dfa: &DFA<S>) -> HashMap<S, String>95 fn state_variant_names<S: StateID>(dfa: &DFA<S>) -> HashMap<S, String> {
96 let mut variants = HashMap::new();
97 for (id, _) in dfa.iter() {
98 if dfa.is_match_state(id) {
99 continue;
100 }
101 variants.insert(id, format!("S::S{}", id.to_usize()));
102 }
103 variants
104 }
105