aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-02-03 09:51:06 +0000
committerAleksey Kladov <[email protected]>2018-02-03 09:51:06 +0000
commitbb381a7ff7a21cad98d80005a81f2586684f80a0 (patch)
tree5163533d7f4814b8c716e3549660494ce5291853 /tools
parent6d9753bf548b22ab1a54462f72c9c0bf4ff69382 (diff)
Move tools to a separate package
Diffstat (limited to 'tools')
-rw-r--r--tools/Cargo.toml12
-rw-r--r--tools/src/bin/gen.rs118
-rw-r--r--tools/src/bin/parse.rs20
3 files changed, 150 insertions, 0 deletions
diff --git a/tools/Cargo.toml b/tools/Cargo.toml
new file mode 100644
index 000000000..e46874929
--- /dev/null
+++ b/tools/Cargo.toml
@@ -0,0 +1,12 @@
1[package]
2name = "tools"
3version = "0.1.0"
4authors = ["Aleksey Kladov <[email protected]>"]
5publish = false
6
7[dependencies]
8serde = "1.0.26"
9serde_derive = "1.0.26"
10file = "1.1.1"
11ron = "0.1.5"
12libsyntax2 = { path = "../" }
diff --git a/tools/src/bin/gen.rs b/tools/src/bin/gen.rs
new file mode 100644
index 000000000..17cdea7a1
--- /dev/null
+++ b/tools/src/bin/gen.rs
@@ -0,0 +1,118 @@
1extern crate serde;
2#[macro_use]
3extern crate serde_derive;
4
5extern crate file;
6extern crate ron;
7
8use std::path::PathBuf;
9use std::fmt::Write;
10
11fn main() {
12 let grammar = Grammar::read();
13 let text = grammar.to_syntax_kinds();
14 let target = generated_file();
15 if text != file::get_text(&target).unwrap_or_default() {
16 file::put_text(&target, &text).unwrap();
17 }
18}
19
20#[derive(Deserialize)]
21struct Grammar {
22 keywords: Vec<String>,
23 tokens: Vec<String>,
24 nodes: Vec<String>,
25}
26
27impl Grammar {
28 fn read() -> Grammar {
29 let text = file::get_text(&grammar_file()).unwrap();
30 ron::de::from_str(&text).unwrap()
31 }
32
33 fn to_syntax_kinds(&self) -> String {
34 let mut acc = String::new();
35 acc.push_str("#![allow(bad_style, missing_docs, unreachable_pub)]\n");
36 acc.push_str("#![cfg_attr(rustfmt, rustfmt_skip)]\n");
37 acc.push_str("//! Generated from grammar.ron\n");
38 acc.push_str("use tree::SyntaxInfo;\n");
39 acc.push_str("\n");
40
41 let syntax_kinds: Vec<String> = self.keywords
42 .iter()
43 .map(|kw| kw_token(kw))
44 .chain(self.tokens.iter().cloned())
45 .chain(self.nodes.iter().cloned())
46 .collect();
47
48 // enum SyntaxKind
49 acc.push_str("/// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`.\n");
50 acc.push_str("#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]\n");
51 acc.push_str("pub enum SyntaxKind {\n");
52 for kind in syntax_kinds.iter() {
53 write!(acc, " {},\n", scream(kind)).unwrap();
54 }
55 acc.push_str("\n");
56 acc.push_str(" // Technical SyntaxKinds: they appear temporally during parsing,\n");
57 acc.push_str(" // but never end up in the final tree\n");
58 acc.push_str(" #[doc(hidden)]\n");
59 acc.push_str(" TOMBSTONE,\n");
60 acc.push_str(" #[doc(hidden)]\n");
61 acc.push_str(" EOF,\n");
62 acc.push_str("}\n");
63 acc.push_str("pub(crate) use self::SyntaxKind::*;\n");
64 acc.push_str("\n");
65
66 // fn info
67 acc.push_str("impl SyntaxKind {\n");
68 acc.push_str(" pub(crate) fn info(self) -> &'static SyntaxInfo {\n");
69 acc.push_str(" match self {\n");
70 for kind in syntax_kinds.iter() {
71 let sname = scream(kind);
72 write!(
73 acc,
74 " {sname} => &SyntaxInfo {{ name: \"{sname}\" }},\n",
75 sname = sname
76 ).unwrap();
77 }
78 acc.push_str("\n");
79 acc.push_str(" TOMBSTONE => &SyntaxInfo { name: \"TOMBSTONE\" },\n");
80 acc.push_str(" EOF => &SyntaxInfo { name: \"EOF\" },\n");
81 acc.push_str(" }\n");
82 acc.push_str(" }\n");
83 acc.push_str("}\n");
84 acc.push_str("\n");
85
86 // fn ident_to_keyword
87 acc.push_str("pub(crate) fn ident_to_keyword(ident: &str) -> Option<SyntaxKind> {\n");
88 acc.push_str(" match ident {\n");
89 for kw in self.keywords.iter() {
90 write!(acc, " {:?} => Some({}),\n", kw, kw_token(kw)).unwrap();
91 }
92 acc.push_str(" _ => None,\n");
93 acc.push_str(" }\n");
94 acc.push_str("}\n");
95 acc
96 }
97}
98
99fn grammar_file() -> PathBuf {
100 base_dir().join("grammar.ron")
101}
102
103fn generated_file() -> PathBuf {
104 base_dir().join("src/syntax_kinds.rs")
105}
106
107fn scream(word: &str) -> String {
108 word.chars().map(|c| c.to_ascii_uppercase()).collect()
109}
110
111fn kw_token(keyword: &str) -> String {
112 format!("{}_KW", scream(keyword))
113}
114
115fn base_dir() -> PathBuf {
116 let dir = env!("CARGO_MANIFEST_DIR");
117 PathBuf::from(dir).parent().unwrap().to_owned()
118}
diff --git a/tools/src/bin/parse.rs b/tools/src/bin/parse.rs
new file mode 100644
index 000000000..af1325bfc
--- /dev/null
+++ b/tools/src/bin/parse.rs
@@ -0,0 +1,20 @@
1extern crate libsyntax2;
2
3use std::io::Read;
4
5use libsyntax2::{parse, tokenize};
6use libsyntax2::utils::dump_tree;
7
8fn main() {
9 let text = read_input();
10 let tokens = tokenize(&text);
11 let file = parse(text, &tokens);
12 let tree = dump_tree(&file);
13 println!("{}", tree);
14}
15
16fn read_input() -> String {
17 let mut buff = String::new();
18 ::std::io::stdin().read_to_string(&mut buff).unwrap();
19 buff
20}