diff options
Diffstat (limited to 'src/bin')
-rw-r--r-- | src/bin/gen.rs | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/bin/gen.rs b/src/bin/gen.rs new file mode 100644 index 000000000..d3539321e --- /dev/null +++ b/src/bin/gen.rs | |||
@@ -0,0 +1,82 @@ | |||
1 | extern crate serde; | ||
2 | #[macro_use] | ||
3 | extern crate serde_derive; | ||
4 | |||
5 | extern crate ron; | ||
6 | extern crate file; | ||
7 | |||
8 | use std::path::PathBuf; | ||
9 | use std::ascii::AsciiExt; | ||
10 | use std::fmt::Write; | ||
11 | |||
12 | fn main() { | ||
13 | let grammar = Grammar::read(); | ||
14 | let text = grammar.to_syntax_kinds(); | ||
15 | file::put_text(&generated_file(), &text).unwrap(); | ||
16 | } | ||
17 | |||
18 | #[derive(Deserialize)] | ||
19 | struct Grammar { | ||
20 | syntax_kinds: Vec<String>, | ||
21 | } | ||
22 | |||
23 | impl Grammar { | ||
24 | fn read() -> Grammar { | ||
25 | let text = file::get_text(&grammar_file()).unwrap(); | ||
26 | ron::de::from_str(&text).unwrap() | ||
27 | } | ||
28 | |||
29 | fn to_syntax_kinds(&self) -> String { | ||
30 | let mut acc = String::new(); | ||
31 | acc.push_str("// Generated from grammar.ron\n"); | ||
32 | acc.push_str("use tree::{SyntaxKind, SyntaxInfo};\n"); | ||
33 | acc.push_str("\n"); | ||
34 | for (idx, kind) in self.syntax_kinds.iter().enumerate() { | ||
35 | let sname = scream(kind); | ||
36 | write!( | ||
37 | acc, | ||
38 | "pub const {}: SyntaxKind = SyntaxKind({});\n", | ||
39 | sname, idx | ||
40 | ).unwrap(); | ||
41 | } | ||
42 | acc.push_str("\n"); | ||
43 | for kind in self.syntax_kinds.iter() { | ||
44 | let sname = scream(kind); | ||
45 | write!( | ||
46 | acc, | ||
47 | "static {sname}_INFO: SyntaxInfo = SyntaxInfo {{\n name: \"{sname}\",\n}};\n", | ||
48 | sname = sname | ||
49 | ).unwrap(); | ||
50 | } | ||
51 | acc.push_str("\n"); | ||
52 | |||
53 | acc.push_str("pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo {\n"); | ||
54 | acc.push_str(" match kind {\n"); | ||
55 | for kind in self.syntax_kinds.iter() { | ||
56 | let sname = scream(kind); | ||
57 | write!( | ||
58 | acc, | ||
59 | " {sname} => &{sname}_INFO,\n", | ||
60 | sname = sname | ||
61 | ).unwrap(); | ||
62 | } | ||
63 | acc.push_str(" _ => unreachable!()\n"); | ||
64 | acc.push_str(" }\n"); | ||
65 | acc.push_str("}\n"); | ||
66 | acc | ||
67 | } | ||
68 | } | ||
69 | |||
70 | fn grammar_file() -> PathBuf { | ||
71 | let dir = env!("CARGO_MANIFEST_DIR"); | ||
72 | PathBuf::from(dir).join("grammar.ron") | ||
73 | } | ||
74 | |||
75 | fn generated_file() -> PathBuf { | ||
76 | let dir = env!("CARGO_MANIFEST_DIR"); | ||
77 | PathBuf::from(dir).join("src/syntax_kinds.rs") | ||
78 | } | ||
79 | |||
80 | fn scream(word: &str) -> String { | ||
81 | word.chars().map(|c| c.to_ascii_uppercase()).collect() | ||
82 | } \ No newline at end of file | ||