diff options
author | Aleksey Kladov <[email protected]> | 2018-08-01 08:40:07 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-01 08:40:07 +0100 |
commit | 966e9db2b83802dfb55d55bd3a26e69dced1bbd7 (patch) | |
tree | 6d3bda084eab1221bcad7602aa26a2c307850a72 | |
parent | b9189ed2db8cb1934e677a17fcc6282c66306df1 (diff) |
Extract libeditor
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | cli/src/main.rs | 4 | ||||
-rw-r--r-- | code/native/Cargo.toml | 2 | ||||
-rw-r--r-- | code/native/src/lib.rs | 40 | ||||
-rw-r--r-- | libeditor/Cargo.toml | 9 | ||||
-rw-r--r-- | libeditor/src/lib.rs | 53 | ||||
-rw-r--r-- | src/algo/walk.rs | 1 | ||||
-rw-r--r-- | src/ast.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/parser_impl/event.rs | 2 | ||||
-rw-r--r-- | src/parser_impl/mod.rs | 8 | ||||
-rw-r--r-- | src/syntax_kinds/generated.rs | 41 | ||||
-rw-r--r-- | src/syntax_kinds/generated.rs.tera | 10 | ||||
-rw-r--r-- | src/yellow/builder.rs | 10 | ||||
-rw-r--r-- | tests/parser.rs | 2 |
15 files changed, 138 insertions, 50 deletions
diff --git a/Cargo.toml b/Cargo.toml index 0a9d1815e..d61613352 100644 --- a/Cargo.toml +++ b/Cargo.toml | |||
@@ -5,7 +5,7 @@ authors = ["Aleksey Kladov <[email protected]>"] | |||
5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
6 | 6 | ||
7 | [workspace] | 7 | [workspace] |
8 | members = [ "tools", "cli" ] | 8 | members = [ "tools", "cli", "libeditor" ] |
9 | 9 | ||
10 | [dependencies] | 10 | [dependencies] |
11 | unicode-xid = "0.1.0" | 11 | unicode-xid = "0.1.0" |
diff --git a/cli/src/main.rs b/cli/src/main.rs index f6e7e2fed..0044841ed 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs | |||
@@ -52,7 +52,7 @@ fn main() -> Result<()> { | |||
52 | fn parse() -> Result<String> { | 52 | fn parse() -> Result<String> { |
53 | let text = read_stdin()?; | 53 | let text = read_stdin()?; |
54 | let start = Instant::now(); | 54 | let start = Instant::now(); |
55 | let file = libsyntax2::parse(text); | 55 | let file = libsyntax2::parse(&text); |
56 | eprintln!("elapsed {:?}", start.elapsed()); | 56 | eprintln!("elapsed {:?}", start.elapsed()); |
57 | let tree = libsyntax2::utils::dump_tree(&file); | 57 | let tree = libsyntax2::utils::dump_tree(&file); |
58 | Ok(tree) | 58 | Ok(tree) |
@@ -74,7 +74,7 @@ fn render_test(file: &Path, line: usize) -> Result<(String, String)> { | |||
74 | None => bail!("No test found at line {} at {}", line, file.display()), | 74 | None => bail!("No test found at line {} at {}", line, file.display()), |
75 | Some((_start_line, test)) => test, | 75 | Some((_start_line, test)) => test, |
76 | }; | 76 | }; |
77 | let file = libsyntax2::parse(test.text.clone()); | 77 | let file = libsyntax2::parse(&test.text); |
78 | let tree = libsyntax2::utils::dump_tree(&file); | 78 | let tree = libsyntax2::utils::dump_tree(&file); |
79 | Ok((test.text, tree)) | 79 | Ok((test.text, tree)) |
80 | } | 80 | } |
diff --git a/code/native/Cargo.toml b/code/native/Cargo.toml index 1648dfb33..3a27051b2 100644 --- a/code/native/Cargo.toml +++ b/code/native/Cargo.toml | |||
@@ -16,4 +16,4 @@ neon-build = "0.2.0" | |||
16 | 16 | ||
17 | [dependencies] | 17 | [dependencies] |
18 | neon = "0.2.0" | 18 | neon = "0.2.0" |
19 | libsyntax2 = { path = "../../" } | 19 | libeditor = { path = "../../libeditor" } |
diff --git a/code/native/src/lib.rs b/code/native/src/lib.rs index 068767fab..aae7ad2f3 100644 --- a/code/native/src/lib.rs +++ b/code/native/src/lib.rs | |||
@@ -1,42 +1,20 @@ | |||
1 | #[macro_use] | 1 | #[macro_use] |
2 | extern crate neon; | 2 | extern crate neon; |
3 | extern crate libsyntax2; | 3 | extern crate libeditor; |
4 | 4 | ||
5 | use libsyntax2::{ | ||
6 | TextRange, | ||
7 | File, | ||
8 | utils::dump_tree, | ||
9 | SyntaxKind::*, | ||
10 | algo, | ||
11 | }; | ||
12 | use neon::prelude::*; | 5 | use neon::prelude::*; |
13 | 6 | ||
14 | pub struct Wrapper { | 7 | pub struct Wrapper { |
15 | inner: File, | 8 | inner: libeditor::File, |
16 | } | 9 | } |
17 | 10 | ||
18 | impl Wrapper { | ||
19 | fn highlight(&self) -> Vec<(TextRange, &'static str)> { | ||
20 | let mut res = Vec::new(); | ||
21 | let syntax = self.inner.syntax(); | ||
22 | for node in algo::walk::preorder(syntax.as_ref()) { | ||
23 | if node.kind() == ERROR { | ||
24 | res.push((node.range(), "error")) | ||
25 | } | ||
26 | } | ||
27 | res | ||
28 | } | ||
29 | } | ||
30 | |||
31 | |||
32 | |||
33 | declare_types! { | 11 | declare_types! { |
34 | /// A class for generating greeting strings. | 12 | /// A class for generating greeting strings. |
35 | pub class RustFile for Wrapper { | 13 | pub class RustFile for Wrapper { |
36 | init(mut cx) { | 14 | init(mut cx) { |
37 | let text = cx.argument::<JsString>(0)?.value(); | 15 | let text = cx.argument::<JsString>(0)?.value(); |
38 | Ok(Wrapper { | 16 | Ok(Wrapper { |
39 | inner: File::parse(&text) | 17 | inner: libeditor::File::new(&text) |
40 | }) | 18 | }) |
41 | } | 19 | } |
42 | 20 | ||
@@ -45,7 +23,7 @@ declare_types! { | |||
45 | let tree = { | 23 | let tree = { |
46 | let guard = cx.lock(); | 24 | let guard = cx.lock(); |
47 | let wrapper = this.borrow(&guard); | 25 | let wrapper = this.borrow(&guard); |
48 | dump_tree(&wrapper.inner.syntax()) | 26 | wrapper.inner.syntax_tree() |
49 | }; | 27 | }; |
50 | Ok(cx.string(tree.as_str()).upcast()) | 28 | Ok(cx.string(tree.as_str()).upcast()) |
51 | } | 29 | } |
@@ -55,15 +33,15 @@ declare_types! { | |||
55 | let highlights = { | 33 | let highlights = { |
56 | let guard = cx.lock(); | 34 | let guard = cx.lock(); |
57 | let wrapper = this.borrow(&guard); | 35 | let wrapper = this.borrow(&guard); |
58 | wrapper.highlight() | 36 | wrapper.inner.highlight() |
59 | }; | 37 | }; |
60 | let res = cx.empty_array(); | 38 | let res = cx.empty_array(); |
61 | for (i, (range, tag)) in highlights.into_iter().enumerate() { | 39 | for (i, hl) in highlights.into_iter().enumerate() { |
62 | let start: u32 = range.start().into(); | 40 | let start: u32 = hl.range.start().into(); |
63 | let end: u32 = range.end().into(); | 41 | let end: u32 = hl.range.end().into(); |
64 | let start = cx.number(start); | 42 | let start = cx.number(start); |
65 | let end = cx.number(end); | 43 | let end = cx.number(end); |
66 | let tag = cx.string(tag); | 44 | let tag = cx.string(hl.tag); |
67 | let hl = cx.empty_array(); | 45 | let hl = cx.empty_array(); |
68 | hl.set(&mut cx, 0, start)?; | 46 | hl.set(&mut cx, 0, start)?; |
69 | hl.set(&mut cx, 1, end)?; | 47 | hl.set(&mut cx, 1, end)?; |
diff --git a/libeditor/Cargo.toml b/libeditor/Cargo.toml new file mode 100644 index 000000000..1a532ce2f --- /dev/null +++ b/libeditor/Cargo.toml | |||
@@ -0,0 +1,9 @@ | |||
1 | [package] | ||
2 | name = "libeditor" | ||
3 | version = "0.1.0" | ||
4 | authors = ["Aleksey Kladov <[email protected]>"] | ||
5 | publish = false | ||
6 | |||
7 | [dependencies] | ||
8 | libsyntax2 = { path = "../" } | ||
9 | text_unit = "0.1.2" | ||
diff --git a/libeditor/src/lib.rs b/libeditor/src/lib.rs new file mode 100644 index 000000000..119bdb2d6 --- /dev/null +++ b/libeditor/src/lib.rs | |||
@@ -0,0 +1,53 @@ | |||
1 | extern crate libsyntax2; | ||
2 | extern crate text_unit; | ||
3 | |||
4 | use libsyntax2::{ | ||
5 | algo::walk, | ||
6 | SyntaxKind::*, | ||
7 | }; | ||
8 | use text_unit::TextRange; | ||
9 | |||
10 | pub struct File { | ||
11 | inner: libsyntax2::File | ||
12 | } | ||
13 | |||
14 | pub struct HighlightedRange { | ||
15 | pub range: TextRange, | ||
16 | pub tag: &'static str, | ||
17 | } | ||
18 | |||
19 | impl File { | ||
20 | pub fn new(text: &str) -> File { | ||
21 | File { | ||
22 | inner: libsyntax2::File::parse(text) | ||
23 | } | ||
24 | } | ||
25 | |||
26 | pub fn highlight(&self) -> Vec<HighlightedRange> { | ||
27 | let syntax = self.inner.syntax(); | ||
28 | let mut res = Vec::new(); | ||
29 | for node in walk::preorder(syntax.as_ref()) { | ||
30 | let tag = match node.kind() { | ||
31 | ERROR => "error", | ||
32 | COMMENT | DOC_COMMENT => "comment", | ||
33 | STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string", | ||
34 | ATTR => "attribute", | ||
35 | NAME_REF => "text", | ||
36 | NAME => "function", | ||
37 | INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", | ||
38 | LIFETIME => "parameter", | ||
39 | k if k.is_keyword() => "keyword", | ||
40 | _ => continue, | ||
41 | }; | ||
42 | res.push(HighlightedRange { | ||
43 | range: node.range(), | ||
44 | tag | ||
45 | }) | ||
46 | } | ||
47 | res | ||
48 | } | ||
49 | |||
50 | pub fn syntax_tree(&self) -> String { | ||
51 | ::libsyntax2::utils::dump_tree(&self.inner.syntax()) | ||
52 | } | ||
53 | } | ||
diff --git a/src/algo/walk.rs b/src/algo/walk.rs index a50ec2a09..ad0f2d8fb 100644 --- a/src/algo/walk.rs +++ b/src/algo/walk.rs | |||
@@ -6,7 +6,6 @@ pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = SyntaxNodeR | |||
6 | WalkEvent::Exit(_) => None, | 6 | WalkEvent::Exit(_) => None, |
7 | }) | 7 | }) |
8 | } | 8 | } |
9 | |||
10 | #[derive(Debug, Copy, Clone)] | 9 | #[derive(Debug, Copy, Clone)] |
11 | pub enum WalkEvent<'a> { | 10 | pub enum WalkEvent<'a> { |
12 | Enter(SyntaxNodeRef<'a>), | 11 | Enter(SyntaxNodeRef<'a>), |
diff --git a/src/ast.rs b/src/ast.rs index 48e1d23ac..caf5fb7ef 100644 --- a/src/ast.rs +++ b/src/ast.rs | |||
@@ -9,7 +9,7 @@ pub struct File<R: TreeRoot = Arc<SyntaxRoot>> { | |||
9 | impl File<Arc<SyntaxRoot>> { | 9 | impl File<Arc<SyntaxRoot>> { |
10 | pub fn parse(text: &str) -> Self { | 10 | pub fn parse(text: &str) -> Self { |
11 | File { | 11 | File { |
12 | syntax: ::parse(text.to_owned()), | 12 | syntax: ::parse(text), |
13 | } | 13 | } |
14 | } | 14 | } |
15 | } | 15 | } |
diff --git a/src/lib.rs b/src/lib.rs index 8f25de9a4..611b87492 100644 --- a/src/lib.rs +++ b/src/lib.rs | |||
@@ -45,7 +45,7 @@ pub use { | |||
45 | yellow::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot}, | 45 | yellow::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot}, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | pub fn parse(text: String) -> SyntaxNode { | 48 | pub fn parse(text: &str) -> SyntaxNode { |
49 | let tokens = tokenize(&text); | 49 | let tokens = tokenize(&text); |
50 | parser_impl::parse::<yellow::GreenBuilder>(text, &tokens) | 50 | parser_impl::parse::<yellow::GreenBuilder>(text, &tokens) |
51 | } | 51 | } |
diff --git a/src/parser_impl/event.rs b/src/parser_impl/event.rs index eb5d0a4be..66a0b6fc0 100644 --- a/src/parser_impl/event.rs +++ b/src/parser_impl/event.rs | |||
@@ -76,7 +76,7 @@ pub(crate) enum Event { | |||
76 | }, | 76 | }, |
77 | } | 77 | } |
78 | 78 | ||
79 | pub(super) fn process(builder: &mut impl Sink, tokens: &[Token], events: Vec<Event>) { | 79 | pub(super) fn process<'a>(builder: &mut impl Sink<'a>, tokens: &[Token], events: Vec<Event>) { |
80 | let mut idx = 0; | 80 | let mut idx = 0; |
81 | 81 | ||
82 | let mut holes = Vec::new(); | 82 | let mut holes = Vec::new(); |
diff --git a/src/parser_impl/mod.rs b/src/parser_impl/mod.rs index b58094be3..2791c8da5 100644 --- a/src/parser_impl/mod.rs +++ b/src/parser_impl/mod.rs | |||
@@ -14,10 +14,10 @@ use { | |||
14 | 14 | ||
15 | use SyntaxKind::{self, EOF, TOMBSTONE}; | 15 | use SyntaxKind::{self, EOF, TOMBSTONE}; |
16 | 16 | ||
17 | pub(crate) trait Sink { | 17 | pub(crate) trait Sink<'a> { |
18 | type Tree; | 18 | type Tree; |
19 | 19 | ||
20 | fn new(text: String) -> Self; | 20 | fn new(text: &'a str) -> Self; |
21 | 21 | ||
22 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); | 22 | fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); |
23 | fn start_internal(&mut self, kind: SyntaxKind); | 23 | fn start_internal(&mut self, kind: SyntaxKind); |
@@ -27,9 +27,9 @@ pub(crate) trait Sink { | |||
27 | } | 27 | } |
28 | 28 | ||
29 | /// Parse a sequence of tokens into the representative node tree | 29 | /// Parse a sequence of tokens into the representative node tree |
30 | pub(crate) fn parse<S: Sink>(text: String, tokens: &[Token]) -> S::Tree { | 30 | pub(crate) fn parse<'a, S: Sink<'a>>(text: &'a str, tokens: &[Token]) -> S::Tree { |
31 | let events = { | 31 | let events = { |
32 | let input = input::ParserInput::new(&text, tokens); | 32 | let input = input::ParserInput::new(text, tokens); |
33 | let parser_impl = ParserImpl::new(&input); | 33 | let parser_impl = ParserImpl::new(&input); |
34 | let mut parser_api = Parser(parser_impl); | 34 | let mut parser_api = Parser(parser_impl); |
35 | grammar::file(&mut parser_api); | 35 | grammar::file(&mut parser_api); |
diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 435be781c..cbcd0c4e1 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs | |||
@@ -169,6 +169,47 @@ pub enum SyntaxKind { | |||
169 | use self::SyntaxKind::*; | 169 | use self::SyntaxKind::*; |
170 | 170 | ||
171 | impl SyntaxKind { | 171 | impl SyntaxKind { |
172 | pub fn is_keyword(self) -> bool { | ||
173 | match self { | ||
174 | | USE_KW | ||
175 | | FN_KW | ||
176 | | STRUCT_KW | ||
177 | | ENUM_KW | ||
178 | | TRAIT_KW | ||
179 | | IMPL_KW | ||
180 | | TRUE_KW | ||
181 | | FALSE_KW | ||
182 | | AS_KW | ||
183 | | EXTERN_KW | ||
184 | | CRATE_KW | ||
185 | | MOD_KW | ||
186 | | PUB_KW | ||
187 | | SELF_KW | ||
188 | | SUPER_KW | ||
189 | | IN_KW | ||
190 | | WHERE_KW | ||
191 | | FOR_KW | ||
192 | | LOOP_KW | ||
193 | | WHILE_KW | ||
194 | | IF_KW | ||
195 | | ELSE_KW | ||
196 | | MATCH_KW | ||
197 | | CONST_KW | ||
198 | | STATIC_KW | ||
199 | | MUT_KW | ||
200 | | UNSAFE_KW | ||
201 | | TYPE_KW | ||
202 | | REF_KW | ||
203 | | LET_KW | ||
204 | | MOVE_KW | ||
205 | | AUTO_KW | ||
206 | | DEFAULT_KW | ||
207 | | UNION_KW | ||
208 | => true, | ||
209 | _ => false | ||
210 | } | ||
211 | } | ||
212 | |||
172 | pub(crate) fn info(self) -> &'static SyntaxInfo { | 213 | pub(crate) fn info(self) -> &'static SyntaxInfo { |
173 | match self { | 214 | match self { |
174 | SEMI => &SyntaxInfo { name: "SEMI" }, | 215 | SEMI => &SyntaxInfo { name: "SEMI" }, |
diff --git a/src/syntax_kinds/generated.rs.tera b/src/syntax_kinds/generated.rs.tera index d719c8312..4e2ee56c3 100644 --- a/src/syntax_kinds/generated.rs.tera +++ b/src/syntax_kinds/generated.rs.tera | |||
@@ -24,6 +24,16 @@ pub enum SyntaxKind { | |||
24 | use self::SyntaxKind::*; | 24 | use self::SyntaxKind::*; |
25 | 25 | ||
26 | impl SyntaxKind { | 26 | impl SyntaxKind { |
27 | pub fn is_keyword(self) -> bool { | ||
28 | match self { | ||
29 | {%- for kw in concat(a=keywords, b=contextual_keywords) %} | ||
30 | | {{kw | upper}}_KW | ||
31 | {%- endfor %} | ||
32 | => true, | ||
33 | _ => false | ||
34 | } | ||
35 | } | ||
36 | |||
27 | pub(crate) fn info(self) -> &'static SyntaxInfo { | 37 | pub(crate) fn info(self) -> &'static SyntaxInfo { |
28 | match self { | 38 | match self { |
29 | {%- for t in concat(a=single_byte_tokens, b=multi_byte_tokens) %} | 39 | {%- for t in concat(a=single_byte_tokens, b=multi_byte_tokens) %} |
diff --git a/src/yellow/builder.rs b/src/yellow/builder.rs index b68ba789e..dbe646cd7 100644 --- a/src/yellow/builder.rs +++ b/src/yellow/builder.rs | |||
@@ -4,20 +4,18 @@ use { | |||
4 | SyntaxKind, TextRange, TextUnit, | 4 | SyntaxKind, TextRange, TextUnit, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | pub(crate) struct GreenBuilder { | 7 | pub(crate) struct GreenBuilder<'a> { |
8 | text: String, | 8 | text: &'a str, |
9 | stack: Vec<GreenNodeBuilder>, | 9 | stack: Vec<GreenNodeBuilder>, |
10 | pos: TextUnit, | 10 | pos: TextUnit, |
11 | root: Option<GreenNode>, | 11 | root: Option<GreenNode>, |
12 | errors: Vec<SyntaxError>, | 12 | errors: Vec<SyntaxError>, |
13 | } | 13 | } |
14 | 14 | ||
15 | impl GreenBuilder {} | 15 | impl<'a> Sink<'a> for GreenBuilder<'a> { |
16 | |||
17 | impl Sink for GreenBuilder { | ||
18 | type Tree = SyntaxNode; | 16 | type Tree = SyntaxNode; |
19 | 17 | ||
20 | fn new(text: String) -> Self { | 18 | fn new(text: &'a str) -> Self { |
21 | GreenBuilder { | 19 | GreenBuilder { |
22 | text, | 20 | text, |
23 | stack: Vec::new(), | 21 | stack: Vec::new(), |
diff --git a/tests/parser.rs b/tests/parser.rs index 770610974..af2ae11bb 100644 --- a/tests/parser.rs +++ b/tests/parser.rs | |||
@@ -8,7 +8,7 @@ use testutils::dir_tests; | |||
8 | #[test] | 8 | #[test] |
9 | fn parser_tests() { | 9 | fn parser_tests() { |
10 | dir_tests(&["parser/inline", "parser/ok", "parser/err"], |text| { | 10 | dir_tests(&["parser/inline", "parser/ok", "parser/err"], |text| { |
11 | let file = parse(text.to_string()); | 11 | let file = parse(text); |
12 | dump_tree(&file) | 12 | dump_tree(&file) |
13 | }) | 13 | }) |
14 | } | 14 | } |