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